summaryrefslogtreecommitdiff
path: root/benchmark/vm_dstr_bool.rb
diff options
context:
space:
mode:
authorTim Smith <tsmith@mondoo.com>2022-04-17 21:53:43 -0700
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2022-04-19 08:32:37 +0900
commit810b9c344a40802d7736282d86e51d48e8b336a4 (patch)
treefc29a1b466b0f8b2b08b0dc20ea4e76bc61e020a /benchmark/vm_dstr_bool.rb
parent4299375b9b8b49b02b3d131bfbc621cf28752fae (diff)
Resolve several markedown warnings
- Spaces before and after blocks. - Single spaces after sentences everywhere Signed-off-by: Tim Smith <tsmith@mondoo.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5816
Diffstat (limited to 'benchmark/vm_dstr_bool.rb')
0 files changed, 0 insertions, 0 deletions
de'>-rw-r--r--spec/bundled_gems_spec.rb422
-rw-r--r--spec/bundler/bundler/build_metadata_spec.rb50
-rw-r--r--spec/bundler/bundler/bundler_spec.rb372
-rw-r--r--spec/bundler/bundler/ci_detector_spec.rb21
-rw-r--r--spec/bundler/bundler/cli_common_spec.rb22
-rw-r--r--spec/bundler/bundler/cli_spec.rb239
-rw-r--r--spec/bundler/bundler/compact_index_client/parser_spec.rb249
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb236
-rw-r--r--spec/bundler/bundler/current_ruby_spec.rb157
-rw-r--r--spec/bundler/bundler/definition_spec.rb320
-rw-r--r--spec/bundler/bundler/dep_proxy_spec.rb22
-rw-r--r--spec/bundler/bundler/dependency_spec.rb49
-rw-r--r--spec/bundler/bundler/digest_spec.rb24
-rw-r--r--spec/bundler/bundler/dsl_spec.rb427
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb90
-rw-r--r--spec/bundler/bundler/env_spec.rb142
-rw-r--r--spec/bundler/bundler/environment_preserver_spec.rb16
-rw-r--r--spec/bundler/bundler/errors_spec.rb91
-rw-r--r--spec/bundler/bundler/fetcher/base_spec.rb11
-rw-r--r--spec/bundler/bundler/fetcher/compact_index_spec.rb34
-rw-r--r--spec/bundler/bundler/fetcher/dependency_spec.rb57
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb228
-rw-r--r--spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb60
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb100
-rw-r--r--spec/bundler/bundler/fetcher_spec.rb133
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb89
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb205
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb246
-rw-r--r--spec/bundler/bundler/installer/gem_installer_spec.rb36
-rw-r--r--spec/bundler/bundler/installer/parallel_installer_spec.rb100
-rw-r--r--spec/bundler/bundler/installer/spec_installation_spec.rb73
-rw-r--r--spec/bundler/bundler/lockfile_parser_spec.rb166
-rw-r--r--spec/bundler/bundler/mirror_spec.rb24
-rw-r--r--spec/bundler/bundler/override_spec.rb175
-rw-r--r--spec/bundler/bundler/plugin/api/source_spec.rb10
-rw-r--r--spec/bundler/bundler/plugin/dsl_spec.rb8
-rw-r--r--spec/bundler/bundler/plugin/events_spec.rb16
-rw-r--r--spec/bundler/bundler/plugin/index_spec.rb125
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb63
-rw-r--r--spec/bundler/bundler/plugin_spec.rb127
-rw-r--r--spec/bundler/bundler/psyched_yaml_spec.rb9
-rw-r--r--spec/bundler/bundler/remote_specification_spec.rb14
-rw-r--r--spec/bundler/bundler/resolver/candidate_spec.rb20
-rw-r--r--spec/bundler/bundler/resolver/cooldown_spec.rb148
-rw-r--r--spec/bundler/bundler/retry_spec.rb113
-rw-r--r--spec/bundler/bundler/ruby_dsl_spec.rb163
-rw-r--r--spec/bundler/bundler/ruby_version_spec.rb108
-rw-r--r--spec/bundler/bundler/rubygems_ext_spec.rb39
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb116
-rw-r--r--spec/bundler/bundler/settings/validator_spec.rb6
-rw-r--r--spec/bundler/bundler/settings_spec.rb132
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb156
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb310
-rw-r--r--spec/bundler/bundler/source/git_spec.rb99
-rw-r--r--spec/bundler/bundler/source/rubygems/remote_spec.rb79
-rw-r--r--spec/bundler/bundler/source/rubygems_spec.rb71
-rw-r--r--spec/bundler/bundler/source_list_spec.rb128
-rw-r--r--spec/bundler/bundler/source_spec.rb110
-rw-r--r--spec/bundler/bundler/spec_set_spec.rb97
-rw-r--r--spec/bundler/bundler/specifications/foo.gemspec13
-rw-r--r--spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb140
-rw-r--r--spec/bundler/bundler/stub_specification_spec.rb76
-rw-r--r--spec/bundler/bundler/ui/shell_spec.rb89
-rw-r--r--spec/bundler/bundler/ui_spec.rb4
-rw-r--r--spec/bundler/bundler/uri_credentials_filter_spec.rb20
-rw-r--r--spec/bundler/bundler/uri_normalizer_spec.rb25
-rw-r--r--spec/bundler/bundler/vendored_persistent_spec.rb78
-rw-r--r--spec/bundler/bundler/version_ranges_spec.rb37
-rw-r--r--spec/bundler/bundler/worker_spec.rb67
-rw-r--r--spec/bundler/bundler/yaml_serializer_spec.rb61
-rw-r--r--spec/bundler/cache/cache_path_spec.rb18
-rw-r--r--spec/bundler/cache/gems_spec.rb335
-rw-r--r--spec/bundler/cache/git_spec.rb573
-rw-r--r--spec/bundler/cache/path_spec.rb192
-rw-r--r--spec/bundler/cache/platform_spec.rb20
-rw-r--r--spec/bundler/commands/add_spec.rb361
-rw-r--r--spec/bundler/commands/binstubs_spec.rb425
-rw-r--r--spec/bundler/commands/cache_spec.rb620
-rw-r--r--spec/bundler/commands/check_spec.rb533
-rw-r--r--spec/bundler/commands/clean_spec.rb593
-rw-r--r--spec/bundler/commands/config_spec.rb454
-rw-r--r--spec/bundler/commands/console_spec.rb250
-rw-r--r--spec/bundler/commands/doctor_spec.rb135
-rw-r--r--spec/bundler/commands/exec_spec.rb939
-rw-r--r--spec/bundler/commands/fund_spec.rb118
-rw-r--r--spec/bundler/commands/help_spec.rb52
-rw-r--r--spec/bundler/commands/info_spec.rb228
-rw-r--r--spec/bundler/commands/init_spec.rb168
-rw-r--r--spec/bundler/commands/inject_spec.rb117
-rw-r--r--spec/bundler/commands/install_spec.rb2002
-rw-r--r--spec/bundler/commands/issue_spec.rb2
-rw-r--r--spec/bundler/commands/licenses_spec.rb21
-rw-r--r--spec/bundler/commands/list_spec.rb258
-rw-r--r--spec/bundler/commands/lock_spec.rb2723
-rw-r--r--spec/bundler/commands/newgem_spec.rb2235
-rw-r--r--spec/bundler/commands/open_spec.rb217
-rw-r--r--spec/bundler/commands/outdated_spec.rb1125
-rw-r--r--spec/bundler/commands/package_spec.rb306
-rw-r--r--spec/bundler/commands/platform_spec.rb1260
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb183
-rw-r--r--spec/bundler/commands/pristine_spec.rb181
-rw-r--r--spec/bundler/commands/remove_spec.rb509
-rw-r--r--spec/bundler/commands/show_spec.rb185
-rw-r--r--spec/bundler/commands/ssl_spec.rb373
-rw-r--r--spec/bundler/commands/update_spec.rb1846
-rw-r--r--spec/bundler/commands/version_spec.rb66
-rw-r--r--spec/bundler/commands/viz_spec.rb149
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb63
-rw-r--r--spec/bundler/install/binstubs_spec.rb42
-rw-r--r--spec/bundler/install/bundler_spec.rb249
-rw-r--r--spec/bundler/install/cooldown_spec.rb272
-rw-r--r--spec/bundler/install/deploy_spec.rb562
-rw-r--r--spec/bundler/install/failure_spec.rb122
-rw-r--r--spec/bundler/install/force_spec.rb71
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb72
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb136
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb709
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb1040
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb245
-rw-r--r--spec/bundler/install/gemfile/install_if.rb44
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb51
-rw-r--r--spec/bundler/install/gemfile/lockfile_spec.rb34
-rw-r--r--spec/bundler/install/gemfile/override_spec.rb401
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb685
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb664
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb137
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb1418
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb2019
-rw-r--r--spec/bundler/install/gemfile_spec.rb171
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb822
-rw-r--r--spec/bundler/install/gems/dependency_api_fallback_spec.rb19
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb488
-rw-r--r--spec/bundler/install/gems/env_spec.rb36
-rw-r--r--spec/bundler/install/gems/flex_spec.rb344
-rw-r--r--spec/bundler/install/gems/fund_spec.rb164
-rw-r--r--spec/bundler/install/gems/gemfile_source_header_spec.rb24
-rw-r--r--spec/bundler/install/gems/mirror_probe_spec.rb68
-rw-r--r--spec/bundler/install/gems/mirror_spec.rb24
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb114
-rw-r--r--spec/bundler/install/gems/no_build_extension_spec.rb54
-rw-r--r--spec/bundler/install/gems/no_install_plugin_spec.rb53
-rw-r--r--spec/bundler/install/gems/post_install_spec.rb48
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb695
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb467
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb178
-rw-r--r--spec/bundler/install/gems/win32_spec.rb13
-rw-r--r--spec/bundler/install/gemspecs_spec.rb95
-rw-r--r--spec/bundler/install/git_spec.rb350
-rw-r--r--spec/bundler/install/global_cache_spec.rb282
-rw-r--r--spec/bundler/install/path_spec.rb246
-rw-r--r--spec/bundler/install/post_bundle_message_spec.rb206
-rw-r--r--spec/bundler/install/prereleases_spec.rb27
-rw-r--r--spec/bundler/install/process_lock_spec.rb92
-rw-r--r--spec/bundler/install/redownload_spec.rb92
-rw-r--r--spec/bundler/install/security_policy_spec.rb37
-rw-r--r--spec/bundler/install/yanked_spec.rb241
-rw-r--r--spec/bundler/lock/git_spec.rb226
-rw-r--r--spec/bundler/lock/lockfile_bundler_1_spec.rb1386
-rw-r--r--spec/bundler/lock/lockfile_spec.rb2047
-rw-r--r--spec/bundler/other/bundle_ruby_spec.rb155
-rw-r--r--spec/bundler/other/cli_dispatch_spec.rb25
-rw-r--r--spec/bundler/other/cli_man_pages_spec.rb100
-rw-r--r--spec/bundler/other/compatibility_guard_spec.rb25
-rw-r--r--spec/bundler/other/ext_spec.rb70
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb846
-rw-r--r--spec/bundler/other/platform_spec.rb1312
-rw-r--r--spec/bundler/other/ssl_cert_spec.rb18
-rw-r--r--spec/bundler/plugins/command_spec.rb48
-rw-r--r--spec/bundler/plugins/hook_spec.rb256
-rw-r--r--spec/bundler/plugins/install_spec.rb267
-rw-r--r--spec/bundler/plugins/list_spec.rb60
-rw-r--r--spec/bundler/plugins/source/example_spec.rb171
-rw-r--r--spec/bundler/plugins/source_spec.rb19
-rw-r--r--spec/bundler/plugins/uninstall_spec.rb74
-rw-r--r--spec/bundler/quality_es_spec.rb61
-rw-r--r--spec/bundler/quality_spec.rb252
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb44
-rw-r--r--spec/bundler/realworld/double_check_spec.rb10
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb359
-rw-r--r--spec/bundler/realworld/ffi_spec.rb57
-rw-r--r--spec/bundler/realworld/fixtures/tapioca/Gemfile5
-rw-r--r--spec/bundler/realworld/fixtures/tapioca/Gemfile.lock49
-rw-r--r--spec/bundler/realworld/fixtures/warbler/.gitignore1
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile7
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock35
-rw-r--r--spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb3
-rw-r--r--spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec10
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb53
-rw-r--r--spec/bundler/realworld/git_spec.rb11
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb144
-rw-r--r--spec/bundler/realworld/parallel_spec.rb24
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb35
-rw-r--r--spec/bundler/resolver/basic_spec.rb186
-rw-r--r--spec/bundler/resolver/platform_spec.rb337
-rw-r--r--spec/bundler/runtime/env_helpers_spec.rb236
-rw-r--r--spec/bundler/runtime/executable_spec.rb151
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb138
-rw-r--r--spec/bundler/runtime/inline_spec.rb597
-rw-r--r--spec/bundler/runtime/load_spec.rb44
-rw-r--r--spec/bundler/runtime/platform_spec.rb388
-rw-r--r--spec/bundler/runtime/require_spec.rb166
-rw-r--r--spec/bundler/runtime/requiring_spec.rb15
-rw-r--r--spec/bundler/runtime/self_management_spec.rb279
-rw-r--r--spec/bundler/runtime/setup_spec.rb1243
-rw-r--r--spec/bundler/runtime/with_clean_env_spec.rb151
-rw-r--r--spec/bundler/spec_helper.rb230
-rw-r--r--spec/bundler/support/activate.rb9
-rw-r--r--spec/bundler/support/artifice/compact_index.rb120
-rw-r--r--spec/bundler/support/artifice/compact_index_api_missing.rb13
-rw-r--r--spec/bundler/support/artifice/compact_index_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_checksum_mismatch.rb10
-rw-r--r--spec/bundler/support/artifice/compact_index_concurrent_download.rb15
-rw-r--r--spec/bundler/support/artifice/compact_index_cooldown.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_creds_diff_host.rb10
-rw-r--r--spec/bundler/support/artifice/compact_index_etag_match.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index_extra.rb35
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api.rb50
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api_missing.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_missing.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_host_redirect.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_mirror_down.rb21
-rw-r--r--spec/bundler/support/artifice/compact_index_no_checksums.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index_no_gem.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update.rb14
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_bad_digest.rb40
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_no_digest_not_incremental.rb42
-rw-r--r--spec/bundler/support/artifice/compact_index_precompiled_before.rb25
-rw-r--r--spec/bundler/support/artifice/compact_index_range_ignored.rb40
-rw-r--r--spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_rate_limited.rb48
-rw-r--r--spec/bundler/support/artifice/compact_index_redirects.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_dependencies.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb9
-rw-r--r--spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb15
-rw-r--r--spec/bundler/support/artifice/endpoint.rb98
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb10
-rw-r--r--spec/bundler/support/artifice/endpoint_api_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_api_missing.rb18
-rw-r--r--spec/bundler/support/artifice/endpoint_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_creds_diff_host.rb10
-rw-r--r--spec/bundler/support/artifice/endpoint_extra.rb14
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_api.rb14
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_missing.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_fallback.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_host_redirect.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail.rb11
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb15
-rw-r--r--spec/bundler/support/artifice/endpoint_mirror_source.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_timeout.rb6
-rw-r--r--spec/bundler/support/artifice/fail.rb30
-rw-r--r--spec/bundler/support/artifice/helpers/artifice.rb30
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb128
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_cooldown.rb13
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra.rb33
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra_api.rb48
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb113
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_extra.rb29
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_fallback.rb15
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb9
-rw-r--r--spec/bundler/support/artifice/helpers/rack_request.rb100
-rw-r--r--spec/bundler/support/artifice/vcr.rb72
-rw-r--r--spec/bundler/support/artifice/windows.rb20
-rw-r--r--spec/bundler/support/build_metadata.rb53
-rw-r--r--spec/bundler/support/builders.rb638
-rwxr-xr-xspec/bundler/support/bundle6
-rw-r--r--spec/bundler/support/bundle.rb7
-rw-r--r--spec/bundler/support/checksums.rb135
-rw-r--r--spec/bundler/support/code_climate.rb26
-rw-r--r--spec/bundler/support/command_execution.rb67
-rw-r--r--spec/bundler/support/env.rb13
-rw-r--r--spec/bundler/support/filters.rb42
-rw-r--r--spec/bundler/support/hax.rb95
-rw-r--r--spec/bundler/support/helpers.rb741
-rw-r--r--spec/bundler/support/indexes.rb69
-rw-r--r--spec/bundler/support/less_than_proc.rb20
-rw-r--r--spec/bundler/support/manpages.rb14
-rw-r--r--spec/bundler/support/matchers.rb173
-rw-r--r--spec/bundler/support/options.rb15
-rw-r--r--spec/bundler/support/path.rb323
-rw-r--r--spec/bundler/support/platforms.rb95
-rw-r--r--spec/bundler/support/rubygems_ext.rb259
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb124
-rw-r--r--spec/bundler/support/setup.rb9
-rw-r--r--spec/bundler/support/shards.rb200
-rw-r--r--spec/bundler/support/silent_logger.rb10
-rw-r--r--spec/bundler/support/sometimes.rb57
-rw-r--r--spec/bundler/support/streams.rb19
-rw-r--r--spec/bundler/support/subprocess.rb115
-rw-r--r--spec/bundler/support/sudo.rb18
-rw-r--r--spec/bundler/support/switch_rubygems.rb5
-rw-r--r--spec/bundler/support/the_bundle.rb20
-rw-r--r--spec/bundler/support/vendored_net_http.rb23
-rw-r--r--spec/bundler/update/force_spec.rb30
-rw-r--r--spec/bundler/update/gemfile_spec.rb47
-rw-r--r--spec/bundler/update/gems/fund_spec.rb50
-rw-r--r--spec/bundler/update/gems/post_install_spec.rb28
-rw-r--r--spec/bundler/update/git_spec.rb217
-rw-r--r--spec/bundler/update/path_spec.rb5
-rw-r--r--spec/bundler/update/redownload_spec.rb36
-rw-r--r--spec/default.mspec151
-rw-r--r--spec/lib/formatter_overrides.rb6
-rw-r--r--spec/lib/spec_coverage.rb1
-rw-r--r--spec/mmtk.mspec12
-rw-r--r--spec/mspec/.rspec1
-rw-r--r--spec/mspec/Gemfile4
-rw-r--r--spec/mspec/Gemfile.lock32
-rw-r--r--spec/mspec/README.md37
-rwxr-xr-xspec/mspec/bin/mspec2
-rw-r--r--spec/mspec/lib/mspec.rb14
-rw-r--r--[-rwxr-xr-x]spec/mspec/lib/mspec/commands/mkspec.rb20
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-ci.rb8
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-run.rb11
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-tag.rb6
-rw-r--r--[-rwxr-xr-x]spec/mspec/lib/mspec/commands/mspec.rb18
-rw-r--r--spec/mspec/lib/mspec/expectations/expectations.rb22
-rw-r--r--spec/mspec/lib/mspec/expectations/should.rb32
-rw-r--r--spec/mspec/lib/mspec/guards/bug.rb19
-rw-r--r--spec/mspec/lib/mspec/guards/guard.rb2
-rw-r--r--spec/mspec/lib/mspec/guards/platform.rb57
-rw-r--r--spec/mspec/lib/mspec/guards/superuser.rb10
-rw-r--r--spec/mspec/lib/mspec/guards/version.rb65
-rw-r--r--spec/mspec/lib/mspec/helpers.rb1
-rw-r--r--spec/mspec/lib/mspec/helpers/datetime.rb3
-rw-r--r--spec/mspec/lib/mspec/helpers/flunk.rb2
-rw-r--r--spec/mspec/lib/mspec/helpers/frozen_error_class.rb17
-rw-r--r--spec/mspec/lib/mspec/helpers/fs.rb10
-rw-r--r--spec/mspec/lib/mspec/helpers/io.rb40
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb36
-rw-r--r--spec/mspec/lib/mspec/helpers/ruby_exe.rb115
-rw-r--r--spec/mspec/lib/mspec/helpers/scratch.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/tmp.rb29
-rw-r--r--spec/mspec/lib/mspec/helpers/warning.rb14
-rw-r--r--spec/mspec/lib/mspec/matchers.rb1
-rw-r--r--spec/mspec/lib/mspec/matchers/base.rb96
-rw-r--r--spec/mspec/lib/mspec/matchers/be_close.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/block_caller.rb34
-rw-r--r--spec/mspec/lib/mspec/matchers/complain.rb25
-rw-r--r--spec/mspec/lib/mspec/matchers/eql.rb8
-rw-r--r--spec/mspec/lib/mspec/matchers/equal.rb8
-rw-r--r--spec/mspec/lib/mspec/matchers/equal_element.rb4
-rw-r--r--spec/mspec/lib/mspec/matchers/have_instance_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_private_instance_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_private_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_public_instance_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/have_singleton_method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/include.rb4
-rw-r--r--spec/mspec/lib/mspec/matchers/match_yaml.rb6
-rw-r--r--spec/mspec/lib/mspec/matchers/method.rb2
-rw-r--r--spec/mspec/lib/mspec/matchers/output.rb10
-rw-r--r--spec/mspec/lib/mspec/matchers/raise_error.rb113
-rw-r--r--spec/mspec/lib/mspec/matchers/skip.rb5
-rw-r--r--spec/mspec/lib/mspec/mocks/mock.rb29
-rw-r--r--spec/mspec/lib/mspec/mocks/object.rb4
-rw-r--r--spec/mspec/lib/mspec/mocks/proxy.rb6
-rw-r--r--spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb84
-rw-r--r--spec/mspec/lib/mspec/runner/actions/filter.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb204
-rw-r--r--spec/mspec/lib/mspec/runner/actions/profile.rb60
-rw-r--r--spec/mspec/lib/mspec/runner/actions/tag.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/actions/taglist.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/actions/tally.rb14
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb145
-rw-r--r--spec/mspec/lib/mspec/runner/context.rb38
-rw-r--r--spec/mspec/lib/mspec/runner/evaluate.rb4
-rw-r--r--spec/mspec/lib/mspec/runner/example.rb14
-rw-r--r--spec/mspec/lib/mspec/runner/exception.rb31
-rw-r--r--spec/mspec/lib/mspec/runner/formatters.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/base.rb150
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/describe.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/dotted.rb110
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/file.rb9
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/html.rb10
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/junit.rb15
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/launchable.rb88
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/method.rb28
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/multi.rb37
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/profile.rb60
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/specdoc.rb14
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/spinner.rb20
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/stats.rb57
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/summary.rb11
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/unit.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/yaml.rb10
-rw-r--r--spec/mspec/lib/mspec/runner/mspec.rb98
-rw-r--r--spec/mspec/lib/mspec/runner/object.rb12
-rw-r--r--spec/mspec/lib/mspec/runner/parallel.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/shared.rb10
-rw-r--r--spec/mspec/lib/mspec/runner/tag.rb2
-rw-r--r--spec/mspec/lib/mspec/utils/format.rb24
-rw-r--r--spec/mspec/lib/mspec/utils/name_map.rb24
-rw-r--r--spec/mspec/lib/mspec/utils/options.rb68
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb55
-rw-r--r--spec/mspec/lib/mspec/utils/version.rb2
-rw-r--r--spec/mspec/lib/mspec/utils/warnings.rb65
-rw-r--r--spec/mspec/spec/commands/mkspec_spec.rb196
-rw-r--r--spec/mspec/spec/commands/mspec_ci_spec.rb77
-rw-r--r--spec/mspec/spec/commands/mspec_run_spec.rb79
-rw-r--r--spec/mspec/spec/commands/mspec_spec.rb119
-rw-r--r--spec/mspec/spec/commands/mspec_tag_spec.rb170
-rw-r--r--spec/mspec/spec/expectations/expectations_spec.rb18
-rw-r--r--spec/mspec/spec/expectations/should.rb73
-rw-r--r--spec/mspec/spec/expectations/should_spec.rb28
-rw-r--r--spec/mspec/spec/fixtures/config.mspec2
-rwxr-xr-xspec/mspec/spec/fixtures/my_ruby2
-rw-r--r--spec/mspec/spec/fixtures/should.rb75
-rw-r--r--spec/mspec/spec/guards/block_device_spec.rb26
-rw-r--r--spec/mspec/spec/guards/bug_spec.rb84
-rw-r--r--spec/mspec/spec/guards/conflict_spec.rb30
-rw-r--r--spec/mspec/spec/guards/endian_spec.rb34
-rw-r--r--spec/mspec/spec/guards/feature_spec.rb82
-rw-r--r--spec/mspec/spec/guards/guard_spec.rb222
-rw-r--r--spec/mspec/spec/guards/platform_spec.rb243
-rw-r--r--spec/mspec/spec/guards/quarantine_spec.rb20
-rw-r--r--spec/mspec/spec/guards/superuser_spec.rb22
-rw-r--r--spec/mspec/spec/guards/support_spec.rb28
-rw-r--r--spec/mspec/spec/guards/user_spec.rb10
-rw-r--r--spec/mspec/spec/guards/version_spec.rb90
-rw-r--r--spec/mspec/spec/helpers/argf_spec.rb16
-rw-r--r--spec/mspec/spec/helpers/argv_spec.rb10
-rw-r--r--spec/mspec/spec/helpers/datetime_spec.rb18
-rw-r--r--spec/mspec/spec/helpers/fixture_spec.rb8
-rw-r--r--spec/mspec/spec/helpers/flunk_spec.rb10
-rw-r--r--spec/mspec/spec/helpers/fs_spec.rb60
-rw-r--r--spec/mspec/spec/helpers/io_spec.rb94
-rw-r--r--spec/mspec/spec/helpers/mock_to_path_spec.rb14
-rw-r--r--spec/mspec/spec/helpers/numeric_spec.rb20
-rw-r--r--spec/mspec/spec/helpers/ruby_exe_spec.rb165
-rw-r--r--spec/mspec/spec/helpers/scratch_spec.rb10
-rw-r--r--spec/mspec/spec/helpers/suppress_warning_spec.rb4
-rw-r--r--spec/mspec/spec/helpers/tmp_spec.rb12
-rw-r--r--spec/mspec/spec/integration/interpreter_spec.rb8
-rw-r--r--spec/mspec/spec/integration/object_methods_spec.rb6
-rw-r--r--spec/mspec/spec/integration/run_spec.rb54
-rw-r--r--spec/mspec/spec/integration/tag_spec.rb31
-rw-r--r--spec/mspec/spec/matchers/base_spec.rb265
-rw-r--r--spec/mspec/spec/matchers/be_an_instance_of_spec.rb22
-rw-r--r--spec/mspec/spec/matchers/be_ancestor_of_spec.rb10
-rw-r--r--spec/mspec/spec/matchers/be_close_spec.rb24
-rw-r--r--spec/mspec/spec/matchers/be_computed_by_spec.rb14
-rw-r--r--spec/mspec/spec/matchers/be_empty_spec.rb10
-rw-r--r--spec/mspec/spec/matchers/be_false_spec.rb16
-rw-r--r--spec/mspec/spec/matchers/be_kind_of_spec.rb22
-rw-r--r--spec/mspec/spec/matchers/be_nan_spec.rb12
-rw-r--r--spec/mspec/spec/matchers/be_nil_spec.rb14
-rw-r--r--spec/mspec/spec/matchers/be_true_or_false_spec.rb8
-rw-r--r--spec/mspec/spec/matchers/be_true_spec.rb16
-rw-r--r--spec/mspec/spec/matchers/block_caller_spec.rb6
-rw-r--r--spec/mspec/spec/matchers/complain_spec.rb78
-rw-r--r--spec/mspec/spec/matchers/eql_spec.rb22
-rw-r--r--spec/mspec/spec/matchers/equal_element_spec.rb78
-rw-r--r--spec/mspec/spec/matchers/equal_spec.rb20
-rw-r--r--spec/mspec/spec/matchers/have_class_variable_spec.rb18
-rw-r--r--spec/mspec/spec/matchers/have_constant_spec.rb14
-rw-r--r--spec/mspec/spec/matchers/have_instance_method_spec.rb20
-rw-r--r--spec/mspec/spec/matchers/have_instance_variable_spec.rb18
-rw-r--r--spec/mspec/spec/matchers/have_method_spec.rb24
-rw-r--r--spec/mspec/spec/matchers/have_private_instance_method_spec.rb20
-rw-r--r--spec/mspec/spec/matchers/have_private_method_spec.rb16
-rw-r--r--spec/mspec/spec/matchers/have_protected_instance_method_spec.rb20
-rw-r--r--spec/mspec/spec/matchers/have_public_instance_method_spec.rb20
-rw-r--r--spec/mspec/spec/matchers/have_singleton_method_spec.rb16
-rw-r--r--spec/mspec/spec/matchers/include_any_of_spec.rb26
-rw-r--r--spec/mspec/spec/matchers/include_spec.rb22
-rw-r--r--spec/mspec/spec/matchers/infinity_spec.rb18
-rw-r--r--spec/mspec/spec/matchers/match_yaml_spec.rb22
-rw-r--r--spec/mspec/spec/matchers/output_spec.rb48
-rw-r--r--spec/mspec/spec/matchers/output_to_fd_spec.rb30
-rw-r--r--spec/mspec/spec/matchers/raise_error_spec.rb184
-rw-r--r--spec/mspec/spec/matchers/respond_to_spec.rb26
-rw-r--r--spec/mspec/spec/matchers/signed_zero_spec.rb18
-rw-r--r--spec/mspec/spec/mocks/mock_spec.rb241
-rw-r--r--spec/mspec/spec/mocks/proxy_spec.rb196
-rw-r--r--spec/mspec/spec/runner/actions/filter_spec.rb44
-rw-r--r--spec/mspec/spec/runner/actions/tag_spec.rb144
-rw-r--r--spec/mspec/spec/runner/actions/taglist_spec.rb70
-rw-r--r--spec/mspec/spec/runner/actions/tagpurge_spec.rb66
-rw-r--r--spec/mspec/spec/runner/actions/tally_spec.rb167
-rw-r--r--spec/mspec/spec/runner/actions/timer_spec.rb22
-rw-r--r--spec/mspec/spec/runner/context_spec.rb369
-rw-r--r--spec/mspec/spec/runner/example_spec.rb60
-rw-r--r--spec/mspec/spec/runner/exception_spec.rb50
-rw-r--r--spec/mspec/spec/runner/filters/match_spec.rb16
-rw-r--r--spec/mspec/spec/runner/filters/profile_spec.rb70
-rw-r--r--spec/mspec/spec/runner/filters/regexp_spec.rb18
-rw-r--r--spec/mspec/spec/runner/filters/tag_spec.rb48
-rw-r--r--spec/mspec/spec/runner/formatters/describe_spec.rb24
-rw-r--r--spec/mspec/spec/runner/formatters/dotted_spec.rb121
-rw-r--r--spec/mspec/spec/runner/formatters/file_spec.rb34
-rw-r--r--spec/mspec/spec/runner/formatters/html_spec.rb88
-rw-r--r--spec/mspec/spec/runner/formatters/junit_spec.rb100
-rw-r--r--spec/mspec/spec/runner/formatters/method_spec.rb69
-rw-r--r--spec/mspec/spec/runner/formatters/multi_spec.rb24
-rw-r--r--spec/mspec/spec/runner/formatters/specdoc_spec.rb30
-rw-r--r--spec/mspec/spec/runner/formatters/spinner_spec.rb32
-rw-r--r--spec/mspec/spec/runner/formatters/summary_spec.rb4
-rw-r--r--spec/mspec/spec/runner/formatters/unit_spec.rb33
-rw-r--r--spec/mspec/spec/runner/formatters/yaml_spec.rb79
-rw-r--r--spec/mspec/spec/runner/mspec_spec.rb300
-rw-r--r--spec/mspec/spec/runner/shared_spec.rb20
-rw-r--r--spec/mspec/spec/runner/tag_spec.rb96
-rw-r--r--spec/mspec/spec/spec_helper.rb23
-rw-r--r--spec/mspec/spec/utils/deprecate_spec.rb10
-rw-r--r--spec/mspec/spec/utils/fixtures/this_file_raises.rb1
-rw-r--r--spec/mspec/spec/utils/fixtures/this_file_raises2.rb1
-rw-r--r--spec/mspec/spec/utils/name_map_spec.rb90
-rw-r--r--spec/mspec/spec/utils/options_spec.rb491
-rw-r--r--spec/mspec/spec/utils/script_spec.rb257
-rw-r--r--spec/mspec/spec/utils/version_spec.rb30
-rwxr-xr-xspec/mspec/tool/check_require_spec_helper.rb34
-rwxr-xr-xspec/mspec/tool/pull-latest-mspec-spec33
-rwxr-xr-x[-rw-r--r--]spec/mspec/tool/remove_old_guards.rb126
-rw-r--r--spec/mspec/tool/sync/sync-rubyspec.rb95
-rwxr-xr-xspec/mspec/tool/tag_from_output.rb65
-rwxr-xr-xspec/mspec/tool/wrap_with_guard.rb28
-rw-r--r--spec/ruby/.mspec.constants236
-rw-r--r--spec/ruby/.rubocop.yml116
-rw-r--r--spec/ruby/.rubocop_todo.yml129
-rw-r--r--spec/ruby/.travis.yml30
-rw-r--r--spec/ruby/CHANGES.before-2008-05-1017796
-rw-r--r--spec/ruby/CONTRIBUTING.md170
-rw-r--r--spec/ruby/README.md99
-rw-r--r--spec/ruby/appveyor.yml34
-rwxr-xr-xspec/ruby/bin/rubocop12
-rw-r--r--spec/ruby/command_line/backtrace_limit_spec.rb93
-rwxr-xr-xspec/ruby/command_line/dash_0_spec.rb13
-rw-r--r--spec/ruby/command_line/dash_a_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_e_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_encoding_spec.rb8
-rw-r--r--spec/ruby/command_line/dash_l_spec.rb31
-rw-r--r--spec/ruby/command_line/dash_n_spec.rb8
-rw-r--r--spec/ruby/command_line/dash_p_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_r_spec.rb19
-rw-r--r--spec/ruby/command_line/dash_upper_c_spec.rb23
-rw-r--r--spec/ruby/command_line/dash_upper_e_spec.rb3
-rw-r--r--spec/ruby/command_line/dash_upper_f_spec.rb2
-rw-r--r--spec/ruby/command_line/dash_upper_i_spec.rb10
-rw-r--r--spec/ruby/command_line/dash_upper_k_spec.rb20
-rw-r--r--spec/ruby/command_line/dash_upper_s_spec.rb42
-rw-r--r--spec/ruby/command_line/dash_upper_u_spec.rb37
-rw-r--r--spec/ruby/command_line/dash_upper_w_spec.rb24
-rw-r--r--spec/ruby/command_line/dash_upper_x_spec.rb6
-rw-r--r--spec/ruby/command_line/dash_v_spec.rb7
-rw-r--r--spec/ruby/command_line/dash_w_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_x_spec.rb6
-rw-r--r--spec/ruby/command_line/error_message_spec.rb13
-rw-r--r--spec/ruby/command_line/feature_spec.rb71
-rw-r--r--spec/ruby/command_line/fixtures/backtrace.rb35
-rw-r--r--spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt2
-rw-r--r--spec/ruby/command_line/fixtures/bin/embedded_ruby.txt4
-rw-r--r--spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh2
-rw-r--r--spec/ruby/command_line/fixtures/change_directory_script.rb (renamed from spec/ruby/command_line/fixtures/dash_upper_c_script.rb)0
-rw-r--r--spec/ruby/command_line/fixtures/debug_info.rb1
-rw-r--r--spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rbbin121 -> 90 bytes-rw-r--r--spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb2
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_raw.rb3
-rw-r--r--spec/ruby/command_line/fixtures/test_file.rb2
-rw-r--r--spec/ruby/command_line/frozen_strings_spec.rb72
-rw-r--r--spec/ruby/command_line/rubylib_spec.rb17
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb78
-rw-r--r--spec/ruby/command_line/shared/change_directory.rb21
-rw-r--r--spec/ruby/command_line/shared/verbose.rb2
-rw-r--r--spec/ruby/command_line/syntax_error_spec.rb8
-rw-r--r--spec/ruby/core/argf/argf_spec.rb4
-rw-r--r--spec/ruby/core/argf/argv_spec.rb2
-rw-r--r--spec/ruby/core/argf/binmode_spec.rb12
-rw-r--r--spec/ruby/core/argf/bytes_spec.rb6
-rw-r--r--spec/ruby/core/argf/chars_spec.rb6
-rw-r--r--spec/ruby/core/argf/close_spec.rb8
-rw-r--r--spec/ruby/core/argf/closed_spec.rb2
-rw-r--r--spec/ruby/core/argf/codepoints_spec.rb6
-rw-r--r--spec/ruby/core/argf/each_byte_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_char_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_codepoint_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_line_spec.rb62
-rw-r--r--spec/ruby/core/argf/each_spec.rb5
-rw-r--r--spec/ruby/core/argf/eof_spec.rb28
-rw-r--r--spec/ruby/core/argf/filename_spec.rb28
-rw-r--r--spec/ruby/core/argf/fileno_spec.rb24
-rw-r--r--spec/ruby/core/argf/gets_spec.rb30
-rw-r--r--spec/ruby/core/argf/inspect_spec.rb7
-rw-r--r--spec/ruby/core/argf/lines_spec.rb6
-rw-r--r--spec/ruby/core/argf/path_spec.rb5
-rw-r--r--spec/ruby/core/argf/pos_spec.rb31
-rw-r--r--spec/ruby/core/argf/read_nonblock_spec.rb4
-rw-r--r--spec/ruby/core/argf/read_spec.rb30
-rw-r--r--spec/ruby/core/argf/readchar_spec.rb2
-rw-r--r--spec/ruby/core/argf/readline_spec.rb2
-rw-r--r--spec/ruby/core/argf/readlines_spec.rb22
-rw-r--r--spec/ruby/core/argf/readpartial_spec.rb10
-rw-r--r--spec/ruby/core/argf/rewind_spec.rb2
-rw-r--r--spec/ruby/core/argf/seek_spec.rb2
-rw-r--r--spec/ruby/core/argf/shared/each_byte.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_char.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_codepoint.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_line.rb62
-rw-r--r--spec/ruby/core/argf/shared/eof.rb24
-rw-r--r--spec/ruby/core/argf/shared/filename.rb28
-rw-r--r--spec/ruby/core/argf/shared/fileno.rb24
-rw-r--r--spec/ruby/core/argf/shared/getc.rb2
-rw-r--r--spec/ruby/core/argf/shared/pos.rb31
-rw-r--r--spec/ruby/core/argf/shared/read.rb4
-rw-r--r--spec/ruby/core/argf/shared/readlines.rb22
-rw-r--r--spec/ruby/core/argf/skip_spec.rb2
-rw-r--r--spec/ruby/core/argf/tell_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_a_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_i_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_io_spec.rb2
-rw-r--r--spec/ruby/core/array/all_spec.rb13
-rw-r--r--spec/ruby/core/array/allocate_spec.rb4
-rw-r--r--spec/ruby/core/array/any_spec.rb18
-rw-r--r--spec/ruby/core/array/append_spec.rb15
-rw-r--r--spec/ruby/core/array/assoc_spec.rb40
-rw-r--r--spec/ruby/core/array/at_spec.rb4
-rw-r--r--spec/ruby/core/array/bsearch_index_spec.rb34
-rw-r--r--spec/ruby/core/array/bsearch_spec.rb26
-rw-r--r--spec/ruby/core/array/clear_spec.rb28
-rw-r--r--spec/ruby/core/array/clone_spec.rb12
-rw-r--r--spec/ruby/core/array/collect_spec.rb138
-rw-r--r--spec/ruby/core/array/combination_spec.rb8
-rw-r--r--spec/ruby/core/array/compact_spec.rb42
-rw-r--r--spec/ruby/core/array/comparison_spec.rb2
-rw-r--r--spec/ruby/core/array/concat_spec.rb98
-rw-r--r--spec/ruby/core/array/constructor_spec.rb4
-rw-r--r--spec/ruby/core/array/count_spec.rb11
-rw-r--r--spec/ruby/core/array/cycle_spec.rb26
-rw-r--r--spec/ruby/core/array/deconstruct_spec.rb9
-rw-r--r--spec/ruby/core/array/delete_at_spec.rb24
-rw-r--r--spec/ruby/core/array/delete_if_spec.rb56
-rw-r--r--spec/ruby/core/array/delete_spec.rb24
-rw-r--r--spec/ruby/core/array/difference_spec.rb22
-rw-r--r--spec/ruby/core/array/dig_spec.rb14
-rw-r--r--spec/ruby/core/array/drop_spec.rb25
-rw-r--r--spec/ruby/core/array/drop_while_spec.rb9
-rw-r--r--spec/ruby/core/array/dup_spec.rb12
-rw-r--r--spec/ruby/core/array/each_index_spec.rb20
-rw-r--r--spec/ruby/core/array/each_spec.rb58
-rw-r--r--spec/ruby/core/array/element_reference_spec.rb861
-rw-r--r--spec/ruby/core/array/element_set_spec.rb151
-rw-r--r--spec/ruby/core/array/empty_spec.rb6
-rw-r--r--spec/ruby/core/array/eql_spec.rb4
-rw-r--r--spec/ruby/core/array/equal_value_spec.rb16
-rw-r--r--spec/ruby/core/array/fetch_spec.rb12
-rw-r--r--spec/ruby/core/array/fetch_values_spec.rb55
-rw-r--r--spec/ruby/core/array/fill_spec.rb151
-rw-r--r--spec/ruby/core/array/filter_spec.rb17
-rw-r--r--spec/ruby/core/array/find_index_spec.rb40
-rw-r--r--spec/ruby/core/array/first_spec.rb24
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb796
-rw-r--r--spec/ruby/core/array/fixtures/encoded_strings.rb30
-rw-r--r--spec/ruby/core/array/flatten_spec.rb70
-rw-r--r--spec/ruby/core/array/frozen_spec.rb6
-rw-r--r--spec/ruby/core/array/hash_spec.rb8
-rw-r--r--spec/ruby/core/array/index_spec.rb5
-rw-r--r--spec/ruby/core/array/initialize_spec.rb46
-rw-r--r--spec/ruby/core/array/insert_spec.rb18
-rw-r--r--spec/ruby/core/array/inspect_spec.rb105
-rw-r--r--spec/ruby/core/array/intersect_spec.rb64
-rw-r--r--spec/ruby/core/array/intersection_spec.rb86
-rw-r--r--spec/ruby/core/array/join_spec.rb110
-rw-r--r--spec/ruby/core/array/keep_if_spec.rb3
-rw-r--r--spec/ruby/core/array/last_spec.rb24
-rw-r--r--spec/ruby/core/array/length_spec.rb11
-rw-r--r--spec/ruby/core/array/map_spec.rb10
-rw-r--r--spec/ruby/core/array/max_spec.rb18
-rw-r--r--spec/ruby/core/array/min_spec.rb20
-rw-r--r--spec/ruby/core/array/minmax_spec.rb14
-rw-r--r--spec/ruby/core/array/minus_spec.rb84
-rw-r--r--spec/ruby/core/array/multiply_spec.rb62
-rw-r--r--spec/ruby/core/array/new_spec.rb36
-rw-r--r--spec/ruby/core/array/none_spec.rb13
-rw-r--r--spec/ruby/core/array/one_spec.rb13
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb17
-rw-r--r--spec/ruby/core/array/pack/at_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb17
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb84
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb8
-rw-r--r--spec/ruby/core/array/pack/comment_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb15
-rw-r--r--spec/ruby/core/array/pack/l_spec.rb16
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb24
-rw-r--r--spec/ruby/core/array/pack/p_spec.rb20
-rw-r--r--spec/ruby/core/array/pack/percent_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/r_spec.rb89
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb42
-rw-r--r--spec/ruby/core/array/pack/shared/encodings.rb4
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb112
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb48
-rw-r--r--spec/ruby/core/array/pack/shared/numeric_basic.rb30
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb16
-rw-r--r--spec/ruby/core/array/pack/shared/taint.rb31
-rw-r--r--spec/ruby/core/array/pack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb20
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb7
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb14
-rw-r--r--spec/ruby/core/array/partition_spec.rb6
-rw-r--r--spec/ruby/core/array/permutation_spec.rb10
-rw-r--r--spec/ruby/core/array/plus_spec.rb41
-rw-r--r--spec/ruby/core/array/pop_spec.rb74
-rw-r--r--spec/ruby/core/array/prepend_spec.rb8
-rw-r--r--spec/ruby/core/array/product_spec.rb25
-rw-r--r--spec/ruby/core/array/push_spec.rb33
-rw-r--r--spec/ruby/core/array/rassoc_spec.rb18
-rw-r--r--spec/ruby/core/array/reject_spec.rb57
-rw-r--r--spec/ruby/core/array/repeated_combination_spec.rb10
-rw-r--r--spec/ruby/core/array/repeated_permutation_spec.rb4
-rw-r--r--spec/ruby/core/array/replace_spec.rb60
-rw-r--r--spec/ruby/core/array/reverse_each_spec.rb18
-rw-r--r--spec/ruby/core/array/reverse_spec.rb8
-rw-r--r--spec/ruby/core/array/rindex_spec.rb21
-rw-r--r--spec/ruby/core/array/rotate_spec.rb54
-rw-r--r--spec/ruby/core/array/sample_spec.rb84
-rw-r--r--spec/ruby/core/array/select_spec.rb35
-rw-r--r--spec/ruby/core/array/shared/clone.rb30
-rw-r--r--spec/ruby/core/array/shared/collect.rb136
-rw-r--r--spec/ruby/core/array/shared/difference.rb78
-rw-r--r--spec/ruby/core/array/shared/enumeratorize.rb2
-rw-r--r--spec/ruby/core/array/shared/eql.rb66
-rw-r--r--spec/ruby/core/array/shared/index.rb37
-rw-r--r--spec/ruby/core/array/shared/inspect.rb131
-rw-r--r--spec/ruby/core/array/shared/intersection.rb85
-rw-r--r--spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb25
-rw-r--r--spec/ruby/core/array/shared/join.rb146
-rw-r--r--spec/ruby/core/array/shared/keep_if.rb53
-rw-r--r--spec/ruby/core/array/shared/length.rb11
-rw-r--r--spec/ruby/core/array/shared/push.rb33
-rw-r--r--spec/ruby/core/array/shared/replace.rb60
-rw-r--r--spec/ruby/core/array/shared/select.rb32
-rw-r--r--spec/ruby/core/array/shared/slice.rb459
-rw-r--r--spec/ruby/core/array/shared/union.rb79
-rw-r--r--spec/ruby/core/array/shared/unshift.rb46
-rw-r--r--spec/ruby/core/array/shift_spec.rb38
-rw-r--r--spec/ruby/core/array/shuffle_spec.rb59
-rw-r--r--spec/ruby/core/array/size_spec.rb6
-rw-r--r--spec/ruby/core/array/slice_spec.rb71
-rw-r--r--spec/ruby/core/array/sort_by_spec.rb51
-rw-r--r--spec/ruby/core/array/sort_spec.rb64
-rw-r--r--spec/ruby/core/array/sum_spec.rb108
-rw-r--r--spec/ruby/core/array/take_spec.rb7
-rw-r--r--spec/ruby/core/array/take_while_spec.rb11
-rw-r--r--spec/ruby/core/array/to_a_spec.rb4
-rw-r--r--spec/ruby/core/array/to_ary_spec.rb4
-rw-r--r--spec/ruby/core/array/to_h_spec.rb61
-rw-r--r--spec/ruby/core/array/to_s_spec.rb7
-rw-r--r--spec/ruby/core/array/transpose_spec.rb10
-rw-r--r--spec/ruby/core/array/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/array/union_spec.rb81
-rw-r--r--spec/ruby/core/array/uniq_spec.rb64
-rw-r--r--spec/ruby/core/array/unshift_spec.rb64
-rw-r--r--spec/ruby/core/array/values_at_spec.rb13
-rw-r--r--spec/ruby/core/array/zip_spec.rb10
-rw-r--r--spec/ruby/core/basicobject/__send___spec.rb2
-rw-r--r--spec/ruby/core/basicobject/basicobject_spec.rb22
-rw-r--r--spec/ruby/core/basicobject/equal_spec.rb20
-rw-r--r--spec/ruby/core/basicobject/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/basicobject/fixtures/classes.rb228
-rw-r--r--spec/ruby/core/basicobject/initialize_spec.rb6
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb211
-rw-r--r--spec/ruby/core/basicobject/instance_exec_spec.rb56
-rw-r--r--spec/ruby/core/basicobject/method_missing_spec.rb3
-rw-r--r--spec/ruby/core/basicobject/not_equal_spec.rb16
-rw-r--r--spec/ruby/core/basicobject/not_spec.rb4
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb65
-rw-r--r--spec/ruby/core/basicobject/singleton_method_removed_spec.rb2
-rw-r--r--spec/ruby/core/basicobject/singleton_method_undefined_spec.rb2
-rw-r--r--spec/ruby/core/binding/clone_spec.rb6
-rw-r--r--spec/ruby/core/binding/dup_spec.rb23
-rw-r--r--spec/ruby/core/binding/eval_spec.rb32
-rw-r--r--spec/ruby/core/binding/fixtures/classes.rb14
-rw-r--r--spec/ruby/core/binding/fixtures/location.rb6
-rw-r--r--spec/ruby/core/binding/local_variable_defined_spec.rb2
-rw-r--r--spec/ruby/core/binding/local_variable_get_spec.rb16
-rw-r--r--spec/ruby/core/binding/local_variable_set_spec.rb8
-rw-r--r--spec/ruby/core/binding/local_variables_spec.rb2
-rw-r--r--spec/ruby/core/binding/shared/clone.rb22
-rw-r--r--spec/ruby/core/binding/source_location_spec.rb14
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb120
-rw-r--r--spec/ruby/core/class/allocate_spec.rb12
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb29
-rw-r--r--spec/ruby/core/class/dup_spec.rb7
-rw-r--r--spec/ruby/core/class/inherited_spec.rb21
-rw-r--r--spec/ruby/core/class/initialize_spec.rb18
-rw-r--r--spec/ruby/core/class/new_spec.rb27
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb85
-rw-r--r--spec/ruby/core/class/superclass_spec.rb4
-rw-r--r--spec/ruby/core/class/to_s_spec.rb23
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb219
-rw-r--r--spec/ruby/core/comparable/equal_value_spec.rb10
-rw-r--r--spec/ruby/core/comparable/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/comparable/gt_spec.rb2
-rw-r--r--spec/ruby/core/comparable/gte_spec.rb2
-rw-r--r--spec/ruby/core/comparable/lt_spec.rb8
-rw-r--r--spec/ruby/core/comparable/lte_spec.rb2
-rw-r--r--spec/ruby/core/complex/abs_spec.rb10
-rw-r--r--spec/ruby/core/complex/angle_spec.rb5
-rw-r--r--spec/ruby/core/complex/arg_spec.rb9
-rw-r--r--spec/ruby/core/complex/coerce_spec.rb32
-rw-r--r--spec/ruby/core/complex/comparison_spec.rb25
-rw-r--r--spec/ruby/core/complex/conj_spec.rb5
-rw-r--r--spec/ruby/core/complex/conjugate_spec.rb8
-rw-r--r--spec/ruby/core/complex/constants_spec.rb2
-rw-r--r--spec/ruby/core/complex/divide_spec.rb82
-rw-r--r--spec/ruby/core/complex/eql_spec.rb12
-rw-r--r--spec/ruby/core/complex/equal_value_spec.rb12
-rw-r--r--spec/ruby/core/complex/exponent_spec.rb6
-rw-r--r--spec/ruby/core/complex/fdiv_spec.rb42
-rw-r--r--spec/ruby/core/complex/finite_spec.rb50
-rw-r--r--spec/ruby/core/complex/imag_spec.rb5
-rw-r--r--spec/ruby/core/complex/imaginary_spec.rb8
-rw-r--r--spec/ruby/core/complex/infinite_spec.rb48
-rw-r--r--spec/ruby/core/complex/inspect_spec.rb21
-rw-r--r--spec/ruby/core/complex/integer_spec.rb4
-rw-r--r--spec/ruby/core/complex/magnitude_spec.rb5
-rw-r--r--spec/ruby/core/complex/marshal_dump_spec.rb2
-rw-r--r--spec/ruby/core/complex/negative_spec.rb6
-rw-r--r--spec/ruby/core/complex/phase_spec.rb5
-rw-r--r--spec/ruby/core/complex/polar_spec.rb18
-rw-r--r--spec/ruby/core/complex/positive_spec.rb6
-rw-r--r--spec/ruby/core/complex/quo_spec.rb5
-rw-r--r--spec/ruby/core/complex/rationalize_spec.rb8
-rw-r--r--spec/ruby/core/complex/real_spec.rb8
-rw-r--r--spec/ruby/core/complex/rect_spec.rb9
-rw-r--r--spec/ruby/core/complex/rectangular_spec.rb110
-rw-r--r--spec/ruby/core/complex/shared/abs.rb10
-rw-r--r--spec/ruby/core/complex/shared/arg.rb9
-rw-r--r--spec/ruby/core/complex/shared/conjugate.rb8
-rw-r--r--spec/ruby/core/complex/shared/divide.rb82
-rw-r--r--spec/ruby/core/complex/shared/image.rb8
-rw-r--r--spec/ruby/core/complex/shared/rect.rb94
-rw-r--r--spec/ruby/core/complex/to_c_spec.rb12
-rw-r--r--spec/ruby/core/complex/to_f_spec.rb6
-rw-r--r--spec/ruby/core/complex/to_i_spec.rb6
-rw-r--r--spec/ruby/core/complex/to_r_spec.rb16
-rw-r--r--spec/ruby/core/complex/to_s_spec.rb11
-rw-r--r--spec/ruby/core/conditionvariable/broadcast_spec.rb39
-rw-r--r--spec/ruby/core/conditionvariable/marshal_dump_spec.rb8
-rw-r--r--spec/ruby/core/conditionvariable/signal_spec.rb76
-rw-r--r--spec/ruby/core/conditionvariable/wait_spec.rb174
-rw-r--r--spec/ruby/core/data/constants_spec.rb11
-rw-r--r--spec/ruby/core/data/deconstruct_keys_spec.rb110
-rw-r--r--spec/ruby/core/data/deconstruct_spec.rb8
-rw-r--r--spec/ruby/core/data/define_spec.rb34
-rw-r--r--spec/ruby/core/data/eql_spec.rb63
-rw-r--r--spec/ruby/core/data/equal_value_spec.rb63
-rw-r--r--spec/ruby/core/data/fixtures/classes.rb41
-rw-r--r--spec/ruby/core/data/hash_spec.rb25
-rw-r--r--spec/ruby/core/data/initialize_spec.rb204
-rw-r--r--spec/ruby/core/data/inspect_spec.rb63
-rw-r--r--spec/ruby/core/data/members_spec.rb21
-rw-r--r--spec/ruby/core/data/to_h_spec.rb63
-rw-r--r--spec/ruby/core/data/to_s_spec.rb9
-rw-r--r--spec/ruby/core/data/with_spec.rb55
-rw-r--r--spec/ruby/core/dir/chdir_spec.rb128
-rw-r--r--spec/ruby/core/dir/children_spec.rb177
-rw-r--r--spec/ruby/core/dir/chroot_spec.rb8
-rw-r--r--spec/ruby/core/dir/close_spec.rb42
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb134
-rw-r--r--spec/ruby/core/dir/each_spec.rb15
-rw-r--r--spec/ruby/core/dir/empty_spec.rb46
-rw-r--r--spec/ruby/core/dir/entries_spec.rb22
-rw-r--r--spec/ruby/core/dir/exist_spec.rb63
-rw-r--r--spec/ruby/core/dir/exists_spec.rb15
-rw-r--r--spec/ruby/core/dir/fchdir_spec.rb71
-rw-r--r--spec/ruby/core/dir/fileno_spec.rb4
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb68
-rw-r--r--spec/ruby/core/dir/for_fd_spec.rb77
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb18
-rw-r--r--spec/ruby/core/dir/getwd_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb202
-rw-r--r--spec/ruby/core/dir/home_spec.rb81
-rw-r--r--spec/ruby/core/dir/inspect_spec.rb4
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb60
-rw-r--r--spec/ruby/core/dir/open_spec.rb73
-rw-r--r--spec/ruby/core/dir/path_spec.rb26
-rw-r--r--spec/ruby/core/dir/pos_spec.rb23
-rw-r--r--spec/ruby/core/dir/pwd_spec.rb45
-rw-r--r--spec/ruby/core/dir/read_spec.rb35
-rw-r--r--spec/ruby/core/dir/scan_spec.rb224
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb21
-rw-r--r--spec/ruby/core/dir/shared/closed.rb4
-rw-r--r--spec/ruby/core/dir/shared/delete.rb30
-rw-r--r--spec/ruby/core/dir/shared/exist.rb56
-rw-r--r--spec/ruby/core/dir/shared/glob.rb188
-rw-r--r--spec/ruby/core/dir/shared/open.rb63
-rw-r--r--spec/ruby/core/dir/shared/path.rb32
-rw-r--r--spec/ruby/core/dir/shared/pos.rb27
-rw-r--r--spec/ruby/core/dir/shared/pwd.rb49
-rw-r--r--spec/ruby/core/dir/tell_spec.rb27
-rw-r--r--spec/ruby/core/dir/to_path_spec.rb12
-rw-r--r--spec/ruby/core/encoding/aliases_spec.rb60
-rw-r--r--spec/ruby/core/encoding/ascii_compatible_spec.rb23
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb963
-rw-r--r--spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb58
-rw-r--r--spec/ruby/core/encoding/converter/constants_spec.rb182
-rw-r--r--spec/ruby/core/encoding/converter/convert_spec.rb72
-rw-r--r--spec/ruby/core/encoding/converter/convpath_spec.rb36
-rw-r--r--spec/ruby/core/encoding/converter/destination_encoding_spec.rb14
-rw-r--r--spec/ruby/core/encoding/converter/finish_spec.rb54
-rw-r--r--spec/ruby/core/encoding/converter/last_error_spec.rb156
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb196
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb421
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb113
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb97
-rw-r--r--spec/ruby/core/encoding/converter/replacement_spec.rb114
-rw-r--r--spec/ruby/core/encoding/converter/search_convpath_spec.rb48
-rw-r--r--spec/ruby/core/encoding/converter/source_encoding_spec.rb14
-rw-r--r--spec/ruby/core/encoding/default_external_spec.rb98
-rw-r--r--spec/ruby/core/encoding/default_internal_spec.rb120
-rw-r--r--spec/ruby/core/encoding/dummy_spec.rb29
-rw-r--r--spec/ruby/core/encoding/find_spec.rb118
-rw-r--r--spec/ruby/core/encoding/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/encoding/inspect_spec.rb28
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb27
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb27
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb45
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb43
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb45
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb45
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb53
-rw-r--r--spec/ruby/core/encoding/list_spec.rb64
-rw-r--r--spec/ruby/core/encoding/locale_charmap_spec.rb39
-rw-r--r--spec/ruby/core/encoding/name_list_spec.rb30
-rw-r--r--spec/ruby/core/encoding/name_spec.rb16
-rw-r--r--spec/ruby/core/encoding/names_spec.rb48
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb48
-rw-r--r--spec/ruby/core/encoding/shared/name.rb15
-rw-r--r--spec/ruby/core/encoding/to_s_spec.rb8
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb21
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb21
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb39
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb45
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb47
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb180
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb184
-rw-r--r--spec/ruby/core/enumerable/chain_spec.rb23
-rw-r--r--spec/ruby/core/enumerable/chunk_spec.rb38
-rw-r--r--spec/ruby/core/enumerable/chunk_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/collect_concat_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/collect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/compact_spec.rb9
-rw-r--r--spec/ruby/core/enumerable/cycle_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/detect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/drop_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/drop_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb26
-rw-r--r--spec/ruby/core/enumerable/each_entry_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb28
-rw-r--r--spec/ruby/core/enumerable/each_with_index_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_with_object_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/entries_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/filter_map_spec.rb24
-rw-r--r--spec/ruby/core/enumerable/filter_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/find_all_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_index_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/first_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb11
-rw-r--r--spec/ruby/core/enumerable/flat_map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/grep_spec.rb37
-rw-r--r--spec/ruby/core/enumerable/grep_v_spec.rb39
-rw-r--r--spec/ruby/core/enumerable/group_by_spec.rb16
-rw-r--r--spec/ruby/core/enumerable/lazy_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/max_by_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/max_spec.rb14
-rw-r--r--spec/ruby/core/enumerable/min_by_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/min_spec.rb16
-rw-r--r--spec/ruby/core/enumerable/minmax_by_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/minmax_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb154
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb179
-rw-r--r--spec/ruby/core/enumerable/partition_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/reject_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/reverse_each_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/select_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/collect.rb77
-rw-r--r--spec/ruby/core/enumerable/shared/collect_concat.rb4
-rw-r--r--spec/ruby/core/enumerable/shared/entries.rb8
-rw-r--r--spec/ruby/core/enumerable/shared/find.rb16
-rw-r--r--spec/ruby/core/enumerable/shared/find_all.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/include.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/inject.rb87
-rw-r--r--spec/ruby/core/enumerable/shared/take.rb8
-rw-r--r--spec/ruby/core/enumerable/shared/value_packing.rb26
-rw-r--r--spec/ruby/core/enumerable/slice_after_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/slice_before_spec.rb12
-rw-r--r--spec/ruby/core/enumerable/slice_when_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/sort_by_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/sort_spec.rb12
-rw-r--r--spec/ruby/core/enumerable/sum_spec.rb56
-rw-r--r--spec/ruby/core/enumerable/take_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/take_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb91
-rw-r--r--spec/ruby/core/enumerable/to_a_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/to_h_spec.rb54
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb30
-rw-r--r--spec/ruby/core/enumerable/uniq_spec.rb120
-rw-r--r--spec/ruby/core/enumerable/zip_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb16
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb17
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb16
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb17
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb9
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb9
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb17
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb17
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/chain/each_spec.rb15
-rw-r--r--spec/ruby/core/enumerator/chain/initialize_spec.rb31
-rw-r--r--spec/ruby/core/enumerator/chain/inspect_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/chain/rewind_spec.rb51
-rw-r--r--spec/ruby/core/enumerator/chain/size_spec.rb22
-rw-r--r--spec/ruby/core/enumerator/each_spec.rb103
-rw-r--r--spec/ruby/core/enumerator/each_with_index_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/each_with_object_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/enum_for_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/feed_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/fixtures/classes.rb (renamed from spec/ruby/fixtures/enumerator/classes.rb)0
-rw-r--r--spec/ruby/core/enumerator/generator/each_spec.rb40
-rw-r--r--spec/ruby/core/enumerator/generator/initialize_spec.rb26
-rw-r--r--spec/ruby/core/enumerator/initialize_spec.rb26
-rw-r--r--spec/ruby/core/enumerator/inject_spec.rb15
-rw-r--r--spec/ruby/core/enumerator/inspect_spec.rb5
-rw-r--r--spec/ruby/core/enumerator/lazy/chunk_spec.rb30
-rw-r--r--spec/ruby/core/enumerator/lazy/chunk_while_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/drop_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/lazy/drop_while_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/lazy/eager_spec.rb27
-rw-r--r--spec/ruby/core/enumerator/lazy/filter_map_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/filter_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/flat_map_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/lazy/force_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/grep_spec.rb47
-rw-r--r--spec/ruby/core/enumerator/lazy/grep_v_spec.rb47
-rw-r--r--spec/ruby/core/enumerator/lazy/initialize_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb15
-rw-r--r--spec/ruby/core/enumerator/lazy/reject_spec.rb24
-rw-r--r--spec/ruby/core/enumerator/lazy/select_spec.rb39
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/collect.rb10
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/collect_concat.rb16
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/select.rb12
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/to_enum.rb13
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_after_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_before_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_when_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/take_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/lazy/take_while_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/uniq_spec.rb110
-rw-r--r--spec/ruby/core/enumerator/lazy/with_index_spec.rb36
-rw-r--r--spec/ruby/core/enumerator/lazy/zip_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb113
-rw-r--r--spec/ruby/core/enumerator/next_spec.rb36
-rw-r--r--spec/ruby/core/enumerator/next_values_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/peek_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/peek_values_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/plus_spec.rb33
-rw-r--r--spec/ruby/core/enumerator/produce_spec.rb78
-rw-r--r--spec/ruby/core/enumerator/product/each_spec.rb85
-rw-r--r--spec/ruby/core/enumerator/product/initialize_copy_spec.rb52
-rw-r--r--spec/ruby/core/enumerator/product/initialize_spec.rb31
-rw-r--r--spec/ruby/core/enumerator/product/inspect_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/product/rewind_spec.rb62
-rw-r--r--spec/ruby/core/enumerator/product/size_spec.rb64
-rw-r--r--spec/ruby/core/enumerator/product_spec.rb91
-rw-r--r--spec/ruby/core/enumerator/rewind_spec.rb38
-rw-r--r--spec/ruby/core/enumerator/shared/enum_for.rb57
-rw-r--r--spec/ruby/core/enumerator/shared/with_index.rb33
-rw-r--r--spec/ruby/core/enumerator/shared/with_object.rb42
-rw-r--r--spec/ruby/core/enumerator/size_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/to_enum_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/with_index_spec.rb33
-rw-r--r--spec/ruby/core/enumerator/with_object_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/yielder/append_spec.rb24
-rw-r--r--spec/ruby/core/enumerator/yielder/initialize_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/yielder/yield_spec.rb23
-rw-r--r--spec/ruby/core/env/assoc_spec.rb10
-rw-r--r--spec/ruby/core/env/clear_spec.rb2
-rw-r--r--spec/ruby/core/env/clone_spec.rb21
-rw-r--r--spec/ruby/core/env/delete_if_spec.rb39
-rw-r--r--spec/ruby/core/env/delete_spec.rb33
-rw-r--r--spec/ruby/core/env/dup_spec.rb9
-rw-r--r--spec/ruby/core/env/each_key_spec.rb10
-rw-r--r--spec/ruby/core/env/each_pair_spec.rb2
-rw-r--r--spec/ruby/core/env/each_spec.rb2
-rw-r--r--spec/ruby/core/env/each_value_spec.rb14
-rw-r--r--spec/ruby/core/env/element_reference_spec.rb68
-rw-r--r--spec/ruby/core/env/empty_spec.rb6
-rw-r--r--spec/ruby/core/env/except_spec.rb34
-rw-r--r--spec/ruby/core/env/fetch_spec.rb43
-rw-r--r--spec/ruby/core/env/fetch_values_spec.rb51
-rw-r--r--spec/ruby/core/env/filter_spec.rb13
-rw-r--r--spec/ruby/core/env/fixtures/common.rb9
-rw-r--r--spec/ruby/core/env/index_spec.rb6
-rw-r--r--spec/ruby/core/env/indexes_spec.rb1
-rw-r--r--spec/ruby/core/env/indices_spec.rb1
-rw-r--r--spec/ruby/core/env/inspect_spec.rb2
-rw-r--r--spec/ruby/core/env/keep_if_spec.rb33
-rw-r--r--spec/ruby/core/env/key_spec.rb32
-rw-r--r--spec/ruby/core/env/keys_spec.rb4
-rw-r--r--spec/ruby/core/env/length_spec.rb2
-rw-r--r--spec/ruby/core/env/merge_spec.rb6
-rw-r--r--spec/ruby/core/env/rassoc_spec.rb21
-rw-r--r--spec/ruby/core/env/rehash_spec.rb6
-rw-r--r--spec/ruby/core/env/reject_spec.rb36
-rw-r--r--spec/ruby/core/env/replace_spec.rb50
-rw-r--r--spec/ruby/core/env/select_spec.rb32
-rw-r--r--spec/ruby/core/env/shared/each.rb60
-rw-r--r--spec/ruby/core/env/shared/include.rb23
-rw-r--r--spec/ruby/core/env/shared/key.rb13
-rw-r--r--spec/ruby/core/env/shared/select.rb61
-rw-r--r--spec/ruby/core/env/shared/store.rb20
-rw-r--r--spec/ruby/core/env/shared/to_hash.rb21
-rw-r--r--spec/ruby/core/env/shared/update.rb104
-rw-r--r--spec/ruby/core/env/shared/value.rb22
-rw-r--r--spec/ruby/core/env/shift_spec.rb84
-rw-r--r--spec/ruby/core/env/size_spec.rb2
-rw-r--r--spec/ruby/core/env/slice_spec.rb37
-rw-r--r--spec/ruby/core/env/spec_helper.rb26
-rw-r--r--spec/ruby/core/env/to_a_spec.rb14
-rw-r--r--spec/ruby/core/env/to_h_spec.rb73
-rw-r--r--spec/ruby/core/env/to_hash_spec.rb2
-rw-r--r--spec/ruby/core/env/update_spec.rb23
-rw-r--r--spec/ruby/core/env/values_at_spec.rb31
-rw-r--r--spec/ruby/core/env/values_spec.rb13
-rw-r--r--spec/ruby/core/exception/args_spec.rb5
-rw-r--r--spec/ruby/core/exception/arguments_spec.rb11
-rw-r--r--spec/ruby/core/exception/backtrace_locations_spec.rb6
-rw-r--r--spec/ruby/core/exception/backtrace_spec.rb60
-rw-r--r--spec/ruby/core/exception/case_compare_spec.rb34
-rw-r--r--spec/ruby/core/exception/cause_spec.rb35
-rw-r--r--spec/ruby/core/exception/destination_encoding_name_spec.rb9
-rw-r--r--spec/ruby/core/exception/destination_encoding_spec.rb9
-rw-r--r--spec/ruby/core/exception/detailed_message_spec.rb50
-rw-r--r--spec/ruby/core/exception/dup_spec.rb19
-rw-r--r--spec/ruby/core/exception/equal_value_spec.rb18
-rw-r--r--spec/ruby/core/exception/errno_spec.rb37
-rw-r--r--spec/ruby/core/exception/error_bytes_spec.rb5
-rw-r--r--spec/ruby/core/exception/error_char_spec.rb5
-rw-r--r--spec/ruby/core/exception/exception_spec.rb74
-rw-r--r--spec/ruby/core/exception/exit_value_spec.rb10
-rw-r--r--spec/ruby/core/exception/fixtures/common.rb7
-rw-r--r--spec/ruby/core/exception/fixtures/syntax_error.rb3
-rw-r--r--spec/ruby/core/exception/fixtures/thread_fiber_ensure.rb22
-rw-r--r--spec/ruby/core/exception/fixtures/thread_fiber_ensure_non_root_fiber.rb25
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb54
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb236
-rw-r--r--spec/ruby/core/exception/hierarchy_spec.rb62
-rw-r--r--spec/ruby/core/exception/incomplete_input_spec.rb5
-rw-r--r--spec/ruby/core/exception/initialize_spec.rb1
-rw-r--r--spec/ruby/core/exception/inspect_spec.rb4
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb33
-rw-r--r--spec/ruby/core/exception/io_error_spec.rb22
-rw-r--r--spec/ruby/core/exception/key_error_spec.rb19
-rw-r--r--spec/ruby/core/exception/name_error_spec.rb27
-rw-r--r--spec/ruby/core/exception/name_spec.rb16
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb175
-rw-r--r--spec/ruby/core/exception/range_error_spec.rb7
-rw-r--r--spec/ruby/core/exception/readagain_bytes_spec.rb5
-rw-r--r--spec/ruby/core/exception/reason_spec.rb10
-rw-r--r--spec/ruby/core/exception/receiver_spec.rb20
-rw-r--r--spec/ruby/core/exception/result_spec.rb14
-rw-r--r--spec/ruby/core/exception/script_error_spec.rb15
-rw-r--r--spec/ruby/core/exception/set_backtrace_spec.rb51
-rw-r--r--spec/ruby/core/exception/shared/new.rb4
-rw-r--r--spec/ruby/core/exception/shared/set_backtrace.rb64
-rw-r--r--spec/ruby/core/exception/signal_exception_spec.rb57
-rw-r--r--spec/ruby/core/exception/signm_spec.rb6
-rw-r--r--spec/ruby/core/exception/signo_spec.rb6
-rw-r--r--spec/ruby/core/exception/source_encoding_name_spec.rb9
-rw-r--r--spec/ruby/core/exception/source_encoding_spec.rb9
-rw-r--r--spec/ruby/core/exception/standard_error_spec.rb61
-rw-r--r--spec/ruby/core/exception/status_spec.rb6
-rw-r--r--spec/ruby/core/exception/success_spec.rb12
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb25
-rw-r--r--spec/ruby/core/exception/system_call_error_spec.rb122
-rw-r--r--spec/ruby/core/exception/system_exit_spec.rb59
-rw-r--r--spec/ruby/core/exception/system_stack_error_spec.rb7
-rw-r--r--spec/ruby/core/exception/to_s_spec.rb16
-rw-r--r--spec/ruby/core/exception/top_level_spec.rb65
-rw-r--r--spec/ruby/core/exception/uncaught_throw_error_spec.rb6
-rw-r--r--spec/ruby/core/false/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/false/dup_spec.rb8
-rw-r--r--spec/ruby/core/false/falseclass_spec.rb8
-rw-r--r--spec/ruby/core/false/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/false/to_s_spec.rb8
-rw-r--r--spec/ruby/core/fiber/alive_spec.rb44
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb73
-rw-r--r--spec/ruby/core/fiber/current_spec.rb50
-rw-r--r--spec/ruby/core/fiber/fixtures/classes.rb22
-rw-r--r--spec/ruby/core/fiber/fixtures/scheduler.rb35
-rw-r--r--spec/ruby/core/fiber/inspect_spec.rb35
-rw-r--r--spec/ruby/core/fiber/kill_spec.rb88
-rw-r--r--spec/ruby/core/fiber/new_spec.rb60
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb141
-rw-r--r--spec/ruby/core/fiber/resume_spec.rb130
-rw-r--r--spec/ruby/core/fiber/scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/set_scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/shared/blocking.rb41
-rw-r--r--spec/ruby/core/fiber/shared/resume.rb58
-rw-r--r--spec/ruby/core/fiber/shared/scheduler.rb51
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb177
-rw-r--r--spec/ruby/core/fiber/transfer_spec.rb84
-rw-r--r--spec/ruby/core/fiber/yield_spec.rb76
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb59
-rw-r--r--spec/ruby/core/file/atime_spec.rb35
-rw-r--r--spec/ruby/core/file/basename_spec.rb61
-rw-r--r--spec/ruby/core/file/birthtime_spec.rb64
-rw-r--r--spec/ruby/core/file/chmod_spec.rb16
-rw-r--r--spec/ruby/core/file/chown_spec.rb28
-rw-r--r--spec/ruby/core/file/constants/constants_spec.rb8
-rw-r--r--spec/ruby/core/file/ctime_spec.rb13
-rw-r--r--spec/ruby/core/file/dirname_spec.rb98
-rw-r--r--spec/ruby/core/file/empty_spec.rb12
-rw-r--r--spec/ruby/core/file/exist_spec.rb6
-rw-r--r--spec/ruby/core/file/exists_spec.rb6
-rw-r--r--spec/ruby/core/file/expand_path_spec.rb179
-rw-r--r--spec/ruby/core/file/extname_spec.rb52
-rw-r--r--spec/ruby/core/file/fixtures/file_types.rb6
-rw-r--r--spec/ruby/core/file/flock_spec.rb36
-rw-r--r--spec/ruby/core/file/ftype_spec.rb19
-rw-r--r--spec/ruby/core/file/initialize_spec.rb4
-rw-r--r--spec/ruby/core/file/inspect_spec.rb2
-rw-r--r--spec/ruby/core/file/join_spec.rb19
-rw-r--r--spec/ruby/core/file/lchmod_spec.rb24
-rw-r--r--spec/ruby/core/file/lchown_spec.rb4
-rw-r--r--spec/ruby/core/file/link_spec.rb16
-rw-r--r--spec/ruby/core/file/lstat_spec.rb4
-rw-r--r--spec/ruby/core/file/lutime_spec.rb43
-rw-r--r--spec/ruby/core/file/mkfifo_spec.rb4
-rw-r--r--spec/ruby/core/file/mtime_spec.rb35
-rw-r--r--spec/ruby/core/file/new_spec.rb129
-rw-r--r--spec/ruby/core/file/open_spec.rb279
-rw-r--r--spec/ruby/core/file/path_spec.rb41
-rw-r--r--spec/ruby/core/file/printf_spec.rb2
-rw-r--r--spec/ruby/core/file/readlink_spec.rb6
-rw-r--r--spec/ruby/core/file/realdirpath_spec.rb6
-rw-r--r--spec/ruby/core/file/realpath_spec.rb16
-rw-r--r--spec/ruby/core/file/rename_spec.rb16
-rw-r--r--spec/ruby/core/file/reopen_spec.rb2
-rw-r--r--spec/ruby/core/file/setuid_spec.rb4
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb93
-rw-r--r--spec/ruby/core/file/shared/open.rb2
-rw-r--r--spec/ruby/core/file/shared/path.rb62
-rw-r--r--spec/ruby/core/file/shared/read.rb8
-rw-r--r--spec/ruby/core/file/shared/stat.rb8
-rw-r--r--spec/ruby/core/file/shared/unlink.rb14
-rw-r--r--spec/ruby/core/file/shared/update_time.rb105
-rw-r--r--spec/ruby/core/file/size_spec.rb8
-rw-r--r--spec/ruby/core/file/socket_spec.rb32
-rw-r--r--spec/ruby/core/file/split_spec.rb11
-rw-r--r--spec/ruby/core/file/stat/atime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/birthtime_spec.rb36
-rw-r--r--spec/ruby/core/file/stat/blocks_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/ctime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/dev_major_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/dev_minor_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/dev_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/ftype_spec.rb6
-rw-r--r--spec/ruby/core/file/stat/ino_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/inspect_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/mtime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/new_spec.rb6
-rw-r--r--spec/ruby/core/file/stat/nlink_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/owned_spec.rb6
-rw-r--r--spec/ruby/core/file/stat/pipe_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/rdev_major_spec.rb17
-rw-r--r--spec/ruby/core/file/stat/rdev_minor_spec.rb17
-rw-r--r--spec/ruby/core/file/stat/rdev_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/setgid_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/setuid_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/socket_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/sticky_spec.rb4
-rw-r--r--spec/ruby/core/file/stat_spec.rb24
-rw-r--r--spec/ruby/core/file/sticky_spec.rb2
-rw-r--r--spec/ruby/core/file/symlink_spec.rb12
-rw-r--r--spec/ruby/core/file/truncate_spec.rb30
-rw-r--r--spec/ruby/core/file/umask_spec.rb10
-rw-r--r--spec/ruby/core/file/utime_spec.rb53
-rw-r--r--spec/ruby/core/file/world_readable_spec.rb4
-rw-r--r--spec/ruby/core/file/world_writable_spec.rb4
-rw-r--r--spec/ruby/core/file/zero_spec.rb6
-rw-r--r--spec/ruby/core/filetest/exist_spec.rb6
-rw-r--r--spec/ruby/core/filetest/exists_spec.rb6
-rw-r--r--spec/ruby/core/filetest/grpowned_spec.rb2
-rw-r--r--spec/ruby/core/filetest/owned_spec.rb4
-rw-r--r--spec/ruby/core/filetest/pipe_spec.rb4
-rw-r--r--spec/ruby/core/filetest/setgid_spec.rb4
-rw-r--r--spec/ruby/core/filetest/setuid_spec.rb4
-rw-r--r--spec/ruby/core/filetest/socket_spec.rb6
-rw-r--r--spec/ruby/core/filetest/zero_spec.rb6
-rw-r--r--spec/ruby/core/float/ceil_spec.rb35
-rw-r--r--spec/ruby/core/float/coerce_spec.rb4
-rw-r--r--spec/ruby/core/float/comparison_spec.rb103
-rw-r--r--spec/ruby/core/float/constants_spec.rb2
-rw-r--r--spec/ruby/core/float/denominator_spec.rb2
-rw-r--r--spec/ruby/core/float/divide_spec.rb24
-rw-r--r--spec/ruby/core/float/divmod_spec.rb24
-rw-r--r--spec/ruby/core/float/dup_spec.rb10
-rw-r--r--spec/ruby/core/float/eql_spec.rb8
-rw-r--r--spec/ruby/core/float/finite_spec.rb8
-rw-r--r--spec/ruby/core/float/float_spec.rb8
-rw-r--r--spec/ruby/core/float/floor_spec.rb35
-rw-r--r--spec/ruby/core/float/gt_spec.rb25
-rw-r--r--spec/ruby/core/float/gte_spec.rb25
-rw-r--r--spec/ruby/core/float/inspect_spec.rb6
-rw-r--r--spec/ruby/core/float/lt_spec.rb25
-rw-r--r--spec/ruby/core/float/lte_spec.rb25
-rw-r--r--spec/ruby/core/float/magnitude_spec.rb1
-rw-r--r--spec/ruby/core/float/minus_spec.rb2
-rw-r--r--spec/ruby/core/float/multiply_spec.rb6
-rw-r--r--spec/ruby/core/float/nan_spec.rb6
-rw-r--r--spec/ruby/core/float/negative_spec.rb33
-rw-r--r--spec/ruby/core/float/next_float_spec.rb4
-rw-r--r--spec/ruby/core/float/numerator_spec.rb4
-rw-r--r--spec/ruby/core/float/plus_spec.rb2
-rw-r--r--spec/ruby/core/float/positive_spec.rb33
-rw-r--r--spec/ruby/core/float/prev_float_spec.rb4
-rw-r--r--spec/ruby/core/float/rationalize_spec.rb8
-rw-r--r--spec/ruby/core/float/round_spec.rb199
-rw-r--r--spec/ruby/core/float/shared/abs.rb2
-rw-r--r--spec/ruby/core/float/shared/arg.rb4
-rw-r--r--spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb32
-rw-r--r--spec/ruby/core/float/shared/comparison_exception_in_coerce.rb34
-rw-r--r--spec/ruby/core/float/shared/equal.rb21
-rw-r--r--spec/ruby/core/float/shared/modulo.rb12
-rw-r--r--spec/ruby/core/float/shared/quo.rb12
-rw-r--r--spec/ruby/core/float/shared/to_i.rb16
-rw-r--r--spec/ruby/core/float/shared/to_s.rb308
-rw-r--r--spec/ruby/core/float/to_s_spec.rb118
-rw-r--r--spec/ruby/core/float/truncate_spec.rb14
-rw-r--r--spec/ruby/core/float/uminus_spec.rb2
-rw-r--r--spec/ruby/core/float/uplus_spec.rb2
-rw-r--r--spec/ruby/core/float/zero_spec.rb6
-rw-r--r--spec/ruby/core/gc/auto_compact_spec.rb24
-rw-r--r--spec/ruby/core/gc/config_spec.rb97
-rw-r--r--spec/ruby/core/gc/count_spec.rb12
-rw-r--r--spec/ruby/core/gc/disable_spec.rb2
-rw-r--r--spec/ruby/core/gc/enable_spec.rb2
-rw-r--r--spec/ruby/core/gc/measure_total_time_spec.rb17
-rw-r--r--spec/ruby/core/gc/profiler/disable_spec.rb2
-rw-r--r--spec/ruby/core/gc/profiler/enable_spec.rb2
-rw-r--r--spec/ruby/core/gc/profiler/enabled_spec.rb4
-rw-r--r--spec/ruby/core/gc/profiler/result_spec.rb2
-rw-r--r--spec/ruby/core/gc/profiler/total_time_spec.rb2
-rw-r--r--spec/ruby/core/gc/start_spec.rb4
-rw-r--r--spec/ruby/core/gc/stat_spec.rb62
-rw-r--r--spec/ruby/core/gc/stress_spec.rb8
-rw-r--r--spec/ruby/core/gc/total_time_spec.rb13
-rw-r--r--spec/ruby/core/hash/allocate_spec.rb2
-rw-r--r--spec/ruby/core/hash/any_spec.rb4
-rw-r--r--spec/ruby/core/hash/assoc_spec.rb14
-rw-r--r--spec/ruby/core/hash/clear_spec.rb8
-rw-r--r--spec/ruby/core/hash/clone_spec.rb2
-rw-r--r--spec/ruby/core/hash/compact_spec.rb106
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb67
-rw-r--r--spec/ruby/core/hash/constructor_spec.rb55
-rw-r--r--spec/ruby/core/hash/deconstruct_keys_spec.rb23
-rw-r--r--spec/ruby/core/hash/default_proc_spec.rb34
-rw-r--r--spec/ruby/core/hash/default_spec.rb8
-rw-r--r--spec/ruby/core/hash/delete_if_spec.rb10
-rw-r--r--spec/ruby/core/hash/delete_spec.rb22
-rw-r--r--spec/ruby/core/hash/dig_spec.rb18
-rw-r--r--spec/ruby/core/hash/each_key_spec.rb2
-rw-r--r--spec/ruby/core/hash/each_pair_spec.rb106
-rw-r--r--spec/ruby/core/hash/each_spec.rb10
-rw-r--r--spec/ruby/core/hash/each_value_spec.rb2
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb20
-rw-r--r--spec/ruby/core/hash/element_set_spec.rb118
-rw-r--r--spec/ruby/core/hash/empty_spec.rb10
-rw-r--r--spec/ruby/core/hash/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/hash/except_spec.rb42
-rw-r--r--spec/ruby/core/hash/fetch_spec.rb20
-rw-r--r--spec/ruby/core/hash/fetch_values_spec.rb6
-rw-r--r--spec/ruby/core/hash/filter_spec.rb13
-rw-r--r--spec/ruby/core/hash/fixtures/name.rb30
-rw-r--r--spec/ruby/core/hash/flatten_spec.rb6
-rw-r--r--spec/ruby/core/hash/gt_spec.rb2
-rw-r--r--spec/ruby/core/hash/gte_spec.rb2
-rw-r--r--spec/ruby/core/hash/has_key_spec.rb6
-rw-r--r--spec/ruby/core/hash/has_value_spec.rb15
-rw-r--r--spec/ruby/core/hash/hash_spec.rb15
-rw-r--r--spec/ruby/core/hash/include_spec.rb39
-rw-r--r--spec/ruby/core/hash/index_spec.rb7
-rw-r--r--spec/ruby/core/hash/initialize_spec.rb22
-rw-r--r--spec/ruby/core/hash/inspect_spec.rb122
-rw-r--r--spec/ruby/core/hash/invert_spec.rb21
-rw-r--r--spec/ruby/core/hash/keep_if_spec.rb12
-rw-r--r--spec/ruby/core/hash/key_spec.rb30
-rw-r--r--spec/ruby/core/hash/keys_spec.rb4
-rw-r--r--spec/ruby/core/hash/length_spec.rb6
-rw-r--r--spec/ruby/core/hash/lt_spec.rb2
-rw-r--r--spec/ruby/core/hash/lte_spec.rb2
-rw-r--r--spec/ruby/core/hash/member_spec.rb6
-rw-r--r--spec/ruby/core/hash/merge_spec.rb72
-rw-r--r--spec/ruby/core/hash/new_spec.rb40
-rw-r--r--spec/ruby/core/hash/rassoc_spec.rb10
-rw-r--r--spec/ruby/core/hash/rehash_spec.rb79
-rw-r--r--spec/ruby/core/hash/reject_spec.rb40
-rw-r--r--spec/ruby/core/hash/replace_spec.rb76
-rw-r--r--spec/ruby/core/hash/ruby2_keywords_hash_spec.rb81
-rw-r--r--spec/ruby/core/hash/select_spec.rb108
-rw-r--r--spec/ruby/core/hash/shared/comparison.rb10
-rw-r--r--spec/ruby/core/hash/shared/each.rb68
-rw-r--r--spec/ruby/core/hash/shared/eql.rb102
-rw-r--r--spec/ruby/core/hash/shared/equal.rb90
-rw-r--r--spec/ruby/core/hash/shared/greater_than.rb6
-rw-r--r--spec/ruby/core/hash/shared/index.rb27
-rw-r--r--spec/ruby/core/hash/shared/iteration.rb6
-rw-r--r--spec/ruby/core/hash/shared/key.rb38
-rw-r--r--spec/ruby/core/hash/shared/length.rb12
-rw-r--r--spec/ruby/core/hash/shared/less_than.rb6
-rw-r--r--spec/ruby/core/hash/shared/replace.rb51
-rw-r--r--spec/ruby/core/hash/shared/select.rb91
-rw-r--r--spec/ruby/core/hash/shared/store.rb98
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb96
-rw-r--r--spec/ruby/core/hash/shared/update.rb59
-rw-r--r--spec/ruby/core/hash/shared/value.rb14
-rw-r--r--spec/ruby/core/hash/shared/values_at.rb9
-rw-r--r--spec/ruby/core/hash/shift_spec.rb36
-rw-r--r--spec/ruby/core/hash/size_spec.rb13
-rw-r--r--spec/ruby/core/hash/slice_spec.rb103
-rw-r--r--spec/ruby/core/hash/store_spec.rb6
-rw-r--r--spec/ruby/core/hash/to_a_spec.rb12
-rw-r--r--spec/ruby/core/hash/to_h_spec.rb86
-rw-r--r--spec/ruby/core/hash/to_hash_spec.rb4
-rw-r--r--spec/ruby/core/hash/to_proc_spec.rb28
-rw-r--r--spec/ruby/core/hash/to_s_spec.rb6
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb222
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb167
-rw-r--r--spec/ruby/core/hash/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/hash/update_spec.rb76
-rw-r--r--spec/ruby/core/hash/value_spec.rb6
-rw-r--r--spec/ruby/core/hash/values_at_spec.rb10
-rw-r--r--spec/ruby/core/hash/values_spec.rb2
-rw-r--r--spec/ruby/core/integer/allbits_spec.rb62
-rw-r--r--spec/ruby/core/integer/anybits_spec.rb60
-rw-r--r--spec/ruby/core/integer/bit_and_spec.rb24
-rw-r--r--spec/ruby/core/integer/bit_or_spec.rb45
-rw-r--r--spec/ruby/core/integer/bit_xor_spec.rb47
-rw-r--r--spec/ruby/core/integer/ceil_spec.rb14
-rw-r--r--spec/ruby/core/integer/ceildiv_spec.rb20
-rw-r--r--spec/ruby/core/integer/chr_spec.rb108
-rw-r--r--spec/ruby/core/integer/coerce_spec.rb70
-rw-r--r--spec/ruby/core/integer/comparison_spec.rb38
-rw-r--r--spec/ruby/core/integer/complement_spec.rb6
-rw-r--r--spec/ruby/core/integer/constants_spec.rb13
-rw-r--r--spec/ruby/core/integer/digits_spec.rb67
-rw-r--r--spec/ruby/core/integer/div_spec.rb62
-rw-r--r--spec/ruby/core/integer/divide_spec.rb73
-rw-r--r--spec/ruby/core/integer/divmod_spec.rb48
-rw-r--r--spec/ruby/core/integer/downto_spec.rb10
-rw-r--r--spec/ruby/core/integer/dup_spec.rb18
-rw-r--r--spec/ruby/core/integer/element_reference_spec.rb85
-rw-r--r--spec/ruby/core/integer/eql_spec.rb25
-rw-r--r--spec/ruby/core/integer/even_spec.rb26
-rw-r--r--spec/ruby/core/integer/fdiv_spec.rb59
-rw-r--r--spec/ruby/core/integer/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/integer/floor_spec.rb14
-rw-r--r--spec/ruby/core/integer/gcd_spec.rb27
-rw-r--r--spec/ruby/core/integer/gcdlcm_spec.rb16
-rw-r--r--spec/ruby/core/integer/gt_spec.rb21
-rw-r--r--spec/ruby/core/integer/gte_spec.rb21
-rw-r--r--spec/ruby/core/integer/integer_spec.rb14
-rw-r--r--spec/ruby/core/integer/lcm_spec.rb16
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb82
-rw-r--r--spec/ruby/core/integer/lt_spec.rb21
-rw-r--r--spec/ruby/core/integer/lte_spec.rb26
-rw-r--r--spec/ruby/core/integer/minus_spec.rb45
-rw-r--r--spec/ruby/core/integer/multiply_spec.rb28
-rw-r--r--spec/ruby/core/integer/nobits_spec.rb60
-rw-r--r--spec/ruby/core/integer/odd_spec.rb26
-rw-r--r--spec/ruby/core/integer/ord_spec.rb16
-rw-r--r--spec/ruby/core/integer/plus_spec.rb62
-rw-r--r--spec/ruby/core/integer/pow_spec.rb84
-rw-r--r--spec/ruby/core/integer/pred_spec.rb10
-rw-r--r--spec/ruby/core/integer/rationalize_spec.rb6
-rw-r--r--spec/ruby/core/integer/remainder_spec.rb20
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb86
-rw-r--r--spec/ruby/core/integer/round_spec.rb84
-rw-r--r--spec/ruby/core/integer/shared/abs.rb4
-rw-r--r--spec/ruby/core/integer/shared/arithmetic_coerce.rb22
-rw-r--r--spec/ruby/core/integer/shared/comparison_coerce.rb24
-rw-r--r--spec/ruby/core/integer/shared/equal.rb9
-rw-r--r--spec/ruby/core/integer/shared/exponent.rb136
-rw-r--r--spec/ruby/core/integer/shared/integer_ceil_precision.rb54
-rw-r--r--spec/ruby/core/integer/shared/integer_floor_precision.rb42
-rw-r--r--spec/ruby/core/integer/shared/integer_rounding.rb26
-rw-r--r--spec/ruby/core/integer/shared/modulo.rb86
-rw-r--r--spec/ruby/core/integer/shared/to_i.rb8
-rw-r--r--spec/ruby/core/integer/size_spec.rb4
-rw-r--r--spec/ruby/core/integer/sqrt_spec.rb46
-rw-r--r--spec/ruby/core/integer/to_f_spec.rb6
-rw-r--r--spec/ruby/core/integer/to_r_spec.rb8
-rw-r--r--spec/ruby/core/integer/to_s_spec.rb78
-rw-r--r--spec/ruby/core/integer/truncate_spec.rb18
-rw-r--r--spec/ruby/core/integer/try_convert_spec.rb48
-rw-r--r--spec/ruby/core/integer/uminus_spec.rb14
-rw-r--r--spec/ruby/core/integer/upto_spec.rb10
-rw-r--r--spec/ruby/core/integer/zero_spec.rb13
-rw-r--r--spec/ruby/core/io/advise_spec.rb53
-rw-r--r--spec/ruby/core/io/autoclose_spec.rb77
-rw-r--r--spec/ruby/core/io/binmode_spec.rb12
-rw-r--r--spec/ruby/core/io/binread_spec.rb22
-rw-r--r--spec/ruby/core/io/binwrite_spec.rb2
-rw-r--r--spec/ruby/core/io/buffer/and_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/bit_count_spec.rb64
-rw-r--r--spec/ruby/core/io/buffer/empty_spec.rb27
-rw-r--r--spec/ruby/core/io/buffer/external_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/for_spec.rb95
-rw-r--r--spec/ruby/core/io/buffer/free_spec.rb102
-rw-r--r--spec/ruby/core/io/buffer/initialize_spec.rb119
-rw-r--r--spec/ruby/core/io/buffer/internal_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/locked_spec.rb75
-rw-r--r--spec/ruby/core/io/buffer/map_spec.rb343
-rw-r--r--spec/ruby/core/io/buffer/mapped_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/not_spec.rb37
-rw-r--r--spec/ruby/core/io/buffer/null_spec.rb27
-rw-r--r--spec/ruby/core/io/buffer/or_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/private_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/readonly_spec.rb28
-rw-r--r--spec/ruby/core/io/buffer/resize_spec.rb151
-rw-r--r--spec/ruby/core/io/buffer/shared/null_and_empty.rb57
-rw-r--r--spec/ruby/core/io/buffer/shared_spec.rb33
-rw-r--r--spec/ruby/core/io/buffer/string_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/transfer_spec.rb117
-rw-r--r--spec/ruby/core/io/buffer/valid_spec.rb99
-rw-r--r--spec/ruby/core/io/buffer/xor_spec.rb62
-rw-r--r--spec/ruby/core/io/bytes_spec.rb43
-rw-r--r--spec/ruby/core/io/chars_spec.rb12
-rw-r--r--spec/ruby/core/io/close_on_exec_spec.rb20
-rw-r--r--spec/ruby/core/io/close_read_spec.rb15
-rw-r--r--spec/ruby/core/io/close_spec.rb63
-rw-r--r--spec/ruby/core/io/close_write_spec.rb26
-rw-r--r--spec/ruby/core/io/closed_spec.rb4
-rw-r--r--spec/ruby/core/io/codepoints_spec.rb25
-rw-r--r--spec/ruby/core/io/copy_stream_spec.rb91
-rw-r--r--spec/ruby/core/io/dup_spec.rb83
-rw-r--r--spec/ruby/core/io/each_byte_spec.rb6
-rw-r--r--spec/ruby/core/io/each_codepoint_spec.rb6
-rw-r--r--spec/ruby/core/io/eof_spec.rb36
-rw-r--r--spec/ruby/core/io/external_encoding_spec.rb315
-rw-r--r--spec/ruby/core/io/fcntl_spec.rb2
-rw-r--r--spec/ruby/core/io/fileno_spec.rb2
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb37
-rw-r--r--spec/ruby/core/io/fixtures/copy_in_out.rb2
-rw-r--r--spec/ruby/core/io/flush_spec.rb31
-rw-r--r--spec/ruby/core/io/foreach_spec.rb55
-rw-r--r--spec/ruby/core/io/fsync_spec.rb2
-rw-r--r--spec/ruby/core/io/getbyte_spec.rb18
-rw-r--r--spec/ruby/core/io/getc_spec.rb6
-rw-r--r--spec/ruby/core/io/gets_spec.rb111
-rw-r--r--spec/ruby/core/io/initialize_spec.rb29
-rw-r--r--spec/ruby/core/io/inspect_spec.rb4
-rw-r--r--spec/ruby/core/io/internal_encoding_spec.rb235
-rw-r--r--spec/ruby/core/io/ioctl_spec.rb14
-rw-r--r--spec/ruby/core/io/lineno_spec.rb51
-rw-r--r--spec/ruby/core/io/lines_spec.rb42
-rw-r--r--spec/ruby/core/io/new_spec.rb8
-rw-r--r--spec/ruby/core/io/nonblock_spec.rb48
-rw-r--r--spec/ruby/core/io/open_spec.rb27
-rw-r--r--spec/ruby/core/io/output_spec.rb8
-rw-r--r--spec/ruby/core/io/path_spec.rb12
-rw-r--r--spec/ruby/core/io/pid_spec.rb4
-rw-r--r--spec/ruby/core/io/pipe_spec.rb55
-rw-r--r--spec/ruby/core/io/popen_spec.rb97
-rw-r--r--spec/ruby/core/io/pread_spec.rb178
-rw-r--r--spec/ruby/core/io/print_spec.rb29
-rw-r--r--spec/ruby/core/io/printf_spec.rb2
-rw-r--r--spec/ruby/core/io/puts_spec.rb44
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb100
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb73
-rw-r--r--spec/ruby/core/io/read_spec.rb481
-rw-r--r--spec/ruby/core/io/readbyte_spec.rb6
-rw-r--r--spec/ruby/core/io/readchar_spec.rb72
-rw-r--r--spec/ruby/core/io/readline_spec.rb45
-rw-r--r--spec/ruby/core/io/readlines_spec.rb129
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb41
-rw-r--r--spec/ruby/core/io/reopen_spec.rb57
-rw-r--r--spec/ruby/core/io/rewind_spec.rb19
-rw-r--r--spec/ruby/core/io/seek_spec.rb8
-rw-r--r--spec/ruby/core/io/select_spec.rb110
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb262
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb329
-rw-r--r--spec/ruby/core/io/shared/binwrite.rb27
-rw-r--r--spec/ruby/core/io/shared/chars.rb10
-rw-r--r--spec/ruby/core/io/shared/codepoints.rb6
-rw-r--r--spec/ruby/core/io/shared/each.rb102
-rw-r--r--spec/ruby/core/io/shared/gets_ascii.rb2
-rw-r--r--spec/ruby/core/io/shared/new.rb235
-rw-r--r--spec/ruby/core/io/shared/pos.rb16
-rw-r--r--spec/ruby/core/io/shared/readlines.rb176
-rw-r--r--spec/ruby/core/io/shared/tty.rb5
-rw-r--r--spec/ruby/core/io/shared/write.rb73
-rw-r--r--spec/ruby/core/io/stat_spec.rb9
-rw-r--r--spec/ruby/core/io/sync_spec.rb4
-rw-r--r--spec/ruby/core/io/sysopen_spec.rb16
-rw-r--r--spec/ruby/core/io/sysread_spec.rb55
-rw-r--r--spec/ruby/core/io/sysseek_spec.rb11
-rw-r--r--spec/ruby/core/io/syswrite_spec.rb17
-rw-r--r--spec/ruby/core/io/to_i_spec.rb2
-rw-r--r--spec/ruby/core/io/to_io_spec.rb4
-rw-r--r--spec/ruby/core/io/try_convert_spec.rb12
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb28
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb23
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb34
-rw-r--r--spec/ruby/core/io/write_spec.rb230
-rw-r--r--spec/ruby/core/kernel/Array_spec.rb6
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb177
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb267
-rw-r--r--spec/ruby/core/kernel/Hash_spec.rb6
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb390
-rw-r--r--spec/ruby/core/kernel/Rational_spec.rb234
-rw-r--r--spec/ruby/core/kernel/String_spec.rb16
-rw-r--r--spec/ruby/core/kernel/__dir___spec.rb11
-rw-r--r--spec/ruby/core/kernel/abort_spec.rb2
-rw-r--r--spec/ruby/core/kernel/at_exit_spec.rb37
-rw-r--r--spec/ruby/core/kernel/autoload_relative_spec.rb114
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb40
-rw-r--r--spec/ruby/core/kernel/backtick_spec.rb44
-rw-r--r--spec/ruby/core/kernel/binding_spec.rb4
-rw-r--r--spec/ruby/core/kernel/block_given_spec.rb7
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb87
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb89
-rw-r--r--spec/ruby/core/kernel/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/kernel/catch_spec.rb10
-rw-r--r--spec/ruby/core/kernel/chomp_spec.rb38
-rw-r--r--spec/ruby/core/kernel/chop_spec.rb38
-rw-r--r--spec/ruby/core/kernel/class_spec.rb22
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb97
-rw-r--r--spec/ruby/core/kernel/comparison_spec.rb6
-rw-r--r--spec/ruby/core/kernel/define_singleton_method_spec.rb49
-rw-r--r--spec/ruby/core/kernel/dup_spec.rb10
-rw-r--r--spec/ruby/core/kernel/eql_spec.rb2
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb283
-rw-r--r--spec/ruby/core/kernel/exec_spec.rb6
-rw-r--r--spec/ruby/core/kernel/exit_spec.rb14
-rw-r--r--spec/ruby/core/kernel/extend_spec.rb26
-rw-r--r--spec/ruby/core/kernel/fail_spec.rb25
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/__dir__.rb2
-rw-r--r--spec/ruby/core/kernel/fixtures/autoload_relative_b.rb7
-rw-r--r--spec/ruby/core/kernel/fixtures/autoload_relative_d.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb154
-rw-r--r--spec/ruby/core/kernel/fixtures/eval_return_with_lambda.rb2
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb14
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_require.rb1
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_require_caller.rb2
-rw-r--r--spec/ruby/core/kernel/fork_spec.rb2
-rw-r--r--spec/ruby/core/kernel/format_spec.rb35
-rw-r--r--spec/ruby/core/kernel/freeze_spec.rb56
-rw-r--r--spec/ruby/core/kernel/frozen_spec.rb54
-rw-r--r--spec/ruby/core/kernel/gets_spec.rb2
-rw-r--r--spec/ruby/core/kernel/global_variables_spec.rb6
-rw-r--r--spec/ruby/core/kernel/gsub_spec.rb10
-rw-r--r--spec/ruby/core/kernel/initialize_clone_spec.rb26
-rw-r--r--spec/ruby/core/kernel/initialize_copy_spec.rb36
-rw-r--r--spec/ruby/core/kernel/initialize_dup_spec.rb20
-rw-r--r--spec/ruby/core/kernel/inspect_spec.rb90
-rw-r--r--spec/ruby/core/kernel/instance_of_spec.rb8
-rw-r--r--spec/ruby/core/kernel/instance_variable_defined_spec.rb14
-rw-r--r--spec/ruby/core/kernel/instance_variable_get_spec.rb34
-rw-r--r--spec/ruby/core/kernel/instance_variable_set_spec.rb54
-rw-r--r--spec/ruby/core/kernel/instance_variables_spec.rb17
-rw-r--r--spec/ruby/core/kernel/is_a_spec.rb2
-rw-r--r--spec/ruby/core/kernel/iterator_spec.rb12
-rw-r--r--spec/ruby/core/kernel/itself_spec.rb2
-rw-r--r--spec/ruby/core/kernel/kind_of_spec.rb2
-rw-r--r--spec/ruby/core/kernel/lambda_spec.rb62
-rw-r--r--spec/ruby/core/kernel/load_spec.rb2
-rw-r--r--spec/ruby/core/kernel/local_variables_spec.rb22
-rw-r--r--spec/ruby/core/kernel/loop_spec.rb6
-rw-r--r--spec/ruby/core/kernel/match_spec.rb11
-rw-r--r--spec/ruby/core/kernel/method_spec.rb59
-rw-r--r--spec/ruby/core/kernel/methods_spec.rb34
-rw-r--r--spec/ruby/core/kernel/nil_spec.rb10
-rw-r--r--spec/ruby/core/kernel/not_match_spec.rb4
-rw-r--r--spec/ruby/core/kernel/open_spec.rb128
-rw-r--r--spec/ruby/core/kernel/p_spec.rb42
-rw-r--r--spec/ruby/core/kernel/pp_spec.rb9
-rw-r--r--spec/ruby/core/kernel/print_spec.rb14
-rw-r--r--spec/ruby/core/kernel/printf_spec.rb30
-rw-r--r--spec/ruby/core/kernel/private_methods_spec.rb10
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb30
-rw-r--r--spec/ruby/core/kernel/protected_methods_spec.rb10
-rw-r--r--spec/ruby/core/kernel/public_method_spec.rb12
-rw-r--r--spec/ruby/core/kernel/public_methods_spec.rb19
-rw-r--r--spec/ruby/core/kernel/public_send_spec.rb26
-rw-r--r--spec/ruby/core/kernel/putc_spec.rb2
-rw-r--r--spec/ruby/core/kernel/puts_spec.rb2
-rw-r--r--spec/ruby/core/kernel/raise_spec.rb213
-rw-r--r--spec/ruby/core/kernel/rand_spec.rb126
-rw-r--r--spec/ruby/core/kernel/readline_spec.rb2
-rw-r--r--spec/ruby/core/kernel/readlines_spec.rb2
-rw-r--r--spec/ruby/core/kernel/remove_instance_variable_spec.rb29
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb158
-rw-r--r--spec/ruby/core/kernel/require_spec.rb35
-rw-r--r--spec/ruby/core/kernel/respond_to_missing_spec.rb20
-rw-r--r--spec/ruby/core/kernel/respond_to_spec.rb32
-rw-r--r--spec/ruby/core/kernel/select_spec.rb8
-rw-r--r--spec/ruby/core/kernel/set_trace_func_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/dup_clone.rb98
-rw-r--r--spec/ruby/core/kernel/shared/kind_of.rb8
-rw-r--r--spec/ruby/core/kernel/shared/lambda.rb4
-rw-r--r--spec/ruby/core/kernel/shared/load.rb150
-rw-r--r--spec/ruby/core/kernel/shared/method.rb20
-rw-r--r--spec/ruby/core/kernel/shared/require.rb365
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb1075
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb65
-rw-r--r--spec/ruby/core/kernel/shared/then.rb12
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb53
-rw-r--r--spec/ruby/core/kernel/singleton_method_spec.rb52
-rw-r--r--spec/ruby/core/kernel/singleton_methods_spec.rb77
-rw-r--r--spec/ruby/core/kernel/sleep_spec.rb90
-rw-r--r--spec/ruby/core/kernel/spawn_spec.rb6
-rw-r--r--spec/ruby/core/kernel/sprintf_spec.rb56
-rw-r--r--spec/ruby/core/kernel/srand_spec.rb26
-rw-r--r--spec/ruby/core/kernel/sub_spec.rb4
-rw-r--r--spec/ruby/core/kernel/syscall_spec.rb2
-rw-r--r--spec/ruby/core/kernel/system_spec.rb65
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb41
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb8
-rw-r--r--spec/ruby/core/kernel/tap_spec.rb4
-rw-r--r--spec/ruby/core/kernel/test_spec.rb16
-rw-r--r--spec/ruby/core/kernel/then_spec.rb6
-rw-r--r--spec/ruby/core/kernel/throw_spec.rb22
-rw-r--r--spec/ruby/core/kernel/to_s_spec.rb8
-rw-r--r--spec/ruby/core/kernel/trace_var_spec.rb6
-rw-r--r--spec/ruby/core/kernel/trap_spec.rb7
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb21
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb21
-rw-r--r--spec/ruby/core/kernel/untrace_var_spec.rb2
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb21
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb24
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb263
-rw-r--r--spec/ruby/core/kernel/yield_self_spec.rb6
-rw-r--r--spec/ruby/core/main/define_method_spec.rb6
-rw-r--r--spec/ruby/core/main/fixtures/classes.rb8
-rw-r--r--spec/ruby/core/main/fixtures/using.rb1
-rw-r--r--spec/ruby/core/main/fixtures/using_in_main.rb5
-rw-r--r--spec/ruby/core/main/fixtures/using_in_method.rb5
-rw-r--r--spec/ruby/core/main/include_spec.rb4
-rw-r--r--spec/ruby/core/main/private_spec.rb37
-rw-r--r--spec/ruby/core/main/public_spec.rb34
-rw-r--r--spec/ruby/core/main/ruby2_keywords_spec.rb9
-rw-r--r--spec/ruby/core/main/using_spec.rb34
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb721
-rw-r--r--spec/ruby/core/marshal/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb217
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb12
-rw-r--r--spec/ruby/core/marshal/float_spec.rb2
-rw-r--r--spec/ruby/core/marshal/shared/load.rb879
-rw-r--r--spec/ruby/core/matchdata/allocate_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/begin_spec.rb136
-rw-r--r--spec/ruby/core/matchdata/bytebegin_spec.rb132
-rw-r--r--spec/ruby/core/matchdata/byteend_spec.rb104
-rw-r--r--spec/ruby/core/matchdata/byteoffset_spec.rb93
-rw-r--r--spec/ruby/core/matchdata/captures_spec.rb5
-rw-r--r--spec/ruby/core/matchdata/deconstruct_keys_spec.rb78
-rw-r--r--spec/ruby/core/matchdata/deconstruct_spec.rb6
-rw-r--r--spec/ruby/core/matchdata/dup_spec.rb14
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb43
-rw-r--r--spec/ruby/core/matchdata/end_spec.rb108
-rw-r--r--spec/ruby/core/matchdata/fixtures/classes.rb3
-rw-r--r--spec/ruby/core/matchdata/inspect_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/integer_at_spec.rb38
-rw-r--r--spec/ruby/core/matchdata/match_length_spec.rb32
-rw-r--r--spec/ruby/core/matchdata/match_spec.rb32
-rw-r--r--spec/ruby/core/matchdata/named_captures_spec.rb30
-rw-r--r--spec/ruby/core/matchdata/names_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/offset_spec.rb106
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb32
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb32
-rw-r--r--spec/ruby/core/matchdata/regexp_spec.rb13
-rw-r--r--spec/ruby/core/matchdata/shared/captures.rb13
-rw-r--r--spec/ruby/core/matchdata/shared/eql.rb8
-rw-r--r--spec/ruby/core/matchdata/string_spec.rb14
-rw-r--r--spec/ruby/core/matchdata/to_a_spec.rb6
-rw-r--r--spec/ruby/core/matchdata/to_s_spec.rb6
-rw-r--r--spec/ruby/core/matchdata/values_at_spec.rb69
-rw-r--r--spec/ruby/core/math/acos_spec.rb14
-rw-r--r--spec/ruby/core/math/acosh_spec.rb14
-rw-r--r--spec/ruby/core/math/asin_spec.rb12
-rw-r--r--spec/ruby/core/math/asinh_spec.rb8
-rw-r--r--spec/ruby/core/math/atan2_spec.rb14
-rw-r--r--spec/ruby/core/math/atan_spec.rb8
-rw-r--r--spec/ruby/core/math/atanh_spec.rb4
-rw-r--r--spec/ruby/core/math/cbrt_spec.rb6
-rw-r--r--spec/ruby/core/math/cos_spec.rb32
-rw-r--r--spec/ruby/core/math/cosh_spec.rb8
-rw-r--r--spec/ruby/core/math/erf_spec.rb8
-rw-r--r--spec/ruby/core/math/erfc_spec.rb8
-rw-r--r--spec/ruby/core/math/exp_spec.rb8
-rw-r--r--spec/ruby/core/math/expm1_spec.rb37
-rw-r--r--spec/ruby/core/math/fixtures/common.rb (renamed from spec/ruby/fixtures/math/common.rb)0
-rw-r--r--spec/ruby/core/math/frexp_spec.rb6
-rw-r--r--spec/ruby/core/math/gamma_spec.rb6
-rw-r--r--spec/ruby/core/math/hypot_spec.rb12
-rw-r--r--spec/ruby/core/math/ldexp_spec.rb20
-rw-r--r--spec/ruby/core/math/lgamma_spec.rb19
-rw-r--r--spec/ruby/core/math/log10_spec.rb14
-rw-r--r--spec/ruby/core/math/log1p_spec.rb49
-rw-r--r--spec/ruby/core/math/log2_spec.rb12
-rw-r--r--spec/ruby/core/math/log_spec.rb16
-rw-r--r--spec/ruby/core/math/shared/atanh.rb44
-rw-r--r--spec/ruby/core/math/sin_spec.rb8
-rw-r--r--spec/ruby/core/math/sinh_spec.rb8
-rw-r--r--spec/ruby/core/math/sqrt_spec.rb12
-rw-r--r--spec/ruby/core/math/tan_spec.rb14
-rw-r--r--spec/ruby/core/math/tanh_spec.rb8
-rw-r--r--spec/ruby/core/method/case_compare_spec.rb6
-rw-r--r--spec/ruby/core/method/clone_spec.rb15
-rw-r--r--spec/ruby/core/method/compose_spec.rb99
-rw-r--r--spec/ruby/core/method/curry_spec.rb18
-rw-r--r--spec/ruby/core/method/dup_spec.rb15
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb63
-rw-r--r--spec/ruby/core/method/hash_spec.rb2
-rw-r--r--spec/ruby/core/method/inspect_spec.rb2
-rw-r--r--spec/ruby/core/method/original_name_spec.rb59
-rw-r--r--spec/ruby/core/method/owner_spec.rb4
-rw-r--r--spec/ruby/core/method/parameters_spec.rb79
-rw-r--r--spec/ruby/core/method/private_spec.rb9
-rw-r--r--spec/ruby/core/method/protected_spec.rb9
-rw-r--r--spec/ruby/core/method/public_spec.rb9
-rw-r--r--spec/ruby/core/method/receiver_spec.rb8
-rw-r--r--spec/ruby/core/method/shared/aliased_inspect.rb31
-rw-r--r--spec/ruby/core/method/shared/call.rb8
-rw-r--r--spec/ruby/core/method/shared/dup.rb32
-rw-r--r--spec/ruby/core/method/shared/eql.rb32
-rw-r--r--spec/ruby/core/method/shared/to_s.rb53
-rw-r--r--spec/ruby/core/method/source_location_spec.rb37
-rw-r--r--spec/ruby/core/method/super_method_spec.rb19
-rw-r--r--spec/ruby/core/method/to_proc_spec.rb13
-rw-r--r--spec/ruby/core/method/to_s_spec.rb2
-rw-r--r--spec/ruby/core/method/unbind_spec.rb31
-rw-r--r--spec/ruby/core/module/alias_method_spec.rb78
-rw-r--r--spec/ruby/core/module/allocate_spec.rb14
-rw-r--r--spec/ruby/core/module/ancestors_spec.rb40
-rw-r--r--spec/ruby/core/module/append_features_spec.rb34
-rw-r--r--spec/ruby/core/module/attr_accessor_spec.rb53
-rw-r--r--spec/ruby/core/module/attr_reader_spec.rb26
-rw-r--r--spec/ruby/core/module/attr_spec.rb39
-rw-r--r--spec/ruby/core/module/attr_writer_spec.rb36
-rw-r--r--spec/ruby/core/module/autoload_relative_spec.rb128
-rw-r--r--spec/ruby/core/module/autoload_spec.rb435
-rw-r--r--spec/ruby/core/module/class_variable_defined_spec.rb22
-rw-r--r--spec/ruby/core/module/class_variable_get_spec.rb20
-rw-r--r--spec/ruby/core/module/class_variable_set_spec.rb24
-rw-r--r--spec/ruby/core/module/class_variables_spec.rb16
-rw-r--r--spec/ruby/core/module/comparison_spec.rb2
-rw-r--r--spec/ruby/core/module/const_added_spec.rb238
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb85
-rw-r--r--spec/ruby/core/module/const_get_spec.rb102
-rw-r--r--spec/ruby/core/module/const_missing_spec.rb4
-rw-r--r--spec/ruby/core/module/const_set_spec.rb87
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb281
-rw-r--r--spec/ruby/core/module/constants_spec.rb25
-rw-r--r--spec/ruby/core/module/define_method_spec.rb334
-rw-r--r--spec/ruby/core/module/define_singleton_method_spec.rb4
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb42
-rw-r--r--spec/ruby/core/module/extend_object_spec.rb24
-rw-r--r--spec/ruby/core/module/extended_spec.rb2
-rw-r--r--spec/ruby/core/module/fixtures/autoload_const_source_location.rb6
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb6
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb5
-rw-r--r--spec/ruby/core/module/fixtures/autoload_location.rb3
-rw-r--r--spec/ruby/core/module/fixtures/autoload_overridden.rb3
-rw-r--r--spec/ruby/core/module/fixtures/autoload_relative_a.rb9
-rw-r--r--spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb2
-rw-r--r--spec/ruby/core/module/fixtures/autoload_self_during_require.rb5
-rw-r--r--spec/ruby/core/module/fixtures/autoload_subclass.rb4
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb50
-rw-r--r--spec/ruby/core/module/fixtures/const_added.rb4
-rw-r--r--spec/ruby/core/module/fixtures/module.rb4
-rw-r--r--spec/ruby/core/module/fixtures/multi/foo.rb6
-rw-r--r--spec/ruby/core/module/fixtures/multi/foo/bar_baz.rb11
-rw-r--r--spec/ruby/core/module/fixtures/name.rb3
-rw-r--r--spec/ruby/core/module/fixtures/refine.rb12
-rw-r--r--spec/ruby/core/module/fixtures/set_temporary_name.rb4
-rw-r--r--spec/ruby/core/module/gt_spec.rb10
-rw-r--r--spec/ruby/core/module/gte_spec.rb2
-rw-r--r--spec/ruby/core/module/include_spec.rb432
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb8
-rw-r--r--spec/ruby/core/module/included_spec.rb4
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb55
-rw-r--r--spec/ruby/core/module/instance_methods_spec.rb30
-rw-r--r--spec/ruby/core/module/lt_spec.rb10
-rw-r--r--spec/ruby/core/module/lte_spec.rb2
-rw-r--r--spec/ruby/core/module/method_added_spec.rb96
-rw-r--r--spec/ruby/core/module/method_defined_spec.rb57
-rw-r--r--spec/ruby/core/module/method_removed_spec.rb2
-rw-r--r--spec/ruby/core/module/method_undefined_spec.rb2
-rw-r--r--spec/ruby/core/module/module_function_spec.rb181
-rw-r--r--spec/ruby/core/module/name_spec.rb149
-rw-r--r--spec/ruby/core/module/new_spec.rb4
-rw-r--r--spec/ruby/core/module/prepend_features_spec.rb24
-rw-r--r--spec/ruby/core/module/prepend_spec.rb524
-rw-r--r--spec/ruby/core/module/prepended_spec.rb2
-rw-r--r--spec/ruby/core/module/private_class_method_spec.rb36
-rw-r--r--spec/ruby/core/module/private_constant_spec.rb10
-rw-r--r--spec/ruby/core/module/private_instance_methods_spec.rb18
-rw-r--r--spec/ruby/core/module/private_method_defined_spec.rb70
-rw-r--r--spec/ruby/core/module/private_spec.rb78
-rw-r--r--spec/ruby/core/module/protected_instance_methods_spec.rb12
-rw-r--r--spec/ruby/core/module/protected_method_defined_spec.rb70
-rw-r--r--spec/ruby/core/module/protected_spec.rb22
-rw-r--r--spec/ruby/core/module/public_class_method_spec.rb34
-rw-r--r--spec/ruby/core/module/public_constant_spec.rb4
-rw-r--r--spec/ruby/core/module/public_instance_method_spec.rb28
-rw-r--r--spec/ruby/core/module/public_instance_methods_spec.rb14
-rw-r--r--spec/ruby/core/module/public_method_defined_spec.rb22
-rw-r--r--spec/ruby/core/module/public_spec.rb21
-rw-r--r--spec/ruby/core/module/refine_spec.rb458
-rw-r--r--spec/ruby/core/module/refinements_spec.rb43
-rw-r--r--spec/ruby/core/module/remove_class_variable_spec.rb12
-rw-r--r--spec/ruby/core/module/remove_const_spec.rb55
-rw-r--r--spec/ruby/core/module/remove_method_spec.rb63
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb248
-rw-r--r--spec/ruby/core/module/set_temporary_name_spec.rb145
-rw-r--r--spec/ruby/core/module/shared/attr_added.rb34
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb77
-rw-r--r--spec/ruby/core/module/shared/class_exec.rb12
-rw-r--r--spec/ruby/core/module/shared/set_visibility.rb75
-rw-r--r--spec/ruby/core/module/singleton_class_spec.rb10
-rw-r--r--spec/ruby/core/module/to_s_spec.rb56
-rw-r--r--spec/ruby/core/module/undef_method_spec.rb70
-rw-r--r--spec/ruby/core/module/undefined_instance_methods_spec.rb25
-rw-r--r--spec/ruby/core/module/used_refinements_spec.rb85
-rw-r--r--spec/ruby/core/module/using_spec.rb112
-rw-r--r--spec/ruby/core/mutex/lock_spec.rb89
-rw-r--r--spec/ruby/core/mutex/locked_spec.rb8
-rw-r--r--spec/ruby/core/mutex/owned_spec.rb16
-rw-r--r--spec/ruby/core/mutex/sleep_spec.rb50
-rw-r--r--spec/ruby/core/mutex/synchronize_spec.rb47
-rw-r--r--spec/ruby/core/mutex/try_lock_spec.rb8
-rw-r--r--spec/ruby/core/mutex/unlock_spec.rb8
-rw-r--r--spec/ruby/core/nil/case_compare_spec.rb13
-rw-r--r--spec/ruby/core/nil/dup_spec.rb8
-rw-r--r--spec/ruby/core/nil/match_spec.rb21
-rw-r--r--spec/ruby/core/nil/nil_spec.rb2
-rw-r--r--spec/ruby/core/nil/nilclass_spec.rb8
-rw-r--r--spec/ruby/core/nil/rationalize_spec.rb4
-rw-r--r--spec/ruby/core/nil/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/nil/to_c_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_i_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb8
-rw-r--r--spec/ruby/core/numeric/abs2_spec.rb4
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb30
-rw-r--r--spec/ruby/core/numeric/coerce_spec.rb12
-rw-r--r--spec/ruby/core/numeric/comparison_spec.rb8
-rw-r--r--spec/ruby/core/numeric/div_spec.rb6
-rw-r--r--spec/ruby/core/numeric/dup_spec.rb16
-rw-r--r--spec/ruby/core/numeric/eql_spec.rb12
-rw-r--r--spec/ruby/core/numeric/fdiv_spec.rb5
-rw-r--r--spec/ruby/core/numeric/finite_spec.rb10
-rw-r--r--spec/ruby/core/numeric/i_spec.rb2
-rw-r--r--spec/ruby/core/numeric/infinite_spec.rb10
-rw-r--r--spec/ruby/core/numeric/integer_spec.rb2
-rw-r--r--spec/ruby/core/numeric/magnitude_spec.rb1
-rw-r--r--spec/ruby/core/numeric/negative_spec.rb16
-rw-r--r--spec/ruby/core/numeric/polar_spec.rb6
-rw-r--r--spec/ruby/core/numeric/positive_spec.rb16
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb34
-rw-r--r--spec/ruby/core/numeric/real_spec.rb6
-rw-r--r--spec/ruby/core/numeric/remainder_spec.rb7
-rw-r--r--spec/ruby/core/numeric/shared/conj.rb2
-rw-r--r--spec/ruby/core/numeric/shared/imag.rb6
-rw-r--r--spec/ruby/core/numeric/shared/quo.rb7
-rw-r--r--spec/ruby/core/numeric/shared/rect.rb28
-rw-r--r--spec/ruby/core/numeric/shared/step.rb320
-rw-r--r--spec/ruby/core/numeric/singleton_method_added_spec.rb16
-rw-r--r--spec/ruby/core/numeric/step_spec.rb113
-rw-r--r--spec/ruby/core/numeric/to_c_spec.rb4
-rw-r--r--spec/ruby/core/numeric/zero_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/_id2ref_spec.rb74
-rw-r--r--spec/ruby/core/objectspace/add_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/call_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb242
-rw-r--r--spec/ruby/core/objectspace/each_object_spec.rb47
-rw-r--r--spec/ruby/core/objectspace/finalizers_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/objectspace/garbage_collect_spec.rb8
-rw-r--r--spec/ruby/core/objectspace/remove_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/undefine_finalizer_spec.rb30
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/clear_spec.rb25
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/delete_spec.rb49
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb105
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb80
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb26
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb19
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/key_spec.rb42
-rw-r--r--spec/ruby/core/objectspace/weakmap/delete_spec.rb28
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_key_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_pair_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_value_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_reference_spec.rb24
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_set_spec.rb38
-rw-r--r--spec/ruby/core/objectspace/weakmap/include_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/inspect_spec.rb25
-rw-r--r--spec/ruby/core/objectspace/weakmap/key_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/keys_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/length_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/member_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/each.rb10
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/include.rb30
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/members.rb14
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/size.rb14
-rw-r--r--spec/ruby/core/objectspace/weakmap/size_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/values_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap_spec.rb12
-rw-r--r--spec/ruby/core/proc/allocate_spec.rb4
-rw-r--r--spec/ruby/core/proc/arity_spec.rb16
-rw-r--r--spec/ruby/core/proc/binding_spec.rb6
-rw-r--r--spec/ruby/core/proc/block_pass_spec.rb24
-rw-r--r--spec/ruby/core/proc/clone_spec.rb22
-rw-r--r--spec/ruby/core/proc/compose_spec.rb142
-rw-r--r--spec/ruby/core/proc/curry_spec.rb85
-rw-r--r--spec/ruby/core/proc/dup_spec.rb20
-rw-r--r--spec/ruby/core/proc/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/proc/eql_spec.rb2
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/proc/fixtures/common.rb23
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref.rb1
-rw-r--r--spec/ruby/core/proc/fixtures/source_location.rb8
-rw-r--r--spec/ruby/core/proc/hash_spec.rb6
-rw-r--r--spec/ruby/core/proc/lambda_spec.rb43
-rw-r--r--spec/ruby/core/proc/new_spec.rb42
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb134
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb66
-rw-r--r--spec/ruby/core/proc/shared/call.rb39
-rw-r--r--spec/ruby/core/proc/shared/call_arguments.rb24
-rw-r--r--spec/ruby/core/proc/shared/compose.rb22
-rw-r--r--spec/ruby/core/proc/shared/dup.rb33
-rw-r--r--spec/ruby/core/proc/shared/equal.rb75
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb47
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb41
-rw-r--r--spec/ruby/core/proc/to_proc_spec.rb4
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/argv0_spec.rb23
-rw-r--r--spec/ruby/core/process/clock_getres_spec.rb33
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb152
-rw-r--r--spec/ruby/core/process/constants_spec.rb153
-rw-r--r--spec/ruby/core/process/daemon_spec.rb15
-rw-r--r--spec/ruby/core/process/detach_spec.rb41
-rw-r--r--spec/ruby/core/process/egid_spec.rb43
-rw-r--r--spec/ruby/core/process/euid_spec.rb43
-rw-r--r--spec/ruby/core/process/exec_spec.rb107
-rw-r--r--spec/ruby/core/process/exit_spec.rb2
-rw-r--r--spec/ruby/core/process/fixtures/argv0.rb6
-rw-r--r--spec/ruby/core/process/fixtures/clocks.rb18
-rw-r--r--spec/ruby/core/process/fixtures/common.rb8
-rw-r--r--spec/ruby/core/process/fixtures/in.txt1
-rw-r--r--spec/ruby/core/process/fixtures/kill.rb2
-rw-r--r--spec/ruby/core/process/getpriority_spec.rb8
-rw-r--r--spec/ruby/core/process/getrlimit_spec.rb37
-rw-r--r--spec/ruby/core/process/gid_spec.rb4
-rw-r--r--spec/ruby/core/process/groups_spec.rb12
-rw-r--r--spec/ruby/core/process/initgroups_spec.rb4
-rw-r--r--spec/ruby/core/process/kill_spec.rb18
-rw-r--r--spec/ruby/core/process/last_status_spec.rb26
-rw-r--r--spec/ruby/core/process/maxgroups_spec.rb2
-rw-r--r--spec/ruby/core/process/pid_spec.rb2
-rw-r--r--spec/ruby/core/process/ppid_spec.rb18
-rw-r--r--spec/ruby/core/process/set_proctitle_spec.rb2
-rw-r--r--spec/ruby/core/process/setpgid_spec.rb3
-rw-r--r--spec/ruby/core/process/setpriority_spec.rb31
-rw-r--r--spec/ruby/core/process/setrlimit_spec.rb117
-rw-r--r--spec/ruby/core/process/setsid_spec.rb37
-rw-r--r--spec/ruby/core/process/spawn_spec.rb460
-rw-r--r--spec/ruby/core/process/status/bit_and_spec.rb37
-rw-r--r--spec/ruby/core/process/status/equal_value_spec.rb12
-rw-r--r--spec/ruby/core/process/status/exited_spec.rb13
-rw-r--r--spec/ruby/core/process/status/exitstatus_spec.rb4
-rw-r--r--spec/ruby/core/process/status/right_shift_spec.rb36
-rw-r--r--spec/ruby/core/process/status/signaled_spec.rb12
-rw-r--r--spec/ruby/core/process/status/success_spec.rb22
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb18
-rw-r--r--spec/ruby/core/process/status/to_i_spec.rb10
-rw-r--r--spec/ruby/core/process/status/wait_spec.rb100
-rw-r--r--spec/ruby/core/process/times_spec.rb28
-rw-r--r--spec/ruby/core/process/tms/cstime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/cutime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/element_reference_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/members_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/new_spec.rb5
-rw-r--r--spec/ruby/core/process/tms/stime_spec.rb12
-rw-r--r--spec/ruby/core/process/tms/utime_spec.rb12
-rw-r--r--spec/ruby/core/process/uid_spec.rb61
-rw-r--r--spec/ruby/core/process/wait2_spec.rb25
-rw-r--r--spec/ruby/core/process/wait_spec.rb25
-rw-r--r--spec/ruby/core/process/waitall_spec.rb10
-rw-r--r--spec/ruby/core/process/waitpid_spec.rb5
-rw-r--r--spec/ruby/core/process/warmup_spec.rb9
-rw-r--r--spec/ruby/core/queue/append_spec.rb6
-rw-r--r--spec/ruby/core/queue/clear_spec.rb6
-rw-r--r--spec/ruby/core/queue/close_spec.rb6
-rw-r--r--spec/ruby/core/queue/closed_spec.rb6
-rw-r--r--spec/ruby/core/queue/deq_spec.rb11
-rw-r--r--spec/ruby/core/queue/empty_spec.rb6
-rw-r--r--spec/ruby/core/queue/enq_spec.rb6
-rw-r--r--spec/ruby/core/queue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/queue/initialize_spec.rb60
-rw-r--r--spec/ruby/core/queue/length_spec.rb6
-rw-r--r--spec/ruby/core/queue/num_waiting_spec.rb6
-rw-r--r--spec/ruby/core/queue/pop_spec.rb11
-rw-r--r--spec/ruby/core/queue/push_spec.rb6
-rw-r--r--spec/ruby/core/queue/shift_spec.rb11
-rw-r--r--spec/ruby/core/queue/size_spec.rb6
-rw-r--r--spec/ruby/core/random/bytes_spec.rb11
-rw-r--r--spec/ruby/core/random/default_spec.rb4
-rw-r--r--spec/ruby/core/random/fixtures/classes.rb15
-rw-r--r--spec/ruby/core/random/new_seed_spec.rb4
-rw-r--r--spec/ruby/core/random/new_spec.rb11
-rw-r--r--spec/ruby/core/random/rand_spec.rb62
-rw-r--r--spec/ruby/core/random/random_number_spec.rb8
-rw-r--r--spec/ruby/core/random/raw_seed_spec.rb9
-rw-r--r--spec/ruby/core/random/seed_spec.rb2
-rw-r--r--spec/ruby/core/random/shared/bytes.rb10
-rw-r--r--spec/ruby/core/random/shared/rand.rb9
-rw-r--r--spec/ruby/core/random/shared/urandom.rb23
-rw-r--r--spec/ruby/core/random/urandom_spec.rb26
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb377
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb19
-rw-r--r--spec/ruby/core/range/clone_spec.rb26
-rw-r--r--spec/ruby/core/range/count_spec.rb12
-rw-r--r--spec/ruby/core/range/cover_spec.rb7
-rw-r--r--spec/ruby/core/range/dup_spec.rb14
-rw-r--r--spec/ruby/core/range/each_spec.rb49
-rw-r--r--spec/ruby/core/range/eql_spec.rb2
-rw-r--r--spec/ruby/core/range/equal_value_spec.rb8
-rw-r--r--spec/ruby/core/range/exclude_end_spec.rb20
-rw-r--r--spec/ruby/core/range/first_spec.rb12
-rw-r--r--spec/ruby/core/range/fixtures/classes.rb22
-rw-r--r--spec/ruby/core/range/frozen_spec.rb25
-rw-r--r--spec/ruby/core/range/hash_spec.rb10
-rw-r--r--spec/ruby/core/range/include_spec.rb6
-rw-r--r--spec/ruby/core/range/initialize_spec.rb22
-rw-r--r--spec/ruby/core/range/inspect_spec.rb19
-rw-r--r--spec/ruby/core/range/last_spec.rb16
-rw-r--r--spec/ruby/core/range/max_spec.rb57
-rw-r--r--spec/ruby/core/range/member_spec.rb2
-rw-r--r--spec/ruby/core/range/min_spec.rb35
-rw-r--r--spec/ruby/core/range/minmax_spec.rb130
-rw-r--r--spec/ruby/core/range/new_spec.rb50
-rw-r--r--spec/ruby/core/range/overlap_spec.rb87
-rw-r--r--spec/ruby/core/range/percent_spec.rb16
-rw-r--r--spec/ruby/core/range/reverse_each_spec.rb125
-rw-r--r--spec/ruby/core/range/shared/cover.rb146
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb54
-rw-r--r--spec/ruby/core/range/shared/equal_value.rb6
-rw-r--r--spec/ruby/core/range/shared/include.rb34
-rw-r--r--spec/ruby/core/range/size_spec.rb85
-rw-r--r--spec/ruby/core/range/step_spec.rb611
-rw-r--r--spec/ruby/core/range/to_a_spec.rb19
-rw-r--r--spec/ruby/core/range/to_s_spec.rb14
-rw-r--r--spec/ruby/core/range/to_set_spec.rb54
-rw-r--r--spec/ruby/core/rational/abs_spec.rb3
-rw-r--r--spec/ruby/core/rational/ceil_spec.rb47
-rw-r--r--spec/ruby/core/rational/coerce_spec.rb5
-rw-r--r--spec/ruby/core/rational/comparison_spec.rb87
-rw-r--r--spec/ruby/core/rational/denominator_spec.rb13
-rw-r--r--spec/ruby/core/rational/div_spec.rb47
-rw-r--r--spec/ruby/core/rational/divide_spec.rb67
-rw-r--r--spec/ruby/core/rational/divmod_spec.rb37
-rw-r--r--spec/ruby/core/rational/equal_value_spec.rb32
-rw-r--r--spec/ruby/core/rational/exponent_spec.rb235
-rw-r--r--spec/ruby/core/rational/fdiv_spec.rb4
-rw-r--r--spec/ruby/core/rational/fixtures/rational.rb (renamed from spec/ruby/fixtures/rational.rb)0
-rw-r--r--spec/ruby/core/rational/floor_spec.rb48
-rw-r--r--spec/ruby/core/rational/hash_spec.rb8
-rw-r--r--spec/ruby/core/rational/inspect_spec.rb13
-rw-r--r--spec/ruby/core/rational/integer_spec.rb5
-rw-r--r--spec/ruby/core/rational/magnitude_spec.rb3
-rw-r--r--spec/ruby/core/rational/marshal_dump_spec.rb2
-rw-r--r--spec/ruby/core/rational/minus_spec.rb50
-rw-r--r--spec/ruby/core/rational/modulo_spec.rb42
-rw-r--r--spec/ruby/core/rational/multiply_spec.rb58
-rw-r--r--spec/ruby/core/rational/numerator_spec.rb9
-rw-r--r--spec/ruby/core/rational/plus_spec.rb44
-rw-r--r--spec/ruby/core/rational/quo_spec.rb24
-rw-r--r--spec/ruby/core/rational/rational_spec.rb4
-rw-r--r--spec/ruby/core/rational/rationalize_spec.rb4
-rw-r--r--spec/ruby/core/rational/remainder_spec.rb4
-rw-r--r--spec/ruby/core/rational/round_spec.rb105
-rw-r--r--spec/ruby/core/rational/shared/abs.rb11
-rw-r--r--spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb11
-rw-r--r--spec/ruby/core/rational/to_f_spec.rb15
-rw-r--r--spec/ruby/core/rational/to_i_spec.rb11
-rw-r--r--spec/ruby/core/rational/to_r_spec.rb14
-rw-r--r--spec/ruby/core/rational/to_s_spec.rb13
-rw-r--r--spec/ruby/core/rational/truncate_spec.rb70
-rw-r--r--spec/ruby/core/rational/zero_spec.rb7
-rw-r--r--spec/ruby/core/refinement/append_features_spec.rb19
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb21
-rw-r--r--spec/ruby/core/refinement/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb287
-rw-r--r--spec/ruby/core/refinement/include_spec.rb13
-rw-r--r--spec/ruby/core/refinement/prepend_features_spec.rb19
-rw-r--r--spec/ruby/core/refinement/prepend_spec.rb13
-rw-r--r--spec/ruby/core/refinement/refined_class_spec.rb34
-rw-r--r--spec/ruby/core/refinement/shared/target.rb13
-rw-r--r--spec/ruby/core/refinement/target_spec.rb6
-rw-r--r--spec/ruby/core/regexp/case_compare_spec.rb24
-rw-r--r--spec/ruby/core/regexp/casefold_spec.rb4
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb17
-rw-r--r--spec/ruby/core/regexp/encoding_spec.rb10
-rw-r--r--spec/ruby/core/regexp/fixed_encoding_spec.rb16
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb24
-rw-r--r--spec/ruby/core/regexp/last_match_spec.rb46
-rw-r--r--spec/ruby/core/regexp/linear_time_spec.rb80
-rw-r--r--spec/ruby/core/regexp/match_spec.rb94
-rw-r--r--spec/ruby/core/regexp/named_captures_spec.rb4
-rw-r--r--spec/ruby/core/regexp/names_spec.rb4
-rw-r--r--spec/ruby/core/regexp/new_spec.rb25
-rw-r--r--spec/ruby/core/regexp/options_spec.rb8
-rw-r--r--spec/ruby/core/regexp/shared/new.rb321
-rw-r--r--spec/ruby/core/regexp/shared/new_ascii.rb464
-rw-r--r--spec/ruby/core/regexp/shared/new_ascii_8bit.rb553
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb30
-rw-r--r--spec/ruby/core/regexp/source_spec.rb26
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb33
-rw-r--r--spec/ruby/core/regexp/try_convert_spec.rb8
-rw-r--r--spec/ruby/core/regexp/union_spec.rb87
-rw-r--r--spec/ruby/core/set/add_spec.rb34
-rw-r--r--spec/ruby/core/set/append_spec.rb6
-rw-r--r--spec/ruby/core/set/case_compare_spec.rb11
-rw-r--r--spec/ruby/core/set/case_equality_spec.rb6
-rw-r--r--spec/ruby/core/set/classify_spec.rb26
-rw-r--r--spec/ruby/core/set/clear_spec.rb16
-rw-r--r--spec/ruby/core/set/collect_spec.rb6
-rw-r--r--spec/ruby/core/set/compare_by_identity_spec.rb153
-rw-r--r--spec/ruby/core/set/comparison_spec.rb26
-rw-r--r--spec/ruby/core/set/constructor_spec.rb14
-rw-r--r--spec/ruby/core/set/delete_if_spec.rb37
-rw-r--r--spec/ruby/core/set/delete_spec.rb36
-rw-r--r--spec/ruby/core/set/difference_spec.rb6
-rw-r--r--spec/ruby/core/set/disjoint_spec.rb22
-rw-r--r--spec/ruby/core/set/divide_spec.rb68
-rw-r--r--spec/ruby/core/set/each_spec.rb26
-rw-r--r--spec/ruby/core/set/empty_spec.rb9
-rw-r--r--spec/ruby/core/set/enumerable/to_set_spec.rb12
-rw-r--r--spec/ruby/core/set/eql_spec.rb14
-rw-r--r--spec/ruby/core/set/equal_value_spec.rb34
-rw-r--r--spec/ruby/core/set/exclusion_spec.rb17
-rw-r--r--spec/ruby/core/set/filter_spec.rb6
-rw-r--r--spec/ruby/core/set/fixtures/set_like.rb30
-rw-r--r--spec/ruby/core/set/flatten_merge_spec.rb24
-rw-r--r--spec/ruby/core/set/flatten_spec.rb49
-rw-r--r--spec/ruby/core/set/hash_spec.rb19
-rw-r--r--spec/ruby/core/set/include_spec.rb6
-rw-r--r--spec/ruby/core/set/initialize_clone_spec.rb15
-rw-r--r--spec/ruby/core/set/initialize_spec.rb88
-rw-r--r--spec/ruby/core/set/inspect_spec.rb6
-rw-r--r--spec/ruby/core/set/intersect_spec.rb22
-rw-r--r--spec/ruby/core/set/intersection_spec.rb10
-rw-r--r--spec/ruby/core/set/join_spec.rb30
-rw-r--r--spec/ruby/core/set/keep_if_spec.rb37
-rw-r--r--spec/ruby/core/set/length_spec.rb6
-rw-r--r--spec/ruby/core/set/map_spec.rb6
-rw-r--r--spec/ruby/core/set/member_spec.rb6
-rw-r--r--spec/ruby/core/set/merge_spec.rb29
-rw-r--r--spec/ruby/core/set/minus_spec.rb6
-rw-r--r--spec/ruby/core/set/plus_spec.rb6
-rw-r--r--spec/ruby/core/set/pretty_print_cycle_spec.rb14
-rw-r--r--spec/ruby/core/set/proper_subset_spec.rb35
-rw-r--r--spec/ruby/core/set/proper_superset_spec.rb42
-rw-r--r--spec/ruby/core/set/reject_spec.rb41
-rw-r--r--spec/ruby/core/set/replace_spec.rb24
-rw-r--r--spec/ruby/core/set/select_spec.rb (renamed from spec/ruby/library/set/select_spec.rb)0
-rw-r--r--spec/ruby/core/set/set_spec.rb10
-rw-r--r--spec/ruby/core/set/shared/add.rb14
-rw-r--r--spec/ruby/core/set/shared/collect.rb20
-rw-r--r--spec/ruby/core/set/shared/difference.rb15
-rw-r--r--spec/ruby/core/set/shared/include.rb29
-rw-r--r--spec/ruby/core/set/shared/inspect.rb45
-rw-r--r--spec/ruby/core/set/shared/intersection.rb15
-rw-r--r--spec/ruby/core/set/shared/length.rb (renamed from spec/ruby/library/set/shared/length.rb)0
-rw-r--r--spec/ruby/core/set/shared/select.rb41
-rw-r--r--spec/ruby/core/set/shared/union.rb15
-rw-r--r--spec/ruby/core/set/size_spec.rb6
-rw-r--r--spec/ruby/core/set/sortedset/sortedset_spec.rb13
-rw-r--r--spec/ruby/core/set/subset_spec.rb35
-rw-r--r--spec/ruby/core/set/subtract_spec.rb16
-rw-r--r--spec/ruby/core/set/superset_spec.rb42
-rw-r--r--spec/ruby/core/set/to_a_spec.rb7
-rw-r--r--spec/ruby/core/set/to_s_spec.rb11
-rw-r--r--spec/ruby/core/set/union_spec.rb10
-rw-r--r--spec/ruby/core/signal/fixtures/trap_all.rb15
-rw-r--r--spec/ruby/core/signal/list_spec.rb4
-rw-r--r--spec/ruby/core/signal/signame_spec.rb16
-rw-r--r--spec/ruby/core/signal/trap_spec.rb261
-rw-r--r--spec/ruby/core/sizedqueue/append_spec.rb16
-rw-r--r--spec/ruby/core/sizedqueue/clear_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/close_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/closed_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/deq_spec.rb11
-rw-r--r--spec/ruby/core/sizedqueue/empty_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/enq_spec.rb16
-rw-r--r--spec/ruby/core/sizedqueue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/length_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/max_spec.rb10
-rw-r--r--spec/ruby/core/sizedqueue/new_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/num_waiting_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/pop_spec.rb11
-rw-r--r--spec/ruby/core/sizedqueue/push_spec.rb16
-rw-r--r--spec/ruby/core/sizedqueue/shift_spec.rb11
-rw-r--r--spec/ruby/core/sizedqueue/size_spec.rb6
-rw-r--r--spec/ruby/core/string/allocate_spec.rb4
-rw-r--r--spec/ruby/core/string/append_as_bytes_spec.rb60
-rw-r--r--spec/ruby/core/string/append_spec.rb6
-rw-r--r--spec/ruby/core/string/ascii_only_spec.rb125
-rw-r--r--spec/ruby/core/string/b_spec.rb26
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb298
-rw-r--r--spec/ruby/core/string/byterindex_spec.rb353
-rw-r--r--spec/ruby/core/string/bytes_spec.rb34
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb48
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb22
-rw-r--r--spec/ruby/core/string/bytesplice_spec.rb290
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb258
-rw-r--r--spec/ruby/core/string/casecmp_spec.rb146
-rw-r--r--spec/ruby/core/string/center_spec.rb82
-rw-r--r--spec/ruby/core/string/chars_spec.rb8
-rw-r--r--spec/ruby/core/string/chilled_string_spec.rb151
-rw-r--r--spec/ruby/core/string/chomp_spec.rb201
-rw-r--r--spec/ruby/core/string/chop_spec.rb73
-rw-r--r--spec/ruby/core/string/chr_spec.rb78
-rw-r--r--spec/ruby/core/string/clear_spec.rb59
-rw-r--r--spec/ruby/core/string/clone_spec.rb8
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb22
-rw-r--r--spec/ruby/core/string/comparison_spec.rb14
-rw-r--r--spec/ruby/core/string/concat_spec.rb31
-rw-r--r--spec/ruby/core/string/count_spec.rb14
-rw-r--r--spec/ruby/core/string/crypt_spec.rb131
-rw-r--r--spec/ruby/core/string/dedup_spec.rb6
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb126
-rw-r--r--spec/ruby/core/string/delete_spec.rb38
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb126
-rw-r--r--spec/ruby/core/string/downcase_spec.rb253
-rw-r--r--spec/ruby/core/string/dump_spec.rb129
-rw-r--r--spec/ruby/core/string/dup_spec.rb19
-rw-r--r--spec/ruby/core/string/each_byte_spec.rb20
-rw-r--r--spec/ruby/core/string/each_char_spec.rb1
-rw-r--r--spec/ruby/core/string/each_codepoint_spec.rb8
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb15
-rw-r--r--spec/ruby/core/string/element_set_spec.rb455
-rw-r--r--spec/ruby/core/string/empty_spec.rb10
-rw-r--r--spec/ruby/core/string/encode_spec.rb303
-rw-r--r--spec/ruby/core/string/encoding_spec.rb361
-rw-r--r--spec/ruby/core/string/end_with_spec.rb46
-rw-r--r--spec/ruby/core/string/eql_spec.rb8
-rw-r--r--spec/ruby/core/string/fixtures/classes.rb11
-rw-r--r--spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb2
-rw-r--r--spec/ruby/core/string/fixtures/to_c.rb5
-rw-r--r--spec/ruby/core/string/fixtures/utf-8-encoding.rb7
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb107
-rw-r--r--spec/ruby/core/string/freeze_spec.rb5
-rw-r--r--spec/ruby/core/string/getbyte_spec.rb12
-rw-r--r--spec/ruby/core/string/grapheme_clusters_spec.rb15
-rw-r--r--spec/ruby/core/string/gsub_spec.rb247
-rw-r--r--spec/ruby/core/string/include_spec.rb24
-rw-r--r--spec/ruby/core/string/index_spec.rb97
-rw-r--r--spec/ruby/core/string/initialize_spec.rb4
-rw-r--r--spec/ruby/core/string/insert_spec.rb63
-rw-r--r--spec/ruby/core/string/inspect_spec.rb50
-rw-r--r--spec/ruby/core/string/lines_spec.rb11
-rw-r--r--spec/ruby/core/string/ljust_spec.rb80
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb66
-rw-r--r--spec/ruby/core/string/match_spec.rb76
-rw-r--r--spec/ruby/core/string/modulo_spec.rb272
-rw-r--r--spec/ruby/core/string/multiply_spec.rb2
-rw-r--r--spec/ruby/core/string/new_spec.rb18
-rw-r--r--spec/ruby/core/string/ord_spec.rb43
-rw-r--r--spec/ruby/core/string/partition_spec.rb29
-rw-r--r--spec/ruby/core/string/percent_spec.rb13
-rw-r--r--spec/ruby/core/string/plus_spec.rb34
-rw-r--r--spec/ruby/core/string/prepend_spec.rb49
-rw-r--r--spec/ruby/core/string/reverse_spec.rb56
-rw-r--r--spec/ruby/core/string/rindex_spec.rb60
-rw-r--r--spec/ruby/core/string/rjust_spec.rb80
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb42
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb52
-rw-r--r--spec/ruby/core/string/scan_spec.rb75
-rw-r--r--spec/ruby/core/string/scrub_spec.rb73
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb27
-rw-r--r--spec/ruby/core/string/shared/byte_index_common.rb63
-rw-r--r--spec/ruby/core/string/shared/chars.rb106
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb39
-rw-r--r--spec/ruby/core/string/shared/concat.rb91
-rw-r--r--spec/ruby/core/string/shared/dedup.rb51
-rw-r--r--spec/ruby/core/string/shared/each_char_without_block.rb2
-rw-r--r--spec/ruby/core/string/shared/each_codepoint_without_block.rb14
-rw-r--r--spec/ruby/core/string/shared/each_line.rb129
-rw-r--r--spec/ruby/core/string/shared/each_line_without_block.rb2
-rw-r--r--spec/ruby/core/string/shared/encode.rb259
-rw-r--r--spec/ruby/core/string/shared/eql.rb22
-rw-r--r--spec/ruby/core/string/shared/equal_value.rb12
-rw-r--r--spec/ruby/core/string/shared/grapheme_clusters.rb11
-rw-r--r--spec/ruby/core/string/shared/length.rb55
-rw-r--r--spec/ruby/core/string/shared/partition.rb33
-rw-r--r--spec/ruby/core/string/shared/replace.rb47
-rw-r--r--spec/ruby/core/string/shared/slice.rb264
-rw-r--r--spec/ruby/core/string/shared/strip.rb14
-rw-r--r--spec/ruby/core/string/shared/succ.rb25
-rw-r--r--spec/ruby/core/string/shared/to_a.rb9
-rw-r--r--spec/ruby/core/string/shared/to_s.rb9
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb45
-rw-r--r--spec/ruby/core/string/slice_spec.rb240
-rw-r--r--spec/ruby/core/string/split_spec.rb345
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb42
-rw-r--r--spec/ruby/core/string/start_with_spec.rb74
-rw-r--r--spec/ruby/core/string/strip_spec.rb44
-rw-r--r--spec/ruby/core/string/sub_spec.rb193
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb236
-rw-r--r--spec/ruby/core/string/to_c_spec.rb116
-rw-r--r--spec/ruby/core/string/to_f_spec.rb103
-rw-r--r--spec/ruby/core/string/to_i_spec.rb36
-rw-r--r--spec/ruby/core/string/to_r_spec.rb8
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb101
-rw-r--r--spec/ruby/core/string/tr_spec.rb77
-rw-r--r--spec/ruby/core/string/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/string/uminus_spec.rb55
-rw-r--r--spec/ruby/core/string/undump_spec.rb824
-rw-r--r--spec/ruby/core/string/unicode_normalize_spec.rb17
-rw-r--r--spec/ruby/core/string/unicode_normalized_spec.rb29
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/at_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb22
-rw-r--r--spec/ruby/core/string/unpack/c_spec.rb10
-rw-r--r--spec/ruby/core/string/unpack/carret_spec.rb43
-rw-r--r--spec/ruby/core/string/unpack/comment_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb22
-rw-r--r--spec/ruby/core/string/unpack/l_spec.rb16
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb21
-rw-r--r--spec/ruby/core/string/unpack/p_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/percent_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/r_spec.rb85
-rw-r--r--spec/ruby/core/string/unpack/shared/basic.rb18
-rw-r--r--spec/ruby/core/string/unpack/shared/float.rb36
-rw-r--r--spec/ruby/core/string/unpack/shared/integer.rb40
-rw-r--r--spec/ruby/core/string/unpack/shared/taint.rb79
-rw-r--r--spec/ruby/core/string/unpack/shared/unicode.rb6
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb18
-rw-r--r--spec/ruby/core/string/unpack/x_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb7
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb63
-rw-r--r--spec/ruby/core/string/unpack_spec.rb46
-rw-r--r--spec/ruby/core/string/upcase_spec.rb235
-rw-r--r--spec/ruby/core/string/uplus_spec.rb50
-rw-r--r--spec/ruby/core/string/upto_spec.rb22
-rw-r--r--spec/ruby/core/string/valid_encoding/utf_8_spec.rb214
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb242
-rw-r--r--spec/ruby/core/struct/clone_spec.rb7
-rw-r--r--spec/ruby/core/struct/constants_spec.rb13
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb130
-rw-r--r--spec/ruby/core/struct/deconstruct_spec.rb10
-rw-r--r--spec/ruby/core/struct/dig_spec.rb16
-rw-r--r--spec/ruby/core/struct/dup_spec.rb3
-rw-r--r--spec/ruby/core/struct/each_pair_spec.rb4
-rw-r--r--spec/ruby/core/struct/each_spec.rb2
-rw-r--r--spec/ruby/core/struct/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/struct/element_set_spec.rb15
-rw-r--r--spec/ruby/core/struct/eql_spec.rb2
-rw-r--r--spec/ruby/core/struct/filter_spec.rb10
-rw-r--r--spec/ruby/core/struct/fixtures/classes.rb9
-rw-r--r--spec/ruby/core/struct/hash_spec.rb24
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb33
-rw-r--r--spec/ruby/core/struct/inspect_spec.rb8
-rw-r--r--spec/ruby/core/struct/instance_variable_get_spec.rb16
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb45
-rw-r--r--spec/ruby/core/struct/members_spec.rb12
-rw-r--r--spec/ruby/core/struct/new_spec.rb202
-rw-r--r--spec/ruby/core/struct/shared/dup.rb9
-rw-r--r--spec/ruby/core/struct/shared/inspect.rb35
-rw-r--r--spec/ruby/core/struct/shared/select.rb6
-rw-r--r--spec/ruby/core/struct/struct_spec.rb9
-rw-r--r--spec/ruby/core/struct/to_h_spec.rb51
-rw-r--r--spec/ruby/core/struct/values_at_spec.rb55
-rw-r--r--spec/ruby/core/symbol/all_symbols_spec.rb15
-rw-r--r--spec/ruby/core/symbol/capitalize_spec.rb23
-rw-r--r--spec/ruby/core/symbol/casecmp_spec.rb152
-rw-r--r--spec/ruby/core/symbol/comparison_spec.rb8
-rw-r--r--spec/ruby/core/symbol/downcase_spec.rb16
-rw-r--r--spec/ruby/core/symbol/dup_spec.rb8
-rw-r--r--spec/ruby/core/symbol/empty_spec.rb4
-rw-r--r--spec/ruby/core/symbol/end_with_spec.rb8
-rw-r--r--spec/ruby/core/symbol/inspect_spec.rb34
-rw-r--r--spec/ruby/core/symbol/intern_spec.rb2
-rw-r--r--spec/ruby/core/symbol/match_spec.rb75
-rw-r--r--spec/ruby/core/symbol/name_spec.rb17
-rw-r--r--spec/ruby/core/symbol/shared/id2name.rb21
-rw-r--r--spec/ruby/core/symbol/shared/slice.rb74
-rw-r--r--spec/ruby/core/symbol/start_with_spec.rb8
-rw-r--r--spec/ruby/core/symbol/swapcase_spec.rb20
-rw-r--r--spec/ruby/core/symbol/symbol_spec.rb8
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb59
-rw-r--r--spec/ruby/core/symbol/upcase_spec.rb16
-rw-r--r--spec/ruby/core/systemexit/success_spec.rb4
-rw-r--r--spec/ruby/core/thread/abort_on_exception_spec.rb12
-rw-r--r--spec/ruby/core/thread/alive_spec.rb20
-rw-r--r--spec/ruby/core/thread/allocate_spec.rb4
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb13
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb82
-rw-r--r--spec/ruby/core/thread/backtrace/location/base_label_spec.rb27
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/classes.rb122
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/locations_in_main.rb5
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/locations_in_required.rb3
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/main.rb4
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/path.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb11
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb1
-rw-r--r--spec/ruby/core/thread/backtrace/location/inspect_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/label_spec.rb215
-rw-r--r--spec/ruby/core/thread/backtrace/location/lineno_spec.rb12
-rw-r--r--spec/ruby/core/thread/backtrace/location/path_spec.rb37
-rw-r--r--spec/ruby/core/thread/backtrace/location/to_s_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb79
-rw-r--r--spec/ruby/core/thread/backtrace_spec.rb40
-rw-r--r--spec/ruby/core/thread/current_spec.rb10
-rw-r--r--spec/ruby/core/thread/each_caller_location_spec.rb47
-rw-r--r--spec/ruby/core/thread/element_reference_spec.rb15
-rw-r--r--spec/ruby/core/thread/element_set_spec.rb33
-rw-r--r--spec/ruby/core/thread/exclusive_spec.rb18
-rw-r--r--spec/ruby/core/thread/exit_spec.rb2
-rw-r--r--spec/ruby/core/thread/fetch_spec.rb94
-rw-r--r--spec/ruby/core/thread/fixtures/classes.rb37
-rw-r--r--spec/ruby/core/thread/group_spec.rb15
-rw-r--r--spec/ruby/core/thread/handle_interrupt_spec.rb125
-rw-r--r--spec/ruby/core/thread/ignore_deadlock_spec.rb19
-rw-r--r--spec/ruby/core/thread/initialize_spec.rb4
-rw-r--r--spec/ruby/core/thread/inspect_spec.rb42
-rw-r--r--spec/ruby/core/thread/join_spec.rb37
-rw-r--r--spec/ruby/core/thread/key_spec.rb23
-rw-r--r--spec/ruby/core/thread/keys_spec.rb12
-rw-r--r--spec/ruby/core/thread/kill_spec.rb6
-rw-r--r--spec/ruby/core/thread/list_spec.rb35
-rw-r--r--spec/ruby/core/thread/name_spec.rb4
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb31
-rw-r--r--spec/ruby/core/thread/new_spec.rb41
-rw-r--r--spec/ruby/core/thread/pending_interrupt_spec.rb32
-rw-r--r--spec/ruby/core/thread/priority_spec.rb8
-rw-r--r--spec/ruby/core/thread/raise_spec.rb114
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb227
-rw-r--r--spec/ruby/core/thread/shared/exit.rb65
-rw-r--r--spec/ruby/core/thread/shared/start.rb10
-rw-r--r--spec/ruby/core/thread/shared/to_s.rb53
-rw-r--r--spec/ruby/core/thread/shared/wakeup.rb5
-rw-r--r--spec/ruby/core/thread/stop_spec.rb20
-rw-r--r--spec/ruby/core/thread/thread_variable_get_spec.rb45
-rw-r--r--spec/ruby/core/thread/thread_variable_set_spec.rb44
-rw-r--r--spec/ruby/core/thread/thread_variable_spec.rb47
-rw-r--r--spec/ruby/core/thread/thread_variables_spec.rb25
-rw-r--r--spec/ruby/core/thread/to_s_spec.rb6
-rw-r--r--spec/ruby/core/thread/value_spec.rb12
-rw-r--r--spec/ruby/core/threadgroup/add_spec.rb9
-rw-r--r--spec/ruby/core/threadgroup/default_spec.rb2
-rw-r--r--spec/ruby/core/threadgroup/enclose_spec.rb13
-rw-r--r--spec/ruby/core/threadgroup/enclosed_spec.rb4
-rw-r--r--spec/ruby/core/threadgroup/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/threadgroup/list_spec.rb15
-rw-r--r--spec/ruby/core/time/_dump_spec.rb10
-rw-r--r--spec/ruby/core/time/_load_spec.rb15
-rw-r--r--spec/ruby/core/time/at_spec.rb225
-rw-r--r--spec/ruby/core/time/ceil_spec.rb44
-rw-r--r--spec/ruby/core/time/comparison_spec.rb28
-rw-r--r--spec/ruby/core/time/deconstruct_keys_spec.rb43
-rw-r--r--spec/ruby/core/time/dup_spec.rb18
-rw-r--r--spec/ruby/core/time/eql_spec.rb16
-rw-r--r--spec/ruby/core/time/fixtures/classes.rb85
-rw-r--r--spec/ruby/core/time/floor_spec.rb36
-rw-r--r--spec/ruby/core/time/friday_spec.rb4
-rw-r--r--spec/ruby/core/time/getlocal_spec.rb132
-rw-r--r--spec/ruby/core/time/gmt_spec.rb4
-rw-r--r--spec/ruby/core/time/hash_spec.rb4
-rw-r--r--spec/ruby/core/time/inspect_spec.rb27
-rw-r--r--spec/ruby/core/time/iso8601_spec.rb6
-rw-r--r--spec/ruby/core/time/localtime_spec.rb83
-rw-r--r--spec/ruby/core/time/minus_spec.rb38
-rw-r--r--spec/ruby/core/time/monday_spec.rb4
-rw-r--r--spec/ruby/core/time/new_spec.rb662
-rw-r--r--spec/ruby/core/time/now_spec.rb175
-rw-r--r--spec/ruby/core/time/nsec_spec.rb4
-rw-r--r--spec/ruby/core/time/plus_spec.rb45
-rw-r--r--spec/ruby/core/time/round_spec.rb4
-rw-r--r--spec/ruby/core/time/saturday_spec.rb4
-rw-r--r--spec/ruby/core/time/shared/gmt_offset.rb6
-rw-r--r--spec/ruby/core/time/shared/gmtime.rb17
-rw-r--r--spec/ruby/core/time/shared/inspect.rb6
-rw-r--r--spec/ruby/core/time/shared/local.rb11
-rw-r--r--spec/ruby/core/time/shared/now.rb19
-rw-r--r--spec/ruby/core/time/shared/time_params.rb63
-rw-r--r--spec/ruby/core/time/shared/to_i.rb7
-rw-r--r--spec/ruby/core/time/shared/xmlschema.rb31
-rw-r--r--spec/ruby/core/time/strftime_spec.rb49
-rw-r--r--spec/ruby/core/time/subsec_spec.rb14
-rw-r--r--spec/ruby/core/time/succ_spec.rb19
-rw-r--r--spec/ruby/core/time/sunday_spec.rb4
-rw-r--r--spec/ruby/core/time/thursday_spec.rb4
-rw-r--r--spec/ruby/core/time/to_r_spec.rb4
-rw-r--r--spec/ruby/core/time/tuesday_spec.rb4
-rw-r--r--spec/ruby/core/time/usec_spec.rb4
-rw-r--r--spec/ruby/core/time/utc_spec.rb47
-rw-r--r--spec/ruby/core/time/wednesday_spec.rb4
-rw-r--r--spec/ruby/core/time/xmlschema_spec.rb6
-rw-r--r--spec/ruby/core/time/yday_spec.rb13
-rw-r--r--spec/ruby/core/time/zone_spec.rb31
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb30
-rw-r--r--spec/ruby/core/tracepoint/binding_spec.rb4
-rw-r--r--spec/ruby/core/tracepoint/callee_id_spec.rb23
-rw-r--r--spec/ruby/core/tracepoint/defined_class_spec.rb11
-rw-r--r--spec/ruby/core/tracepoint/disable_spec.rb63
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb537
-rw-r--r--spec/ruby/core/tracepoint/enabled_spec.rb7
-rw-r--r--spec/ruby/core/tracepoint/eval_script_spec.rb23
-rw-r--r--spec/ruby/core/tracepoint/event_spec.rb7
-rw-r--r--spec/ruby/core/tracepoint/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb137
-rw-r--r--spec/ruby/core/tracepoint/lineno_spec.rb14
-rw-r--r--spec/ruby/core/tracepoint/method_id_spec.rb12
-rw-r--r--spec/ruby/core/tracepoint/new_spec.rb46
-rw-r--r--spec/ruby/core/tracepoint/parameters_spec.rb37
-rw-r--r--spec/ruby/core/tracepoint/path_spec.rb20
-rw-r--r--spec/ruby/core/tracepoint/raised_exception_spec.rb24
-rw-r--r--spec/ruby/core/tracepoint/return_value_spec.rb6
-rw-r--r--spec/ruby/core/tracepoint/self_spec.rb20
-rw-r--r--spec/ruby/core/tracepoint/trace_spec.rb5
-rw-r--r--spec/ruby/core/true/case_compare_spec.rb13
-rw-r--r--spec/ruby/core/true/dup_spec.rb8
-rw-r--r--spec/ruby/core/true/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/true/to_s_spec.rb8
-rw-r--r--spec/ruby/core/true/trueclass_spec.rb8
-rw-r--r--spec/ruby/core/unboundmethod/bind_call_spec.rb58
-rw-r--r--spec/ruby/core/unboundmethod/bind_spec.rb30
-rw-r--r--spec/ruby/core/unboundmethod/clone_spec.rb13
-rw-r--r--spec/ruby/core/unboundmethod/dup_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb86
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb38
-rw-r--r--spec/ruby/core/unboundmethod/hash_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/inspect_spec.rb2
-rw-r--r--spec/ruby/core/unboundmethod/original_name_spec.rb59
-rw-r--r--spec/ruby/core/unboundmethod/owner_spec.rb5
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/shared/dup.rb32
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb14
-rw-r--r--spec/ruby/core/unboundmethod/source_location_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/to_s_spec.rb2
-rw-r--r--spec/ruby/core/warning/categories_spec.rb12
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb27
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb39
-rw-r--r--spec/ruby/core/warning/performance_warning_spec.rb28
-rw-r--r--spec/ruby/core/warning/warn_spec.rb199
-rw-r--r--spec/ruby/default.mspec30
-rw-r--r--spec/ruby/fixtures/class.rb8
-rw-r--r--spec/ruby/fixtures/code/a/load_fixture.dylib1
-rw-r--r--spec/ruby/fixtures/code/c/load_fixture.rb1
-rw-r--r--spec/ruby/fixtures/code/concurrent.rb2
-rw-r--r--spec/ruby/fixtures/code/concurrent_require_fixture.rb4
-rw-r--r--spec/ruby/fixtures/code/d/load_fixture.rb.rb1
-rw-r--r--spec/ruby/fixtures/code/load_fixture.dylib1
-rw-r--r--spec/ruby/fixtures/code/load_fixture.ext.dylib1
-rw-r--r--spec/ruby/fixtures/code/load_wrap_fixture.rb12
-rw-r--r--spec/ruby/fixtures/code/wrap_fixture.rb3
-rw-r--r--spec/ruby/fixtures/code_loading.rb15
-rw-r--r--spec/ruby/fixtures/constants.rb42
-rw-r--r--spec/ruby/fixtures/io.rb12
-rw-r--r--spec/ruby/language/BEGIN_spec.rb7
-rw-r--r--spec/ruby/language/END_spec.rb33
-rw-r--r--spec/ruby/language/README2
-rw-r--r--spec/ruby/language/alias_spec.rb80
-rw-r--r--spec/ruby/language/and_spec.rb16
-rw-r--r--spec/ruby/language/array_spec.rb18
-rw-r--r--spec/ruby/language/assignments_spec.rb582
-rw-r--r--spec/ruby/language/block_spec.rb496
-rw-r--r--spec/ruby/language/break_spec.rb55
-rw-r--r--spec/ruby/language/case_spec.rb227
-rw-r--r--spec/ruby/language/class_spec.rb142
-rw-r--r--spec/ruby/language/class_variable_spec.rb44
-rw-r--r--spec/ruby/language/comment_spec.rb13
-rw-r--r--spec/ruby/language/constants_spec.rb352
-rw-r--r--spec/ruby/language/def_spec.rb194
-rw-r--r--spec/ruby/language/defined_spec.rb484
-rw-r--r--spec/ruby/language/delegation_spec.rb162
-rw-r--r--spec/ruby/language/encoding_spec.rb14
-rw-r--r--spec/ruby/language/ensure_spec.rb145
-rw-r--r--spec/ruby/language/execution_spec.rb78
-rw-r--r--spec/ruby/language/file_spec.rb18
-rw-r--r--spec/ruby/language/fixtures/block.rb4
-rw-r--r--spec/ruby/language/fixtures/break.rb10
-rw-r--r--spec/ruby/language/fixtures/break_lambda_toplevel.rb2
-rw-r--r--spec/ruby/language/fixtures/break_lambda_toplevel_block.rb2
-rw-r--r--spec/ruby/language/fixtures/break_lambda_toplevel_method.rb2
-rw-r--r--spec/ruby/language/fixtures/class_with_class_variable.rb9
-rw-r--r--spec/ruby/language/fixtures/constant_visibility.rb18
-rw-r--r--spec/ruby/language/fixtures/defined.rb36
-rw-r--r--spec/ruby/language/fixtures/delegation.rb11
-rw-r--r--spec/ruby/language/fixtures/for_scope.rb15
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files_diff_enc.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files_no_comment.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_one_literal.rb4
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required.rb2
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rbbin181 -> 107 bytes-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required_no_comment.rb2
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb2
-rw-r--r--spec/ruby/language/fixtures/hash_strings_ascii8bit.rb7
-rw-r--r--spec/ruby/language/fixtures/hash_strings_binary.rb7
-rw-r--r--spec/ruby/language/fixtures/module.rb9
-rw-r--r--spec/ruby/language/fixtures/private.rb26
-rw-r--r--spec/ruby/language/fixtures/rescue/top_level.rb7
-rw-r--r--spec/ruby/language/fixtures/rescue_captures.rb107
-rw-r--r--spec/ruby/language/fixtures/return.rb8
-rw-r--r--spec/ruby/language/fixtures/send.rb19
-rw-r--r--spec/ruby/language/fixtures/squiggly_heredoc.rb32
-rw-r--r--spec/ruby/language/fixtures/super.rb118
-rw-r--r--spec/ruby/language/fixtures/variables.rb72
-rw-r--r--spec/ruby/language/fixtures/yield.rb4
-rw-r--r--spec/ruby/language/for_spec.rb217
-rw-r--r--spec/ruby/language/hash_spec.rb209
-rw-r--r--spec/ruby/language/heredoc_spec.rb34
-rw-r--r--spec/ruby/language/if_spec.rb98
-rw-r--r--spec/ruby/language/it_parameter_spec.rb108
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb398
-rw-r--r--spec/ruby/language/lambda_spec.rb194
-rw-r--r--spec/ruby/language/line_spec.rb2
-rw-r--r--spec/ruby/language/loop_spec.rb2
-rw-r--r--spec/ruby/language/magic_comment_spec.rb3
-rw-r--r--spec/ruby/language/match_spec.rb15
-rw-r--r--spec/ruby/language/metaclass_spec.rb28
-rw-r--r--spec/ruby/language/method_spec.rb831
-rw-r--r--spec/ruby/language/module_spec.rb70
-rw-r--r--spec/ruby/language/next_spec.rb14
-rw-r--r--spec/ruby/language/not_spec.rb32
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb113
-rw-r--r--spec/ruby/language/numbers_spec.rb16
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb456
-rw-r--r--spec/ruby/language/or_spec.rb32
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb1310
-rw-r--r--spec/ruby/language/precedence_spec.rb116
-rw-r--r--spec/ruby/language/predefined_spec.rb1072
-rw-r--r--spec/ruby/language/private_spec.rb26
-rw-r--r--spec/ruby/language/proc_spec.rb75
-rw-r--r--spec/ruby/language/range_spec.rb30
-rw-r--r--spec/ruby/language/redo_spec.rb6
-rw-r--r--spec/ruby/language/regexp/anchors_spec.rb62
-rw-r--r--spec/ruby/language/regexp/back-references_spec.rb98
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb266
-rw-r--r--spec/ruby/language/regexp/empty_checks_spec.rb135
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb89
-rw-r--r--spec/ruby/language/regexp/escapes_spec.rb114
-rw-r--r--spec/ruby/language/regexp/grouping_spec.rb42
-rw-r--r--spec/ruby/language/regexp/interpolation_spec.rb6
-rw-r--r--spec/ruby/language/regexp/modifiers_spec.rb52
-rw-r--r--spec/ruby/language/regexp/repetition_spec.rb109
-rw-r--r--spec/ruby/language/regexp/subexpression_call_spec.rb50
-rw-r--r--spec/ruby/language/regexp_spec.rb88
-rw-r--r--spec/ruby/language/rescue_spec.rb287
-rw-r--r--spec/ruby/language/reserved_keywords.rb149
-rw-r--r--spec/ruby/language/retry_spec.rb7
-rw-r--r--spec/ruby/language/return_spec.rb377
-rw-r--r--spec/ruby/language/safe_navigator_spec.rb86
-rw-r--r--spec/ruby/language/safe_spec.rb98
-rw-r--r--spec/ruby/language/send_spec.rb99
-rw-r--r--spec/ruby/language/shared/__FILE__.rb4
-rw-r--r--spec/ruby/language/shared/__LINE__.rb2
-rw-r--r--spec/ruby/language/singleton_class_spec.rb124
-rw-r--r--spec/ruby/language/source_encoding_spec.rb6
-rw-r--r--spec/ruby/language/string_spec.rb114
-rw-r--r--spec/ruby/language/super_spec.rb271
-rw-r--r--spec/ruby/language/symbol_spec.rb36
-rw-r--r--spec/ruby/language/throw_spec.rb12
-rw-r--r--spec/ruby/language/undef_spec.rb25
-rw-r--r--spec/ruby/language/until_spec.rb2
-rw-r--r--spec/ruby/language/variables_spec.rb220
-rw-r--r--spec/ruby/language/while_spec.rb18
-rw-r--r--spec/ruby/language/yield_spec.rb97
-rw-r--r--spec/ruby/library/English/English_spec.rb86
-rw-r--r--spec/ruby/library/English/alias_spec.rb14
-rw-r--r--spec/ruby/library/abbrev/abbrev_spec.rb4
-rw-r--r--spec/ruby/library/base64/decode64_spec.rb20
-rw-r--r--spec/ruby/library/base64/encode64_spec.rb9
-rw-r--r--spec/ruby/library/base64/strict_decode64_spec.rb41
-rw-r--r--spec/ruby/library/base64/strict_encode64_spec.rb19
-rw-r--r--spec/ruby/library/bigdecimal/BigDecimal_spec.rb188
-rw-r--r--spec/ruby/library/bigdecimal/abs_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/add_spec.rb34
-rw-r--r--spec/ruby/library/bigdecimal/ceil_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/clone_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/comparison_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/constants_spec.rb70
-rw-r--r--spec/ruby/library/bigdecimal/core_spec.rb62
-rw-r--r--spec/ruby/library/bigdecimal/div_spec.rb52
-rw-r--r--spec/ruby/library/bigdecimal/divide_spec.rb10
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb96
-rw-r--r--spec/ruby/library/bigdecimal/dup_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/finite_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/fix_spec.rb34
-rw-r--r--spec/ruby/library/bigdecimal/floor_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/frac_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/gt_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/gte_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/hash_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/inspect_spec.rb41
-rw-r--r--spec/ruby/library/bigdecimal/lt_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/lte_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/minus_spec.rb26
-rw-r--r--spec/ruby/library/bigdecimal/mode_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/mult_spec.rb4
-rw-r--r--spec/ruby/library/bigdecimal/multiply_spec.rb15
-rw-r--r--spec/ruby/library/bigdecimal/nan_spec.rb22
-rw-r--r--spec/ruby/library/bigdecimal/nonzero_spec.rb10
-rw-r--r--spec/ruby/library/bigdecimal/plus_spec.rb13
-rw-r--r--spec/ruby/library/bigdecimal/precs_spec.rb48
-rw-r--r--spec/ruby/library/bigdecimal/quo_spec.rb4
-rw-r--r--spec/ruby/library/bigdecimal/remainder_spec.rb51
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb254
-rw-r--r--spec/ruby/library/bigdecimal/shared/clone.rb13
-rw-r--r--spec/ruby/library/bigdecimal/shared/modulo.rb61
-rw-r--r--spec/ruby/library/bigdecimal/shared/mult.rb20
-rw-r--r--spec/ruby/library/bigdecimal/shared/power.rb8
-rw-r--r--spec/ruby/library/bigdecimal/shared/quo.rb19
-rw-r--r--spec/ruby/library/bigdecimal/shared/to_int.rb8
-rw-r--r--spec/ruby/library/bigdecimal/split_spec.rb20
-rw-r--r--spec/ruby/library/bigdecimal/sqrt_spec.rb44
-rw-r--r--spec/ruby/library/bigdecimal/sub_spec.rb17
-rw-r--r--spec/ruby/library/bigdecimal/to_d_spec.rb10
-rw-r--r--spec/ruby/library/bigdecimal/to_f_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/to_i_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/to_r_spec.rb18
-rw-r--r--spec/ruby/library/bigdecimal/to_s_spec.rb38
-rw-r--r--spec/ruby/library/bigdecimal/truncate_spec.rb22
-rw-r--r--spec/ruby/library/bigdecimal/uminus_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/util_spec.rb40
-rw-r--r--spec/ruby/library/bigdecimal/ver_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/zero_spec.rb26
-rw-r--r--spec/ruby/library/bigmath/log_spec.rb10
-rw-r--r--spec/ruby/library/cgi/cookie/domain_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/expires_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/initialize_spec.rb235
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb42
-rw-r--r--spec/ruby/library/cgi/cookie/path_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/secure_spec.rb99
-rw-r--r--spec/ruby/library/cgi/cookie/to_s_spec.rb50
-rw-r--r--spec/ruby/library/cgi/cookie/value_spec.rb121
-rw-r--r--spec/ruby/library/cgi/escapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/escapeHTML_spec.rb10
-rw-r--r--spec/ruby/library/cgi/escapeURIComponent_spec.rb78
-rw-r--r--spec/ruby/library/cgi/escape_spec.rb22
-rw-r--r--spec/ruby/library/cgi/htmlextension/a_spec.rb73
-rw-r--r--spec/ruby/library/cgi/htmlextension/base_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/blockquote_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/br_spec.rb31
-rw-r--r--spec/ruby/library/cgi/htmlextension/caption_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb121
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/doctype_spec.rb41
-rw-r--r--spec/ruby/library/cgi/htmlextension/file_field_spec.rb105
-rw-r--r--spec/ruby/library/cgi/htmlextension/form_spec.rb85
-rw-r--r--spec/ruby/library/cgi/htmlextension/frame_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/frameset_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/hidden_spec.rb87
-rw-r--r--spec/ruby/library/cgi/htmlextension/html_spec.rb99
-rw-r--r--spec/ruby/library/cgi/htmlextension/image_button_spec.rb101
-rw-r--r--spec/ruby/library/cgi/htmlextension/img_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb93
-rw-r--r--spec/ruby/library/cgi/htmlextension/password_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_button_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_group_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/reset_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/submit_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/text_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/textarea_spec.rb107
-rw-r--r--spec/ruby/library/cgi/http_header_spec.rb11
-rw-r--r--spec/ruby/library/cgi/initialize_spec.rb209
-rw-r--r--spec/ruby/library/cgi/out_spec.rb97
-rw-r--r--spec/ruby/library/cgi/parse_spec.rb37
-rw-r--r--spec/ruby/library/cgi/pretty_spec.rb19
-rw-r--r--spec/ruby/library/cgi/print_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_charset_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_language_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/auth_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cache_control_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/content_length_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/content_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cookies_spec.rb15
-rw-r--r--spec/ruby/library/cgi/queryextension/element_reference_spec.rb41
-rw-r--r--spec/ruby/library/cgi/queryextension/from_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/has_key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/include_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/keys_spec.rb29
-rw-r--r--spec/ruby/library/cgi/queryextension/multipart_spec.rb47
-rw-r--r--spec/ruby/library/cgi/queryextension/negotiate_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/params_spec.rb55
-rw-r--r--spec/ruby/library/cgi/queryextension/path_info_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/path_translated_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/pragma_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/query_string_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/referer_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_addr_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_ident_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_user_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/request_method_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/script_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_port_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/server_protocol_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_software_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/shared/has_key.rb6
-rw-r--r--spec/ruby/library/cgi/queryextension/user_agent_spec.rb33
-rw-r--r--spec/ruby/library/cgi/rfc1123_date_spec.rb15
-rw-r--r--spec/ruby/library/cgi/shared/http_header.rb10
-rw-r--r--spec/ruby/library/cgi/unescapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/unescapeHTML_spec.rb11
-rw-r--r--spec/ruby/library/cgi/unescapeURIComponent_spec.rb128
-rw-r--r--spec/ruby/library/cgi/unescape_spec.rb12
-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/marshal_dump_spec.rb9
-rw-r--r--spec/ruby/library/conditionvariable/signal_spec.rb69
-rw-r--r--spec/ruby/library/conditionvariable/wait_spec.rb123
-rw-r--r--spec/ruby/library/coverage/fixtures/code_with_begin.rb3
-rw-r--r--spec/ruby/library/coverage/fixtures/eval_code.rb11
-rw-r--r--spec/ruby/library/coverage/fixtures/spec_helper.rb11
-rw-r--r--spec/ruby/library/coverage/peek_result_spec.rb1
-rw-r--r--spec/ruby/library/coverage/result_spec.rb295
-rw-r--r--spec/ruby/library/coverage/running_spec.rb20
-rw-r--r--spec/ruby/library/coverage/start_spec.rb83
-rw-r--r--spec/ruby/library/coverage/supported_spec.rb30
-rw-r--r--spec/ruby/library/csv/generate_spec.rb4
-rw-r--r--spec/ruby/library/csv/liberal_parsing_spec.rb26
-rw-r--r--spec/ruby/library/csv/parse_spec.rb14
-rw-r--r--spec/ruby/library/csv/readlines_spec.rb14
-rw-r--r--spec/ruby/library/date/accessor_spec.rb2
-rw-r--r--spec/ruby/library/date/add_month_spec.rb8
-rw-r--r--spec/ruby/library/date/add_spec.rb8
-rw-r--r--spec/ruby/library/date/civil_spec.rb7
-rw-r--r--spec/ruby/library/date/constants_spec.rb8
-rw-r--r--spec/ruby/library/date/deconstruct_keys_spec.rb42
-rw-r--r--spec/ruby/library/date/eql_spec.rb4
-rw-r--r--spec/ruby/library/date/friday_spec.rb4
-rw-r--r--spec/ruby/library/date/gregorian_leap_spec.rb10
-rw-r--r--spec/ruby/library/date/gregorian_spec.rb8
-rw-r--r--spec/ruby/library/date/infinity_spec.rb14
-rw-r--r--spec/ruby/library/date/iso8601_spec.rb35
-rw-r--r--spec/ruby/library/date/julian_leap_spec.rb10
-rw-r--r--spec/ruby/library/date/julian_spec.rb8
-rw-r--r--spec/ruby/library/date/minus_month_spec.rb8
-rw-r--r--spec/ruby/library/date/minus_spec.rb6
-rw-r--r--spec/ruby/library/date/mon_spec.rb3
-rw-r--r--spec/ruby/library/date/monday_spec.rb2
-rw-r--r--spec/ruby/library/date/month_spec.rb6
-rw-r--r--spec/ruby/library/date/new_spec.rb1
-rw-r--r--spec/ruby/library/date/parse_spec.rb33
-rw-r--r--spec/ruby/library/date/plus_spec.rb2
-rw-r--r--spec/ruby/library/date/rfc3339_spec.rb13
-rw-r--r--spec/ruby/library/date/saturday_spec.rb2
-rw-r--r--spec/ruby/library/date/shared/civil.rb24
-rw-r--r--spec/ruby/library/date/shared/commercial.rb18
-rw-r--r--spec/ruby/library/date/shared/month.rb6
-rw-r--r--spec/ruby/library/date/shared/new_bang.rb14
-rw-r--r--spec/ruby/library/date/shared/parse.rb4
-rw-r--r--spec/ruby/library/date/shared/parse_eu.rb8
-rw-r--r--spec/ruby/library/date/shared/parse_us.rb8
-rw-r--r--spec/ruby/library/date/shared/valid_civil.rb16
-rw-r--r--spec/ruby/library/date/shared/valid_commercial.rb24
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb19
-rw-r--r--spec/ruby/library/date/strftime_spec.rb9
-rw-r--r--spec/ruby/library/date/sunday_spec.rb2
-rw-r--r--spec/ruby/library/date/thursday_spec.rb2
-rw-r--r--spec/ruby/library/date/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/date/today_spec.rb2
-rw-r--r--spec/ruby/library/date/tuesday_spec.rb2
-rw-r--r--spec/ruby/library/date/wednesday_spec.rb2
-rw-r--r--spec/ruby/library/date/yday_spec.rb3
-rw-r--r--spec/ruby/library/datetime/add_spec.rb2
-rw-r--r--spec/ruby/library/datetime/deconstruct_keys_spec.rb44
-rw-r--r--spec/ruby/library/datetime/hour_spec.rb12
-rw-r--r--spec/ruby/library/datetime/new_spec.rb2
-rw-r--r--spec/ruby/library/datetime/now_spec.rb6
-rw-r--r--spec/ruby/library/datetime/parse_spec.rb12
-rw-r--r--spec/ruby/library/datetime/rfc2822_spec.rb4
-rw-r--r--spec/ruby/library/datetime/shared/min.rb12
-rw-r--r--spec/ruby/library/datetime/shared/sec.rb8
-rw-r--r--spec/ruby/library/datetime/strftime_spec.rb15
-rw-r--r--spec/ruby/library/datetime/subtract_spec.rb12
-rw-r--r--spec/ruby/library/datetime/time/to_datetime_spec.rb40
-rw-r--r--spec/ruby/library/datetime/to_date_spec.rb4
-rw-r--r--spec/ruby/library/datetime/to_s_spec.rb4
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb42
-rw-r--r--spec/ruby/library/datetime/yday_spec.rb7
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_method_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb10
-rw-r--r--spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb1
-rw-r--r--spec/ruby/library/delegate/delegator/eql_spec.rb55
-rw-r--r--spec/ruby/library/delegate/delegator/equal_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/equal_value_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/frozen_spec.rb16
-rw-r--r--spec/ruby/library/delegate/delegator/marshal_spec.rb2
-rw-r--r--spec/ruby/library/delegate/delegator/method_spec.rb26
-rw-r--r--spec/ruby/library/delegate/delegator/methods_spec.rb14
-rw-r--r--spec/ruby/library/delegate/delegator/not_equal_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/private_methods_spec.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/protected_methods_spec.rb4
-rw-r--r--spec/ruby/library/delegate/delegator/public_methods_spec.rb4
-rw-r--r--spec/ruby/library/delegate/delegator/send_spec.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/taint_spec.rb15
-rw-r--r--spec/ruby/library/delegate/delegator/tap_spec.rb2
-rw-r--r--spec/ruby/library/delegate/delegator/trust_spec.rb14
-rw-r--r--spec/ruby/library/delegate/delegator/untaint_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/untrust_spec.rb15
-rw-r--r--spec/ruby/library/digest/bubblebabble_spec.rb10
-rw-r--r--spec/ruby/library/digest/hexencode_spec.rb6
-rw-r--r--spec/ruby/library/digest/instance/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/instance/new_spec.rb19
-rw-r--r--spec/ruby/library/digest/instance/shared/update.rb8
-rw-r--r--spec/ruby/library/digest/instance/update_spec.rb7
-rw-r--r--spec/ruby/library/digest/md5/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/md5/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/md5/shared/constants.rb3
-rw-r--r--spec/ruby/library/digest/md5/shared/sample.rb17
-rw-r--r--spec/ruby/library/digest/sha1/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha1/shared/constants.rb5
-rw-r--r--spec/ruby/library/digest/sha2/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha256/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha256/file_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha256/shared/constants.rb3
-rw-r--r--spec/ruby/library/digest/sha384/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha384/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha384/shared/constants.rb3
-rw-r--r--spec/ruby/library/digest/sha512/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha512/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha512/shared/constants.rb3
-rw-r--r--spec/ruby/library/drb/start_service_spec.rb47
-rw-r--r--spec/ruby/library/erb/def_class_spec.rb2
-rw-r--r--spec/ruby/library/erb/def_module_spec.rb3
-rw-r--r--spec/ruby/library/erb/defmethod/def_erb_method_spec.rb2
-rw-r--r--spec/ruby/library/erb/filename_spec.rb8
-rw-r--r--spec/ruby/library/erb/fixtures/classes.rb6
-rw-r--r--spec/ruby/library/erb/new_spec.rb48
-rw-r--r--spec/ruby/library/erb/result_spec.rb8
-rw-r--r--spec/ruby/library/erb/run_spec.rb10
-rw-r--r--spec/ruby/library/erb/util/shared/url_encode.rb16
-rw-r--r--spec/ruby/library/etc/confstr_spec.rb8
-rw-r--r--spec/ruby/library/etc/getgrgid_spec.rb15
-rw-r--r--spec/ruby/library/etc/getgrnam_spec.rb6
-rw-r--r--spec/ruby/library/etc/getlogin_spec.rb4
-rw-r--r--spec/ruby/library/etc/getpwnam_spec.rb4
-rw-r--r--spec/ruby/library/etc/getpwuid_spec.rb4
-rw-r--r--spec/ruby/library/etc/group_spec.rb6
-rw-r--r--spec/ruby/library/etc/nprocessors_spec.rb2
-rw-r--r--spec/ruby/library/etc/passwd_spec.rb4
-rw-r--r--spec/ruby/library/etc/struct_group_spec.rb2
-rw-r--r--spec/ruby/library/etc/struct_passwd_spec.rb2
-rw-r--r--spec/ruby/library/etc/sysconf_spec.rb4
-rw-r--r--spec/ruby/library/etc/sysconfdir_spec.rb4
-rw-r--r--spec/ruby/library/etc/systmpdir_spec.rb4
-rw-r--r--spec/ruby/library/etc/uname_spec.rb14
-rw-r--r--spec/ruby/library/expect/expect_spec.rb9
-rw-r--r--spec/ruby/library/fiber/alive_spec.rb48
-rw-r--r--spec/ruby/library/fiber/current_spec.rb53
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb14
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb88
-rw-r--r--spec/ruby/library/fiddle/handle/initialize_spec.rb10
-rw-r--r--spec/ruby/library/find/find_spec.rb2
-rw-r--r--spec/ruby/library/find/fixtures/common.rb14
-rw-r--r--spec/ruby/library/getoptlong/error_message_spec.rb2
-rw-r--r--spec/ruby/library/getoptlong/ordering_spec.rb8
-rw-r--r--spec/ruby/library/getoptlong/set_options_spec.rb28
-rw-r--r--spec/ruby/library/getoptlong/shared/get.rb12
-rw-r--r--spec/ruby/library/getoptlong/terminate_spec.rb2
-rw-r--r--spec/ruby/library/getoptlong/terminated_spec.rb6
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb42
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb162
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb37
-rw-r--r--spec/ruby/library/ipaddr/ipv4_conversion_spec.rb8
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb19
-rw-r--r--spec/ruby/library/ipaddr/operator_spec.rb31
-rw-r--r--spec/ruby/library/ipaddr/reverse_spec.rb8
-rw-r--r--spec/ruby/library/irb/fixtures/irb.rb3
-rw-r--r--spec/ruby/library/irb/irb_spec.rb19
-rw-r--r--spec/ruby/library/logger/device/close_spec.rb2
-rw-r--r--spec/ruby/library/logger/device/new_spec.rb14
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb2
-rw-r--r--spec/ruby/library/logger/logger/add_spec.rb12
-rw-r--r--spec/ruby/library/logger/logger/close_spec.rb2
-rw-r--r--spec/ruby/library/logger/logger/datetime_format_spec.rb2
-rw-r--r--spec/ruby/library/logger/logger/debug_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/error_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/fatal_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/info_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/new_spec.rb114
-rw-r--r--spec/ruby/library/logger/logger/unknown_spec.rb2
-rw-r--r--spec/ruby/library/logger/logger/warn_spec.rb4
-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/mathn_spec.rb9
-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/antisymmetric_spec.rb53
-rw-r--r--spec/ruby/library/matrix/build_spec.rb20
-rw-r--r--spec/ruby/library/matrix/clone_spec.rb8
-rw-r--r--spec/ruby/library/matrix/coerce_spec.rb4
-rw-r--r--spec/ruby/library/matrix/column_spec.rb6
-rw-r--r--spec/ruby/library/matrix/column_vector_spec.rb6
-rw-r--r--spec/ruby/library/matrix/column_vectors_spec.rb4
-rw-r--r--spec/ruby/library/matrix/columns_spec.rb4
-rw-r--r--spec/ruby/library/matrix/constructor_spec.rb20
-rw-r--r--spec/ruby/library/matrix/diagonal_spec.rb18
-rw-r--r--spec/ruby/library/matrix/divide_spec.rb16
-rw-r--r--spec/ruby/library/matrix/each_spec.rb16
-rw-r--r--spec/ruby/library/matrix/each_with_index_spec.rb16
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb2
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb2
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb2
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb12
-rw-r--r--spec/ruby/library/matrix/element_reference_spec.rb4
-rw-r--r--spec/ruby/library/matrix/empty_spec.rb32
-rw-r--r--spec/ruby/library/matrix/eql_spec.rb2
-rw-r--r--spec/ruby/library/matrix/exponent_spec.rb25
-rw-r--r--spec/ruby/library/matrix/find_index_spec.rb24
-rw-r--r--spec/ruby/library/matrix/hash_spec.rb4
-rw-r--r--spec/ruby/library/matrix/hermitian_spec.rb14
-rw-r--r--spec/ruby/library/matrix/lower_triangular_spec.rb22
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb4
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb8
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/l_spec.rb2
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/p_spec.rb2
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/solve_spec.rb12
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb4
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/u_spec.rb2
-rw-r--r--spec/ruby/library/matrix/minor_spec.rb2
-rw-r--r--spec/ruby/library/matrix/minus_spec.rb20
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb19
-rw-r--r--spec/ruby/library/matrix/new_spec.rb2
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb10
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb10
-rw-r--r--spec/ruby/library/matrix/permutation_spec.rb16
-rw-r--r--spec/ruby/library/matrix/plus_spec.rb20
-rw-r--r--spec/ruby/library/matrix/real_spec.rb12
-rw-r--r--spec/ruby/library/matrix/regular_spec.rb16
-rw-r--r--spec/ruby/library/matrix/round_spec.rb2
-rw-r--r--spec/ruby/library/matrix/row_spec.rb6
-rw-r--r--spec/ruby/library/matrix/row_vector_spec.rb4
-rw-r--r--spec/ruby/library/matrix/row_vectors_spec.rb4
-rw-r--r--spec/ruby/library/matrix/rows_spec.rb8
-rw-r--r--spec/ruby/library/matrix/scalar_spec.rb4
-rw-r--r--spec/ruby/library/matrix/shared/collect.rb6
-rw-r--r--spec/ruby/library/matrix/shared/conjugate.rb2
-rw-r--r--spec/ruby/library/matrix/shared/determinant.rb8
-rw-r--r--spec/ruby/library/matrix/shared/equal_value.rb20
-rw-r--r--spec/ruby/library/matrix/shared/identity.rb4
-rw-r--r--spec/ruby/library/matrix/shared/imaginary.rb2
-rw-r--r--spec/ruby/library/matrix/shared/inverse.rb8
-rw-r--r--spec/ruby/library/matrix/shared/rectangular.rb2
-rw-r--r--spec/ruby/library/matrix/shared/trace.rb2
-rw-r--r--spec/ruby/library/matrix/shared/transpose.rb2
-rw-r--r--spec/ruby/library/matrix/singular_spec.rb16
-rw-r--r--spec/ruby/library/matrix/square_spec.rb16
-rw-r--r--spec/ruby/library/matrix/symmetric_spec.rb10
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb18
-rw-r--r--spec/ruby/library/matrix/upper_triangular_spec.rb22
-rw-r--r--spec/ruby/library/matrix/vector/cross_product_spec.rb4
-rw-r--r--spec/ruby/library/matrix/vector/each2_spec.rb12
-rw-r--r--spec/ruby/library/matrix/vector/eql_spec.rb4
-rw-r--r--spec/ruby/library/matrix/vector/inner_product_spec.rb4
-rw-r--r--spec/ruby/library/matrix/vector/normalize_spec.rb8
-rw-r--r--spec/ruby/library/matrix/zero_spec.rb14
-rw-r--r--spec/ruby/library/mkmf/mkmf_spec.rb7
-rw-r--r--spec/ruby/library/monitor/enter_spec.rb28
-rw-r--r--spec/ruby/library/monitor/exit_spec.rb10
-rw-r--r--spec/ruby/library/monitor/mon_initialize_spec.rb2
-rw-r--r--spec/ruby/library/monitor/new_cond_spec.rb88
-rw-r--r--spec/ruby/library/monitor/synchronize_spec.rb41
-rw-r--r--spec/ruby/library/monitor/try_enter_spec.rb39
-rw-r--r--spec/ruby/library/net-ftp/FTPError_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/FTPPermError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPProtoError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPReplyError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPTempError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/abort_spec.rb65
-rw-r--r--spec/ruby/library/net-ftp/acct_spec.rb61
-rw-r--r--spec/ruby/library/net-ftp/binary_spec.rb27
-rw-r--r--spec/ruby/library/net-ftp/chdir_spec.rb102
-rw-r--r--spec/ruby/library/net-ftp/close_spec.rb33
-rw-r--r--spec/ruby/library/net-ftp/closed_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/connect_spec.rb46
-rw-r--r--spec/ruby/library/net-ftp/debug_mode_spec.rb26
-rw-r--r--spec/ruby/library/net-ftp/default_passive_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/delete_spec.rb62
-rw-r--r--spec/ruby/library/net-ftp/dir_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/fixtures/default_passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/default_passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/putbinaryfile (renamed from spec/ruby/library/net/ftp/fixtures/putbinaryfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/puttextfile (renamed from spec/ruby/library/net/ftp/fixtures/puttextfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/server.rb279
-rw-r--r--spec/ruby/library/net-ftp/get_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/getbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/getdir_spec.rb10
-rw-r--r--spec/ruby/library/net-ftp/gettextfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/help_spec.rb69
-rw-r--r--spec/ruby/library/net-ftp/initialize_spec.rb408
-rw-r--r--spec/ruby/library/net-ftp/last_response_code_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/last_response_spec.rb28
-rw-r--r--spec/ruby/library/net-ftp/lastresp_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/list_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/login_spec.rb198
-rw-r--r--spec/ruby/library/net-ftp/ls_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/mdtm_spec.rb41
-rw-r--r--spec/ruby/library/net-ftp/mkdir_spec.rb64
-rw-r--r--spec/ruby/library/net-ftp/mtime_spec.rb53
-rw-r--r--spec/ruby/library/net-ftp/nlst_spec.rb95
-rw-r--r--spec/ruby/library/net-ftp/noop_spec.rb41
-rw-r--r--spec/ruby/library/net-ftp/open_spec.rb58
-rw-r--r--spec/ruby/library/net-ftp/passive_spec.rb31
-rw-r--r--spec/ruby/library/net-ftp/put_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/putbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/puttextfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/pwd_spec.rb56
-rw-r--r--spec/ruby/library/net-ftp/quit_spec.rb36
-rw-r--r--spec/ruby/library/net-ftp/rename_spec.rb97
-rw-r--r--spec/ruby/library/net-ftp/resume_spec.rb26
-rw-r--r--spec/ruby/library/net-ftp/retrbinary_spec.rb33
-rw-r--r--spec/ruby/library/net-ftp/retrlines_spec.rb37
-rw-r--r--spec/ruby/library/net-ftp/return_code_spec.rb27
-rw-r--r--spec/ruby/library/net-ftp/rmdir_spec.rb61
-rw-r--r--spec/ruby/library/net-ftp/sendcmd_spec.rb57
-rw-r--r--spec/ruby/library/net-ftp/set_socket_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/shared/getbinaryfile.rb152
-rw-r--r--spec/ruby/library/net-ftp/shared/gettextfile.rb102
-rw-r--r--spec/ruby/library/net-ftp/shared/last_response_code.rb27
-rw-r--r--spec/ruby/library/net-ftp/shared/list.rb106
-rw-r--r--spec/ruby/library/net-ftp/shared/putbinaryfile.rb169
-rw-r--r--spec/ruby/library/net-ftp/shared/puttextfile.rb130
-rw-r--r--spec/ruby/library/net-ftp/shared/pwd.rb5
-rw-r--r--spec/ruby/library/net-ftp/site_spec.rb56
-rw-r--r--spec/ruby/library/net-ftp/size_spec.rb51
-rw-r--r--spec/ruby/library/net-ftp/spec_helper.rb7
-rw-r--r--spec/ruby/library/net-ftp/status_spec.rb70
-rw-r--r--spec/ruby/library/net-ftp/storbinary_spec.rb52
-rw-r--r--spec/ruby/library/net-ftp/storlines_spec.rb47
-rw-r--r--spec/ruby/library/net-ftp/system_spec.rb51
-rw-r--r--spec/ruby/library/net-ftp/voidcmd_spec.rb57
-rw-r--r--spec/ruby/library/net-ftp/welcome_spec.rb28
-rw-r--r--spec/ruby/library/net-http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPClientExcepton_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net-http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net-http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net-http/http/fixtures/http_server.rb123
-rw-r--r--spec/ruby/library/net-http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_spec.rb94
-rw-r--r--spec/ruby/library/net-http/http/head2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net-http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net-http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net-http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net-http/http/post_spec.rb76
-rw-r--r--spec/ruby/library/net-http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net-http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net-http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net-http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net-http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net-http/http/shared/request_get.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_head.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_post.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_put.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/started.rb26
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_1.rb6
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_2.rb6
-rw-r--r--spec/ruby/library/net-http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net-http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net-http/httpexceptions/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net-http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_exist_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb135
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net-http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net-http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net-http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net-http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net-http/httpheader/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpheader/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/initialize_http_header_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net-http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_capitalized.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_header.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_name.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_content_type.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_content_type.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_form_data.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_form_data.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_range.rb89
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/size.rb18
-rw-r--r--spec/ruby/library/net-http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net-http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_new_spec.rb23
-rw-r--r--spec/ruby/library/net-http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net-http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/shared/body.rb20
-rw-r--r--spec/ruby/library/net-http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/net/FTPError_spec.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.rb8
-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/server.rb277
-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.rb409
-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.rb28
-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.rb69
-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/HTTPClientExcepton_spec.rb14
-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.rb26
-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.rb105
-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.rb8
-rw-r--r--spec/ruby/library/net/http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net/http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net/http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net/http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net/http/http/post_spec.rb76
-rw-r--r--spec/ruby/library/net/http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net/http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net/http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net/http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net/http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net/http/http/shared/request_get.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_head.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_post.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_put.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/started.rb26
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_1.rb6
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_2.rb6
-rw-r--r--spec/ruby/library/net/http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net/http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net/http/httpexceptions/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.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net/http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net/http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/initialize_http_header_spec.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_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.rb29
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_type_spec.rb29
-rw-r--r--spec/ruby/library/net/http/httpresponse/exception_type_spec.rb18
-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.rb85
-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.rb29
-rw-r--r--spec/ruby/library/objectspace/dump_all_spec.rb112
-rw-r--r--spec/ruby/library/objectspace/dump_spec.rb70
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb6
-rw-r--r--spec/ruby/library/objectspace/memsize_of_all_spec.rb22
-rw-r--r--spec/ruby/library/objectspace/memsize_of_spec.rb34
-rw-r--r--spec/ruby/library/objectspace/reachable_objects_from_spec.rb59
-rw-r--r--spec/ruby/library/objectspace/trace_object_allocations_spec.rb163
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb13
-rw-r--r--spec/ruby/library/observer/notify_observers_spec.rb4
-rw-r--r--spec/ruby/library/open3/popen3_spec.rb10
-rw-r--r--spec/ruby/library/openssl/cipher_spec.rb2
-rw-r--r--spec/ruby/library/openssl/config/freeze_spec.rb20
-rw-r--r--spec/ruby/library/openssl/digest/append_spec.rb6
-rw-r--r--spec/ruby/library/openssl/digest/block_length_spec.rb44
-rw-r--r--spec/ruby/library/openssl/digest/digest_length_spec.rb44
-rw-r--r--spec/ruby/library/openssl/digest/digest_spec.rb62
-rw-r--r--spec/ruby/library/openssl/digest/initialize_spec.rb137
-rw-r--r--spec/ruby/library/openssl/digest/name_spec.rb16
-rw-r--r--spec/ruby/library/openssl/digest/reset_spec.rb36
-rw-r--r--spec/ruby/library/openssl/digest/shared/update.rb123
-rw-r--r--spec/ruby/library/openssl/digest/update_spec.rb6
-rw-r--r--spec/ruby/library/openssl/fixed_length_secure_compare_spec.rb42
-rw-r--r--spec/ruby/library/openssl/hmac/digest_spec.rb2
-rw-r--r--spec/ruby/library/openssl/hmac/hexdigest_spec.rb2
-rw-r--r--spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb162
-rw-r--r--spec/ruby/library/openssl/kdf/scrypt_spec.rb210
-rw-r--r--spec/ruby/library/openssl/random/shared/random_bytes.rb8
-rw-r--r--spec/ruby/library/openssl/secure_compare_spec.rb38
-rw-r--r--spec/ruby/library/openssl/shared/constants.rb2
-rw-r--r--spec/ruby/library/openssl/x509/name/parse_spec.rb8
-rw-r--r--spec/ruby/library/openssl/x509/store/verify_spec.rb78
-rw-r--r--spec/ruby/library/openstruct/delete_field_spec.rb6
-rw-r--r--spec/ruby/library/openstruct/equal_value_spec.rb22
-rw-r--r--spec/ruby/library/openstruct/frozen_spec.rb16
-rw-r--r--spec/ruby/library/openstruct/initialize_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/marshal_load_spec.rb4
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb35
-rw-r--r--spec/ruby/library/openstruct/new_spec.rb4
-rw-r--r--spec/ruby/library/openstruct/shared/inspect.rb2
-rw-r--r--spec/ruby/library/openstruct/to_h_spec.rb41
-rw-r--r--spec/ruby/library/optionparser/order_spec.rb36
-rw-r--r--spec/ruby/library/optionparser/parse_spec.rb36
-rw-r--r--spec/ruby/library/pathname/absolute_spec.rb8
-rw-r--r--spec/ruby/library/pathname/birthtime_spec.rb16
-rw-r--r--spec/ruby/library/pathname/divide_spec.rb6
-rw-r--r--spec/ruby/library/pathname/empty_spec.rb46
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb92
-rw-r--r--spec/ruby/library/pathname/inspect_spec.rb10
-rw-r--r--spec/ruby/library/pathname/new_spec.rb17
-rw-r--r--spec/ruby/library/pathname/pathname_spec.rb19
-rw-r--r--spec/ruby/library/pathname/plus_spec.rb6
-rw-r--r--spec/ruby/library/pathname/realdirpath_spec.rb2
-rw-r--r--spec/ruby/library/pathname/realpath_spec.rb2
-rw-r--r--spec/ruby/library/pathname/relative_path_from_spec.rb8
-rw-r--r--spec/ruby/library/pathname/relative_spec.rb8
-rw-r--r--spec/ruby/library/pathname/root_spec.rb10
-rw-r--r--spec/ruby/library/pathname/shared/plus.rb8
-rw-r--r--spec/ruby/library/pp/pp_spec.rb11
-rw-r--r--spec/ruby/library/prime/each_spec.rb22
-rw-r--r--spec/ruby/library/prime/instance_spec.rb10
-rw-r--r--spec/ruby/library/prime/integer/prime_division_spec.rb2
-rw-r--r--spec/ruby/library/prime/integer/prime_spec.rb14
-rw-r--r--spec/ruby/library/prime/prime_division_spec.rb4
-rw-r--r--spec/ruby/library/prime/prime_spec.rb14
-rw-r--r--spec/ruby/library/random/formatter/alphanumeric_spec.rb54
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb160
-rw-r--r--spec/ruby/library/rbconfig/sizeof/limits_spec.rb40
-rw-r--r--spec/ruby/library/rbconfig/sizeof/sizeof_spec.rb6
-rw-r--r--spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb17
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb17
-rw-r--r--spec/ruby/library/readline/basic_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/basic_word_break_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completer_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completer_word_break_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_append_character_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_case_fold_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_proc_spec.rb4
-rw-r--r--spec/ruby/library/readline/constants_spec.rb4
-rw-r--r--spec/ruby/library/readline/emacs_editing_mode_spec.rb2
-rw-r--r--spec/ruby/library/readline/filename_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/append_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/delete_at_spec.rb11
-rw-r--r--spec/ruby/library/readline/history/each_spec.rb6
-rw-r--r--spec/ruby/library/readline/history/element_reference_spec.rb17
-rw-r--r--spec/ruby/library/readline/history/element_set_spec.rb4
-rw-r--r--spec/ruby/library/readline/history/empty_spec.rb6
-rw-r--r--spec/ruby/library/readline/history/history_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/pop_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/push_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/shift_spec.rb9
-rw-r--r--spec/ruby/library/readline/readline_spec.rb5
-rw-r--r--spec/ruby/library/readline/spec_helper.rb4
-rw-r--r--spec/ruby/library/readline/vi_editing_mode_spec.rb2
-rw-r--r--spec/ruby/library/resolv/fixtures/hosts1
-rw-r--r--spec/ruby/library/resolv/get_address_spec.rb16
-rw-r--r--spec/ruby/library/resolv/get_addresses_spec.rb12
-rw-r--r--spec/ruby/library/resolv/get_name_spec.rb15
-rw-r--r--spec/ruby/library/resolv/get_names_spec.rb11
-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.rb19
-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.rb14
-rw-r--r--spec/ruby/library/rexml/attribute/value_spec.rb14
-rw-r--r--spec/ruby/library/rexml/attribute/write_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attribute/xpath_spec.rb19
-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.rb22
-rw-r--r--spec/ruby/library/rexml/attributes/each_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attributes/element_reference_spec.rb18
-rw-r--r--spec/ruby/library/rexml/attributes/element_set_spec.rb25
-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.rb19
-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.rb23
-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.rb16
-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/element_reference_spec.rb22
-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.rb20
-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.rb23
-rw-r--r--spec/ruby/library/rexml/text/inspect_spec.rb8
-rw-r--r--spec/ruby/library/rexml/text/new_spec.rb48
-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.rb12
-rw-r--r--spec/ruby/library/rexml/text/to_s_spec.rb17
-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.rb20
-rw-r--r--spec/ruby/library/rexml/text/write_with_substitution_spec.rb33
-rw-r--r--spec/ruby/library/ripper/lex_spec.rb23
-rw-r--r--spec/ruby/library/ripper/sexp_spec.rb13
-rw-r--r--spec/ruby/library/rubygems/gem/bin_path_spec.rb35
-rw-r--r--spec/ruby/library/rubygems/gem/load_path_insert_index_spec.rb10
-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.rb12
-rw-r--r--spec/ruby/library/securerandom/bytes_spec.rb8
-rw-r--r--spec/ruby/library/securerandom/hex_spec.rb18
-rw-r--r--spec/ruby/library/securerandom/random_bytes_spec.rb17
-rw-r--r--spec/ruby/library/securerandom/random_number_spec.rb58
-rw-r--r--spec/ruby/library/set/add_spec.rb27
-rw-r--r--spec/ruby/library/set/append_spec.rb7
-rw-r--r--spec/ruby/library/set/case_compare_spec.rb14
-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/compare_by_identity_spec.rb147
-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/filter_spec.rb8
-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.rb7
-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/shared/add.rb14
-rw-r--r--spec/ruby/library/set/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/shared/include.rb29
-rw-r--r--spec/ruby/library/set/shared/inspect.rb15
-rw-r--r--spec/ruby/library/set/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/shared/select.rb42
-rw-r--r--spec/ruby/library/set/shared/union.rb15
-rw-r--r--spec/ruby/library/set/size_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/add_spec.rb39
-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/filter_spec.rb9
-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.rb30
-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.rb7
-rw-r--r--spec/ruby/library/set/sortedset/shared/add.rb14
-rw-r--r--spec/ruby/library/set/sortedset/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/sortedset/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/include.rb7
-rw-r--r--spec/ruby/library/set/sortedset/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/length.rb6
-rw-r--r--spec/ruby/library/set/sortedset/shared/select.rb35
-rw-r--r--spec/ruby/library/set/sortedset/shared/union.rb15
-rw-r--r--spec/ruby/library/set/sortedset/size_spec.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.rb17
-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/to_s_spec.rb13
-rw-r--r--spec/ruby/library/set/union_spec.rb11
-rw-r--r--spec/ruby/library/shellwords/shellwords_spec.rb21
-rw-r--r--spec/ruby/library/singleton/allocate_spec.rb2
-rw-r--r--spec/ruby/library/singleton/clone_spec.rb2
-rw-r--r--spec/ruby/library/singleton/dup_spec.rb2
-rw-r--r--spec/ruby/library/singleton/instance_spec.rb12
-rw-r--r--spec/ruby/library/singleton/load_spec.rb13
-rw-r--r--spec/ruby/library/singleton/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/afamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/bind_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/canonname_spec.rb4
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_from_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_to_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb62
-rw-r--r--spec/ruby/library/socket/addrinfo/foreach_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb24
-rw-r--r--spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb154
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_spec.rb26
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_address_spec.rb33
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_port_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb28
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb26
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb30
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb22
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb38
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb10
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb10
-rw-r--r--spec/ruby/library/socket/addrinfo/listen_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb58
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_load_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/pfamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/protocol_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/socktype_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/tcp_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/udp_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_path_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_spec.rb52
-rw-r--r--spec/ruby/library/socket/ancillarydata/cmsg_is_spec.rb4
-rw-r--r--spec/ruby/library/socket/ancillarydata/initialize_spec.rb70
-rw-r--r--spec/ruby/library/socket/ancillarydata/int_spec.rb4
-rw-r--r--spec/ruby/library/socket/ancillarydata/ip_pktinfo_spec.rb16
-rw-r--r--spec/ruby/library/socket/ancillarydata/ipv6_pktinfo_addr_spec.rb2
-rw-r--r--spec/ruby/library/socket/ancillarydata/ipv6_pktinfo_spec.rb10
-rw-r--r--spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb10
-rw-r--r--spec/ruby/library/socket/basicsocket/close_read_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/close_write_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/connect_address_spec.rb86
-rw-r--r--spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb66
-rw-r--r--spec/ruby/library/socket/basicsocket/for_fd_spec.rb6
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeereid_spec.rb4
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeername_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockname_spec.rb6
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockopt_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/local_address_spec.rb10
-rw-r--r--spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb74
-rw-r--r--spec/ruby/library/socket/basicsocket/read_spec.rb47
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb97
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_spec.rb126
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb86
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_spec.rb82
-rw-r--r--spec/ruby/library/socket/basicsocket/remote_address_spec.rb10
-rw-r--r--spec/ruby/library/socket/basicsocket/send_spec.rb104
-rw-r--r--spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb22
-rw-r--r--spec/ruby/library/socket/basicsocket/sendmsg_spec.rb6
-rw-r--r--spec/ruby/library/socket/basicsocket/setsockopt_spec.rb80
-rw-r--r--spec/ruby/library/socket/basicsocket/shutdown_spec.rb44
-rw-r--r--spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb43
-rw-r--r--spec/ruby/library/socket/constants/constants_spec.rb28
-rw-r--r--spec/ruby/library/socket/fixtures/classes.rb62
-rw-r--r--spec/ruby/library/socket/ipsocket/addr_spec.rb8
-rw-r--r--spec/ruby/library/socket/ipsocket/getaddress_spec.rb15
-rw-r--r--spec/ruby/library/socket/ipsocket/inspect_spec.rb24
-rw-r--r--spec/ruby/library/socket/ipsocket/peeraddr_spec.rb6
-rw-r--r--spec/ruby/library/socket/ipsocket/recvfrom_spec.rb62
-rw-r--r--spec/ruby/library/socket/option/bool_spec.rb4
-rw-r--r--spec/ruby/library/socket/option/initialize_spec.rb30
-rw-r--r--spec/ruby/library/socket/option/int_spec.rb6
-rw-r--r--spec/ruby/library/socket/option/linger_spec.rb18
-rw-r--r--spec/ruby/library/socket/option/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/shared/address.rb259
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb69
-rw-r--r--spec/ruby/library/socket/shared/partially_closable_sockets.rb2
-rw-r--r--spec/ruby/library/socket/shared/socketpair.rb38
-rw-r--r--spec/ruby/library/socket/socket/accept_loop_spec.rb18
-rw-r--r--spec/ruby/library/socket/socket/accept_nonblock_spec.rb27
-rw-r--r--spec/ruby/library/socket/socket/accept_spec.rb13
-rw-r--r--spec/ruby/library/socket/socket/bind_spec.rb38
-rw-r--r--spec/ruby/library/socket/socket/connect_nonblock_spec.rb114
-rw-r--r--spec/ruby/library/socket/socket/connect_spec.rb32
-rw-r--r--spec/ruby/library/socket/socket/getaddrinfo_spec.rb70
-rw-r--r--spec/ruby/library/socket/socket/gethostbyaddr_spec.rb43
-rw-r--r--spec/ruby/library/socket/socket/gethostbyname_spec.rb32
-rw-r--r--spec/ruby/library/socket/socket/gethostname_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/getifaddrs_spec.rb42
-rw-r--r--spec/ruby/library/socket/socket/getnameinfo_spec.rb18
-rw-r--r--spec/ruby/library/socket/socket/getservbyname_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/getservbyport_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/initialize_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/ip_address_list_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/listen_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pair_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb90
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_spec.rb73
-rw-r--r--spec/ruby/library/socket/socket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/socketpair_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/sysaccept_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/tcp_server_loop_spec.rb23
-rw-r--r--spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/tcp_spec.rb34
-rw-r--r--spec/ruby/library/socket/socket/udp_server_loop_on_spec.rb4
-rw-r--r--spec/ruby/library/socket/socket/udp_server_loop_spec.rb30
-rw-r--r--spec/ruby/library/socket/socket/udp_server_recv_spec.rb15
-rw-r--r--spec/ruby/library/socket/socket/udp_server_sockets_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/unix_server_loop_spec.rb69
-rw-r--r--spec/ruby/library/socket/socket/unix_server_socket_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unix_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb34
-rw-r--r--spec/ruby/library/socket/spec_helper.rb25
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb17
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb43
-rw-r--r--spec/ruby/library/socket/tcpserver/gets_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/initialize_spec.rb12
-rw-r--r--spec/ruby/library/socket/tcpserver/listen_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/new_spec.rb65
-rw-r--r--spec/ruby/library/socket/tcpserver/sysaccept_spec.rb8
-rw-r--r--spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb32
-rw-r--r--spec/ruby/library/socket/tcpsocket/initialize_spec.rb49
-rw-r--r--spec/ruby/library/socket/tcpsocket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/new_spec.rb5
-rw-r--r--spec/ruby/library/socket/tcpsocket/open_spec.rb1
-rw-r--r--spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb14
-rw-r--r--spec/ruby/library/socket/tcpsocket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb71
-rw-r--r--spec/ruby/library/socket/udpsocket/bind_spec.rb6
-rw-r--r--spec/ruby/library/socket/udpsocket/initialize_spec.rb31
-rw-r--r--spec/ruby/library/socket/udpsocket/inspect_spec.rb25
-rw-r--r--spec/ruby/library/socket/udpsocket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/new_spec.rb18
-rw-r--r--spec/ruby/library/socket/udpsocket/open_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb33
-rw-r--r--spec/ruby/library/socket/udpsocket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/send_spec.rb18
-rw-r--r--spec/ruby/library/socket/udpsocket/write_spec.rb4
-rw-r--r--spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb113
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb161
-rw-r--r--spec/ruby/library/socket/unixserver/for_fd_spec.rb28
-rw-r--r--spec/ruby/library/socket/unixserver/initialize_spec.rb36
-rw-r--r--spec/ruby/library/socket/unixserver/listen_spec.rb24
-rw-r--r--spec/ruby/library/socket/unixserver/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixserver/open_spec.rb26
-rw-r--r--spec/ruby/library/socket/unixserver/shared/new.rb26
-rw-r--r--spec/ruby/library/socket/unixserver/sysaccept_spec.rb64
-rw-r--r--spec/ruby/library/socket/unixsocket/addr_spec.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/initialize_spec.rb62
-rw-r--r--spec/ruby/library/socket/unixsocket/inspect_spec.rb18
-rw-r--r--spec/ruby/library/socket/unixsocket/local_address_spec.rb107
-rw-r--r--spec/ruby/library/socket/unixsocket/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb26
-rw-r--r--spec/ruby/library/socket/unixsocket/pair_spec.rb41
-rw-r--r--spec/ruby/library/socket/unixsocket/partially_closable_spec.rb32
-rw-r--r--spec/ruby/library/socket/unixsocket/path_spec.rb34
-rw-r--r--spec/ruby/library/socket/unixsocket/peeraddr_spec.rb38
-rw-r--r--spec/ruby/library/socket/unixsocket/recv_io_spec.rb15
-rw-r--r--spec/ruby/library/socket/unixsocket/recvfrom_spec.rb140
-rw-r--r--spec/ruby/library/socket/unixsocket/remote_address_spec.rb60
-rw-r--r--spec/ruby/library/socket/unixsocket/send_io_spec.rb9
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/new.rb28
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/pair.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/socketpair_spec.rb46
-rw-r--r--spec/ruby/library/stringio/append_spec.rb28
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb18
-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.rb10
-rw-r--r--spec/ruby/library/stringio/close_spec.rb8
-rw-r--r--spec/ruby/library/stringio/close_write_spec.rb12
-rw-r--r--spec/ruby/library/stringio/closed_read_spec.rb6
-rw-r--r--spec/ruby/library/stringio/closed_spec.rb10
-rw-r--r--spec/ruby/library/stringio/closed_write_spec.rb6
-rw-r--r--spec/ruby/library/stringio/codepoints_spec.rb9
-rw-r--r--spec/ruby/library/stringio/each_char_spec.rb2
-rw-r--r--spec/ruby/library/stringio/each_codepoint_spec.rb2
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb14
-rw-r--r--spec/ruby/library/stringio/each_spec.rb18
-rw-r--r--spec/ruby/library/stringio/fcntl_spec.rb2
-rw-r--r--spec/ruby/library/stringio/fileno_spec.rb5
-rw-r--r--spec/ruby/library/stringio/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/stringio/flush_spec.rb4
-rw-r--r--spec/ruby/library/stringio/fsync_spec.rb4
-rw-r--r--spec/ruby/library/stringio/getch_spec.rb16
-rw-r--r--spec/ruby/library/stringio/getpass_spec.rb11
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb260
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb297
-rw-r--r--spec/ruby/library/stringio/inspect_spec.rb19
-rw-r--r--spec/ruby/library/stringio/lineno_spec.rb8
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb21
-rw-r--r--spec/ruby/library/stringio/new_spec.rb10
-rw-r--r--spec/ruby/library/stringio/open_spec.rb190
-rw-r--r--spec/ruby/library/stringio/path_spec.rb2
-rw-r--r--spec/ruby/library/stringio/pid_spec.rb2
-rw-r--r--spec/ruby/library/stringio/pos_spec.rb2
-rw-r--r--spec/ruby/library/stringio/print_spec.rb32
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb49
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb33
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb53
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb24
-rw-r--r--spec/ruby/library/stringio/read_spec.rb6
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb141
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb47
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb50
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb151
-rw-r--r--spec/ruby/library/stringio/rewind_spec.rb2
-rw-r--r--spec/ruby/library/stringio/seek_spec.rb24
-rw-r--r--spec/ruby/library/stringio/set_encoding_by_bom_spec.rb237
-rw-r--r--spec/ruby/library/stringio/set_encoding_spec.rb22
-rw-r--r--spec/ruby/library/stringio/shared/codepoints.rb12
-rw-r--r--spec/ruby/library/stringio/shared/each.rb117
-rw-r--r--spec/ruby/library/stringio/shared/each_byte.rb12
-rw-r--r--spec/ruby/library/stringio/shared/each_char.rb10
-rw-r--r--spec/ruby/library/stringio/shared/eof.rb10
-rw-r--r--spec/ruby/library/stringio/shared/getc.rb22
-rw-r--r--spec/ruby/library/stringio/shared/gets.rb249
-rw-r--r--spec/ruby/library/stringio/shared/isatty.rb2
-rw-r--r--spec/ruby/library/stringio/shared/read.rb62
-rw-r--r--spec/ruby/library/stringio/shared/readchar.rb8
-rw-r--r--spec/ruby/library/stringio/shared/sysread.rb4
-rw-r--r--spec/ruby/library/stringio/shared/write.rb78
-rw-r--r--spec/ruby/library/stringio/string_spec.rb12
-rw-r--r--spec/ruby/library/stringio/stringio_spec.rb2
-rw-r--r--spec/ruby/library/stringio/sync_spec.rb4
-rw-r--r--spec/ruby/library/stringio/sysread_spec.rb7
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb34
-rw-r--r--spec/ruby/library/stringio/ungetbyte_spec.rb38
-rw-r--r--spec/ruby/library/stringio/ungetc_spec.rb24
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/append_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/captures_spec.rb36
-rw-r--r--spec/ruby/library/stringscanner/charpos_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb77
-rw-r--r--spec/ruby/library/stringscanner/check_until_spec.rb120
-rw-r--r--spec/ruby/library/stringscanner/clear_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/concat_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/dup_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/element_reference_spec.rb19
-rw-r--r--spec/ruby/library/stringscanner/empty_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/eos_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/exist_spec.rb99
-rw-r--r--spec/ruby/library/stringscanner/fixed_anchor_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/get_byte_spec.rb81
-rw-r--r--spec/ruby/library/stringscanner/getbyte_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/getch_spec.rb65
-rw-r--r--spec/ruby/library/stringscanner/initialize_spec.rb12
-rw-r--r--spec/ruby/library/stringscanner/inspect_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/match_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/matched_size_spec.rb21
-rw-r--r--spec/ruby/library/stringscanner/matched_spec.rb4
-rw-r--r--spec/ruby/library/stringscanner/must_C_version_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/named_captures_spec.rb28
-rw-r--r--spec/ruby/library/stringscanner/peek_byte_spec.rb35
-rw-r--r--spec/ruby/library/stringscanner/peek_spec.rb39
-rw-r--r--spec/ruby/library/stringscanner/peep_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/rest_size_spec.rb27
-rw-r--r--spec/ruby/library/stringscanner/rest_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/restsize_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/scan_byte_spec.rb98
-rw-r--r--spec/ruby/library/stringscanner/scan_full_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_integer_spec.rb157
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb74
-rw-r--r--spec/ruby/library/stringscanner/scan_until_spec.rb120
-rw-r--r--spec/ruby/library/stringscanner/search_full_spec.rb105
-rw-r--r--spec/ruby/library/stringscanner/shared/bol.rb16
-rw-r--r--spec/ruby/library/stringscanner/shared/concat.rb16
-rw-r--r--spec/ruby/library/stringscanner/shared/eos.rb17
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range.rb15
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range_matched.rb13
-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.rb13
-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/size_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/skip_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/skip_until_spec.rb116
-rw-r--r--spec/ruby/library/stringscanner/string_spec.rb4
-rw-r--r--spec/ruby/library/stringscanner/terminate_spec.rb8
-rw-r--r--spec/ruby/library/stringscanner/unscan_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/values_at_spec.rb68
-rw-r--r--spec/ruby/library/syslog/close_spec.rb20
-rw-r--r--spec/ruby/library/syslog/constants_spec.rb4
-rw-r--r--spec/ruby/library/syslog/facility_spec.rb6
-rw-r--r--spec/ruby/library/syslog/ident_spec.rb6
-rw-r--r--spec/ruby/library/syslog/inspect_spec.rb4
-rw-r--r--spec/ruby/library/syslog/log_spec.rb26
-rw-r--r--spec/ruby/library/syslog/mask_spec.rb16
-rw-r--r--spec/ruby/library/syslog/open_spec.rb14
-rw-r--r--spec/ruby/library/syslog/opened_spec.rb16
-rw-r--r--spec/ruby/library/syslog/options_spec.rb6
-rw-r--r--spec/ruby/library/syslog/shared/log.rb19
-rw-r--r--spec/ruby/library/syslog/shared/reopen.rb14
-rw-r--r--spec/ruby/library/tempfile/_close_spec.rb4
-rw-r--r--spec/ruby/library/tempfile/callback_spec.rb6
-rw-r--r--spec/ruby/library/tempfile/close_spec.rb12
-rw-r--r--spec/ruby/library/tempfile/create_spec.rb176
-rw-r--r--spec/ruby/library/tempfile/initialize_spec.rb11
-rw-r--r--spec/ruby/library/tempfile/open_spec.rb30
-rw-r--r--spec/ruby/library/tempfile/path_spec.rb2
-rw-r--r--spec/ruby/library/tempfile/shared/length.rb6
-rw-r--r--spec/ruby/library/tempfile/shared/unlink.rb2
-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.rb7
-rw-r--r--spec/ruby/library/thread/queue/closed_spec.rb7
-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/queue_spec.rb8
-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/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.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/closed_spec.rb7
-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/thread/sizedqueue_spec.rb8
-rw-r--r--spec/ruby/library/time/iso8601_spec.rb4
-rw-r--r--spec/ruby/library/time/shared/rfc2822.rb28
-rw-r--r--spec/ruby/library/time/shared/xmlschema.rb52
-rw-r--r--spec/ruby/library/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/time/to_datetime_spec.rb27
-rw-r--r--spec/ruby/library/time/to_time_spec.rb18
-rw-r--r--spec/ruby/library/time/xmlschema_spec.rb2
-rw-r--r--spec/ruby/library/timeout/error_spec.rb2
-rw-r--r--spec/ruby/library/timeout/timeout_spec.rb39
-rw-r--r--spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb22
-rw-r--r--spec/ruby/library/tmpdir/dir/tmpdir_spec.rb4
-rw-r--r--spec/ruby/library/uri/generic/host_spec.rb5
-rw-r--r--spec/ruby/library/uri/generic/to_s_spec.rb5
-rw-r--r--spec/ruby/library/uri/join_spec.rb4
-rw-r--r--spec/ruby/library/uri/mailto/build_spec.rb8
-rw-r--r--spec/ruby/library/uri/parse_spec.rb24
-rw-r--r--spec/ruby/library/uri/plus_spec.rb172
-rw-r--r--spec/ruby/library/uri/select_spec.rb12
-rw-r--r--spec/ruby/library/uri/set_component_spec.rb60
-rw-r--r--spec/ruby/library/uri/shared/eql.rb6
-rw-r--r--spec/ruby/library/uri/shared/join.rb4
-rw-r--r--spec/ruby/library/uri/shared/parse.rb37
-rw-r--r--spec/ruby/library/uri/uri_spec.rb4
-rw-r--r--spec/ruby/library/weakref/__getobj___spec.rb6
-rw-r--r--spec/ruby/library/weakref/allocate_spec.rb2
-rw-r--r--spec/ruby/library/weakref/fixtures/classes.rb6
-rw-r--r--spec/ruby/library/weakref/send_spec.rb4
-rw-r--r--spec/ruby/library/weakref/weakref_alive_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/fixtures/classes.rb16
-rw-r--r--spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/_invoke_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole/codepage_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/connect_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/const_load_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/constants_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/create_guid_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/invoke_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/locale_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/new_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/setproperty_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/ole_method.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/setproperty.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/new_spec.rb15
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb13
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb37
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_spec.rb27
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/new_spec.rb23
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/params_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/shared/name.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/visible_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/default_spec.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/input_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/optional_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/retval_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/shared/name.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/guid_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/new_spec.rb38
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progid_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progids_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/variables_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/visible_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/name_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/value_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb5
-rw-r--r--spec/ruby/library/yaml/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.rb27
-rw-r--r--spec/ruby/library/yaml/dump_stream_spec.rb3
-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.rb8
-rw-r--r--spec/ruby/library/yaml/fixtures/strings.rb56
-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.rb135
-rw-r--r--spec/ruby/library/yaml/load_stream_spec.rb3
-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.rb12
-rw-r--r--spec/ruby/library/yaml/parse_spec.rb9
-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.rb5
-rw-r--r--spec/ruby/library/yaml/shared/load.rb142
-rw-r--r--spec/ruby/library/yaml/tagurize_spec.rb11
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb41
-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/yaml/unsafe_load_spec.rb9
-rw-r--r--spec/ruby/library/zlib/adler32_spec.rb4
-rw-r--r--spec/ruby/library/zlib/crc32_spec.rb4
-rw-r--r--spec/ruby/library/zlib/crc_table_spec.rb143
-rw-r--r--spec/ruby/library/zlib/deflate/append_spec.rb1
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb9
-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.rb2
-rw-r--r--spec/ruby/library/zlib/deflate_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gunzip_spec.rb14
-rw-r--r--spec/ruby/library/zlib/gzip_spec.rb15
-rw-r--r--spec/ruby/library/zlib/gzipfile/close_spec.rb8
-rw-r--r--spec/ruby/library/zlib/gzipfile/closed_spec.rb4
-rw-r--r--spec/ruby/library/zlib/gzipfile/comment_spec.rb3
-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.rb3
-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.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_char_spec.rb51
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_line_spec.rb3
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_spec.rb3
-rw-r--r--spec/ruby/library/zlib/gzipreader/eof_spec.rb28
-rw-r--r--spec/ruby/library/zlib/gzipreader/getc_spec.rb6
-rw-r--r--spec/ruby/library/zlib/gzipreader/gets_spec.rb4
-rw-r--r--spec/ruby/library/zlib/gzipreader/lineno_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/mtime_spec.rb11
-rw-r--r--spec/ruby/library/zlib/gzipreader/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/open_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/pos_spec.rb4
-rw-r--r--spec/ruby/library/zlib/gzipreader/read_spec.rb16
-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.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/rewind_spec.rb3
-rw-r--r--spec/ruby/library/zlib/gzipreader/shared/each.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/tell_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb14
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetc_spec.rb46
-rw-r--r--spec/ruby/library/zlib/gzipreader/unused_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/append_spec.rb4
-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.rb3
-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.rb2
-rw-r--r--spec/ruby/library/zlib/inflate/append_spec.rb2
-rw-r--r--spec/ruby/library/zlib/inflate/finish_spec.rb3
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb19
-rw-r--r--spec/ruby/library/zlib/inflate/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate/set_dictionary_spec.rb2
-rw-r--r--spec/ruby/library/zlib/inflate/sync_point_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate/sync_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate_spec.rb2
-rw-r--r--spec/ruby/library/zlib/zlib_version_spec.rb7
-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/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.rb2
-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
-rw-r--r--spec/ruby/optional/capi/README9
-rw-r--r--spec/ruby/optional/capi/array_spec.rb122
-rw-r--r--spec/ruby/optional/capi/basic_object_spec.rb24
-rw-r--r--spec/ruby/optional/capi/bignum_spec.rb58
-rw-r--r--spec/ruby/optional/capi/binding_spec.rb16
-rw-r--r--spec/ruby/optional/capi/class_spec.rb234
-rw-r--r--spec/ruby/optional/capi/constants_spec.rb109
-rw-r--r--spec/ruby/optional/capi/data_spec.rb68
-rw-r--r--spec/ruby/optional/capi/debug_spec.rb74
-rw-r--r--spec/ruby/optional/capi/digest_spec.rb103
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb458
-rw-r--r--spec/ruby/optional/capi/exception_spec.rb153
-rw-r--r--spec/ruby/optional/capi/ext/array_spec.c247
-rw-r--r--spec/ruby/optional/capi/ext/basic_object_spec.c19
-rw-r--r--spec/ruby/optional/capi/ext/bignum_spec.c59
-rw-r--r--spec/ruby/optional/capi/ext/binding_spec.c19
-rw-r--r--spec/ruby/optional/capi/ext/boolean_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c163
-rw-r--r--spec/ruby/optional/capi/ext/class_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/complex_spec.c33
-rw-r--r--spec/ruby/optional/capi/ext/constants_spec.c690
-rw-r--r--spec/ruby/optional/capi/ext/data_spec.c23
-rw-r--r--spec/ruby/optional/capi/ext/debug_spec.c93
-rw-r--r--spec/ruby/optional/capi/ext/digest_spec.c168
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c349
-rw-r--r--spec/ruby/optional/capi/ext/enumerator_spec.c12
-rw-r--r--spec/ruby/optional/capi/ext/exception_spec.c68
-rw-r--r--spec/ruby/optional/capi/ext/fiber_spec.c64
-rw-r--r--spec/ruby/optional/capi/ext/file_spec.c15
-rw-r--r--spec/ruby/optional/capi/ext/finalizer_spec.c25
-rw-r--r--spec/ruby/optional/capi/ext/fixnum_spec.c28
-rw-r--r--spec/ruby/optional/capi/ext/float_spec.c27
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c160
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c130
-rw-r--r--spec/ruby/optional/capi/ext/hash_spec.c126
-rw-r--r--spec/ruby/optional/capi/ext/integer_spec.c20
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c313
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c334
-rw-r--r--spec/ruby/optional/capi/ext/language_spec.c42
-rw-r--r--spec/ruby/optional/capi/ext/marshal_spec.c14
-rw-r--r--spec/ruby/optional/capi/ext/module_spec.c148
-rw-r--r--spec/ruby/optional/capi/ext/module_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/mutex_spec.c61
-rw-r--r--spec/ruby/optional/capi/ext/numeric_spec.c135
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c399
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c100
-rw-r--r--spec/ruby/optional/capi/ext/range_spec.c68
-rw-r--r--spec/ruby/optional/capi/ext/rational_spec.c43
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c104
-rw-r--r--spec/ruby/optional/capi/ext/regexp_spec.c58
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h628
-rw-r--r--spec/ruby/optional/capi/ext/set_spec.c65
-rw-r--r--spec/ruby/optional/capi/ext/st_spec.c12
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c629
-rw-r--r--spec/ruby/optional/capi/ext/struct_spec.c90
-rw-r--r--spec/ruby/optional/capi/ext/symbol_spec.c76
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c105
-rw-r--r--spec/ruby/optional/capi/ext/time_spec.c48
-rw-r--r--spec/ruby/optional/capi/ext/tracepoint_spec.c49
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c106
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c92
-rw-r--r--spec/ruby/optional/capi/fiber_spec.rb86
-rw-r--r--spec/ruby/optional/capi/file_spec.rb10
-rw-r--r--spec/ruby/optional/capi/finalizer_spec.rb40
-rw-r--r--spec/ruby/optional/capi/fixnum_spec.rb111
-rw-r--r--spec/ruby/optional/capi/fixtures/class.rb13
-rw-r--r--spec/ruby/optional/capi/fixtures/kernel.rb19
-rw-r--r--spec/ruby/optional/capi/fixtures/module.rb4
-rw-r--r--spec/ruby/optional/capi/fixtures/object.rb29
-rw-r--r--spec/ruby/optional/capi/fixtures/read.txt1
-rw-r--r--spec/ruby/optional/capi/float_spec.rb17
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb122
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb114
-rw-r--r--spec/ruby/optional/capi/hash_spec.rb129
-rw-r--r--spec/ruby/optional/capi/integer_spec.rb34
-rw-r--r--spec/ruby/optional/capi/io_spec.rb519
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb652
-rw-r--r--spec/ruby/optional/capi/language_spec.rb37
-rw-r--r--spec/ruby/optional/capi/module_spec.rb128
-rw-r--r--spec/ruby/optional/capi/mutex_spec.rb54
-rw-r--r--spec/ruby/optional/capi/numeric_spec.rb322
-rw-r--r--spec/ruby/optional/capi/object_spec.rb468
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb132
-rw-r--r--spec/ruby/optional/capi/range_spec.rb158
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb48
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb59
-rw-r--r--spec/ruby/optional/capi/set_spec.rb96
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb27
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb94
-rw-r--r--spec/ruby/optional/capi/string_spec.rb979
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb145
-rw-r--r--spec/ruby/optional/capi/symbol_spec.rb47
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb90
-rw-r--r--spec/ruby/optional/capi/time_spec.rb173
-rw-r--r--spec/ruby/optional/capi/tracepoint_spec.rb56
-rw-r--r--spec/ruby/optional/capi/typed_data_spec.rb53
-rw-r--r--spec/ruby/optional/capi/util_spec.rb157
-rw-r--r--spec/ruby/optional/thread_safety/fixtures/classes.rb39
-rw-r--r--spec/ruby/optional/thread_safety/hash_spec.rb210
-rw-r--r--spec/ruby/security/cve_2010_1330_spec.rb10
-rw-r--r--spec/ruby/security/cve_2011_4815_spec.rb4
-rw-r--r--spec/ruby/security/cve_2013_4164_spec.rb4
-rw-r--r--spec/ruby/security/cve_2014_8080_spec.rb32
-rw-r--r--spec/ruby/security/cve_2017_17742_spec.rb34
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb14
-rw-r--r--spec/ruby/security/cve_2018_6914_spec.rb61
-rw-r--r--spec/ruby/security/cve_2018_8778_spec.rb6
-rw-r--r--spec/ruby/security/cve_2018_8779_spec.rb8
-rw-r--r--spec/ruby/security/cve_2018_8780_spec.rb42
-rw-r--r--spec/ruby/security/cve_2019_8321_spec.rb20
-rw-r--r--spec/ruby/security/cve_2019_8322_spec.rb24
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb46
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb46
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb49
-rw-r--r--spec/ruby/security/cve_2024_49761_spec.rb7
-rw-r--r--spec/ruby/shared/basicobject/method_missing.rb18
-rw-r--r--spec/ruby/shared/basicobject/send.rb29
-rw-r--r--spec/ruby/shared/enumerable/minmax.rb24
-rw-r--r--spec/ruby/shared/enumerator/each.rb89
-rw-r--r--spec/ruby/shared/enumerator/enum_cons.rb12
-rw-r--r--spec/ruby/shared/enumerator/enum_for.rb50
-rw-r--r--spec/ruby/shared/enumerator/new.rb42
-rw-r--r--spec/ruby/shared/enumerator/next.rb28
-rw-r--r--spec/ruby/shared/enumerator/rewind.rb39
-rw-r--r--spec/ruby/shared/enumerator/with_index.rb32
-rw-r--r--spec/ruby/shared/enumerator/with_object.rb42
-rw-r--r--spec/ruby/shared/fiber/resume.rb79
-rw-r--r--spec/ruby/shared/file/directory.rb18
-rw-r--r--spec/ruby/shared/file/executable.rb45
-rw-r--r--spec/ruby/shared/file/executable_real.rb43
-rw-r--r--spec/ruby/shared/file/exist.rb11
-rw-r--r--spec/ruby/shared/file/file.rb8
-rw-r--r--spec/ruby/shared/file/grpowned.rb9
-rw-r--r--spec/ruby/shared/file/identical.rb24
-rw-r--r--spec/ruby/shared/file/readable.rb21
-rw-r--r--spec/ruby/shared/file/readable_real.rb16
-rw-r--r--spec/ruby/shared/file/size.rb4
-rw-r--r--spec/ruby/shared/file/socket.rb32
-rw-r--r--spec/ruby/shared/file/sticky.rb2
-rw-r--r--spec/ruby/shared/file/world_readable.rb20
-rw-r--r--spec/ruby/shared/file/world_writable.rb20
-rw-r--r--spec/ruby/shared/file/writable.rb18
-rw-r--r--spec/ruby/shared/file/writable_real.rb24
-rw-r--r--spec/ruby/shared/file/zero.rb10
-rw-r--r--spec/ruby/shared/hash/key_error.rb30
-rw-r--r--spec/ruby/shared/io/putc.rb12
-rw-r--r--spec/ruby/shared/kernel/at_exit.rb73
-rw-r--r--spec/ruby/shared/kernel/complex.rb133
-rw-r--r--spec/ruby/shared/kernel/equal.rb4
-rw-r--r--spec/ruby/shared/kernel/fixtures/END.rb3
-rw-r--r--spec/ruby/shared/kernel/fixtures/at_exit.rb3
-rw-r--r--spec/ruby/shared/kernel/object_id.rb30
-rw-r--r--spec/ruby/shared/kernel/raise.rb382
-rw-r--r--spec/ruby/shared/math/atanh.rb44
-rw-r--r--spec/ruby/shared/process/abort.rb12
-rw-r--r--spec/ruby/shared/process/exit.rb58
-rw-r--r--spec/ruby/shared/process/fork.rb43
-rw-r--r--spec/ruby/shared/queue/clear.rb12
-rw-r--r--spec/ruby/shared/queue/close.rb14
-rw-r--r--spec/ruby/shared/queue/closed.rb12
-rw-r--r--spec/ruby/shared/queue/deque.rb164
-rw-r--r--spec/ruby/shared/queue/empty.rb12
-rw-r--r--spec/ruby/shared/queue/enque.rb18
-rw-r--r--spec/ruby/shared/queue/freeze.rb8
-rw-r--r--spec/ruby/shared/queue/length.rb (renamed from spec/ruby/library/thread/shared/queue/length.rb)0
-rw-r--r--spec/ruby/shared/queue/num_waiting.rb (renamed from spec/ruby/library/thread/shared/queue/num_waiting.rb)0
-rw-r--r--spec/ruby/shared/rational/Rational.rb103
-rw-r--r--spec/ruby/shared/rational/abs.rb11
-rw-r--r--spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb33
-rw-r--r--spec/ruby/shared/rational/ceil.rb45
-rw-r--r--spec/ruby/shared/rational/coerce.rb21
-rw-r--r--spec/ruby/shared/rational/comparison.rb117
-rw-r--r--spec/ruby/shared/rational/denominator.rb14
-rw-r--r--spec/ruby/shared/rational/div.rb54
-rw-r--r--spec/ruby/shared/rational/divide.rb71
-rw-r--r--spec/ruby/shared/rational/divmod.rb42
-rw-r--r--spec/ruby/shared/rational/equal_value.rb39
-rw-r--r--spec/ruby/shared/rational/exponent.rb178
-rw-r--r--spec/ruby/shared/rational/fdiv.rb5
-rw-r--r--spec/ruby/shared/rational/floor.rb45
-rw-r--r--spec/ruby/shared/rational/hash.rb9
-rw-r--r--spec/ruby/shared/rational/inspect.rb14
-rw-r--r--spec/ruby/shared/rational/marshal_dump.rb5
-rw-r--r--spec/ruby/shared/rational/marshal_load.rb5
-rw-r--r--spec/ruby/shared/rational/minus.rb48
-rw-r--r--spec/ruby/shared/rational/modulo.rb43
-rw-r--r--spec/ruby/shared/rational/multiply.rb62
-rw-r--r--spec/ruby/shared/rational/numerator.rb10
-rw-r--r--spec/ruby/shared/rational/plus.rb48
-rw-r--r--spec/ruby/shared/rational/quo.rb5
-rw-r--r--spec/ruby/shared/rational/remainder.rb5
-rw-r--r--spec/ruby/shared/rational/round.rb99
-rw-r--r--spec/ruby/shared/rational/to_f.rb10
-rw-r--r--spec/ruby/shared/rational/to_i.rb12
-rw-r--r--spec/ruby/shared/rational/to_r.rb11
-rw-r--r--spec/ruby/shared/rational/to_s.rb14
-rw-r--r--spec/ruby/shared/rational/truncate.rb45
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb129
-rw-r--r--spec/ruby/shared/sizedqueue/max.rb47
-rw-r--r--spec/ruby/shared/sizedqueue/new.rb23
-rw-r--r--spec/ruby/shared/sizedqueue/num_waiting.rb12
-rw-r--r--spec/ruby/shared/string/end_with.rb61
-rw-r--r--spec/ruby/shared/string/start_with.rb76
-rw-r--r--spec/ruby/shared/string/times.rb44
-rw-r--r--spec/ruby/shared/time/strftime_for_date.rb10
-rw-r--r--spec/ruby/shared/time/strftime_for_time.rb8
-rw-r--r--spec/ruby/shared/time/yday.rb18
-rw-r--r--spec/ruby/shared/types/rb_num2dbl_fails.rb17
-rw-r--r--spec/ruby/spec_helper.rb12
-rw-r--r--spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt74
-rwxr-xr-xspec/syntax_suggest/fixtures/rexe.rb.txt569
-rw-r--r--spec/syntax_suggest/fixtures/routes.rb.txt121
-rw-r--r--spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt1344
-rw-r--r--spec/syntax_suggest/fixtures/syntax_tree.rb.txt9234
-rw-r--r--spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt64
-rw-r--r--spec/syntax_suggest/fixtures/webmock.rb.txt35
-rw-r--r--spec/syntax_suggest/integration/exe_cli_spec.rb27
-rw-r--r--spec/syntax_suggest/integration/ruby_command_line_spec.rb189
-rw-r--r--spec/syntax_suggest/integration/syntax_suggest_spec.rb260
-rw-r--r--spec/syntax_suggest/spec_helper.rb117
-rw-r--r--spec/syntax_suggest/unit/api_spec.rb104
-rw-r--r--spec/syntax_suggest/unit/around_block_scan_spec.rb165
-rw-r--r--spec/syntax_suggest/unit/block_expand_spec.rb230
-rw-r--r--spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb47
-rw-r--r--spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb44
-rw-r--r--spec/syntax_suggest/unit/capture_code_context_spec.rb229
-rw-r--r--spec/syntax_suggest/unit/clean_document_spec.rb260
-rw-r--r--spec/syntax_suggest/unit/cli_spec.rb224
-rw-r--r--spec/syntax_suggest/unit/code_block_spec.rb77
-rw-r--r--spec/syntax_suggest/unit/code_frontier_spec.rb135
-rw-r--r--spec/syntax_suggest/unit/code_line_spec.rb164
-rw-r--r--spec/syntax_suggest/unit/code_search_spec.rb505
-rw-r--r--spec/syntax_suggest/unit/core_ext_spec.rb32
-rw-r--r--spec/syntax_suggest/unit/display_invalid_blocks_spec.rb174
-rw-r--r--spec/syntax_suggest/unit/explain_syntax_spec.rb283
-rw-r--r--spec/syntax_suggest/unit/mini_stringio_spec.rb25
-rw-r--r--spec/syntax_suggest/unit/pathname_from_message_spec.rb65
-rw-r--r--spec/syntax_suggest/unit/priority_queue_spec.rb95
-rw-r--r--spec/syntax_suggest/unit/scan_history_spec.rb114
-rw-r--r--spec/syntax_suggest/unit/visitor_spec.rb119
4844 files changed, 171149 insertions, 99461 deletions
diff --git a/spec/README.md b/spec/README.md
index 59c2c605c5..6a88c06e09 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -1,14 +1,23 @@
# spec/bundler
-spec/bundler is rspec examples for bundler library(lib/bundler.rb, lib/bundler/*).
+spec/bundler is rspec examples for bundler library (`lib/bundler.rb`, `lib/bundler/*`).
## Running spec/bundler
To run rspec for bundler:
+
```bash
make test-bundler
```
+or run rspec with parallel execution:
+
+```bash
+make test-bundler-parallel
+```
+
+If you specify `BUNDLER_SPECS=foo/bar_spec.rb` then only `spec/bundler/foo/bar_spec.rb` will be run.
+
# spec/ruby
ruby/spec (https://github.com/ruby/spec/) is
@@ -30,41 +39,80 @@ In other words: If adding a spec might reveal a bug in
another implementation, then it is worth adding it.
Currently, the only module which is MRI-specific is `RubyVM`.
+## Changing behavior and versions guards
+
Version guards (`ruby_version_is`) must be added for new features or features
-which change behavior or are removed. See `spec/ruby/CONTRIBUTING.md` for details.
+which change behavior or are removed. This is necessary for other Ruby implementations
+to still be able to run the specs and contribute new specs.
-To verify specs are compatible with older Ruby versions:
+For example, change:
+
+```ruby
+describe "Some spec" do
+ it "some example" do
+ # Old behavior for Ruby < 2.7
+ end
+end
```
+
+to:
+
+```ruby
+describe "Some spec" do
+ ruby_version_is ""..."2.7" do
+ it "some example" do
+ # Old behavior for Ruby < 2.7
+ end
+ end
+
+ ruby_version_is "2.7" do
+ it "some example" do
+ # New behavior for Ruby >= 2.7
+ end
+ end
+end
+```
+
+See `spec/ruby/CONTRIBUTING.md` for more documentation about guards.
+
+To verify specs are compatible with older Ruby versions:
+
+```bash
cd spec/ruby
-$RUBY_MANAGER use 2.3.7
+$RUBY_MANAGER use 2.4.9
../mspec/bin/mspec -j
```
## Running ruby/spec
To run all specs:
+
```bash
make test-spec
```
-Extra arguments can be added via `MSPECOPT`.
+Extra arguments can be added via `SPECOPTS`.
For instance, to show the help:
+
```bash
-make test-spec MSPECOPT=-h
+make test-spec SPECOPTS=-h
```
You can also run the specs in parallel, which is currently experimental.
It takes around 10s instead of 60s on a quad-core laptop.
+
```bash
-make test-spec MSPECOPT=-j
+make test-spec SPECOPTS=-j
```
To run a specific test, add its path to the command:
+
```bash
-make test-spec MSPECOPT=spec/ruby/language/for_spec.rb
+make test-spec SPECOPTS=spec/ruby/language/for_spec.rb
```
If ruby trunk is your current `ruby` in `$PATH`, you can also run `mspec` directly:
+
```bash
# change ruby to trunk
ruby -v # => trunk
@@ -73,8 +121,8 @@ spec/mspec/bin/mspec spec/ruby/language/for_spec.rb
## ruby/spec and test/
-The main difference between a "spec" under spec/ruby and
-a test under test/ is that specs are documenting what they test.
+The main difference between a "spec" under `spec/ruby/` and
+a test under `test/` is that specs are documenting what they test.
This is extremely valuable when reading these tests, as it
helps to quickly understand what specific behavior is tested,
and how a method should behave. Basic English is fine for spec descriptions.
@@ -97,4 +145,16 @@ describe "The for expression" do
end
```
-For more details, see spec/ruby/CONTRIBUTING.md.
+For more details, see `spec/ruby/CONTRIBUTING.md`.
+
+# spec/syntax_suggest
+
+## Running spec/syntax_suggest
+
+To run rspec for syntax_suggest:
+
+```bash
+make test-syntax-suggest
+```
+
+If you specify `SYNTAX_SUGGEST_SPECS=foo/bar_spec.rb` then only `spec/syntax_suggest/foo/bar_spec.rb` will be run.
diff --git a/spec/bin/bundle b/spec/bin/bundle
new file mode 100755
index 0000000000..8f8b535295
--- /dev/null
+++ b/spec/bin/bundle
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/activate"
+
+load File.expand_path("bundle", Spec::Path.exedir)
diff --git a/spec/bin/parallel_rspec b/spec/bin/parallel_rspec
new file mode 100755
index 0000000000..412defa58b
--- /dev/null
+++ b/spec/bin/parallel_rspec
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/setup"
+
+require "turbo_tests"
+TurboTests::CLI.new(ARGV).run
diff --git a/spec/bin/rspec b/spec/bin/rspec
new file mode 100755
index 0000000000..a41aa4896a
--- /dev/null
+++ b/spec/bin/rspec
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/switch_rubygems"
+require_relative "../bundler/support/rubygems_ext"
+
+Spec::Rubygems.gem_load("rspec-core", "rspec")
diff --git a/spec/bundled_gems.mspec b/spec/bundled_gems.mspec
new file mode 100644
index 0000000000..f7edb34c75
--- /dev/null
+++ b/spec/bundled_gems.mspec
@@ -0,0 +1,14 @@
+load File.dirname(__FILE__) + '/default.mspec'
+
+class MSpecScript
+ test_bundled_gems = get(:stdlibs).to_a & get(:bundled_gems).to_a
+ unless ENV["BUNDLED_GEMS"].nil? || ENV["BUNDLED_GEMS"].empty?
+ test_bundled_gems = ENV["BUNDLED_GEMS"].split(",").map do |gem|
+ gem = "openstruct" if gem == "ostruct"
+ test_bundled_gems.find{|test_gem| test_gem.include?(gem) }
+ end.compact
+ exit if test_bundled_gems.empty?
+ end
+ set :library, test_bundled_gems
+ set :files, get(:library)
+end
diff --git a/spec/bundled_gems_spec.rb b/spec/bundled_gems_spec.rb
new file mode 100644
index 0000000000..9af06dd181
--- /dev/null
+++ b/spec/bundled_gems_spec.rb
@@ -0,0 +1,422 @@
+require "bundled_gems"
+
+require "bundler"
+require "fileutils"
+
+require_relative "bundler/support/builders"
+require_relative "bundler/support/helpers"
+require_relative "bundler/support/path"
+
+module Gem
+ def self.ruby=(ruby)
+ @ruby = ruby
+ end
+end
+
+RSpec.configure do |config|
+ config.include Spec::Builders
+ config.include Spec::Helpers
+ config.include Spec::Path
+
+ config.before(:suite) do
+ Gem.ruby = ENV["RUBY"] if ENV["RUBY"]
+
+ require_relative "bundler/support/rubygems_ext"
+ Spec::Helpers.install_dev_bundler
+ FileUtils.mkdir_p Spec::Path.gem_path
+ end
+
+ config.around(:each) do |example|
+ FileUtils.cp_r Spec::Path.pristine_system_gem_path, Spec::Path.system_gem_path
+
+ with_gem_path_as(system_gem_path) do
+ Bundler.ui.silence { example.run }
+
+ all_output = all_commands_output
+ if example.exception && !all_output.empty?
+ message = all_output + "\n" + example.exception.message
+ (class << example.exception; self; end).send(:define_method, :message) do
+ message
+ end
+ end
+ end
+ ensure
+ reset!
+ end
+
+ config.after :suite do
+ FileUtils.rm_rf Spec::Path.pristine_system_gem_path
+ end
+end
+
+RSpec.describe "bundled_gems.rb" do
+ let(:stub_code) {
+ source_lib_dir = File.realpath(Spec::Path.source_lib_dir.to_s)
+ <<~STUB
+ Gem::BUNDLED_GEMS.send(:remove_const, :LIBDIR)
+ Gem::BUNDLED_GEMS.send(:remove_const, :ARCHDIR)
+ Gem::BUNDLED_GEMS.send(:remove_const, :SINCE)
+ Gem::BUNDLED_GEMS.const_set(:LIBDIR, "#{source_lib_dir}/")
+ Gem::BUNDLED_GEMS.const_set(:ARCHDIR, File.expand_path($LOAD_PATH.find{|path| path.include?(".ext/common") }) + "/")
+ Gem::BUNDLED_GEMS.const_set(:SINCE, { "openssl" => RUBY_VERSION, "fileutils" => RUBY_VERSION, "csv" => "3.4.0", "net-smtp" => "3.1.0" })
+ STUB
+ }
+
+ def script(code, options = {})
+ options[:artifice] ||= "compact_index"
+ code = <<~RUBY
+ #{stub_code}
+ require 'bundler/inline'
+
+ #{code}
+ RUBY
+ ruby(code, options)
+ end
+
+ it "Show warning require and LoadError" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ begin
+ require "csv"
+ rescue LoadError
+ end
+ require "openssl"
+ RUBY
+
+ expect(err).to include(/csv used to be loaded from (.*) since Ruby 3.4.0/)
+ expect(err).to include(/-e:15/)
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:18/)
+ end
+
+ it "Show warning when bundled gems called as dependency" do
+ build_lib "activesupport", "7.0.7.2" do |s|
+ s.write "lib/active_support/all.rb", "require 'openssl'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "activesupport", "7.0.7.2"
+ end
+ end
+
+ require "active_support/all"
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/lib\/active_support\/all\.rb:1/)
+ end
+
+ it "Show warning dash gem like net/smtp" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ begin
+ require "net/smtp"
+ rescue LoadError
+ end
+ RUBY
+
+ expect(err).to include(/net\/smtp used to be loaded from (.*) since Ruby 3.1.0/)
+ expect(err).to include(/-e:15/)
+ expect(err).to include("You can add net-smtp")
+ end
+
+ it "Show warning sub-feature like openssl/bn" do
+ skip "This test is not working on Windows" if Gem.win_platform?
+
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ require "openssl/bn"
+ RUBY
+
+ expect(err).to include(/openssl\/bn is found in openssl, (.*) part of the default gems since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:14/)
+ end
+
+ it "Show warning when bundle exec with ruby and script" do
+ code = <<-RUBY
+ #{stub_code}
+ require "openssl"
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+
+ bundle "exec ruby script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:8/)
+ end
+
+ it "Show warning when bundle exec with shebang's script" do
+ skip "This test is not working on Windows" if Gem.win_platform?
+
+ code = <<-RUBY
+ #!/usr/bin/env ruby
+ #{stub_code}
+ require "openssl"
+ RUBY
+ create_file("script.rb", code)
+ FileUtils.chmod(0o777, bundled_app("script.rb"))
+ create_file("Gemfile", "source 'https://rubygems.org'")
+
+ bundle "exec ./script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:9/)
+ end
+
+ it "Show warning when bundle exec with -r option" do
+ create_file("stub.rb", stub_code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ bundle "exec ruby -r./stub -ropenssl -e ''"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ end
+
+ it "Show warning when warn is not the standard one in the current scope" do
+ script <<-RUBY
+ module My
+ def warn(msg)
+ end
+
+ def my
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ require "openssl"
+ end
+
+ extend self
+ end
+
+ My.my
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:19/)
+ end
+
+ it "Don't show warning when bundled gems called as dependency" do
+ build_lib "activesupport", "7.0.7.2" do |s|
+ s.write "lib/active_support/all.rb", "require 'openssl'"
+ end
+ build_lib "openssl", "1.0.0" do |s|
+ s.write "lib/openssl.rb", "puts 'openssl'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "activesupport", "7.0.7.2"
+ gem "openssl"
+ end
+ end
+
+ require "active_support/all"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "Show warning with bootsnap cases" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ # require 'openssl'
+ require Gem::BUNDLED_GEMS::ARCHDIR + 'openssl'
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # test_warn_bootsnap.rb:14: warning: ...
+ end
+
+ it "Show warning with bootsnap for gem with native extension" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ # require 'openssl'
+ require Gem::BUNDLED_GEMS::ARCHDIR + "openssl"
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # test_warn_bootsnap_rubyarchdir_gem.rb:14: warning: ...
+ end
+
+ it "Show warning with bootsnap and some gem in Gemfile" do
+ # Original issue is childprocess 5.0.0 and logger.
+ build_lib "fileutils2", "5.0.0" do |s|
+ # bootsnap expand required feature to full path
+ rubylibpath = File.realpath(File.join(__dir__, "..", "lib"))
+ s.write "lib/fileutils2.rb", "require '#{rubylibpath}/fileutils'"
+ end
+
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ path "#{lib_path}" do
+ gem "fileutils2", "5.0.0"
+ end
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ require Gem.loaded_specs["fileutils2"].full_gem_path + '/lib/fileutils2'
+ RUBY
+
+ expect(err).to include(/fileutils used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # $GEM_HOME/gems/childprocess-5.0.0/lib/childprocess.rb:7: warning:
+ end
+
+ it "Show warning with zeitwerk" do
+ libpath = Dir[File.expand_path("../.bundle/gems/{zeitwerk}-*/lib", __dir__)].map(&:to_s).first
+ code = <<-RUBY
+ #{stub_code}
+ $LOAD_PATH.unshift("#{libpath}")
+ require "zeitwerk"
+ loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
+ loader.setup
+
+ require 'openssl'
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ bundle "exec ruby script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:13/)
+ end
+
+ it "Don't show warning openssl/bn when openssl on Gemfile" do
+ build_lib "openssl", "1.0.0" do |s|
+ s.write "lib/openssl.rb", "puts 'openssl'"
+ s.write "lib/openssl/bn.rb", "puts 'openssl/bn'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "openssl"
+ end
+ end
+
+ require "openssl/bn"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "Don't show warning with net/smtp when net-smtp on Gemfile" do
+ build_lib "net-smtp", "1.0.0" do |s|
+ s.write "lib/net/smtp.rb", "puts 'net-smtp'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "net-smtp"
+ end
+ end
+
+ require "net/smtp"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ describe ".force_activate" do
+ before do
+ allow_any_instance_of(Bundler::Runtime).to receive(:setup).and_raise(Bundler::GemNotFound)
+ end
+
+ context "with bundle environment" do
+ before do
+ code = <<-RUBY
+ #!/usr/bin/env ruby
+
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ end
+
+ it "lockfile is available" do
+ bundle "install"
+ bundle "exec ./script.rb"
+
+ expect(err).to include("gem install csv")
+ end
+
+ it "lockfile is not available" do
+ bundle "exec ./script.rb"
+
+ expect(err).to include("gem install csv")
+ end
+ end
+
+ context "with bundler/inline" do
+ it "foo is available on LOAD_PATH" do
+ build_lib "foo", "1.0.0" do |s|
+ s.write "lib/foo.rb", "puts :foo"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ #!/usr/bin/env ruby
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "foo", "1.0.0"
+ end
+ end
+
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ puts $LOAD_PATH
+ RUBY
+
+ expect(err).to include("gem install csv")
+ expect(out).to include("foo-1.0.0/lib")
+ end
+ end
+
+ context "without bundle environment" do
+ it "warns about installation requirement" do
+ expect_any_instance_of(Object).to receive(:warn)
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/build_metadata_spec.rb b/spec/bundler/bundler/build_metadata_spec.rb
new file mode 100644
index 0000000000..2e69821f68
--- /dev/null
+++ b/spec/bundler/bundler/build_metadata_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require "bundler"
+require "bundler/build_metadata"
+
+RSpec.describe Bundler::BuildMetadata do
+ before do
+ allow(Time).to receive(:now).and_return(Time.at(0))
+ Bundler::BuildMetadata.instance_variable_set(:@timestamp, nil)
+ end
+
+ describe "#timestamp" do
+ it "returns %Y-%m-%d formatted current time if built_at not set" do
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, nil)
+ expect(Bundler::BuildMetadata.timestamp).to eq "1970-01-01"
+ end
+
+ it "returns %Y-%m-%d formatted current time if built_at not set" do
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, "2025-01-01")
+ expect(Bundler::BuildMetadata.timestamp).to eq "2025-01-01"
+ ensure
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, nil)
+ end
+ end
+
+ describe "#git_commit_sha" do
+ context "if instance valuable is defined" do
+ before do
+ Bundler::BuildMetadata.instance_variable_set(:@git_commit_sha, "foo")
+ end
+
+ after do
+ Bundler::BuildMetadata.remove_instance_variable(:@git_commit_sha)
+ end
+
+ it "returns set value" do
+ expect(Bundler::BuildMetadata.git_commit_sha).to eq "foo"
+ end
+ end
+ end
+
+ describe "#to_h" do
+ subject { Bundler::BuildMetadata.to_h }
+
+ it "returns a hash includes Timestamp, and Git SHA" do
+ expect(subject["Timestamp"]).to eq "1970-01-01"
+ expect(subject["Git SHA"]).to be_instance_of(String)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 194d6752b2..bddcbdaef3 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -1,10 +1,74 @@
-# encoding: utf-8
# frozen_string_literal: true
require "bundler"
require "tmpdir"
RSpec.describe Bundler do
+ describe "#load_marshal" do
+ it "is a private method and raises an error" do
+ data = Marshal.dump(Bundler)
+ expect { Bundler.load_marshal(data) }.to raise_error(NoMethodError, /private method [`']load_marshal' called/)
+ end
+
+ it "loads any data" do
+ data = Marshal.dump(Bundler)
+ expect(Bundler.send(:load_marshal, data)).to eq(Bundler)
+ end
+ end
+
+ describe "#safe_load_marshal" do
+ it "fails on unexpected class" do
+ data = Marshal.dump(Bundler)
+ expect { Bundler.safe_load_marshal(data) }.to raise_error(Bundler::MarshalError)
+ end
+
+ it "loads simple structure" do
+ simple_structure = { "name" => [:development] }
+ data = Marshal.dump(simple_structure)
+ expect(Bundler.safe_load_marshal(data)).to eq(simple_structure)
+ end
+
+ it "loads Gem::Specification" do
+ gem_spec = Gem::Specification.new do |s|
+ s.name = "bundler"
+ s.version = Gem::Version.new("2.4.7")
+ s.installed_by_version = Gem::Version.new("0")
+ s.authors = ["André Arko",
+ "Samuel Giddins",
+ "Colby Swandale",
+ "Hiroshi Shibata",
+ "David Rodríguez",
+ "Grey Baker",
+ "Stephanie Morillo",
+ "Chris Morris",
+ "James Wen",
+ "Tim Moore",
+ "André Medeiros",
+ "Jessica Lynn Suttles",
+ "Terence Lee",
+ "Carl Lerche",
+ "Yehuda Katz"]
+ s.date = Time.utc(2023, 2, 15)
+ s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
+ s.email = ["team@bundler.io"]
+ s.homepage = "https://bundler.io"
+ s.metadata = { "bug_tracker_uri" => "https://github.com/ruby/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/ruby/rubygems/blob/master/bundler/CHANGELOG.md",
+ "homepage_uri" => "https://bundler.io/",
+ "source_code_uri" => "https://github.com/ruby/rubygems/tree/master/bundler" }
+ s.require_paths = ["lib"]
+ s.required_ruby_version = Gem::Requirement.new([">= 2.6.0"])
+ s.required_rubygems_version = Gem::Requirement.new([">= 3.0.1"])
+ s.rubygems_version = "3.4.7"
+ s.specification_version = 4
+ s.summary = "The best way to manage your application's dependencies"
+ s.license = false
+ end
+ data = Marshal.dump(gem_spec)
+ expect(Bundler.safe_load_marshal(data)).to eq(gem_spec)
+ end
+ end
+
describe "#load_gemspec_uncached" do
let(:app_gemspec_path) { tmp("test.gemspec") }
subject { Bundler.load_gemspec_uncached(app_gemspec_path) }
@@ -12,7 +76,7 @@ RSpec.describe Bundler do
context "with incorrect YAML file" do
before do
File.open(app_gemspec_path, "wb") do |f|
- f.write strip_whitespace(<<-GEMSPEC)
+ f.write <<~GEMSPEC
---
{:!00 ao=gu\g1= 7~f
GEMSPEC
@@ -22,33 +86,9 @@ RSpec.describe Bundler do
it "catches YAML syntax errors" do
expect { subject }.to raise_error(Bundler::GemspecError, /error while loading `test.gemspec`/)
end
-
- context "on Rubies with a settable YAML engine", :if => defined?(YAML::ENGINE) do
- context "with Syck as YAML::Engine" do
- it "raises a GemspecError after YAML load throws ArgumentError" do
- orig_yamler = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = "syck"
-
- expect { subject }.to raise_error(Bundler::GemspecError)
-
- YAML::ENGINE.yamler = orig_yamler
- end
- end
-
- context "with Psych as YAML::Engine" do
- it "raises a GemspecError after YAML load throws Psych::SyntaxError" do
- orig_yamler = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = "psych"
-
- expect { subject }.to raise_error(Bundler::GemspecError)
-
- YAML::ENGINE.yamler = orig_yamler
- end
- end
- end
end
- context "with correct YAML file", :if => defined?(Encoding) do
+ context "with correct YAML file", if: defined?(Encoding) do
it "can load a gemspec with unicode characters with default ruby encoding" do
# spec_helper forces the external encoding to UTF-8 but that's not the
# default until Ruby 2.0
@@ -59,7 +99,7 @@ RSpec.describe Bundler do
$VERBOSE = verbose
File.open(app_gemspec_path, "wb") do |file|
- file.puts <<-GEMSPEC.gsub(/^\s+/, "")
+ file.puts <<~GEMSPEC
# -*- encoding: utf-8 -*-
Gem::Specification.new do |gem|
gem.author = "André the Giant"
@@ -99,7 +139,7 @@ RSpec.describe Bundler do
end
GEMSPEC
end
- expect(Bundler.rubygems).to receive(:validate).with have_attributes(:name => "validated")
+ expect(Bundler.rubygems).to receive(:validate).with have_attributes(name: "validated")
subject
end
end
@@ -107,7 +147,7 @@ RSpec.describe Bundler do
context "with gemspec containing local variables" do
before do
File.open(app_gemspec_path, "wb") do |f|
- f.write strip_whitespace(<<-GEMSPEC)
+ f.write <<~GEMSPEC
must_not_leak = true
Gem::Specification.new do |gem|
gem.name = "leak check"
@@ -124,68 +164,45 @@ RSpec.describe Bundler do
end
describe "#which" do
- let(:executable) { "executable" }
- let(:path) { %w[/a /b c ../d /e] }
- let(:expected) { "executable" }
-
- before do
- ENV["PATH"] = path.join(File::PATH_SEPARATOR)
-
- allow(File).to receive(:file?).and_return(false)
- allow(File).to receive(:executable?).and_return(false)
- if expected
- expect(File).to receive(:file?).with(expected).and_return(true)
- expect(File).to receive(:executable?).with(expected).and_return(true)
- end
- end
+ it "can detect relative path" do
+ script_path = bundled_app("tmp/test_command")
+ create_file(script_path, "#!/usr/bin/env ruby\n")
- subject { described_class.which(executable) }
+ result = Dir.chdir script_path.dirname.dirname do
+ Bundler.which("test_command")
+ end
+ expect(result).to eq(nil)
- shared_examples_for "it returns the correct executable" do
- it "returns the expected file" do
- expect(subject).to eq(expected)
+ result = Dir.chdir script_path.dirname do
+ Bundler.which("test_command")
end
+
+ expect(result).to eq("test_command") unless Gem.win_platform?
+ expect(result).to eq("test_command.bat") if Gem.win_platform?
end
- it_behaves_like "it returns the correct executable"
+ it "can detect absolute path" do
+ create_file("test_command", "#!/usr/bin/env ruby\n")
- context "when the executable in inside a quoted path" do
- let(:expected) { "/e/executable" }
- it_behaves_like "it returns the correct executable"
+ ENV["PATH"] = bundled_app("test_command").parent.to_s
+
+ result = Bundler.which("test_command")
+ expect(result).to eq(bundled_app("test_command").to_s) unless Gem.win_platform?
+ expect(result).to eq(bundled_app("test_command.bat").to_s) if Gem.win_platform?
end
- context "when the executable is not found" do
- let(:expected) { nil }
- it_behaves_like "it returns the correct executable"
+ it "returns nil when not found" do
+ result = Bundler.which("test_command")
+ expect(result).to eq(nil)
end
end
describe "configuration" do
context "disable_shared_gems" do
it "should unset GEM_PATH with empty string" do
- env = {}
expect(Bundler).to receive(:use_system_gems?).and_return(false)
- Bundler.send(:configure_gem_path, env)
- expect(env.keys).to include("GEM_PATH")
- expect(env["GEM_PATH"]).to eq ""
- end
- end
- end
-
- describe "#rm_rf" do
- context "the directory is world writable" do
- let(:bundler_ui) { Bundler.ui }
- it "should raise a friendly error" do
- allow(File).to receive(:exist?).and_return(true)
- allow(bundler_fileutils).to receive(:remove_entry_secure).and_raise(ArgumentError)
- allow(File).to receive(:world_writable?).and_return(true)
- message = <<EOF
-It is a security vulnerability to allow your home directory to be world-writable, and bundler can not continue.
-You should probably consider fixing this issue by running `chmod o-w ~` on *nix.
-Please refer to http://ruby-doc.org/stdlib-2.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details.
-EOF
- expect(bundler_ui).to receive(:warn).with(message)
- expect { Bundler.send(:rm_rf, bundled_app) }.to raise_error(Bundler::PathError)
+ Bundler.send(:configure_gem_path)
+ expect(ENV["GEM_PATH"]).to eq ""
end
end
end
@@ -193,28 +210,14 @@ EOF
describe "#mkdir_p" do
it "creates a folder at the given path" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- Bundler.mkdir_p(bundled_app.join("foo", "bar"))
- expect(bundled_app.join("foo", "bar")).to exist
- end
-
- context "when mkdir_p requires sudo" do
- it "creates a new folder using sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to receive(:sudo).and_return true
- Bundler.mkdir_p(bundled_app.join("foo"))
- end
- end
+ allow(Bundler).to receive(:root).and_return(bundled_app)
- context "with :no_sudo option" do
- it "forces mkdir_p to not use sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to_not receive(:sudo)
- Bundler.mkdir_p(bundled_app.join("foo"), :no_sudo => true)
- end
+ Bundler.mkdir_p(bundled_app("foo", "bar"))
+ expect(bundled_app("foo", "bar")).to exist
end
end
@@ -233,16 +236,10 @@ EOF
path = "/home/oggy"
allow(Bundler.rubygems).to receive(:user_home).and_return(path)
allow(File).to receive(:directory?).with(path).and_return false
- allow(Etc).to receive(:getlogin).and_return("USER")
- allow(Dir).to receive(:tmpdir).and_return("/TMP")
- allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
- expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
- message = <<EOF
-`/home/oggy` is not a directory.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not a directory.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
+ expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
@@ -253,18 +250,13 @@ EOF
it "should issue a warning and return a temporary user home" do
allow(Bundler.rubygems).to receive(:user_home).and_return(path)
allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).and_call_original
allow(File).to receive(:writable?).with(path).and_return false
allow(File).to receive(:directory?).with(dotbundle).and_return false
- allow(Etc).to receive(:getlogin).and_return("USER")
- allow(Dir).to receive(:tmpdir).and_return("/TMP")
- allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
- expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
- message = <<EOF
-`/home/oggy` is not writable.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not writable.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
+ expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
context ".bundle exists and have correct permissions" do
@@ -283,149 +275,10 @@ EOF
context "home directory is not set" do
it "should issue warning and return a temporary user home" do
allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
- allow(Etc).to receive(:getlogin).and_return("USER")
- allow(Dir).to receive(:tmpdir).and_return("/TMP")
- allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
- expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
- message = <<EOF
-Your home directory is not set.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
- end
- end
- end
-
- describe "#tmp_home_path" do
- it "should create temporary user home" do
- allow(Dir).to receive(:tmpdir).and_return("/TMP")
- allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(false)
- expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home")
- expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home/USER")
- expect(File).to receive(:chmod).with(0o777, "/TMP/bundler/home")
- expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER"))
- end
- end
-
- describe "#requires_sudo?" do
- let!(:tmpdir) { Dir.mktmpdir }
- let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
-
- def clear_cached_requires_sudo
- # Private in ruby 1.8.7
- return unless Bundler.instance_variable_defined?(:@requires_sudo_ran)
- Bundler.send(:remove_instance_variable, :@requires_sudo_ran)
- Bundler.send(:remove_instance_variable, :@requires_sudo)
- end
-
- before do
- clear_cached_requires_sudo
- allow(Bundler).to receive(:which).with("sudo").and_return("/usr/bin/sudo")
- allow(Bundler).to receive(:bundle_path).and_return(bundle_path)
- end
-
- after do
- FileUtils.rm_rf(tmpdir)
- clear_cached_requires_sudo
- end
-
- subject { Bundler.requires_sudo? }
-
- context "bundle_path doesn't exist" do
- it { should be false }
-
- context "and parent dir can't be written" do
- before do
- FileUtils.chmod(0o500, tmpdir)
- end
-
- it { should be true }
- end
-
- context "with unwritable files in a parent dir" do
- # Regression test for https://github.com/bundler/bundler/pull/6316
- # It doesn't matter if there are other unwritable files so long as
- # bundle_path can be created
- before do
- file = File.join(tmpdir, "unrelated_file")
- FileUtils.touch(file)
- FileUtils.chmod(0o400, file)
- end
-
- it { should be false }
- end
- end
-
- context "bundle_path exists" do
- before do
- FileUtils.mkdir_p(bundle_path)
- end
-
- it { should be false }
-
- context "and is unwritable" do
- before do
- FileUtils.chmod(0o500, bundle_path)
- end
-
- it { should be true }
- end
- end
- end
-
- describe "#requires_sudo?" do
- before do
- allow(Bundler).to receive(:which).with("sudo").and_return("/usr/bin/sudo")
- FileUtils.mkdir_p("tmp/vendor/bundle")
- FileUtils.mkdir_p("tmp/vendor/bin_dir")
- end
- after do
- FileUtils.rm_rf("tmp/vendor/bundle")
- FileUtils.rm_rf("tmp/vendor/bin_dir")
- if Bundler.respond_to?(:remove_instance_variable)
- Bundler.remove_instance_variable(:@requires_sudo_ran)
- Bundler.remove_instance_variable(:@requires_sudo)
- else
- # TODO: Remove these code when Bundler drops Ruby 1.8.7 support
- Bundler.send(:remove_instance_variable, :@requires_sudo_ran)
- Bundler.send(:remove_instance_variable, :@requires_sudo)
- end
- end
- context "writable paths" do
- it "should return false and display nothing" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- expect(Bundler.ui).to_not receive(:warn)
- expect(Bundler.requires_sudo?).to eq(false)
- end
- end
- context "unwritable paths" do
- before do
- FileUtils.touch("tmp/vendor/bundle/unwritable1.txt")
- FileUtils.touch("tmp/vendor/bundle/unwritable2.txt")
- FileUtils.touch("tmp/vendor/bin_dir/unwritable3.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable1.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable2.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bin_dir/unwritable3.txt")
- end
- it "should return true and display warn message" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- bin_dir = Pathname("tmp/vendor/bin_dir/")
-
- # allow File#writable? to be called with args other than the stubbed on below
- allow(File).to receive(:writable?).and_call_original
-
- # fake make the directory unwritable
- allow(File).to receive(:writable?).with(bin_dir).and_return(false)
- allow(Bundler).to receive(:system_bindir).and_return(Pathname("tmp/vendor/bin_dir/"))
- message = <<-MESSAGE.chomp
-Following files may not be writable, so sudo is needed:
- tmp/vendor/bin_dir/
- tmp/vendor/bundle/unwritable1.txt
- tmp/vendor/bundle/unwritable2.txt
-MESSAGE
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.requires_sudo?).to eq(true)
+ allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
+ expect(Bundler.ui).to receive(:warn).with("Your home directory is not set.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
+ expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
end
@@ -465,6 +318,7 @@ MESSAGE
it "should use custom home path as root for other paths" do
ENV["BUNDLE_USER_HOME"] = bundle_user_home_custom.to_s
+ allow(Bundler.rubygems).to receive(:user_home).and_raise
expect(Bundler.user_bundle_path).to eq(bundle_user_home_custom)
expect(Bundler.user_bundle_path("home")).to eq(bundle_user_home_custom)
expect(Bundler.user_bundle_path("cache")).to eq(bundle_user_home_custom.join("cache"))
diff --git a/spec/bundler/bundler/ci_detector_spec.rb b/spec/bundler/bundler/ci_detector_spec.rb
new file mode 100644
index 0000000000..299d8005e8
--- /dev/null
+++ b/spec/bundler/bundler/ci_detector_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::CIDetector do
+ # This is properly tested in rubygems, under the name Gem::CIDetector
+ # But the test that confirms that our version _stays in sync_ with that version
+ # will live here.
+
+ it "stays in sync with the rubygems implementation" do
+ rubygems_implementation_path = File.join(git_root, "lib", "rubygems", "ci_detector.rb")
+ expect(File.exist?(rubygems_implementation_path)).to be_truthy
+ rubygems_code = File.read(rubygems_implementation_path)
+ denamespaced_rubygems_code = rubygems_code.sub("Gem", "NAMESPACE")
+
+ bundler_implementation_path = File.join(source_lib_dir, "bundler", "ci_detector.rb")
+ expect(File.exist?(bundler_implementation_path)).to be_truthy
+ bundler_code = File.read(bundler_implementation_path)
+ denamespaced_bundler_code = bundler_code.sub("Bundler", "NAMESPACE")
+
+ expect(denamespaced_bundler_code).to eq(denamespaced_rubygems_code)
+ end
+end
diff --git a/spec/bundler/bundler/cli_common_spec.rb b/spec/bundler/bundler/cli_common_spec.rb
new file mode 100644
index 0000000000..015894b3a1
--- /dev/null
+++ b/spec/bundler/bundler/cli_common_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require "bundler/cli"
+
+RSpec.describe Bundler::CLI::Common do
+ describe "gem_not_found_message" do
+ it "should suggest alternate gem names" do
+ message = subject.gem_not_found_message("ralis", ["BOGUS"])
+ expect(message).to match("Could not find gem 'ralis'.$")
+ message = subject.gem_not_found_message("ralis", ["rails"])
+ expect(message).to match("Did you mean 'rails'?")
+ message = subject.gem_not_found_message("Rails", ["rails"])
+ expect(message).to match("Did you mean 'rails'?")
+ message = subject.gem_not_found_message("meail", %w[email fail eval])
+ expect(message).to match("Did you mean 'email'?")
+ message = subject.gem_not_found_message("nokogri", %w[nokogiri rails sidekiq dog])
+ expect(message).to match("Did you mean 'nokogiri'?")
+ message = subject.gem_not_found_message("methosd", %w[method methods bogus])
+ expect(message).to match(/Did you mean 'method(|s)' or 'method(|s)'?/)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index 9a2591ac96..56caf9937e 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -4,18 +4,20 @@ require "bundler/cli"
RSpec.describe "bundle executable" do
it "returns non-zero exit status when passed unrecognized options" do
- bundle "--invalid_argument"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "--invalid_argument", raise_on_error: false
+ expect(exitstatus).to_not be_zero
end
it "returns non-zero exit status when passed unrecognized task" do
- bundle "unrecognized-task"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "unrecognized-task", raise_on_error: false
+ expect(exitstatus).to_not be_zero
end
it "looks for a binary and executes it if it's named bundler-<task>" do
+ skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform?
+
File.open(tmp("bundler-testtasks"), "w", 0o755) do |f|
- ruby = ENV["BUNDLE_RUBY"] || "/usr/bin/env ruby"
+ ruby = ENV["RUBY"] || "/usr/bin/env ruby"
f.puts "#!#{ruby}\nputs 'Hello, world'\n"
end
@@ -23,83 +25,194 @@ RSpec.describe "bundle executable" do
bundle "testtasks"
end
- expect(exitstatus).to be_zero if exitstatus
expect(out).to eq("Hello, world")
end
+ describe "aliases" do
+ it "aliases e to exec" do
+ bundle "e --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
+ end
+
+ it "aliases ex to exec" do
+ bundle "ex --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
+ end
+
+ it "aliases exe to exec" do
+ bundle "exe --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
+ end
+
+ it "aliases c to check" do
+ bundle "c --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-check")
+ end
+
+ it "aliases i to install" do
+ bundle "i --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-install")
+ end
+
+ it "aliases ls to list" do
+ bundle "ls --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-list")
+ end
+
+ it "aliases package to cache" do
+ bundle "package --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
+ end
+
+ it "aliases pack to cache" do
+ bundle "pack --help"
+
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
+ end
+
+ private
+
+ # Some `man` (e.g., on macOS) always highlights the output even to
+ # non-tty.
+ def out_with_macos_man_workaround
+ out.gsub(/.[\b]/, "")
+ end
+ end
+
context "with no arguments" do
- it "prints a concise help message", :bundler => "3" do
- bundle! ""
- expect(last_command.stderr).to be_empty
- expect(last_command.stdout).to include("Bundler version #{Bundler::VERSION}").
+ it "tries to installs by default but print help on missing Gemfile" do
+ bundle "", raise_on_error: false
+ expect(err).to include("Could not locate Gemfile")
+ expect(out).to include("In a future version of Bundler")
+
+ expect(out).to include("Bundler version #{Bundler::VERSION}").
and include("\n\nBundler commands:\n\n").
and include("\n\n Primary commands:\n").
and include("\n\n Utilities:\n").
and include("\n\nOptions:\n")
end
+
+ it "runs bundle install when default_cli_command set to install" do
+ bundle_config "default_cli_command install"
+ bundle "", raise_on_error: false
+ expect(out).to_not include("In a future version of Bundler")
+ expect(err).to include("Could not locate Gemfile")
+ expect(exitstatus).to_not be_zero
+ end
end
context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do
it "ignores it" do
- gemfile bundled_app("Gemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ gemfile bundled_app_gemfile, <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
G
- bundle :install, :env => { "BUNDLE_GEMFILE" => "" }
+ bundle :install, env: { "BUNDLE_GEMFILE" => "" }
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
- context "when ENV['RUBYGEMS_GEMDEPS'] is set" do
- it "displays a warning" do
- gemfile bundled_app("Gemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
- G
+ context "with --verbose" do
+ before do
+ gemfile "source 'https://gem.repo1'"
+ end
- bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" }
- expect(out).to include("RUBYGEMS_GEMDEPS")
- expect(out).to include("conflict with Bundler")
+ it "prints the running command" do
+ bundle "info bundler", verbose: true
+ expect(out).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION}")
- bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" }
- expect(out).not_to include("RUBYGEMS_GEMDEPS")
+ bundle "install", verbose: true
+ expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
+ end
+
+ it "prints the simulated version too when setting is enabled" do
+ bundle "config set simulate_version 4", verbose: true
+ bundle "info bundler", verbose: true
+ expect(out).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION} (simulating Bundler 4)")
end
end
- context "with --verbose" do
+ context "with verbose configuration" do
+ before do
+ bundle_config "verbose true"
+ end
+
it "prints the running command" do
- gemfile ""
- bundle! "info bundler", :verbose => true
- expect(last_command.stdout).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION}")
+ gemfile "source 'https://gem.repo1'"
+ bundle "info bundler"
+ expect(out).to start_with("Running `bundle info bundler` with bundler #{Bundler::VERSION}")
end
+ end
- it "doesn't print defaults" do
- install_gemfile! "", :verbose => true
- expect(last_command.stdout).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ describe "bundle outdated" do
+ let(:run_command) do
+ bundle "install"
+
+ bundle "outdated #{flags}", raise_on_error: false
end
- it "doesn't print defaults" do
- install_gemfile! "", :verbose => true
- expect(last_command.stdout).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", '0.9.1'
+ G
+ end
+
+ context "with --groups flag" do
+ let(:flags) { "--groups" }
+
+ it "prints a message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("Gem Current Latest Requested Groups")
+ expect(out).to include("myrack 0.9.1 1.0.0 = 0.9.1 default")
+ end
+ end
+
+ context "with --parseable" do
+ let(:flags) { "--parseable" }
+
+ it "prints a message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("myrack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ end
+ end
+
+ context "with --groups and --parseable" do
+ let(:flags) { "--groups --parseable" }
+
+ it "prints a simplified message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("myrack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ end
end
end
describe "printing the outdated warning" do
shared_examples_for "no warning" do
it "prints no warning" do
- bundle "fail"
- expect(last_command.stdboth).to eq("Could not find command \"fail\".")
+ bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
+ expect(stdboth).to eq("Could not find command \"fail\".")
end
end
- let(:bundler_version) { "1.1" }
+ let(:bundler_version) { "2.0" }
let(:latest_version) { nil }
before do
- bundle! "config --global disable_version_check false"
+ bundle_config_global "disable_version_check false"
- simulate_bundler_version(bundler_version)
+ pristine_system_gems "bundler-#{bundler_version}"
if latest_version
info_path = home(".bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/bundler")
info_path.parent.mkpath
@@ -124,35 +237,37 @@ RSpec.describe "bundle executable" do
context "when the latest version is greater than the current version" do
let(:latest_version) { "222.0" }
it "prints the version warning" do
- bundle "fail"
- expect(last_command.stdout).to start_with(<<-EOS.strip)
+ bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
+ expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
-To install the latest version, run `gem install bundler`
+To update to the most recent version, run `bundle update --bundler`
EOS
end
context "and disable_version_check is set" do
- before { bundle! "config disable_version_check true" }
+ before { bundle "config set disable_version_check true", env: { "BUNDLER_VERSION" => bundler_version } }
include_examples "no warning"
end
context "running a parseable command" do
it "prints no warning" do
- bundle! "config --parseable foo"
- expect(last_command.stdboth).to eq ""
+ bundle "config set foo value", env: { "BUNDLER_VERSION" => bundler_version }
+ bundle "config get --parseable foo", env: { "BUNDLER_VERSION" => bundler_version }
+ expect(out).to eq "foo=value"
+ expect(err).to eq ""
- bundle "platform --ruby"
- expect(last_command.stdboth).to eq "Could not locate Gemfile"
+ bundle "platform --ruby", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
+ expect(stdboth).to eq "Could not locate Gemfile"
end
end
context "and is a pre-release" do
let(:latest_version) { "222.0.0.pre.4" }
it "prints the version warning" do
- bundle "fail"
- expect(last_command.stdout).to start_with(<<-EOS.strip)
+ bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
+ expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
-To install the latest version, run `gem install bundler --pre`
+To update to the most recent version, run `bundle update --bundler`
EOS
end
end
@@ -161,13 +276,23 @@ To install the latest version, run `gem install bundler --pre`
end
RSpec.describe "bundler executable" do
- it "shows the bundler version just as the `bundle` executable does", :bundler => "< 3" do
+ it "shows the bundler version just as the `bundle` executable does" do
bundler "--version"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "shows the bundler version just as the `bundle` executable does", :bundler => "3" do
+ bundle_config "simulate_version 5"
bundler "--version"
- expect(out).to eq(Bundler::VERSION)
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
+ end
+
+ it "shows cli_help when bundler install and no Gemfile is found" do
+ bundler "install", raise_on_error: false
+ expect(err).to include("Could not locate Gemfile")
+
+ expect(out).to include("Bundler version #{Bundler::VERSION}").
+ and include("\n\nBundler commands:\n\n").
+ and include("\n\n Primary commands:\n").
+ and include("\n\n Utilities:\n").
+ and include("\n\nOptions:\n")
end
end
diff --git a/spec/bundler/bundler/compact_index_client/parser_spec.rb b/spec/bundler/bundler/compact_index_client/parser_spec.rb
new file mode 100644
index 0000000000..6aa867f058
--- /dev/null
+++ b/spec/bundler/bundler/compact_index_client/parser_spec.rb
@@ -0,0 +1,249 @@
+# frozen_string_literal: true
+
+require "bundler/compact_index_client"
+require "bundler/compact_index_client/parser"
+
+TestCompactIndexClient = Struct.new(:names, :versions, :info_data) do
+ # Requiring the checksum to match the input data helps ensure
+ # that we are parsing the correct checksum from the versions file
+ def info(name, checksum)
+ info_data.dig(name, checksum)
+ end
+
+ def set_info_data(name, value)
+ info_data[name] = value
+ end
+end
+
+RSpec.describe Bundler::CompactIndexClient::Parser do
+ subject(:parser) { described_class.new(compact_index) }
+
+ let(:compact_index) { TestCompactIndexClient.new(names, versions, info_data) }
+ let(:names) { "a\nb\nc\n" }
+ let(:versions) { <<~VERSIONS.dup }
+ created_at: 2024-05-01T00:00:04Z
+ ---
+ a 1.0.0,1.0.1,1.1.0 aaa111
+ b 2.0.0,2.0.0-java bbb222
+ c 3.0.0,3.0.3,3.3.3 ccc333
+ c -3.0.3 ccc333yanked
+ VERSIONS
+ let(:info_data) do
+ {
+ "a" => { "aaa111" => a_info },
+ "b" => { "bbb222" => b_info },
+ "c" => { "ccc333yanked" => c_info },
+ }
+ end
+ let(:a_info) { <<~INFO.dup }
+ ---
+ 1.0.0 |checksum:aaa1,ruby:>= 3.0.0,rubygems:>= 3.2.3
+ 1.0.1 |checksum:aaa2,ruby:>= 3.0.0,rubygems:>= 3.2.3
+ 1.1.0 |checksum:aaa3,ruby:>= 3.0.0,rubygems:>= 3.2.3
+ INFO
+ let(:b_info) { <<~INFO }
+ 2.0.0 a:~> 1.0&<= 3.0|checksum:bbb1
+ 2.0.0-java a:~> 1.0&<= 3.0|checksum:bbb2
+ INFO
+ let(:c_info) { <<~INFO }
+ 3.0.0 a:= 1.0.0,b:~> 2.0|checksum:ccc1,ruby:>= 2.7.0,rubygems:>= 3.0.0
+ 3.3.3 a:>= 1.1.0,b:~> 2.0|checksum:ccc3,ruby:>= 3.0.0,rubygems:>= 3.2.3,created_at:2026-05-12T10:00:00Z
+ INFO
+
+ describe "#available?" do
+ it "returns true versions are available" do
+ expect(parser).to be_available
+ end
+
+ it "returns true when versions has only one gem" do
+ compact_index.versions = +"a 1.0.0 aaa1\n"
+ expect(parser).to be_available
+ end
+
+ it "returns true when versions has a gem and a header" do
+ compact_index.versions = +"---\na 1.0.0 aaa1\n"
+ expect(parser).to be_available
+ end
+
+ it "returns true when versions has a gem and a header with header data" do
+ compact_index.versions = +"created_at: 2024-05-01T00:00:04Z\n---\na 1.0.0 aaa1\n"
+ expect(parser).to be_available
+ end
+
+ it "returns false when versions has only the header" do
+ compact_index.versions = +"---\n"
+ expect(parser).not_to be_available
+ end
+
+ it "returns false when versions has only the header with header data" do
+ compact_index.versions = +"created_at: 2024-05-01T00:00:04Z\n---\n"
+ expect(parser).not_to be_available
+ end
+
+ it "returns false when versions index is not available" do
+ compact_index.versions = nil
+ expect(parser).not_to be_available
+ end
+
+ it "returns false when versions is empty" do
+ compact_index.versions = +""
+ expect(parser).not_to be_available
+ end
+ end
+
+ describe "#names" do
+ it "returns the names" do
+ expect(parser.names).to eq(%w[a b c])
+ end
+
+ it "returns an empty array when names is empty" do
+ compact_index.names = ""
+ expect(parser.names).to eq([])
+ end
+
+ it "returns an empty array when names is not readable" do
+ compact_index.names = nil
+ expect(parser.names).to eq([])
+ end
+ end
+
+ describe "#versions" do
+ it "returns the versions" do
+ expect(parser.versions).to eq(
+ "a" => [
+ ["a", "1.0.0"],
+ ["a", "1.0.1"],
+ ["a", "1.1.0"],
+ ],
+ "b" => [
+ ["b", "2.0.0"],
+ ["b", "2.0.0", "java"],
+ ],
+ "c" => [
+ ["c", "3.0.0"],
+ ["c", "3.3.3"],
+ ],
+ )
+ end
+
+ it "returns an empty hash when versions is empty" do
+ compact_index.versions = ""
+ expect(parser.versions).to eq({})
+ end
+
+ it "returns an empty hash when versions is not readable" do
+ compact_index.versions = nil
+ expect(parser.versions).to eq({})
+ end
+ end
+
+ describe "#info" do
+ let(:a_result) do
+ [
+ [
+ "a",
+ "1.0.0",
+ nil,
+ [],
+ [["checksum", ["aaa1"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ [
+ "a",
+ "1.0.1",
+ nil,
+ [],
+ [["checksum", ["aaa2"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ [
+ "a",
+ "1.1.0",
+ nil,
+ [],
+ [["checksum", ["aaa3"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ ]
+ end
+ let(:b_result) do
+ [
+ [
+ "b",
+ "2.0.0",
+ nil,
+ [["a", ["~> 1.0", "<= 3.0"]]],
+ [["checksum", ["bbb1"]]],
+ ],
+ [
+ "b",
+ "2.0.0",
+ "java",
+ [["a", ["~> 1.0", "<= 3.0"]]],
+ [["checksum", ["bbb2"]]],
+ ],
+ ]
+ end
+ let(:c_result) do
+ [
+ [
+ "c",
+ "3.0.0",
+ nil,
+ [["a", ["= 1.0.0"]], ["b", ["~> 2.0"]]],
+ [["checksum", ["ccc1"]], ["ruby", [">= 2.7.0"]], ["rubygems", [">= 3.0.0"]]],
+ ],
+ [
+ "c",
+ "3.3.3",
+ nil,
+ [["a", [">= 1.1.0"]], ["b", ["~> 2.0"]]],
+ [["checksum", ["ccc3"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]], ["created_at", ["2026-05-12T10:00:00Z"]]],
+ ],
+ ]
+ end
+
+ it "returns the info for example gem 'a' which has no deps" do
+ expect(parser.info("a")).to eq(a_result)
+ end
+
+ it "returns the info for example gem 'b' which has platform and compound deps" do
+ expect(parser.info("b")).to eq(b_result)
+ end
+
+ it "returns the info for example gem 'c' which has deps and yanked version (requires use of correct info checksum)" do
+ expect(parser.info("c")).to eq(c_result)
+ end
+
+ it "returns an empty array when the info is empty" do
+ compact_index.set_info_data("a", {})
+ expect(parser.info("a")).to eq([])
+ end
+
+ it "returns an empty array when the info is not readable" do
+ expect(parser.info("d")).to eq([])
+ end
+
+ it "handles empty lines in the versions file (Artifactory bug that they have yet to fix)" do
+ compact_index.versions = +<<~VERSIONS
+ created_at: 2024-05-01T00:00:04Z
+ ---
+ a 1.0.0,1.0.1,1.1.0 aaa111
+ b 2.0.0,2.0.0-java bbb222
+
+ c 3.0.0,3.0.3,3.3.3 ccc333
+ c -3.0.3 ccc333yanked
+ VERSIONS
+ expect(parser.info("a")).to eq(a_result)
+ end
+
+ it "handles lines without a checksum" do
+ compact_index.versions = <<~VERSIONS
+ created_at: 2024-05-01T00:00:04Z
+ ---
+ a 1.0.0,1.0.1,1.1.0 aaa111
+ b 2.0.0,2.0.0-java
+ c 3.0.0,3.0.3,3.3.3 ccc333
+ VERSIONS
+
+ expect(parser.info("a")).to eq(a_result)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index fd554a7b0d..fd63a652a4 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -1,55 +1,243 @@
# frozen_string_literal: true
-require "net/http"
+require "bundler/vendored_net_http"
require "bundler/compact_index_client"
require "bundler/compact_index_client/updater"
+require "tmpdir"
RSpec.describe Bundler::CompactIndexClient::Updater do
+ subject(:updater) { described_class.new(fetcher) }
+
let(:fetcher) { double(:fetcher) }
- let(:local_path) { Pathname("/tmp/localpath") }
+ let(:local_path) { Pathname.new(Dir.mktmpdir("localpath")).join("versions") }
+ let(:etag_path) { Pathname.new(Dir.mktmpdir("localpath-etags")).join("versions.etag") }
let(:remote_path) { double(:remote_path) }
- subject(:updater) { described_class.new(fetcher) }
+ let(:full_body) { "abc123" }
+ let(:response) { double(:response, body: full_body, is_a?: false) }
+ let(:digest) { Digest::SHA256.base64digest(full_body) }
- context "when the ETag header is missing" do
- # Regression test for https://github.com/bundler/bundler/issues/5463
+ context "when the local path does not exist" do
+ before do
+ allow(response).to receive(:[]).with("Repr-Digest") { nil }
+ allow(response).to receive(:[]).with("Digest") { nil }
+ allow(response).to receive(:[]).with("ETag") { '"thisisanetag"' }
+ end
+
+ it "downloads the file without attempting append" do
+ expect(fetcher).to receive(:call).once.with(remote_path, {}) { response }
+
+ updater.update(remote_path, local_path, etag_path)
- let(:response) { double(:response, :body => "") }
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("thisisanetag")
+ end
- it "MisMatchedChecksumError is raised" do
- # Twice: #update retries on failure
- expect(response).to receive(:[]).with("Content-Encoding").twice { "" }
- expect(response).to receive(:[]).with("ETag").twice { nil }
- expect(fetcher).to receive(:call).twice { response }
+ it "fails immediately on bad checksum" do
+ expect(fetcher).to receive(:call).once.with(remote_path, {}) { response }
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:baddigest:" }
expect do
- updater.update(local_path, remote_path)
- end.to raise_error(Bundler::CompactIndexClient::Updater::MisMatchedChecksumError)
+ updater.update(remote_path, local_path, etag_path)
+ end.to raise_error(Bundler::CompactIndexClient::Updater::MismatchedChecksumError)
+ end
+ end
+
+ context "when the local path exists" do
+ let(:local_body) { "abc" }
+
+ before do
+ local_path.open("w") {|f| f.write(local_body) }
+ end
+
+ context "with an etag" do
+ before do
+ etag_path.open("w") {|f| f.write("LocalEtag") }
+ end
+
+ let(:headers) do
+ {
+ "If-None-Match" => '"LocalEtag"',
+ "Range" => "bytes=2-",
+ }
+ end
+
+ it "does nothing if etags match" do
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { false }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { true }
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq("abc")
+ expect(etag_path.read).to eq("LocalEtag")
+ end
+
+ it "appends the file if etags do not match" do
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
+ allow(response).to receive(:body) { "c123" }
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
+
+ it "replaces the file if response ignores range" do
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ allow(response).to receive(:body) { full_body }
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
+
+ it "tries the request again if the partial response fails digest check" do
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:baddigest:" }
+ allow(response).to receive(:body) { "the beginning of the file changed" }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+
+ full_response = double(:full_response, body: full_body, is_a?: false)
+ allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
+
+ it "tries the request again if the partial response is blank" do
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:baddigest:" }
+ allow(response).to receive(:body) { "" }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+
+ full_response = double(:full_response, body: full_body, is_a?: false)
+ allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
+ end
+
+ context "without an etag file" do
+ let(:headers) do
+ { "Range" => "bytes=2-" }
+ end
+
+ it "appends the file" do
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(response).to receive(:[]).with("ETag") { '"OpaqueEtag"' }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
+ allow(response).to receive(:body) { "c123" }
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("OpaqueEtag")
+ end
+
+ it "replaces the file on full file response that ignores range request" do
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+ allow(response).to receive(:[]).with("Repr-Digest") { nil }
+ allow(response).to receive(:[]).with("Digest") { nil }
+ allow(response).to receive(:[]).with("ETag") { '"OpaqueEtag"' }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { false }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
+ allow(response).to receive(:body) { full_body }
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("OpaqueEtag")
+ end
+
+ it "tries the request again if the partial response fails digest check" do
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:baddigest:" }
+ allow(response).to receive(:body) { "the beginning of the file changed" }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ expect(fetcher).to receive(:call).once.with(remote_path, headers) do
+ # During the failed first request, we simulate another process writing the etag.
+ # This ensures the second request doesn't generate the md5 etag again but just uses whatever is written.
+ etag_path.open("w") {|f| f.write("LocalEtag") }
+ response
+ end
+
+ full_response = double(:full_response, body: full_body, is_a?: false)
+ allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
+ end
+ end
+
+ context "when the ETag header is missing" do
+ # Regression test for https://github.com/rubygems/bundler/issues/5463
+ let(:response) { double(:response, body: full_body) }
+
+ it "treats the response as an update" do
+ allow(response).to receive(:[]).with("Repr-Digest") { nil }
+ allow(response).to receive(:[]).with("Digest") { nil }
+ allow(response).to receive(:[]).with("ETag") { nil }
+ expect(fetcher).to receive(:call) { response }
+
+ updater.update(remote_path, local_path, etag_path)
end
end
context "when the download is corrupt" do
- let(:response) { double(:response, :body => "") }
+ let(:response) { double(:response, body: "") }
it "raises HTTPError" do
- expect(response).to receive(:[]).with("Content-Encoding") { "gzip" }
- expect(fetcher).to receive(:call) { response }
+ expect(fetcher).to receive(:call).and_raise(Zlib::GzipFile::Error)
expect do
- updater.update(local_path, remote_path)
+ updater.update(remote_path, local_path, etag_path)
end.to raise_error(Bundler::HTTPError)
end
end
- context "when bundler doesn't have permissions on Dir.tmpdir" do
- let(:response) { double(:response, :body => "") }
+ context "when receiving non UTF-8 data and default internal encoding set to ASCII" do
+ let(:response) { double(:response, body: "\x8B".b) }
- it "Errno::EACCES is raised" do
- allow(Dir).to receive(:mktmpdir) { raise Errno::EACCES }
+ it "works just fine" do
+ old_verbose = $VERBOSE
+ previous_internal_encoding = Encoding.default_internal
- expect do
- updater.update(local_path, remote_path)
- end.to raise_error(Bundler::PermissionError)
+ begin
+ $VERBOSE = false
+ Encoding.default_internal = "ASCII"
+ allow(response).to receive(:[]).with("Repr-Digest") { nil }
+ allow(response).to receive(:[]).with("Digest") { nil }
+ allow(response).to receive(:[]).with("ETag") { nil }
+ expect(fetcher).to receive(:call) { response }
+
+ updater.update(remote_path, local_path, etag_path)
+ ensure
+ Encoding.default_internal = previous_internal_encoding
+ $VERBOSE = old_verbose
+ end
end
end
end
diff --git a/spec/bundler/bundler/current_ruby_spec.rb b/spec/bundler/bundler/current_ruby_spec.rb
new file mode 100644
index 0000000000..79eb802aa5
--- /dev/null
+++ b/spec/bundler/bundler/current_ruby_spec.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::CurrentRuby do
+ describe "PLATFORM_MAP" do
+ subject { described_class::PLATFORM_MAP }
+
+ # rubocop:disable Naming/VariableNumber
+ let(:platforms) do
+ { ruby: Gem::Platform::RUBY,
+ ruby_18: Gem::Platform::RUBY,
+ ruby_19: Gem::Platform::RUBY,
+ ruby_20: Gem::Platform::RUBY,
+ ruby_21: Gem::Platform::RUBY,
+ ruby_22: Gem::Platform::RUBY,
+ ruby_23: Gem::Platform::RUBY,
+ ruby_24: Gem::Platform::RUBY,
+ ruby_25: Gem::Platform::RUBY,
+ ruby_26: Gem::Platform::RUBY,
+ ruby_27: Gem::Platform::RUBY,
+ ruby_30: Gem::Platform::RUBY,
+ ruby_31: Gem::Platform::RUBY,
+ ruby_32: Gem::Platform::RUBY,
+ ruby_33: Gem::Platform::RUBY,
+ ruby_34: Gem::Platform::RUBY,
+ ruby_40: Gem::Platform::RUBY,
+ ruby_41: Gem::Platform::RUBY,
+ mri: Gem::Platform::RUBY,
+ mri_18: Gem::Platform::RUBY,
+ mri_19: Gem::Platform::RUBY,
+ mri_20: Gem::Platform::RUBY,
+ mri_21: Gem::Platform::RUBY,
+ mri_22: Gem::Platform::RUBY,
+ mri_23: Gem::Platform::RUBY,
+ mri_24: Gem::Platform::RUBY,
+ mri_25: Gem::Platform::RUBY,
+ mri_26: Gem::Platform::RUBY,
+ mri_27: Gem::Platform::RUBY,
+ mri_30: Gem::Platform::RUBY,
+ mri_31: Gem::Platform::RUBY,
+ mri_32: Gem::Platform::RUBY,
+ mri_33: Gem::Platform::RUBY,
+ mri_34: Gem::Platform::RUBY,
+ mri_40: Gem::Platform::RUBY,
+ mri_41: Gem::Platform::RUBY,
+ rbx: Gem::Platform::RUBY,
+ truffleruby: Gem::Platform::RUBY,
+ jruby: Gem::Platform::JAVA,
+ jruby_18: Gem::Platform::JAVA,
+ jruby_19: Gem::Platform::JAVA,
+ windows: Gem::Platform::WINDOWS,
+ windows_18: Gem::Platform::WINDOWS,
+ windows_19: Gem::Platform::WINDOWS,
+ windows_20: Gem::Platform::WINDOWS,
+ windows_21: Gem::Platform::WINDOWS,
+ windows_22: Gem::Platform::WINDOWS,
+ windows_23: Gem::Platform::WINDOWS,
+ windows_24: Gem::Platform::WINDOWS,
+ windows_25: Gem::Platform::WINDOWS,
+ windows_26: Gem::Platform::WINDOWS,
+ windows_27: Gem::Platform::WINDOWS,
+ windows_30: Gem::Platform::WINDOWS,
+ windows_31: Gem::Platform::WINDOWS,
+ windows_32: Gem::Platform::WINDOWS,
+ windows_33: Gem::Platform::WINDOWS,
+ windows_34: Gem::Platform::WINDOWS,
+ windows_40: Gem::Platform::WINDOWS,
+ windows_41: Gem::Platform::WINDOWS }
+ end
+
+ let(:deprecated) do
+ { mswin: Gem::Platform::MSWIN,
+ mswin_18: Gem::Platform::MSWIN,
+ mswin_19: Gem::Platform::MSWIN,
+ mswin_20: Gem::Platform::MSWIN,
+ mswin_21: Gem::Platform::MSWIN,
+ mswin_22: Gem::Platform::MSWIN,
+ mswin_23: Gem::Platform::MSWIN,
+ mswin_24: Gem::Platform::MSWIN,
+ mswin_25: Gem::Platform::MSWIN,
+ mswin_26: Gem::Platform::MSWIN,
+ mswin_27: Gem::Platform::MSWIN,
+ mswin_30: Gem::Platform::MSWIN,
+ mswin_31: Gem::Platform::MSWIN,
+ mswin_32: Gem::Platform::MSWIN,
+ mswin_33: Gem::Platform::MSWIN,
+ mswin_34: Gem::Platform::MSWIN,
+ mswin_40: Gem::Platform::MSWIN,
+ mswin_41: Gem::Platform::MSWIN,
+ mswin64: Gem::Platform::MSWIN64,
+ mswin64_19: Gem::Platform::MSWIN64,
+ mswin64_20: Gem::Platform::MSWIN64,
+ mswin64_21: Gem::Platform::MSWIN64,
+ mswin64_22: Gem::Platform::MSWIN64,
+ mswin64_23: Gem::Platform::MSWIN64,
+ mswin64_24: Gem::Platform::MSWIN64,
+ mswin64_25: Gem::Platform::MSWIN64,
+ mswin64_26: Gem::Platform::MSWIN64,
+ mswin64_27: Gem::Platform::MSWIN64,
+ mswin64_30: Gem::Platform::MSWIN64,
+ mswin64_31: Gem::Platform::MSWIN64,
+ mswin64_32: Gem::Platform::MSWIN64,
+ mswin64_33: Gem::Platform::MSWIN64,
+ mswin64_34: Gem::Platform::MSWIN64,
+ mswin64_40: Gem::Platform::MSWIN64,
+ mswin64_41: Gem::Platform::MSWIN64,
+ mingw: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_18: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_19: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_20: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_21: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_22: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_23: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_24: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_25: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_26: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_27: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_30: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_31: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_32: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_33: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_34: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_40: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_41: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_20: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_21: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_22: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_23: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_24: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_25: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_26: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_27: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_30: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_31: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_32: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_33: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_34: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_40: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_41: Gem::Platform::UNIVERSAL_MINGW }
+ end
+ # rubocop:enable Naming/VariableNumber
+
+ it "includes all platforms" do
+ expect(subject).to eq(platforms.merge(deprecated))
+ end
+ end
+
+ describe "Deprecated platform" do
+ it "outputs an error and aborts when calling maglev?" do
+ expect { Bundler.current_ruby.maglev? }.to raise_error(Bundler::RemovedError, /`CurrentRuby#maglev\?` was removed with no replacement./)
+ end
+
+ it "outputs an error and aborts when calling maglev_31?" do
+ expect { Bundler.current_ruby.maglev_31? }.to raise_error(Bundler::RemovedError, /`CurrentRuby#maglev_31\?` was removed with no replacement./)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb
index a38c0b05b0..8c4a5a0331 100644
--- a/spec/bundler/bundler/definition_spec.rb
+++ b/spec/bundler/bundler/definition_spec.rb
@@ -3,197 +3,216 @@
require "bundler/definition"
RSpec.describe Bundler::Definition do
+ describe "#overrides" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile) { bundled_app_gemfile }
+ end
+
+ subject { Bundler::Definition.new(bundled_app_lock, [], Bundler::SourceList.new, {}) }
+
+ it "defaults to an empty array" do
+ expect(subject.overrides).to eq([])
+ end
+
+ it "is writable" do
+ override = Bundler::Override.new("rails", :version, ">= 8.0")
+ subject.overrides = [override]
+ expect(subject.overrides).to eq([override])
+ end
+ end
+
describe "#lock" do
before do
- allow(Bundler).to receive(:settings) { Bundler::Settings.new(".") }
- allow(Bundler::SharedHelpers).to receive(:find_gemfile) { Pathname.new("Gemfile") }
- allow(Bundler).to receive(:ui) { double("UI", :info => "", :debug => "") }
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile) { bundled_app_gemfile }
+ allow(Bundler).to receive(:ui) { double("UI", info: "", debug: "") }
end
- context "when it's not possible to write to the file" do
- subject { Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) }
+ subject { Bundler::Definition.new(bundled_app_lock, [], Bundler::SourceList.new, {}) }
+
+ context "when it's not possible to write to the file" do
it "raises an PermissionError with explanation" do
- expect(File).to receive(:open).with("Gemfile.lock", "wb").
- and_raise(Errno::EACCES)
- expect { subject.lock("Gemfile.lock") }.
+ allow(File).to receive(:open).and_call_original
+ expect(File).to receive(:open).with(bundled_app_lock, "wb").
+ and_raise(Errno::EACCES.new(bundled_app_lock.to_s))
+ expect { subject.lock }.
to raise_error(Bundler::PermissionError, /Gemfile\.lock/)
end
end
context "when a temporary resource access issue occurs" do
- subject { Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) }
-
it "raises a TemporaryResourceError with explanation" do
- expect(File).to receive(:open).with("Gemfile.lock", "wb").
+ allow(File).to receive(:open).and_call_original
+ expect(File).to receive(:open).with(bundled_app_lock, "wb").
and_raise(Errno::EAGAIN)
- expect { subject.lock("Gemfile.lock") }.
+ expect { subject.lock }.
to raise_error(Bundler::TemporaryResourceError, /temporarily unavailable/)
end
end
+ context "when Bundler::Definition.no_lock is set to true" do
+ before { Bundler::Definition.no_lock = true }
+ after { Bundler::Definition.no_lock = false }
+
+ it "does not create a lockfile" do
+ subject.lock
+ expect(bundled_app_lock).not_to be_file
+ end
+ end
end
describe "detects changes" do
- it "for a path gem with changes", :bundler => "< 3" do
- build_lib "foo", "1.0", :path => lib_path("foo")
+ it "for a path gem with changes" do
+ build_lib "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "1.0"
end
- bundle :install, :env => { "DEBUG" => 1 }
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
+ bundle :install, env: { "DEBUG" => "1" }
expect(out).to match(/re-resolving dependencies/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 1.0)
+ myrack (= 1.0)
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "for a path gem with changes", :bundler => "3" do
- build_lib "foo", "1.0", :path => lib_path("foo")
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "foo", :path => "#{lib_path("foo")}"
- G
-
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ it "with an explicit update" do
+ build_repo4 do
+ build_gem("ffi", "1.9.23") {|s| s.platform = "java" }
+ build_gem("ffi", "1.9.23")
end
- bundle :install, :env => { "DEBUG" => 1 }
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "ffi"
+ G
- expect(out).to match(/re-resolving dependencies/)
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
+ bundle "lock --add-platform java"
- PATH
- remote: #{lib_path("foo")}
- specs:
- foo (1.0)
- rack (= 1.0)
-
- PLATFORMS
- #{lockfile_platforms}
+ bundle "update ffi", env: { "DEBUG" => "1" }
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
+ expect(out).to match(/because bundler is unlocking gems: \(ffi\)/)
end
- it "for a path gem with deps and no changes", :bundler => "< 3" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ it "for a path gem with deps and no changes" do
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "1.0"
s.add_development_dependency "net-ssh", "1.0"
end
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
- bundle :check, :env => { "DEBUG" => 1 }
-
- expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expected_lockfile = <<~G
PATH
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 1.0)
+ myrack (= 1.0)
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
- end
- it "for a path gem with deps and no changes", :bundler => "3" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
- s.add_development_dependency "net-ssh", "1.0"
- end
+ expect(lockfile).to eq(expected_lockfile)
+ bundle :check, env: { "DEBUG" => "1" }
+
+ expect(out).to match(/using resolution from the lockfile/)
+ expect(lockfile).to eq(expected_lockfile)
+ end
+
+ it "for a locked gem for another platform" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "foo", :path => "#{lib_path("foo")}"
+ source "https://gem.repo1"
+ gem "only_java", platform: :jruby
G
- bundle :check, :env => { "DEBUG" => 1 }
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "only_java", "1.1", "java"
+ end
+
+ bundle "lock --add-platform java"
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
-
- PATH
- remote: #{lib_path("foo")}
- specs:
- foo (1.0)
- rack (= 1.0)
+ only_java (1.1-java)
PLATFORMS
- #{lockfile_platforms}
+ #{lockfile_platforms("java")}
DEPENDENCIES
- foo!
-
+ only_java
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "for a rubygems gem" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "foo", "1.0"
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
G
- bundle :check, :env => { "DEBUG" => 1 }
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
foo (1.0)
@@ -202,48 +221,25 @@ RSpec.describe Bundler::Definition do
DEPENDENCIES
foo
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
describe "initialize" do
context "gem version promoter" do
- context "with lockfile" do
- before do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "foo"
- G
- end
-
- it "should get a locked specs list when updating all" do
- definition = Bundler::Definition.new(bundled_app("Gemfile.lock"), [], Bundler::SourceList.new, true)
- locked_specs = definition.gem_version_promoter.locked_specs
- expect(locked_specs.to_a.map(&:name)).to eq ["foo"]
- expect(definition.instance_variable_get("@locked_specs").empty?).to eq true
- end
- end
-
- context "without gemfile or lockfile" do
- it "should not attempt to parse empty lockfile contents" do
- definition = Bundler::Definition.new(nil, [], mock_source_list, true)
- expect(definition.gem_version_promoter.locked_specs.to_a).to eq []
- end
- end
-
context "eager unlock" do
let(:source_list) do
Bundler::SourceList.new.tap do |source_list|
- source_list.global_rubygems_source = "file://#{gem_repo4}"
+ source_list.add_global_rubygems_remote("https://gem.repo4")
end
end
before do
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'isolated_owner'
gem 'shared_owner_a'
@@ -252,7 +248,7 @@ RSpec.describe Bundler::Definition do
lockfile <<-L
GEM
- remote: file://#{gem_repo4}
+ remote: https://gem.repo4
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.1)
@@ -274,6 +270,8 @@ RSpec.describe Bundler::Definition do
BUNDLED WITH
1.13.0
L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "should not eagerly unlock shared dependency with bundle install conservative updating behavior" do
@@ -282,7 +280,7 @@ RSpec.describe Bundler::Definition do
Bundler::Dependency.new("shared_owner_b", ">= 0")]
unlock_hash_for_bundle_install = {}
definition = Bundler::Definition.new(
- bundled_app("Gemfile.lock"),
+ bundled_app_lock,
updated_deps_in_gemfile,
source_list,
unlock_hash_for_bundle_install
@@ -296,10 +294,10 @@ RSpec.describe Bundler::Definition do
Bundler::Dependency.new("shared_owner_a", ">= 0"),
Bundler::Dependency.new("shared_owner_b", ">= 0")]
definition = Bundler::Definition.new(
- bundled_app("Gemfile.lock"),
+ bundled_app_lock,
updated_deps_in_gemfile,
source_list,
- :gems => ["shared_owner_a"], :lock_shared_dependencies => true
+ gems: ["shared_owner_a"], conservative: true
)
locked = definition.send(:converge_locked_specs).map(&:name)
expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b]
@@ -309,31 +307,55 @@ RSpec.describe Bundler::Definition do
end
end
- describe "find_resolved_spec" do
- it "with no platform set in SpecSet" do
- ss = Bundler::SpecSet.new([build_stub_spec("a", "1.0"), build_stub_spec("b", "1.0")])
- dfn = Bundler::Definition.new(nil, [], mock_source_list, true)
- dfn.instance_variable_set("@specs", ss)
- found = dfn.find_resolved_spec(build_spec("a", "0.9", "ruby").first)
- expect(found.name).to eq "a"
- expect(found.version.to_s).to eq "1.0"
+ describe "#precompute_source_requirements_for_indirect_dependencies?" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile) { Pathname.new("Gemfile") }
end
- end
- describe "find_indexed_specs" do
- it "with no platform set in indexed specs" do
- index = Bundler::Index.new
- %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) }
+ let(:sources) { Bundler::SourceList.new }
+ subject { Bundler::Definition.new(nil, [], sources, []) }
- dfn = Bundler::Definition.new(nil, [], mock_source_list, true)
- dfn.instance_variable_set("@index", index)
- found = dfn.find_indexed_specs(build_spec("foo", "0.9", "ruby").first)
- expect(found.length).to eq 3
+ before do
+ allow(sources).to receive(:non_global_rubygems_sources).and_return(non_global_rubygems_sources)
end
- end
- def build_stub_spec(name, version)
- Bundler::StubSpecification.new(name, version, nil, nil)
+ context "when all the scoped sources implement a dependency API" do
+ let(:non_global_rubygems_sources) do
+ [
+ double("non-global-source-0", "dependency_api_available?":true, to_s:"a"),
+ double("non-global-source-1", "dependency_api_available?":true, to_s:"b"),
+ ]
+ end
+
+ it "returns true without warning" do
+ expect(subject).not_to receive(:non_dependency_api_warning)
+
+ expect(subject.send(:precompute_source_requirements_for_indirect_dependencies?)).to be_truthy
+ end
+ end
+
+ context "when some scoped sources do not implement a dependency API" do
+ let(:non_global_rubygems_sources) do
+ [
+ double("non-global-source-0", "dependency_api_available?":true, to_s:"a"),
+ double("non-global-source-1", "dependency_api_available?":false, to_s:"b"),
+ double("non-global-source-2", "dependency_api_available?":false, to_s:"c"),
+ ]
+ end
+
+ it "returns false and warns about the non-API sources" do
+ expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
+Your Gemfile contains scoped sources that don't implement a dependency API, namely:
+
+ * b
+ * c
+
+Using the above gem servers may result in installing unexpected gems. To resolve this warning, make sure you use gem servers that implement dependency APIs, such as gemstash or geminabox gem servers.
+ W
+
+ expect(subject.send(:precompute_source_requirements_for_indirect_dependencies?)).to be_falsy
+ end
+ end
end
def mock_source_list
@@ -346,10 +368,6 @@ RSpec.describe Bundler::Definition do
[]
end
- def rubygems_remotes
- []
- end
-
def replace_sources!(arg)
nil
end
diff --git a/spec/bundler/bundler/dep_proxy_spec.rb b/spec/bundler/bundler/dep_proxy_spec.rb
deleted file mode 100644
index 0f8d6b1076..0000000000
--- a/spec/bundler/bundler/dep_proxy_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe Bundler::DepProxy do
- let(:dep) { Bundler::Dependency.new("rake", ">= 0") }
- subject { described_class.new(dep, Gem::Platform::RUBY) }
- let(:same) { subject }
- let(:other) { subject.dup }
- let(:different) { described_class.new(dep, Gem::Platform::JAVA) }
-
- describe "#eql?" do
- it { expect(subject.eql?(same)).to be true }
- it { expect(subject.eql?(other)).to be true }
- it { expect(subject.eql?(different)).to be false }
- it { expect(subject.eql?(nil)).to be false }
- it { expect(subject.eql?("foobar")).to be false }
- end
-
- describe "#hash" do
- it { expect(subject.hash).to eq(same.hash) }
- it { expect(subject.hash).to eq(other.hash) }
- end
-end
diff --git a/spec/bundler/bundler/dependency_spec.rb b/spec/bundler/bundler/dependency_spec.rb
new file mode 100644
index 0000000000..f930459571
--- /dev/null
+++ b/spec/bundler/bundler/dependency_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Dependency do
+ let(:options) do
+ {}
+ end
+ let(:dependency) do
+ described_class.new(
+ "test_gem",
+ "1.0.0",
+ options
+ )
+ end
+
+ describe "to_lock" do
+ it "returns formatted string" do
+ expect(dependency.to_lock).to eq(" test_gem (= 1.0.0)")
+ end
+
+ it "matches format of Gem::Dependency#to_lock" do
+ gem_dependency = Gem::Dependency.new("test_gem", "1.0.0")
+ expect(dependency.to_lock).to eq(gem_dependency.to_lock)
+ end
+
+ context "when source is passed" do
+ let(:options) do
+ {
+ "source" => Bundler::Source::Git.new({}),
+ }
+ end
+
+ it "returns formatted string with exclamation mark" do
+ expect(dependency.to_lock).to eq(" test_gem (= 1.0.0)!")
+ end
+ end
+ end
+
+ it "is on the current platform" do
+ engine = Gem.win_platform? ? "windows" : RUBY_ENGINE
+
+ dep = described_class.new(
+ "test_gem",
+ "1.0.0",
+ { "platforms" => "#{engine}_#{RbConfig::CONFIG["MAJOR"]}#{RbConfig::CONFIG["MINOR"]}" },
+ )
+
+ expect(dep.current_platform?).to be_truthy
+ end
+end
diff --git a/spec/bundler/bundler/digest_spec.rb b/spec/bundler/bundler/digest_spec.rb
new file mode 100644
index 0000000000..f876827964
--- /dev/null
+++ b/spec/bundler/bundler/digest_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require "openssl"
+require "bundler/digest"
+
+RSpec.describe Bundler::Digest do
+ context "SHA1" do
+ subject { Bundler::Digest }
+ let(:stdlib) { OpenSSL::Digest::SHA1 }
+
+ it "is compatible with stdlib" do
+ random_strings = ["foo", "skfjsdlkfjsdf", "3924m", "ldskfj"]
+
+ # https://www.rfc-editor.org/rfc/rfc3174#section-7.3
+ rfc3174_test_cases = ["abc", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "a", "01234567" * 8]
+
+ (random_strings + rfc3174_test_cases).each do |payload|
+ sha1 = subject.sha1(payload)
+ sha1_stdlib = stdlib.hexdigest(payload)
+ expect(sha1).to be == sha1_stdlib, "#{payload}'s sha1 digest (#{sha1}) did not match stlib's result (#{sha1_stdlib})"
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb
index dcc816eee2..b6e67a312c 100644
--- a/spec/bundler/bundler/dsl_spec.rb
+++ b/spec/bundler/bundler/dsl_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Bundler::Dsl do
it "registers custom hosts" do
subject.git_source(:example) {|repo_name| "git@git.example.com:#{repo_name}.git" }
subject.git_source(:foobar) {|repo_name| "git@foobar.com:#{repo_name}.git" }
- subject.gem("dobry-pies", :example => "strzalek/dobry-pies")
+ subject.gem("dobry-pies", example: "strzalek/dobry-pies")
example_uri = "git@git.example.com:strzalek/dobry-pies.git"
expect(subject.dependencies.first.source.uri).to eq(example_uri)
end
@@ -25,54 +25,144 @@ RSpec.describe Bundler::Dsl do
expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption)
end
- context "default hosts (git, gist)", :bundler => "< 3" do
- it "converts :github to :git" do
- subject.gem("sparks", :github => "indirect/sparks")
- github_uri = "git://github.com/indirect/sparks.git"
+ it "converts :github PR to URI using https" do
+ subject.gem("sparks", github: "https://github.com/indirect/sparks/pull/5")
+ github_uri = "https://github.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(github_uri)
+ expect(subject.dependencies.first.source.ref).to eq("refs/pull/5/head")
+ end
+
+ it "converts :gitlab PR to URI using https" do
+ subject.gem("sparks", gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5")
+ gitlab_uri = "https://gitlab.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(gitlab_uri)
+ expect(subject.dependencies.first.source.ref).to eq("refs/merge-requests/5/head")
+ end
+
+ it "rejects :github PR URI with a branch, ref or tag" do
+ expect do
+ subject.gem("sparks", github: "https://github.com/indirect/sparks/pull/5", branch: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :branch option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", github: "https://github.com/indirect/sparks/pull/5", ref: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :ref option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", github: "https://github.com/indirect/sparks/pull/5", tag: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :tag option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+ end
+
+ it "rejects :gitlab PR URI with a branch, ref or tag" do
+ expect do
+ subject.gem("sparks", gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5", branch: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :branch option can't be used with `gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5", ref: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :ref option can't be used with `gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5", tag: "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :tag option can't be used with `gitlab: "https://gitlab.com/indirect/sparks/-/merge_requests/5"`),
+ )
+ end
+
+ it "rejects :github with :git" do
+ expect do
+ subject.gem("sparks", github: "indirect/sparks", git: "https://github.com/indirect/sparks.git")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :git option can't be used with `github: "indirect/sparks"`),
+ )
+ end
+
+ it "rejects :gitlab with :git" do
+ expect do
+ subject.gem("sparks", gitlab: "indirect/sparks", git: "https://gitlab.com/indirect/sparks.git")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :git option can't be used with `gitlab: "indirect/sparks"`),
+ )
+ end
+
+ context "default hosts" do
+ it "converts :github to URI using https" do
+ subject.gem("sparks", github: "indirect/sparks")
+ github_uri = "https://github.com/indirect/sparks.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
- it "converts numeric :gist to :git" do
- subject.gem("not-really-a-gem", :gist => 2_859_988)
- github_uri = "https://gist.github.com/2859988.git"
+ it "converts :github shortcut to URI using https" do
+ subject.gem("sparks", github: "rails")
+ github_uri = "https://github.com/rails/rails.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
- it "converts :gist to :git" do
- subject.gem("not-really-a-gem", :gist => "2859988")
+ it "converts :gitlab to URI using https" do
+ subject.gem("sparks", gitlab: "indirect/sparks")
+ gitlab_uri = "https://gitlab.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(gitlab_uri)
+ end
+
+ it "converts :gitlab shortcut to URI using https" do
+ subject.gem("sparks", gitlab: "rails")
+ gitlab_uri = "https://gitlab.com/rails/rails.git"
+ expect(subject.dependencies.first.source.uri).to eq(gitlab_uri)
+ end
+
+ it "converts numeric :gist to :git" do
+ subject.gem("not-really-a-gem", gist: 2_859_988)
github_uri = "https://gist.github.com/2859988.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
- it "converts 'rails' to 'rails/rails'" do
- subject.gem("rails", :github => "rails")
- github_uri = "git://github.com/rails/rails.git"
+ it "converts :gist to :git" do
+ subject.gem("not-really-a-gem", gist: "2859988")
+ github_uri = "https://gist.github.com/2859988.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
it "converts :bitbucket to :git" do
- subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
+ subject.gem("not-really-a-gem", bitbucket: "mcorp/flatlab-rails")
bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/flatlab-rails.git"
expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri)
end
it "converts 'mcorp' to 'mcorp/mcorp'" do
- subject.gem("not-really-a-gem", :bitbucket => "mcorp")
+ subject.gem("not-really-a-gem", bitbucket: "mcorp")
bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/mcorp.git"
expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri)
end
end
- context "default git sources", :bundler => "3" do
- it "has none" do
- expect(subject.instance_variable_get(:@git_sources)).to eq({})
+ context "default git sources" do
+ it "has bitbucket, gist, github, and gitlab" do
+ expect(subject.instance_variable_get(:@git_sources).keys.sort).to eq(%w[bitbucket gist github gitlab])
end
end
end
describe "#method_missing" do
it "raises an error for unknown DSL methods" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).
+ expect(Bundler).to receive(:read_file).with(git_root.join("Gemfile").to_s).
and_return("unknown")
error_msg = "There was an error parsing `Gemfile`: Undefined local variable or method `unknown' for Gemfile. Bundler cannot continue."
@@ -83,33 +173,59 @@ RSpec.describe Bundler::Dsl do
describe "#eval_gemfile" do
it "handles syntax errors with a useful message" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return("}")
+ expect(Bundler).to receive(:read_file).with(git_root.join("Gemfile").to_s).and_return("}")
expect { subject.eval_gemfile("Gemfile") }.
- to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'). Bundler cannot continue./)
+ to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'|.+?unexpected '}', ignoring it\n). Bundler cannot continue./m)
end
it "distinguishes syntax errors from evaluation errors" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return(
+ expect(Bundler).to receive(:read_file).with(git_root.join("Gemfile").to_s).and_return(
"ruby '2.1.5', :engine => 'ruby', :engine_version => '1.2.4'"
)
expect { subject.eval_gemfile("Gemfile") }.
to raise_error(Bundler::GemfileError, /There was an error evaluating `Gemfile`: ruby_version must match the :engine_version for MRI/)
end
+
+ it "populates __dir__ and __FILE__ correctly" do
+ abs_path = git_root.join("../fragment.rb").to_s
+ expect(Bundler).to receive(:read_file).with(abs_path).and_return(<<~RUBY)
+ @fragment_dir = __dir__
+ @fragment_file = __FILE__
+ RUBY
+ subject.eval_gemfile("../fragment.rb")
+ expect(subject.instance_variable_get(:@fragment_dir)).to eq(git_root.dirname.to_s)
+ expect(subject.instance_variable_get(:@fragment_file)).to eq(abs_path)
+ end
end
describe "#gem" do
- [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :mri, :mri_18, :mri_19,
- :mri_20, :mri_21, :mri_22, :mri_23, :mri_24, :mri_25, :jruby, :rbx, :truffleruby].each do |platform|
+ # rubocop:disable Naming/VariableNumber
+ [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :ruby_26, :ruby_27,
+ :ruby_30, :ruby_31, :ruby_32, :ruby_33, :ruby_34, :ruby_40, :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22, :mri_23, :mri_24,
+ :mri_25, :mri_26, :mri_27, :mri_30, :mri_31, :mri_32, :mri_33, :mri_34, :mri_40, :jruby, :rbx, :truffleruby].each do |platform|
it "allows #{platform} as a valid platform" do
- subject.gem("foo", :platform => platform)
+ subject.gem("foo", platform: platform)
end
end
+ # rubocop:enable Naming/VariableNumber
+
+ it "allows platforms matching the running Ruby version" do
+ platform = "ruby_#{RbConfig::CONFIG["MAJOR"]}#{RbConfig::CONFIG["MINOR"]}"
+
+ expect { subject.gem("foo", platform: platform) }.not_to raise_error
+ expect(Bundler.current_ruby.respond_to?("#{platform}?")).to be_truthy
+ end
it "rejects invalid platforms" do
- expect { subject.gem("foo", :platform => :bogus) }.
+ expect { subject.gem("foo", platform: :bogus) }.
to raise_error(Bundler::GemfileError, /is not a valid platform/)
end
+ it "warn for legacy windows platforms" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(/\APlatform :mswin, :x64_mingw will be removed in the future./)
+ subject.gem("foo", platforms: [:mswin, :jruby, :x64_mingw])
+ end
+
it "rejects empty gem name" do
expect { subject.gem("") }.
to raise_error(Bundler::GemfileError, /an empty gem name is not valid/)
@@ -156,54 +272,29 @@ RSpec.describe Bundler::Dsl do
end
it "rejects branch option on non-git gems" do
- expect { subject.gem("foo", :branch => "test") }.
+ expect { subject.gem("foo", branch: "test") }.
to raise_error(Bundler::GemfileError, /The `branch` option for `gem 'foo'` is not allowed. Only gems with a git source can specify a branch/)
end
it "allows specifying a branch on git gems" do
- subject.gem("foo", :branch => "test", :git => "http://mytestrepo")
+ subject.gem("foo", branch: "test", git: "http://mytestrepo")
dep = subject.dependencies.last
expect(dep.name).to eq "foo"
end
it "allows specifying a branch on git gems with a git_source" do
subject.git_source(:test_source) {|n| "https://github.com/#{n}" }
- subject.gem("foo", :branch => "test", :test_source => "bundler/bundler")
+ subject.gem("foo", branch: "test", test_source: "bundler/bundler")
dep = subject.dependencies.last
expect(dep.name).to eq "foo"
end
end
- describe "#gemspec" do
- let(:spec) do
- Gem::Specification.new do |gem|
- gem.name = "example"
- gem.platform = platform
- end
- end
-
- before do
- allow(Dir).to receive(:[]).and_return(["spec_path"])
- allow(Bundler).to receive(:load_gemspec).with("spec_path").and_return(spec)
- allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile"))
- end
-
- context "with a ruby platform" do
- let(:platform) { "ruby" }
-
- it "keeps track of the ruby platforms in the dependency" do
- subject.gemspec
- expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::RUBY])
- end
- end
-
- context "with a jruby platform" do
- let(:platform) { "java" }
-
- it "keeps track of the jruby platforms in the dependency" do
- allow(Gem::Platform).to receive(:local).and_return(java)
- subject.gemspec
- expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::JAVA])
+ describe "#platforms" do
+ it "warn for legacy windows platforms" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(/\APlatform :mswin64, :mingw will be removed in the future./)
+ subject.platforms(:mswin64, :jruby, :mingw) do
+ subject.gem("foo")
end
end
end
@@ -229,7 +320,7 @@ RSpec.describe Bundler::Dsl do
# gem 'spree_api'
# gem 'spree_backend'
# end
- describe "#github", :bundler => "< 3" do
+ describe "#github" do
it "from github" do
spree_gems = %w[spree_core spree_api spree_backend]
subject.github "spree" do
@@ -237,36 +328,25 @@ RSpec.describe Bundler::Dsl do
end
subject.dependencies.each do |d|
- expect(d.source.uri).to eq("git://github.com/spree/spree.git")
+ expect(d.source.uri).to eq("https://github.com/spree/spree.git")
end
end
end
-
- describe "#github", :bundler => "3" do
- it "from github" do
- expect do
- spree_gems = %w[spree_core spree_api spree_backend]
- subject.github "spree" do
- spree_gems.each {|spree_gem| subject.send :gem, spree_gem }
- end
- end.to raise_error(Bundler::DeprecatedError, /github method has been removed/)
- end
- end
end
describe "syntax errors" do
it "will raise a Bundler::GemfileError" do
gemfile "gem 'foo', :path => /unquoted/string/syntax/error"
- expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }.
- to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)? unknown regexp options - trg. Bundler cannot continue./)
+ expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }.
+ to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)?.+?unknown regexp options - trg.+ Bundler cannot continue./m)
end
end
- describe "Runtime errors", :unless => Bundler.current_ruby.on_18? do
+ describe "Runtime errors" do
it "will raise a Bundler::GemfileError" do
- gemfile "s = 'foo'.freeze; s.strip!"
- expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }.
- to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: can't modify frozen String. Bundler cannot continue./i)
+ gemfile "raise RuntimeError, 'foo'"
+ expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }.
+ to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: foo. Bundler cannot continue./i)
end
end
@@ -278,7 +358,7 @@ RSpec.describe Bundler::Dsl do
allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile"))
subject.source("https://other-source.org") do
- subject.gem("dobry-pies", :path => "foo")
+ subject.gem("dobry-pies", path: "foo")
subject.gem("foo")
end
@@ -286,4 +366,193 @@ RSpec.describe Bundler::Dsl do
end
end
end
+
+ describe "#source with cooldown" do
+ before do
+ allow(@rubygems).to receive(:add_remote)
+ end
+
+ it "accepts a non-negative integer" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: 7)
+ end.not_to raise_error
+ end
+
+ it "accepts 0 as an explicit disable" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: 0)
+ end.not_to raise_error
+ end
+
+ it "rejects a string" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: "7")
+ end.to raise_error(Bundler::InvalidOption, /non-negative integer/)
+ end
+
+ it "rejects a float" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: 7.5)
+ end.to raise_error(Bundler::InvalidOption, /non-negative integer/)
+ end
+
+ it "rejects a negative integer" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: -7)
+ end.to raise_error(Bundler::InvalidOption, /non-negative integer/)
+ end
+
+ it "rejects an array" do
+ expect do
+ subject.source("https://rubygems.org", cooldown: [7])
+ end.to raise_error(Bundler::InvalidOption, /non-negative integer/)
+ end
+ end
+
+ describe "#override" do
+ it "stores an Override for a gem with a version: operation" do
+ subject.override("rails", version: ">= 8.0")
+
+ expect(subject.overrides.size).to eq(1)
+ override = subject.overrides.first
+ expect(override.target).to eq("rails")
+ expect(override.field).to eq(:version)
+ expect(override.operation).to eq(">= 8.0")
+ end
+
+ it "accepts :ignore_upper as the operation" do
+ subject.override("nokogiri", version: :ignore_upper)
+ expect(subject.overrides.first.operation).to eq(:ignore_upper)
+ end
+
+ it "accepts nil as the operation" do
+ subject.override("legacy", version: nil)
+ expect(subject.overrides.first.operation).to be_nil
+ end
+
+ it "appends to overrides across multiple statements" do
+ subject.override("rails", version: ">= 8.0")
+ subject.override("nokogiri", version: :ignore_upper)
+ expect(subject.overrides.map(&:target)).to eq(["rails", "nokogiri"])
+ end
+
+ it "is empty by default" do
+ expect(subject.overrides).to eq([])
+ end
+
+ it "raises ArgumentError when target is :all and version: is given" do
+ expect do
+ subject.override(:all, version: ">= 8.0")
+ end.to raise_error(ArgumentError, /`override :all, version:` is not allowed/)
+ end
+
+ it "rejects :all + version: even when other fields are also given" do
+ expect do
+ subject.override(:all, required_ruby_version: :ignore_upper, version: ">= 8.0")
+ end.to raise_error(ArgumentError, /`override :all, version:` is not allowed/)
+ end
+
+ it "does not record any override when :all + version: is rejected" do
+ expect do
+ subject.override(:all, version: ">= 8.0")
+ end.to raise_error(ArgumentError)
+ expect(subject.overrides).to eq([])
+ end
+
+ it "raises ArgumentError when target is neither :all nor a string" do
+ expect do
+ subject.override(:rails, version: ">= 8.0")
+ end.to raise_error(ArgumentError, /target must be :all or a gem name string/)
+ end
+
+ it "raises ArgumentError for an unsupported field" do
+ expect do
+ subject.override("rails", as: "y")
+ end.to raise_error(ArgumentError, /unsupported override field `as:`/)
+ end
+
+ it "stores an Override for a gem with a required_ruby_version: operation" do
+ subject.override("rails", required_ruby_version: :ignore_upper)
+ override = subject.overrides.first
+ expect(override.target).to eq("rails")
+ expect(override.field).to eq(:required_ruby_version)
+ expect(override.operation).to eq(:ignore_upper)
+ end
+
+ it "stores an Override for a gem with a required_rubygems_version: operation" do
+ subject.override("rails", required_rubygems_version: nil)
+ override = subject.overrides.first
+ expect(override.field).to eq(:required_rubygems_version)
+ expect(override.operation).to be_nil
+ end
+
+ it "stores an Override targeting :all with a metadata field" do
+ subject.override(:all, required_ruby_version: :ignore_upper)
+ override = subject.overrides.first
+ expect(override.target).to eq(:all)
+ expect(override.field).to eq(:required_ruby_version)
+ expect(override.operation).to eq(:ignore_upper)
+ end
+
+ it "stores an Override targeting :all with required_rubygems_version" do
+ subject.override(:all, required_rubygems_version: nil)
+ override = subject.overrides.first
+ expect(override.target).to eq(:all)
+ expect(override.field).to eq(:required_rubygems_version)
+ end
+
+ it "raises ArgumentError for a non-string, non-symbol, non-nil operation" do
+ expect do
+ subject.override("rails", version: 42)
+ end.to raise_error(ArgumentError, /override operation must be a String, Symbol, or nil/)
+ end
+
+ it "raises ArgumentError for an unsupported symbol operation" do
+ expect do
+ subject.override("rails", version: :explode)
+ end.to raise_error(ArgumentError, /unsupported override operation/)
+ end
+
+ it "raises ArgumentError for an unparsable version string" do
+ expect do
+ subject.override("rails", version: "not a version")
+ end.to raise_error(ArgumentError, /invalid override version requirement/)
+ end
+
+ it "does not record an override when the version string is invalid" do
+ expect do
+ subject.override("rails", version: "not a version")
+ end.to raise_error(ArgumentError)
+ expect(subject.overrides).to eq([])
+ end
+
+ it "rejects atomically when one field in a multi-field call is invalid" do
+ expect do
+ subject.override("rails", version: ">= 8.0", as: "y")
+ end.to raise_error(ArgumentError, /unsupported override field/)
+ expect(subject.overrides).to eq([])
+ end
+
+ it "raises ArgumentError when the same target and field are overridden twice" do
+ subject.override("rails", version: ">= 8.0")
+ expect do
+ subject.override("rails", version: :ignore_upper)
+ end.to raise_error(ArgumentError, /duplicate override for "rails" `version:`/)
+ end
+
+ it "keeps the original override when a duplicate is rejected" do
+ subject.override("rails", version: ">= 8.0")
+ expect do
+ subject.override("rails", version: :ignore_upper)
+ end.to raise_error(ArgumentError)
+ expect(subject.overrides.size).to eq(1)
+ expect(subject.overrides.first.operation).to eq(">= 8.0")
+ end
+
+ it "allows different targets with the same field" do
+ subject.override("rails", version: ">= 8.0")
+ subject.override("nokogiri", version: :ignore_upper)
+ expect(subject.overrides.size).to eq(2)
+ end
+ end
end
diff --git a/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb
index a9371f6617..4fbd59d48f 100644
--- a/spec/bundler/bundler/endpoint_specification_spec.rb
+++ b/spec/bundler/bundler/endpoint_specification_spec.rb
@@ -5,9 +5,10 @@ RSpec.describe Bundler::EndpointSpecification do
let(:version) { "1.0.0" }
let(:platform) { Gem::Platform::RUBY }
let(:dependencies) { [] }
+ let(:spec_fetcher) { double(:spec_fetcher) }
let(:metadata) { nil }
- subject(:spec) { described_class.new(name, version, platform, dependencies, metadata) }
+ subject(:spec) { described_class.new(name, version, platform, spec_fetcher, dependencies, metadata) }
describe "#build_dependency" do
let(:name) { "foo" }
@@ -32,22 +33,6 @@ RSpec.describe Bundler::EndpointSpecification do
)
end
end
-
- context "when there is an ill formed requirement" do
- before do
- allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) {
- raise ArgumentError.new("Ill-formed requirement [\"#<YAML::Syck::DefaultKey")
- }
- # Eliminate extra line break in rspec output due to `puts` in `#build_dependency`
- allow(subject).to receive(:puts) {}
- end
-
- it "should raise a Bundler::GemspecError with invalid gemspec message" do
- expect { subject.send(:build_dependency, name, [requirement1, requirement2]) }.to raise_error(
- Bundler::GemspecError, /Unfortunately, the gem foo \(1\.0\.0\) has an invalid gemspec/
- )
- end
- end
end
describe "#parse_metadata" do
@@ -57,14 +42,81 @@ RSpec.describe Bundler::EndpointSpecification do
expect { subject }.to raise_error(
Bundler::GemspecError,
a_string_including("There was an error parsing the metadata for the gem foo (1.0.0)").
- and(a_string_including('The metadata was {"rubygems"=>">\n"}'))
+ and(a_string_including("The metadata was #{{ "rubygems" => ">\n" }.inspect}"))
)
end
end
+
+ context "when the metadata has created_at" do
+ let(:metadata) { { "created_at" => ["2026-05-12T10:00:00Z"] } }
+
+ it "parses created_at as a Time" do
+ expect(subject.created_at).to eq(Time.utc(2026, 5, 12, 10, 0, 0))
+ end
+ end
+
+ context "when the metadata has a string created_at (older rubygems shape)" do
+ let(:metadata) { { "created_at" => "2026-05-12T10:00:00Z" } }
+
+ it "still parses created_at" do
+ expect(subject.created_at).to eq(Time.utc(2026, 5, 12, 10, 0, 0))
+ end
+ end
+
+ context "when created_at is truncated (older rubygems splits on colons)" do
+ let(:metadata) { { "created_at" => "2026-05-12T10" } }
+
+ it "leaves created_at as nil instead of raising" do
+ expect(subject.created_at).to be_nil
+ end
+ end
+
+ context "when the metadata has no created_at" do
+ let(:metadata) { { "checksum" => ["abc"] } }
+ let(:spec_fetcher) { double(:spec_fetcher, uri: "https://rubygems.org") }
+
+ it "leaves created_at as nil" do
+ allow(Bundler::Checksum).to receive(:from_api).and_return(nil)
+ expect(subject.created_at).to be_nil
+ end
+ end
+
+ context "when the metadata is nil" do
+ it "leaves created_at as nil" do
+ expect(subject.created_at).to be_nil
+ end
+ end
+ end
+
+ describe "#required_ruby_version" do
+ context "required_ruby_version is already set on endpoint specification" do
+ existing_value = "already set value"
+ let(:required_ruby_version) { existing_value }
+
+ it "should return the current value when already set on endpoint specification" do
+ expect(spec.required_ruby_version). eql?(existing_value)
+ end
+ end
+
+ it "should return the remote spec value when not set on endpoint specification and remote spec has one" do
+ remote_value = "remote_value"
+ remote_spec = double(:remote_spec, required_ruby_version: remote_value, required_rubygems_version: nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+
+ expect(spec.required_ruby_version). eql?(remote_value)
+ end
+
+ it "should use the default Gem Requirement value when not set on endpoint specification and not set on remote spec" do
+ remote_spec = double(:remote_spec, required_ruby_version: nil, required_rubygems_version: nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+ expect(spec.required_ruby_version). eql?(Gem::Requirement.default)
+ end
end
it "supports equality comparison" do
- other_spec = described_class.new("bar", version, platform, dependencies, metadata)
+ remote_spec = double(:remote_spec, required_ruby_version: nil, required_rubygems_version: nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+ other_spec = described_class.new("bar", version, platform, spec_fetcher, dependencies, metadata)
expect(spec).to eql(spec)
expect(spec).to_not eql(other_spec)
end
diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb
index 20bd38b021..259b4ee9dc 100644
--- a/spec/bundler/bundler/env_spec.rb
+++ b/spec/bundler/bundler/env_spec.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
require "bundler/settings"
+require "openssl"
RSpec.describe Bundler::Env do
- let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil, nil) }
+ let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil) }
describe "#report" do
it "prints the environment" do
@@ -17,48 +18,128 @@ RSpec.describe Bundler::Env do
expect(out).to include(OpenSSL::OPENSSL_VERSION)
end
+ describe "rubygems paths" do
+ it "prints gem home" do
+ with_clear_paths("GEM_HOME", "/a/b/c") do
+ out = described_class.report
+ expect(out).to include("Gem Home /a/b/c")
+ end
+ end
+
+ it "prints gem path" do
+ with_clear_paths("GEM_PATH", "/a/b/c#{File::PATH_SEPARATOR}d/e/f") do
+ out = described_class.report
+ expect(out).to include("Gem Path /a/b/c#{File::PATH_SEPARATOR}d/e/f")
+ end
+ end
+
+ it "prints user home" do
+ with_clear_paths("HOME", "/a/b/c") do
+ out = described_class.report
+ expect(out).to include("User Home /a/b/c")
+ end
+ end
+
+ it "prints user path" do
+ with_clear_paths("HOME", "/a/b/c") do
+ allow(File).to receive(:exist?)
+ allow(File).to receive(:exist?).with("/a/b/c/.gem").and_return(true)
+ out = described_class.report
+ expect(out).to include("User Path /a/b/c/.gem")
+ end
+ end
+
+ it "prints bin dir" do
+ with_clear_paths("GEM_HOME", "/a/b/c") do
+ out = described_class.report
+ expect(out).to include("Bin Dir /a/b/c/bin")
+ end
+ end
+
+ private
+
+ def with_clear_paths(env_var, env_value)
+ old_env_var = ENV[env_var]
+ ENV[env_var] = env_value
+ Gem.clear_paths
+ yield
+ ensure
+ ENV[env_var] = old_env_var
+ end
+ end
+
context "when there is a Gemfile and a lockfile and print_gemfile is true" do
before do
- gemfile "gem 'rack', '1.0.0'"
+ gemfile "source 'https://gem.repo1'; gem 'myrack', '1.0.0'"
lockfile <<-L
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
1.10.0
L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
- let(:output) { described_class.report(:print_gemfile => true) }
+ let(:output) { described_class.report(print_gemfile: true) }
it "prints the Gemfile" do
expect(output).to include("Gemfile")
- expect(output).to include("'rack', '1.0.0'")
+ expect(output).to include("'myrack', '1.0.0'")
end
it "prints the lockfile" do
expect(output).to include("Gemfile.lock")
- expect(output).to include("rack (1.0.0)")
+ expect(output).to include("myrack (1.0.0)")
end
end
context "when there no Gemfile and print_gemfile is true" do
- let(:output) { described_class.report(:print_gemfile => true) }
+ let(:output) { described_class.report(print_gemfile: true) }
it "prints the environment" do
expect(output).to start_with("## Environment")
end
end
+ context "when there's bundler config with credentials" do
+ before do
+ bundle "config set https://localgemserver.test/ user:pass"
+ end
+
+ let(:output) { described_class.report(print_gemfile: true) }
+
+ it "prints the config with redacted values" do
+ expect(output).to include("https://localgemserver.test")
+ expect(output).to include("user:[REDACTED]")
+ expect(output).to_not include("user:pass")
+ end
+ end
+
+ context "when there's bundler config with OAuth token credentials" do
+ before do
+ bundle "config set https://localgemserver.test/ api_token:x-oauth-basic"
+ end
+
+ let(:output) { described_class.report(print_gemfile: true) }
+
+ it "prints the config with redacted values" do
+ expect(output).to include("https://localgemserver.test")
+ expect(output).to include("[REDACTED]:x-oauth-basic")
+ expect(output).to_not include("api_token:x-oauth-basic")
+ end
+ end
+
context "when Gemfile contains a gemspec and print_gemspecs is true" do
let(:gemspec) do
- strip_whitespace(<<-GEMSPEC)
+ <<~GEMSPEC
Gem::Specification.new do |gem|
gem.name = "foo"
gem.author = "Fumofu"
@@ -67,15 +148,17 @@ RSpec.describe Bundler::Env do
end
before do
- gemfile("gemspec")
+ gemfile("source 'https://gem.repo1'; gemspec")
- File.open(bundled_app.join("foo.gemspec"), "wb") do |f|
+ File.open(bundled_app("foo.gemspec"), "wb") do |f|
f.write(gemspec)
end
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "prints the gemspec" do
- output = described_class.report(:print_gemspecs => true)
+ output = described_class.report(print_gemspecs: true)
expect(output).to include("foo.gemspec")
expect(output).to include(gemspec)
@@ -84,28 +167,30 @@ RSpec.describe Bundler::Env do
context "when eval_gemfile is used" do
it "prints all gemfiles" do
- create_file "other/Gemfile-other", "gem 'rack'"
- create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'"
- create_file "Gemfile-alt", <<-G
- source "file:#{gem_repo1}"
+ gemfile bundled_app("other/Gemfile-other"), "gem 'myrack'"
+ gemfile bundled_app("other/Gemfile"), "eval_gemfile 'Gemfile-other'"
+ gemfile bundled_app("Gemfile-alt"), <<-G
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
G
- gemfile "eval_gemfile #{File.expand_path("Gemfile-alt").dump}"
+ gemfile "eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}"
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
- output = described_class.report(:print_gemspecs => true)
- expect(output).to include(strip_whitespace(<<-ENV))
+ output = described_class.report(print_gemspecs: true)
+ expect(output).to include(<<~ENV)
## Gemfile
### Gemfile
```ruby
- eval_gemfile #{File.expand_path("Gemfile-alt").dump}
+ eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}
```
### Gemfile-alt
```ruby
- source "file:#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
```
@@ -118,13 +203,13 @@ RSpec.describe Bundler::Env do
### other/Gemfile-other
```ruby
- gem 'rack'
+ gem 'myrack'
```
### Gemfile.lock
```
- <No #{bundled_app("Gemfile.lock")} found>
+ <No #{bundled_app_lock} found>
```
ENV
end
@@ -132,8 +217,9 @@ RSpec.describe Bundler::Env do
context "when the git version is OS specific" do
it "includes OS specific information with the version number" do
- expect(git_proxy_stub).to receive(:git).with("--version").
- and_return("git version 1.2.3 (Apple Git-BS)")
+ status = double("success?" => true)
+ expect(Open3).to receive(:capture3).with("git", "--version").
+ and_return(["git version 1.2.3 (Apple Git-BS)", "", status])
expect(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
expect(described_class.report).to include("Git 1.2.3 (Apple Git-BS)")
@@ -141,11 +227,11 @@ RSpec.describe Bundler::Env do
end
end
- describe ".version_of", :ruby_repo do
+ describe ".version_of" do
let(:parsed_version) { described_class.send(:version_of, "ruby") }
it "strips version of new line characters" do
- expect(parsed_version).to_not include("\n")
+ expect(parsed_version).to_not end_with("\n")
end
end
end
diff --git a/spec/bundler/bundler/environment_preserver_spec.rb b/spec/bundler/bundler/environment_preserver_spec.rb
index 530ca6f835..6c7066d0c6 100644
--- a/spec/bundler/bundler/environment_preserver_spec.rb
+++ b/spec/bundler/bundler/environment_preserver_spec.rb
@@ -27,8 +27,12 @@ RSpec.describe Bundler::EnvironmentPreserver do
context "when a key is empty" do
let(:env) { { "foo" => "" } }
- it "should not create backup entries" do
- expect(subject).not_to have_key "BUNDLER_ORIG_foo"
+ it "should keep the original entry" do
+ expect(subject["foo"]).to be_empty
+ end
+
+ it "should still create backup entries" do
+ expect(subject).to have_key "BUNDLER_ORIG_foo"
end
end
@@ -71,8 +75,12 @@ RSpec.describe Bundler::EnvironmentPreserver do
context "when the original key is empty" do
let(:env) { { "foo" => "my-foo", "BUNDLER_ORIG_foo" => "" } }
- it "should keep the current value" do
- expect(subject["foo"]).to eq("my-foo")
+ it "should restore the original value" do
+ expect(subject["foo"]).to be_empty
+ end
+
+ it "should delete the backup value" do
+ expect(subject.key?("BUNDLER_ORIG_foo")).to eq(false)
end
end
end
diff --git a/spec/bundler/bundler/errors_spec.rb b/spec/bundler/bundler/errors_spec.rb
new file mode 100644
index 0000000000..b62d85d32b
--- /dev/null
+++ b/spec/bundler/bundler/errors_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::IncorrectLockfileDependencies do
+ describe "#message" do
+ let(:spec) do
+ double("LazySpecification", full_name: "rubocop-1.82.0")
+ end
+
+ context "without dependency details" do
+ subject { described_class.new(spec) }
+
+ it "provides a basic error message" do
+ expect(subject.message).to include("Bundler found incorrect dependencies in the lockfile for rubocop-1.82.0")
+ expect(subject.message).to include("Please run `bundle install` to regenerate the lockfile.")
+ end
+ end
+
+ context "with dependency details" do
+ let(:actual_dependencies) do
+ [
+ Gem::Dependency.new("json", [">= 2.3", "< 4.0"]),
+ Gem::Dependency.new("parallel", ["~> 1.10"]),
+ Gem::Dependency.new("parser", [">= 3.3.0.2"]),
+ ]
+ end
+
+ let(:lockfile_dependencies) do
+ [
+ Gem::Dependency.new("json", [">= 2.3", "< 3.0"]),
+ Gem::Dependency.new("parallel", ["~> 1.10"]),
+ Gem::Dependency.new("parser", [">= 3.2.0.0"]),
+ ]
+ end
+
+ subject { described_class.new(spec, actual_dependencies, lockfile_dependencies) }
+
+ it "shows only mismatched dependencies" do
+ message = subject.message
+
+ expect(message).to include("json: gemspec specifies")
+ expect(message).to include("parser: gemspec specifies")
+ expect(message).not_to include("parallel")
+ end
+ end
+
+ context "when gemspec has dependencies but lockfile has none" do
+ let(:actual_dependencies) do
+ [
+ Gem::Dependency.new("myrack-test", ["~> 1.0"]),
+ ]
+ end
+
+ let(:lockfile_dependencies) { [] }
+
+ subject { described_class.new(spec, actual_dependencies, lockfile_dependencies) }
+
+ it "shows the dependency as not in lockfile" do
+ message = subject.message
+
+ expect(message).to include("myrack-test: gemspec specifies ~> 1.0, not in lockfile")
+ end
+ end
+
+ context "when gemspec has no dependencies but lockfile has some" do
+ let(:actual_dependencies) { [] }
+
+ let(:lockfile_dependencies) do
+ [
+ Gem::Dependency.new("unexpected", ["~> 1.0"]),
+ ]
+ end
+
+ subject { described_class.new(spec, actual_dependencies, lockfile_dependencies) }
+
+ it "shows the dependency as not in gemspec" do
+ message = subject.message
+
+ expect(message).to include("unexpected: not in gemspec, lockfile has ~> 1.0")
+ end
+ end
+ end
+
+ describe "#status_code" do
+ let(:spec) { double("LazySpecification", full_name: "test-1.0.0") }
+ subject { described_class.new(spec) }
+
+ it "returns 41" do
+ expect(subject.status_code).to eq(41)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/fetcher/base_spec.rb b/spec/bundler/bundler/fetcher/base_spec.rb
index df1245d44d..b8c6b57b10 100644
--- a/spec/bundler/bundler/fetcher/base_spec.rb
+++ b/spec/bundler/bundler/fetcher/base_spec.rb
@@ -4,15 +4,16 @@ RSpec.describe Bundler::Fetcher::Base do
let(:downloader) { double(:downloader) }
let(:remote) { double(:remote) }
let(:display_uri) { "http://sample_uri.com" }
+ let(:gem_remote_fetcher) { nil }
class TestClass < described_class; end
- subject { TestClass.new(downloader, remote, display_uri) }
+ subject { TestClass.new(downloader, remote, display_uri, gem_remote_fetcher) }
describe "#initialize" do
context "with the abstract Base class" do
it "should raise an error" do
- expect { described_class.new(downloader, remote, display_uri) }.to raise_error(RuntimeError, "Abstract class")
+ expect { described_class.new(downloader, remote, display_uri, gem_remote_fetcher) }.to raise_error(RuntimeError, "Abstract class")
end
end
@@ -36,7 +37,7 @@ RSpec.describe Bundler::Fetcher::Base do
end
describe "#fetch_uri" do
- let(:remote_uri_obj) { URI("http://rubygems.org") }
+ let(:remote_uri_obj) { Gem::URI("http://rubygems.org") }
before { allow(subject).to receive(:remote_uri).and_return(remote_uri_obj) }
@@ -49,10 +50,10 @@ RSpec.describe Bundler::Fetcher::Base do
end
context "when the remote uri's host is not rubygems.org" do
- let(:remote_uri_obj) { URI("http://otherhost.org") }
+ let(:remote_uri_obj) { Gem::URI("http://otherhost.org") }
it "should return the remote uri" do
- expect(subject.fetch_uri).to eq(URI("http://otherhost.org"))
+ expect(subject.fetch_uri).to eq(Gem::URI("http://otherhost.org"))
end
end
diff --git a/spec/bundler/bundler/fetcher/compact_index_spec.rb b/spec/bundler/bundler/fetcher/compact_index_spec.rb
index e0f58766ea..aa536673d9 100644
--- a/spec/bundler/bundler/fetcher/compact_index_spec.rb
+++ b/spec/bundler/bundler/fetcher/compact_index_spec.rb
@@ -1,35 +1,41 @@
# frozen_string_literal: true
+# load CompactIndexClient upfront to prevent thread safety issues during parallel specs
+require "bundler/compact_index_client"
+
RSpec.describe Bundler::Fetcher::CompactIndex do
- let(:downloader) { double(:downloader) }
- let(:display_uri) { URI("http://sampleuri.com") }
- let(:remote) { double(:remote, :cache_slug => "lsjdf", :uri => display_uri) }
- let(:compact_index) { described_class.new(downloader, remote, display_uri) }
+ let(:response) { double(:response) }
+ let(:downloader) { double(:downloader, fetch: response) }
+ let(:display_uri) { Gem::URI("http://sampleuri.com") }
+ let(:remote) { double(:remote, cache_slug: "lsjdf", uri: display_uri) }
+ let(:gem_remote_fetcher) { nil }
+ let(:compact_index) { described_class.new(downloader, remote, display_uri, gem_remote_fetcher) }
+ let(:compact_index_client) { double(:compact_index_client, available?: true, info: [["lskdjf", "1", nil, [], []]]) }
before do
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified).and_return(true)
allow(compact_index).to receive(:log_specs) {}
+ allow(compact_index).to receive(:compact_index_client).and_return(compact_index_client)
end
describe "#specs_for_names" do
+ let(:thread_list) { Thread.list.select {|thread| thread.status == "run" } }
+ let(:thread_inspection) { thread_list.map {|th| " * #{th}:\n #{th.backtrace_locations.join("\n ")}" }.join("\n") }
+
it "has only one thread open at the end of the run" do
compact_index.specs_for_names(["lskdjf"])
- thread_count = Thread.list.count {|thread| thread.status == "run" }
- expect(thread_count).to eq 1
+ thread_count = thread_list.count
+ expect(thread_count).to eq(1), "Expected 1 active thread after `#specs_for_names`, but found #{thread_count}. In particular, found:\n#{thread_inspection}"
end
it "calls worker#stop during the run" do
- expect_any_instance_of(Bundler::Worker).to receive(:stop).at_least(:once)
+ expect_any_instance_of(Bundler::Worker).to receive(:stop).at_least(:once).and_call_original
compact_index.specs_for_names(["lskdjf"])
end
describe "#available?" do
- before do
- allow(compact_index).to receive(:compact_index_client).
- and_return(double(:compact_index_client, :update_and_parse_checksums! => true))
- end
-
it "returns true" do
expect(compact_index).to be_available
end
@@ -44,7 +50,7 @@ RSpec.describe Bundler::Fetcher::CompactIndex do
end
end
- context "when OpenSSL is FIPS-enabled", :ruby => ">= 2.0.0" do
+ context "when OpenSSL is FIPS-enabled" do
def remove_cached_md5_availability
return unless Bundler::SharedHelpers.instance_variable_defined?(:@md5_available)
Bundler::SharedHelpers.remove_instance_variable(:@md5_available)
@@ -59,7 +65,7 @@ RSpec.describe Bundler::Fetcher::CompactIndex do
context "when FIPS-mode is active" do
before do
- allow(OpenSSL::Digest::MD5).to receive(:digest).
+ allow(OpenSSL::Digest).to receive(:digest).with("MD5", "").
and_raise(OpenSSL::Digest::DigestError)
end
diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb
index 081fdff34d..501bc269a5 100644
--- a/spec/bundler/bundler/fetcher/dependency_spec.rb
+++ b/spec/bundler/bundler/fetcher/dependency_spec.rb
@@ -2,10 +2,11 @@
RSpec.describe Bundler::Fetcher::Dependency do
let(:downloader) { double(:downloader) }
- let(:remote) { double(:remote, :uri => URI("http://localhost:5000")) }
+ let(:remote) { double(:remote, uri: Gem::URI("http://localhost:5000")) }
let(:display_uri) { "http://sample_uri.com" }
+ let(:gem_remote_fetcher) { nil }
- subject { described_class.new(downloader, remote, display_uri) }
+ subject { described_class.new(downloader, remote, display_uri, gem_remote_fetcher) }
describe "#available?" do
let(:dependency_api_uri) { double(:dependency_api_uri) }
@@ -155,9 +156,9 @@ RSpec.describe Bundler::Fetcher::Dependency do
end
end
- shared_examples_for "the error suggests retrying with the full index" do
- it "should log the inability to fetch from API at debug level" do
- expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`")
+ shared_examples_for "the error is logged" do
+ it "should log the inability to fetch from API at debug level, and mention retrying" do
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API, trying the full index")
subject.specs(gem_names, full_dependency_list, last_spec_list)
end
end
@@ -166,25 +167,21 @@ RSpec.describe Bundler::Fetcher::Dependency do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::HTTPError.new } }
it_behaves_like "the error is properly handled"
- it_behaves_like "the error suggests retrying with the full index"
+ it_behaves_like "the error is logged"
end
context "when a GemspecError occurs" do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::GemspecError.new } }
it_behaves_like "the error is properly handled"
- it_behaves_like "the error suggests retrying with the full index"
+ it_behaves_like "the error is logged"
end
context "when a MarshalError occurs" do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::MarshalError.new } }
it_behaves_like "the error is properly handled"
-
- it "should log the inability to fetch from API and mention retrying" do
- expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API, trying the full index")
- subject.specs(gem_names, full_dependency_list, last_spec_list)
- end
+ it_behaves_like "the error is logged"
end
end
@@ -214,37 +211,49 @@ RSpec.describe Bundler::Fetcher::Dependency do
let(:gem_names) { [%w[foo bar], %w[bundler rubocop]] }
let(:dep_api_uri) { double(:dep_api_uri) }
let(:unmarshalled_gems) { double(:unmarshalled_gems) }
- let(:fetch_response) { double(:fetch_response, :body => double(:body)) }
- let(:rubygems_limit) { 50 }
+ let(:fetch_response) { double(:fetch_response, body: double(:body)) }
+ let(:rubygems_limit) { 100 }
before { allow(subject).to receive(:dependency_api_uri).with(gem_names).and_return(dep_api_uri) }
it "should fetch dependencies from RubyGems and unmarshal them" do
expect(gem_names).to receive(:each_slice).with(rubygems_limit).and_call_original
expect(downloader).to receive(:fetch).with(dep_api_uri).and_return(fetch_response)
- expect(Bundler).to receive(:load_marshal).with(fetch_response.body).and_return([unmarshalled_gems])
+ expect(Bundler).to receive(:safe_load_marshal).with(fetch_response.body).and_return([unmarshalled_gems])
expect(subject.unmarshalled_dep_gems(gem_names)).to eq([unmarshalled_gems])
end
+
+ it "should fetch as many dependencies as specified" do
+ allow(subject).to receive(:dependency_api_uri).with([%w[foo bar]]).and_return(dep_api_uri)
+ allow(subject).to receive(:dependency_api_uri).with([%w[bundler rubocop]]).and_return(dep_api_uri)
+
+ expect(downloader).to receive(:fetch).twice.with(dep_api_uri).and_return(fetch_response)
+ expect(Bundler).to receive(:safe_load_marshal).twice.with(fetch_response.body).and_return([unmarshalled_gems])
+
+ Bundler.settings.temporary(api_request_size: 1) do
+ expect(subject.unmarshalled_dep_gems(gem_names)).to eq([unmarshalled_gems, unmarshalled_gems])
+ end
+ end
end
describe "#get_formatted_specs_and_deps" do
let(:gem_list) do
[
{
- :dependencies => {
+ dependencies: {
"resque" => "req3,req4",
},
- :name => "typhoeus",
- :number => "1.0.1",
- :platform => "ruby",
+ name: "typhoeus",
+ number: "1.0.1",
+ platform: "ruby",
},
{
- :dependencies => {
+ dependencies: {
"faraday" => "req1,req2",
},
- :name => "grape",
- :number => "2.0.2",
- :platform => "jruby",
+ name: "grape",
+ number: "2.0.2",
+ platform: "jruby",
},
]
end
@@ -258,7 +267,7 @@ RSpec.describe Bundler::Fetcher::Dependency do
end
describe "#dependency_api_uri" do
- let(:uri) { URI("http://gem-api.com") }
+ let(:uri) { Gem::URI("http://gem-api.com") }
context "with gem names" do
let(:gem_names) { %w[foo bar bundler rubocop] }
diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb
index c9b4fa662a..edf426328a 100644
--- a/spec/bundler/bundler/fetcher/downloader_spec.rb
+++ b/spec/bundler/bundler/fetcher/downloader_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe Bundler::Fetcher::Downloader do
let(:connection) { double(:connection) }
let(:redirect_limit) { 5 }
- let(:uri) { URI("http://www.uri-to-fetch.com/api/v2/endpoint") }
+ let(:uri) { Gem::URI("http://www.uri-to-fetch.com/api/v2/endpoint") }
let(:options) { double(:options) }
subject { described_class.new(connection, redirect_limit) }
@@ -27,7 +27,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
context "logging" do
- let(:http_response) { Net::HTTPSuccess.new("1.1", 200, "Success") }
+ let(:http_response) { Gem::Net::HTTPSuccess.new("1.1", 200, "Success") }
it "should log the HTTP response code and message to debug" do
expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP 200 Success #{uri}")
@@ -35,68 +35,134 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
- context "when the request response is a Net::HTTPRedirection" do
- let(:http_response) { Net::HTTPRedirection.new(httpv, 308, "Moved") }
+ context "when the request response is a Gem::Net::HTTPRedirection" do
+ let(:http_response) { Gem::Net::HTTPRedirection.new(httpv, 308, "Moved") }
before { http_response["location"] = "http://www.redirect-uri.com/api/v2/endpoint" }
it "should try to fetch the redirect uri and iterate the # requests counter" do
- expect(subject).to receive(:fetch).with(URI("http://www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original
- expect(subject).to receive(:fetch).with(URI("http://www.redirect-uri.com/api/v2/endpoint"), options, 1)
+ expect(subject).to receive(:fetch).with(Gem::URI("http://www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original
+ expect(subject).to receive(:fetch).with(Gem::URI("http://www.redirect-uri.com/api/v2/endpoint"), options, 1)
subject.fetch(uri, options, counter)
end
context "when the redirect uri and original uri are the same" do
- let(:uri) { URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
+ let(:uri) { Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
before { http_response["location"] = "ssh://www.uri-to-fetch.com/api/v1/endpoint" }
it "should set the same user and password for the redirect uri" do
- expect(subject).to receive(:fetch).with(URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original
- expect(subject).to receive(:fetch).with(URI("ssh://username:password@www.uri-to-fetch.com/api/v1/endpoint"), options, 1)
+ expect(subject).to receive(:fetch).with(Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original
+ expect(subject).to receive(:fetch).with(Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v1/endpoint"), options, 1)
subject.fetch(uri, options, counter)
end
end
end
- context "when the request response is a Net::HTTPSuccess" do
- let(:http_response) { Net::HTTPSuccess.new("1.1", 200, "Success") }
+ context "when the request response is a Gem::Net::HTTPSuccess" do
+ let(:http_response) { Gem::Net::HTTPSuccess.new("1.1", 200, "Success") }
it "should return the response body" do
expect(subject.fetch(uri, options, counter)).to eq(http_response)
end
end
- context "when the request response is a Net::HTTPRequestEntityTooLarge" do
- let(:http_response) { Net::HTTPRequestEntityTooLarge.new("1.1", 413, "Too Big") }
+ context "when the request response is a Gem::Net::HTTPRequestEntityTooLarge" do
+ let(:http_response) { Gem::Net::HTTPRequestEntityTooLarge.new("1.1", 413, "Too Big") }
it "should raise a Bundler::Fetcher::FallbackError with the response body" do
expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Body with info")
end
end
- context "when the request response is a Net::HTTPUnauthorized" do
- let(:http_response) { Net::HTTPUnauthorized.new("1.1", 401, "Unauthorized") }
+ context "when the request response is a Gem::Net::HTTPUnauthorized" do
+ let(:http_response) { Gem::Net::HTTPUnauthorized.new("1.1", 401, "Unauthorized") }
it "should raise a Bundler::Fetcher::AuthenticationRequiredError with the uri host" do
expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
/Authentication is required for www.uri-to-fetch.com/)
end
+
+ it "should raise a Bundler::Fetcher::AuthenticationRequiredError with advice" do
+ expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
+ /`bundle config set --global www\.uri-to-fetch\.com username:password`.*`BUNDLE_WWW__URI___TO___FETCH__COM`/m)
+ end
+
+ context "when there are credentials provided in the request" do
+ let(:uri) { Gem::URI("http://user:password@www.uri-to-fetch.com") }
+
+ it "should raise a Bundler::Fetcher::BadAuthenticationError that doesn't contain the password" do
+ expect { subject.fetch(uri, options, counter) }.
+ to raise_error(Bundler::Fetcher::BadAuthenticationError, /Bad username or password for www.uri-to-fetch.com/)
+ end
+ end
+ end
+
+ context "when the request response is a Gem::Net::HTTPForbidden" do
+ let(:http_response) { Gem::Net::HTTPForbidden.new("1.1", 403, "Forbidden") }
+ let(:uri) { Gem::URI("http://user:password@www.uri-to-fetch.com") }
+
+ it "should raise a Bundler::Fetcher::AuthenticationForbiddenError with the uri host" do
+ expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError,
+ /Access token could not be authenticated for www.uri-to-fetch.com/)
+ end
+ end
+
+ context "when the request response is a Gem::Net::HTTPNotFound" do
+ let(:http_response) { Gem::Net::HTTPNotFound.new("1.1", 404, "Not Found") }
+
+ it "should raise a Bundler::Fetcher::FallbackError with Gem::Net::HTTPNotFound" do
+ expect { subject.fetch(uri, options, counter) }.
+ to raise_error(Bundler::Fetcher::FallbackError, "Gem::Net::HTTPNotFound: http://www.uri-to-fetch.com/api/v2/endpoint")
+ end
+
+ context "when there are credentials provided in the request" do
+ let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
+
+ it "should raise a Bundler::Fetcher::FallbackError that doesn't contain the password" do
+ expect { subject.fetch(uri, options, counter) }.
+ to raise_error(Bundler::Fetcher::FallbackError, "Gem::Net::HTTPNotFound: http://username@www.uri-to-fetch.com/api/v2/endpoint")
+ end
+ end
end
- context "when the request response is a Net::HTTPNotFound" do
- let(:http_response) { Net::HTTPNotFound.new("1.1", 404, "Not Found") }
+ context "when the request response is a Gem::Net::HTTPRequestedRangeNotSatisfiable" do
+ let(:http_response) { Gem::Net::HTTPRequestedRangeNotSatisfiable.new("1.1", 416, "Range Not Satisfiable") }
+ let(:success_response) { Gem::Net::HTTPSuccess.new("1.1", 200, "Success") }
+ let(:options) { { "Range" => "bytes=1000-", "If-None-Match" => "some-etag" } }
+
+ before do
+ # First request returns 416, retry request returns success
+ allow(subject).to receive(:request).with(uri, options).and_return(http_response)
+ allow(subject).to receive(:request).with(uri, { "If-None-Match" => "some-etag" }).and_return(success_response)
+ end
+
+ # The 416 handler removes the Range header and retries without incrementing the counter.
+ # Importantly, it does NOT add Accept-Encoding header, which would break Ruby's
+ # automatic gzip decompression (see issue #9271 for details on that bug).
+ it "should retry the request without the Range header" do
+ expect(subject).to receive(:request).with(uri, options).ordered
+ expect(subject).to receive(:request).with(uri, hash_excluding("Range", "Accept-Encoding")).ordered
+ subject.fetch(uri, options, counter)
+ end
+
+ it "should preserve other headers on retry" do
+ expect(subject).to receive(:request).with(uri, options).ordered
+ expect(subject).to receive(:request).with(uri, hash_including("If-None-Match" => "some-etag")).ordered
+ subject.fetch(uri, options, counter)
+ end
- it "should raise a Bundler::Fetcher::FallbackError with Net::HTTPNotFound" do
- expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Net::HTTPNotFound")
+ it "should return the successful response" do
+ result = subject.fetch(uri, options, counter)
+ expect(result).to eq(success_response)
end
end
context "when the request response is some other type" do
- let(:http_response) { Net::HTTPBadGateway.new("1.1", 500, "Fatal Error") }
+ let(:http_response) { Gem::Net::HTTPBadGateway.new("1.1", 500, "Fatal Error") }
it "should raise a Bundler::HTTPError with the response class and body" do
- expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::HTTPError, "Net::HTTPBadGateway: Body with info")
+ expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::HTTPError, "Gem::Net::HTTPBadGateway: Body with info")
end
end
end
@@ -106,7 +172,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
let(:response) { double(:response) }
before do
- allow(Net::HTTP::Get).to receive(:new).with("/api/v2/endpoint", options).and_return(net_http_get)
+ allow(Gem::Net::HTTP::Get).to receive(:new).with("/api/v2/endpoint", options).and_return(net_http_get)
allow(connection).to receive(:request).with(uri, net_http_get).and_return(response)
end
@@ -118,62 +184,46 @@ RSpec.describe Bundler::Fetcher::Downloader do
context "when there is a user provided in the request" do
context "and there is also a password provided" do
context "that contains cgi escaped characters" do
- let(:uri) { URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") }
+ let(:uri) { Gem::URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the username and password" do
+ it "should request basic authentication with the username and password, and log the HTTP GET request to debug, without the password" do
expect(net_http_get).to receive(:basic_auth).with("username", "password$")
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://username@www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
context "that is all unescaped characters" do
- let(:uri) { URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the username and proper cgi compliant password" do
+ let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
+ it "should request basic authentication with the username and proper cgi compliant password, and log the HTTP GET request to debug, without the password" do
expect(net_http_get).to receive(:basic_auth).with("username", "password")
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://username@www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
end
- context "and there is no password provided" do
- let(:uri) { URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") }
+ context "and it's used as the authentication token" do
+ let(:uri) { Gem::URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with just the user" do
+ it "should request basic authentication with just the user, and log the HTTP GET request to debug, without the token" do
expect(net_http_get).to receive(:basic_auth).with("username", nil)
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
- context "that contains cgi escaped characters" do
- let(:uri) { URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") }
+ context "and it's used as the authentication token, and contains cgi escaped characters" do
+ let(:uri) { Gem::URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the proper cgi compliant password user" do
+ it "should request basic authentication with the proper cgi compliant password user, and log the HTTP GET request to debug, without the token" do
expect(net_http_get).to receive(:basic_auth).with("username$", nil)
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
end
- context "when the request response causes a NoMethodError" do
- before { allow(connection).to receive(:request).with(uri, net_http_get) { raise NoMethodError.new(message) } }
-
- context "and the error message is about use_ssl=" do
- let(:message) { "undefined method 'use_ssl='" }
-
- it "should raise a LoadError about openssl" do
- expect { subject.request(uri, options) }.to raise_error(LoadError, "cannot load such file -- openssl")
- end
- end
-
- context "and the error message is not about use_ssl=" do
- let(:message) { "undefined method 'undefined_method_call'" }
-
- it "should raise the original NoMethodError" do
- expect { subject.request(uri, options) }.to raise_error(NoMethodError, "undefined method 'undefined_method_call'")
- end
- end
- end
-
context "when the request response causes a OpenSSL::SSL::SSLError" do
before { allow(connection).to receive(:request).with(uri, net_http_get) { raise OpenSSL::SSL::SSLError.new } }
@@ -183,66 +233,68 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
- context "when the request response causes an error included in HTTP_ERRORS" do
- let(:message) { nil }
- let(:error) { RuntimeError.new(message) }
+ context "when the request response causes an HTTP error" do
+ let(:message) { "error about network" }
+ let(:error) { error_class.new(message) }
before do
- stub_const("Bundler::Fetcher::HTTP_ERRORS", [RuntimeError])
allow(connection).to receive(:request).with(uri, net_http_get) { raise error }
end
- it "should trace log the error" do
- allow(Bundler).to receive_message_chain(:ui, :debug)
- expect(Bundler).to receive_message_chain(:ui, :trace).with(error)
- expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError)
- end
-
- context "when error message is about the host being down" do
- let(:message) { "host down: http://www.uri-to-fetch.com" }
-
- it "should raise a Bundler::Fetcher::NetworkDownError" do
- expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
- /Could not reach host www.uri-to-fetch.com/)
- end
- end
-
- context "when error message is about getaddrinfo issues" do
- let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" }
+ context "that it's retryable" do
+ let(:error_class) { Gem::Timeout::Error }
- it "should raise a Bundler::Fetcher::NetworkDownError" do
- expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
- /Could not reach host www.uri-to-fetch.com/)
+ it "should trace log the error" do
+ allow(Bundler).to receive_message_chain(:ui, :debug)
+ expect(Bundler).to receive_message_chain(:ui, :trace).with(error)
+ expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError)
end
- end
-
- context "when error message is about neither host down or getaddrinfo" do
- let(:message) { "other error about network" }
it "should raise a Bundler::HTTPError" do
expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (other error about network)")
+ "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (error about network)")
end
- context "when the there are credentials provided in the request" do
- let(:uri) { URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
+ context "when there are credentials provided in the request" do
+ let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
before do
allow(net_http_get).to receive(:basic_auth).with("username", "password")
end
it "should raise a Bundler::HTTPError that doesn't contain the password" do
expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://username@www.uri-to-fetch.com/api/v2/endpoint (other error about network)")
+ "Network error while fetching http://username@www.uri-to-fetch.com/api/v2/endpoint (error about network)")
end
end
end
- context "when error message is about no route to host" do
+ context "when error is about the host being down" do
+ let(:error_class) { Gem::Net::HTTP::Persistent::Error }
+ let(:message) { "host down: http://www.uri-to-fetch.com" }
+
+ it "should raise a Bundler::Fetcher::NetworkDownError" do
+ expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
+ /Could not reach host www.uri-to-fetch.com/)
+ end
+ end
+
+ context "when error is about connection refused" do
+ let(:error_class) { Gem::Net::HTTP::Persistent::Error }
+ let(:message) { "connection refused down: http://www.uri-to-fetch.com" }
+
+ it "should raise a Bundler::Fetcher::NetworkDownError" do
+ expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
+ /Could not reach host www.uri-to-fetch.com/)
+ end
+ end
+
+ context "when error is about no route to host" do
+ let(:error_class) { SocketError }
let(:message) { "Failed to open TCP connection to www.uri-to-fetch.com:443 " }
- it "should raise a Bundler::Fetcher::HTTPError" do
- expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (#{message})")
+ it "should raise a Bundler::Fetcher::NetworkDownError" do
+ expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
+ /Could not reach host www.uri-to-fetch.com/)
end
end
end
diff --git a/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb b/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb
new file mode 100644
index 0000000000..df1a58d843
--- /dev/null
+++ b/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require "rubygems/remote_fetcher"
+require "bundler/fetcher/gem_remote_fetcher"
+require_relative "../../support/artifice/helpers/artifice"
+require "bundler/vendored_persistent.rb"
+
+RSpec.describe Bundler::Fetcher::GemRemoteFetcher do
+ describe "Parallel download" do
+ it "download using multiple connections from the pool" do
+ unless Bundler.rubygems.provides?(">= 4.0.0.dev")
+ skip "This example can only run when RubyGems supports multiple http connection pool"
+ end
+
+ require_relative "../../support/artifice/helpers/endpoint"
+ concurrent_ruby_path = Dir[scoped_base_system_gem_path.join("gems/concurrent-ruby-*/lib/concurrent-ruby")].first
+ $LOAD_PATH.unshift(concurrent_ruby_path)
+ require "concurrent-ruby"
+
+ require_rack_test
+ responses = []
+
+ latch1 = Concurrent::CountDownLatch.new
+ latch2 = Concurrent::CountDownLatch.new
+ previous_client = Gem::Request::ConnectionPools.client
+ dummy_endpoint = Class.new(Endpoint) do
+ get "/foo" do
+ latch2.count_down
+ latch1.wait
+
+ responses << "foo"
+ end
+
+ get "/bar" do
+ responses << "bar"
+
+ latch1.count_down
+ end
+ end
+
+ Artifice.activate_with(dummy_endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ first_request = Thread.new do
+ subject.fetch_path("https://example.org/foo")
+ end
+ second_request = Thread.new do
+ latch2.wait
+ subject.fetch_path("https://example.org/bar")
+ end
+
+ [first_request, second_request].each(&:join)
+
+ expect(responses).to eq(["bar", "foo"])
+ ensure
+ Artifice.deactivate
+ Gem::Request::ConnectionPools.client = previous_client
+ end
+ end
+end
diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb
index 0cf0ae764e..a6a18efd98 100644
--- a/spec/bundler/bundler/fetcher/index_spec.rb
+++ b/spec/bundler/bundler/fetcher/index_spec.rb
@@ -1,13 +1,18 @@
# frozen_string_literal: true
+require "rubygems/remote_fetcher"
+
RSpec.describe Bundler::Fetcher::Index do
let(:downloader) { nil }
- let(:remote) { nil }
+ let(:remote) { double(:remote, uri: remote_uri) }
+ let(:remote_uri) { Gem::URI("http://#{userinfo}remote-uri.org") }
+ let(:userinfo) { "" }
let(:display_uri) { "http://sample_uri.com" }
let(:rubygems) { double(:rubygems) }
let(:gem_names) { %w[foo bar] }
+ let(:gem_remote_fetcher) { nil }
- subject { described_class.new(downloader, remote, display_uri) }
+ subject { described_class.new(downloader, remote, display_uri, gem_remote_fetcher) }
before { allow(Bundler).to receive(:rubygems).and_return(rubygems) }
@@ -17,83 +22,54 @@ RSpec.describe Bundler::Fetcher::Index do
end
context "error handling" do
- shared_examples_for "the error is properly handled" do
- let(:remote_uri) { URI("http://remote-uri.org") }
- before do
- allow(subject).to receive(:remote_uri).and_return(remote_uri)
- end
-
- context "when certificate verify failed" do
- let(:error_message) { "certificate verify failed" }
-
- it "should raise a Bundler::Fetcher::CertificateFailureError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError,
- %r{Could not verify the SSL certificate for http://sample_uri.com})
- end
- end
+ before do
+ allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, display_uri) }
+ end
- context "when a 401 response occurs" do
- let(:error_message) { "401" }
+ context "when certificate verify failed" do
+ let(:error_message) { "certificate verify failed" }
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
- %r{Authentication is required for http://remote-uri.org})
- end
+ it "should raise a Bundler::Fetcher::CertificateFailureError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError,
+ %r{Could not verify the SSL certificate for http://sample_uri.com})
end
+ end
- context "when a 403 response occurs" do
- let(:error_message) { "403" }
-
- before do
- allow(remote_uri).to receive(:userinfo).and_return(userinfo)
- end
-
- context "and there was userinfo" do
- let(:userinfo) { double(:userinfo) }
-
- it "should raise a Bundler::Fetcher::BadAuthenticationError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
- %r{Bad username or password for http://remote-uri.org})
- end
- end
-
- context "and there was no userinfo" do
- let(:userinfo) { nil }
+ context "when a 401 response occurs" do
+ let(:error_message) { "401" }
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
- %r{Authentication is required for http://remote-uri.org})
- end
- end
+ it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
+ %r{Authentication is required for http://remote-uri.org})
end
- context "any other message is returned" do
- let(:error_message) { "You get an error, you get an error!" }
+ context "and there was userinfo" do
+ let(:userinfo) { "user:pass@" }
- before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) }
-
- it "should raise a Bundler::HTTPError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com")
+ it "should raise a Bundler::Fetcher::BadAuthenticationError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
+ %r{Bad username or password for http://user@remote-uri.org})
end
end
end
- context "when a Gem::RemoteFetcher::FetchError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, nil) } }
+ context "when a 403 response occurs" do
+ let(:error_message) { "403" }
- it_behaves_like "the error is properly handled"
+ it "should raise a Bundler::Fetcher::AuthenticationForbiddenError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError,
+ %r{Access token could not be authenticated for http://remote-uri.org})
+ end
end
- context "when a OpenSSL::SSL::SSLError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise OpenSSL::SSL::SSLError.new(error_message) } }
+ context "any other message is returned" do
+ let(:error_message) { "You get an error, you get an error!" }
- it_behaves_like "the error is properly handled"
- end
+ before { allow(Bundler).to receive(:ui).and_return(double(trace: nil)) }
- context "when a Net::HTTPFatalError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Net::HTTPFatalError.new(error_message, 404) } }
-
- it_behaves_like "the error is properly handled"
+ it "should raise a Bundler::HTTPError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com due to underlying error <You get an error, you get an error! (http://sample_uri.com)>")
+ end
end
end
end
diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb
index 184b9efa64..e20f7e7c48 100644
--- a/spec/bundler/bundler/fetcher_spec.rb
+++ b/spec/bundler/bundler/fetcher_spec.rb
@@ -3,8 +3,8 @@
require "bundler/fetcher"
RSpec.describe Bundler::Fetcher do
- let(:uri) { URI("https://example.com") }
- let(:remote) { double("remote", :uri => uri, :original_uri => nil) }
+ let(:uri) { Gem::URI("https://example.com") }
+ let(:remote) { double("remote", uri: uri, original_uri: nil) }
subject(:fetcher) { Bundler::Fetcher.new(remote) }
@@ -26,7 +26,7 @@ RSpec.describe Bundler::Fetcher do
context "when Gem.configuration specifies http_proxy " do
let(:proxy) { "http://proxy-example2.com" }
before do
- allow(Bundler.rubygems.configuration).to receive(:[]).with(:http_proxy).and_return(proxy)
+ allow(Gem.configuration).to receive(:[]).with(:http_proxy).and_return(proxy)
end
it "consider Gem.configuration when determine proxy" do
expect(fetcher.http_proxy).to match("http://proxy-example2.com")
@@ -45,9 +45,9 @@ RSpec.describe Bundler::Fetcher do
end
context "when a rubygems source mirror is set" do
- let(:orig_uri) { URI("http://zombo.com") }
+ let(:orig_uri) { Gem::URI("http://zombo.com") }
let(:remote_with_mirror) do
- double("remote", :uri => uri, :original_uri => orig_uri, :anonymized_uri => uri)
+ double("remote", uri: uri, original_uri: orig_uri, anonymized_uri: uri)
end
let(:fetcher) { Bundler::Fetcher.new(remote_with_mirror) }
@@ -61,7 +61,7 @@ RSpec.describe Bundler::Fetcher do
context "when there is no rubygems source mirror set" do
let(:remote_no_mirror) do
- double("remote", :uri => uri, :original_uri => nil, :anonymized_uri => uri)
+ double("remote", uri: uri, original_uri: nil, anonymized_uri: uri)
end
let(:fetcher) { Bundler::Fetcher.new(remote_no_mirror) }
@@ -113,10 +113,10 @@ RSpec.describe Bundler::Fetcher do
context "when gem ssl configuration is set" do
before do
- allow(Bundler.rubygems.configuration).to receive_messages(
- :http_proxy => nil,
- :ssl_client_cert => "cert",
- :ssl_ca_cert => "ca"
+ allow(Gem.configuration).to receive_messages(
+ http_proxy: nil,
+ ssl_client_cert: "cert",
+ ssl_ca_cert: "ca"
)
expect(File).to receive(:read).and_return("")
expect(OpenSSL::X509::Certificate).to receive(:new).and_return("cert")
@@ -143,19 +143,118 @@ RSpec.describe Bundler::Fetcher do
describe "include CI information" do
it "from one CI" do
- with_env_vars("JENKINS_URL" => "foo") do
- ci_part = fetcher.user_agent.split(" ").find {|x| x.match(%r{\Aci/}) }
- expect(ci_part).to match("jenkins")
+ with_env_vars("CI" => nil, "JENKINS_URL" => "foo") do
+ ci_part = fetcher.user_agent.split(" ").find {|x| x.start_with?("ci/") }
+ cis = ci_part.split("/").last.split(",")
+ expect(cis).to include("jenkins")
+ expect(cis).not_to include("ci")
end
end
it "from many CI" do
- with_env_vars("TRAVIS" => "foo", "CI_NAME" => "my_ci") do
- ci_part = fetcher.user_agent.split(" ").find {|x| x.match(%r{\Aci/}) }
- expect(ci_part).to match("travis")
- expect(ci_part).to match("my_ci")
+ with_env_vars("CI" => "true", "SEMAPHORE" => nil, "TRAVIS" => "foo", "GITLAB_CI" => "gitlab", "CI_NAME" => "MY_ci") do
+ ci_part = fetcher.user_agent.split(" ").find {|x| x.start_with?("ci/") }
+ cis = ci_part.split("/").last.split(",")
+ expect(cis).to include("ci", "gitlab", "my_ci", "travis")
+ expect(cis).not_to include("semaphore")
end
end
end
end
+
+ describe "#fetch_spec" do
+ let(:name) { "name" }
+ let(:version) { "1.3.17" }
+ let(:platform) { "platform" }
+ let(:downloader) { double("downloader") }
+ let(:body) { double(Gem::Net::HTTP::Get, body: downloaded_data) }
+
+ context "when attempting to load a Gem::Specification" do
+ let(:spec) { Gem::Specification.new(name, version) }
+ let(:downloaded_data) { Zlib::Deflate.deflate(Marshal.dump(spec)) }
+
+ it "returns the spec" do
+ expect(Bundler::Fetcher::Downloader).to receive(:new).and_return(downloader)
+ expect(downloader).to receive(:fetch).once.and_return(body)
+ result = fetcher.fetch_spec([name, version, platform])
+ expect(result).to eq(spec)
+ end
+ end
+
+ context "when attempting to load an unexpected class" do
+ let(:downloaded_data) { Zlib::Deflate.deflate(Marshal.dump(3)) }
+
+ it "raises a HTTPError error" do
+ expect(Bundler::Fetcher::Downloader).to receive(:new).and_return(downloader)
+ expect(downloader).to receive(:fetch).once.and_return(body)
+ expect { fetcher.fetch_spec([name, version, platform]) }.to raise_error(Bundler::HTTPError, /Gemspec .* contained invalid data/i)
+ end
+ end
+ end
+
+ describe "#specs_with_retry" do
+ let(:downloader) { double(:downloader) }
+ let(:remote) { double(:remote, cache_slug: "slug", uri: uri, original_uri: nil, anonymized_uri: uri) }
+ let(:compact_index) { double(Bundler::Fetcher::CompactIndex, available?: true, api_fetcher?: true) }
+ let(:dependency) { double(Bundler::Fetcher::Dependency, available?: true, api_fetcher?: true) }
+ let(:index) { double(Bundler::Fetcher::Index, available?: true, api_fetcher?: false) }
+
+ before do
+ allow(Bundler::Fetcher::CompactIndex).to receive(:new).and_return(compact_index)
+ allow(Bundler::Fetcher::Dependency).to receive(:new).and_return(dependency)
+ allow(Bundler::Fetcher::Index).to receive(:new).and_return(index)
+ end
+
+ it "picks the first fetcher that works" do
+ expect(compact_index).to receive(:specs).with("name").and_return([["name", "1.2.3", "ruby"]])
+ expect(dependency).not_to receive(:specs)
+ expect(index).not_to receive(:specs)
+ fetcher.specs_with_retry("name", double(Bundler::Source::Rubygems))
+ end
+
+ context "when APIs are not available" do
+ before do
+ allow(compact_index).to receive(:available?).and_return(false)
+ allow(dependency).to receive(:available?).and_return(false)
+ end
+
+ it "uses the index" do
+ expect(compact_index).not_to receive(:specs)
+ expect(dependency).not_to receive(:specs)
+ expect(index).to receive(:specs).with("name").and_return([["name", "1.2.3", "ruby"]])
+
+ fetcher.specs_with_retry("name", double(Bundler::Source::Rubygems))
+ end
+ end
+ end
+
+ describe "#api_fetcher?" do
+ let(:downloader) { double(:downloader) }
+ let(:remote) { double(:remote, cache_slug: "slug", uri: uri, original_uri: nil, anonymized_uri: uri) }
+ let(:compact_index) { double(Bundler::Fetcher::CompactIndex, available?: false, api_fetcher?: true) }
+ let(:dependency) { double(Bundler::Fetcher::Dependency, available?: false, api_fetcher?: true) }
+ let(:index) { double(Bundler::Fetcher::Index, available?: true, api_fetcher?: false) }
+
+ before do
+ allow(Bundler::Fetcher::CompactIndex).to receive(:new).and_return(compact_index)
+ allow(Bundler::Fetcher::Dependency).to receive(:new).and_return(dependency)
+ allow(Bundler::Fetcher::Index).to receive(:new).and_return(index)
+ end
+
+ context "when an api fetcher is available" do
+ before do
+ allow(compact_index).to receive(:available?).and_return(true)
+ end
+
+ it "is truthy" do
+ expect(fetcher).to be_api_fetcher
+ end
+ end
+
+ context "when only the index fetcher is available" do
+ it "is falsey" do
+ expect(fetcher).not_to be_api_fetcher
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb
index 2a1be491ef..426e3c856d 100644
--- a/spec/bundler/bundler/friendly_errors_spec.rb
+++ b/spec/bundler/bundler/friendly_errors_spec.rb
@@ -2,45 +2,30 @@
require "bundler"
require "bundler/friendly_errors"
-require "cgi"
+require "cgi/escape"
+require "cgi/util" unless defined?(CGI::EscapeExt)
RSpec.describe Bundler, "friendly errors" do
context "with invalid YAML in .gemrc" do
before do
- File.open(Gem.configuration.config_file_name, "w") do |f|
+ File.open(home(".gemrc"), "w") do |f|
f.write "invalid: yaml: hah"
end
end
after do
- FileUtils.rm(Gem.configuration.config_file_name)
+ FileUtils.rm(home(".gemrc"))
end
- it "reports a relevant friendly error message", :ruby => ">= 1.9", :rubygems => "< 2.5.0" do
+ it "reports a relevant friendly error message" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, :env => { "DEBUG" => true }
+ bundle :install, env: { "DEBUG" => "true" }
- expect(out).to include("Your RubyGems configuration")
- expect(out).to include("invalid YAML syntax")
- expect(out).to include("Psych::SyntaxError")
- expect(out).not_to include("ERROR REPORT TEMPLATE")
- expect(exitstatus).to eq(25) if exitstatus
- end
-
- it "reports a relevant friendly error message", :ruby => ">= 1.9", :rubygems => ">= 2.5.0" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- bundle :install, :env => { "DEBUG" => true }
-
- expect(last_command.stderr).to include("Failed to load #{home(".gemrc")}")
- expect(exitstatus).to eq(0) if exitstatus
+ expect(err).to include("Failed to load #{home(".gemrc")}")
end
end
@@ -109,7 +94,7 @@ RSpec.describe Bundler, "friendly errors" do
end
it "writes to Bundler.ui.trace" do
- expect(Bundler.ui).to receive(:trace).with(orig_error, nil, true)
+ expect(Bundler.ui).to receive(:trace).with(orig_error)
Bundler::FriendlyErrors.log_error(error)
end
end
@@ -117,35 +102,15 @@ RSpec.describe Bundler, "friendly errors" do
context "BundlerError" do
it "Bundler.ui receive error" do
error = Bundler::BundlerError.new
- expect(Bundler.ui).to receive(:error).with(error.message, :wrap => true)
+ expect(Bundler.ui).to receive(:error).with(error.message, wrap: true)
Bundler::FriendlyErrors.log_error(error)
end
- it_behaves_like "Bundler.ui receive trace", Bundler::BundlerError.new
end
context "Thor::Error" do
it_behaves_like "Bundler.ui receive error", Bundler::Thor::Error.new
end
- context "LoadError" do
- let(:error) { LoadError.new("cannot load such file -- openssl") }
-
- it "Bundler.ui receive error" do
- expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL.")
- Bundler::FriendlyErrors.log_error(error)
- end
-
- it "Bundler.ui receive warn" do
- expect(Bundler.ui).to receive(:warn).with(any_args, :wrap => true)
- Bundler::FriendlyErrors.log_error(error)
- end
-
- it "Bundler.ui receive trace" do
- expect(Bundler.ui).to receive(:trace).with(error)
- Bundler::FriendlyErrors.log_error(error)
- end
- end
-
context "Interrupt" do
it "Bundler.ui receive error" do
expect(Bundler.ui).to receive(:error).with("\nQuitting...")
@@ -157,7 +122,7 @@ RSpec.describe Bundler, "friendly errors" do
context "Gem::InvalidSpecificationException" do
it "Bundler.ui receive error" do
error = Gem::InvalidSpecificationException.new
- expect(Bundler.ui).to receive(:error).with(error.message, :wrap => true)
+ expect(Bundler.ui).to receive(:error).with(error.message, wrap: true)
Bundler::FriendlyErrors.log_error(error)
end
end
@@ -166,17 +131,13 @@ RSpec.describe Bundler, "friendly errors" do
# Does nothing
end
- context "Java::JavaLang::OutOfMemoryError" do
- module Java
- module JavaLang
- class OutOfMemoryError < StandardError; end
- end
- end
-
+ context "Java::JavaLang::OutOfMemoryError", :jruby_only do
it "Bundler.ui receive error" do
- error = Java::JavaLang::OutOfMemoryError.new
- expect(Bundler.ui).to receive(:error).with(/JVM has run out of memory/)
- Bundler::FriendlyErrors.log_error(error)
+ install_gemfile <<-G, raise_on_error: false, env: { "JRUBY_OPTS" => "-J-Xmx32M" }, artifice: nil
+ source "https://gem.repo1"
+ G
+
+ expect(err).to include("JVM has run out of memory")
end
end
@@ -215,9 +176,9 @@ RSpec.describe Bundler, "friendly errors" do
describe "#request_issue_report_for" do
it "calls relevant methods for Bundler.ui" do
- expect(Bundler.ui).to receive(:info)
- expect(Bundler.ui).to receive(:error)
- expect(Bundler.ui).to receive(:warn)
+ expect(Bundler.ui).not_to receive(:info)
+ expect(Bundler.ui).to receive(:error).exactly(3).times
+ expect(Bundler.ui).not_to receive(:warn)
Bundler::FriendlyErrors.request_issue_report_for(StandardError.new)
end
@@ -236,7 +197,7 @@ RSpec.describe Bundler, "friendly errors" do
it "generates a search URL for the exception message" do
exception = Exception.new("Exception message")
- expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=Exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/ruby/rubygems/search?q=Exception+message&type=Issues")
end
it "generates a search URL for only the first line of a multi-line exception message" do
@@ -245,7 +206,7 @@ First line of the exception message
Second line of the exception message
END
- expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=First+line+of+the+exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/ruby/rubygems/search?q=First+line+of+the+exception+message&type=Issues")
end
it "generates the url without colons" do
@@ -254,7 +215,7 @@ Exception ::: with ::: colons :::
END
issues_url = Bundler::FriendlyErrors.issues_url(exception)
expect(issues_url).not_to include("%3A")
- expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/ruby/rubygems/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
end
it "removes information after - for Errono::EACCES" do
@@ -264,7 +225,7 @@ END
allow(exception).to receive(:is_a?).with(Errno).and_return(true)
issues_url = Bundler::FriendlyErrors.issues_url(exception)
expect(issues_url).not_to include("/Users/foo/bar")
- expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/ruby/rubygems/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
end
end
end
diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb
index a627129fe3..b4ae2abdc5 100644
--- a/spec/bundler/bundler/gem_helper_spec.rb
+++ b/spec/bundler/bundler/gem_helper_spec.rb
@@ -9,8 +9,15 @@ RSpec.describe Bundler::GemHelper do
let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") }
before(:each) do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ bundle_config_global "gem.mit false"
+ bundle_config_global "gem.test false"
+ bundle_config_global "gem.coc false"
+ bundle_config_global "gem.linter false"
+ bundle_config_global "gem.ci false"
+ bundle_config_global "gem.changelog false"
+ git("config --global init.defaultBranch main")
bundle "gem #{app_name}"
+ prepare_gemspec(app_gemspec_path)
end
context "determining gemspec" do
@@ -29,15 +36,6 @@ RSpec.describe Bundler::GemHelper do
end
context "interpolates the name" do
- before do
- # Remove exception that prevents public pushes on older RubyGems versions
- if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
- content = File.read(app_gemspec_path)
- content.sub!(/raise "RubyGems 2\.0 or newer.*/, "")
- File.open(app_gemspec_path, "w") {|f| f.write(content) }
- end
- end
-
it "when there is only one gemspec" do
expect(subject.gemspec.name).to eq(app_name)
end
@@ -68,11 +66,21 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message message
end
+ def mock_checksum_message(name, version)
+ message = "#{name} #{version} checksum written to checksums/#{name}-#{version}.gem.sha512."
+ mock_confirm_message message
+ end
+
+ def sha512_hexdigest(path)
+ Digest::SHA512.file(path).hexdigest
+ end
+
subject! { Bundler::GemHelper.new(app_path) }
let(:app_version) { "0.1.0" }
let(:app_gem_dir) { app_path.join("pkg") }
let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") }
- let(:app_gemspec_content) { remove_push_guard(File.read(app_gemspec_path)) }
+ let(:app_sha_path) { app_path.join("checksums", "#{app_name}-#{app_version}.gem.sha512") }
+ let(:app_gemspec_content) { File.read(app_gemspec_path) }
before(:each) do
content = app_gemspec_content.gsub("TODO: ", "")
@@ -81,14 +89,6 @@ RSpec.describe Bundler::GemHelper do
File.open(app_gemspec_path, "w") {|file| file << content }
end
- def remove_push_guard(gemspec_content)
- # Remove exception that prevents public pushes on older RubyGems versions
- if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
- gemspec_content.sub!(/raise "RubyGems 2\.0 or newer.*/, "")
- end
- gemspec_content
- end
-
it "uses a shell UI for output" do
expect(Bundler.ui).to be_a(Bundler::UI::Shell)
end
@@ -113,6 +113,7 @@ RSpec.describe Bundler::GemHelper do
context "before installation" do
it "raises an error with appropriate message" do
task_names.each do |name|
+ skip "Rake::FileTask '#{name}' exists" if File.exist?(name)
expect { Rake.application[name] }.
to raise_error(/^Don't know how to build task '#{name}'/)
end
@@ -154,6 +155,68 @@ RSpec.describe Bundler::GemHelper do
expect(app_gem_path).to exist
end
end
+
+ context "when building in the current working directory" do
+ it "creates .gem file" do
+ mock_build_message app_name, app_version
+ Dir.chdir app_path do
+ Bundler::GemHelper.new.build_gem
+ end
+ expect(app_gem_path).to exist
+ end
+ end
+
+ context "when building in a location relative to the current working directory" do
+ it "creates .gem file" do
+ mock_build_message app_name, app_version
+ Dir.chdir File.dirname(app_path) do
+ Bundler::GemHelper.new(File.basename(app_path)).build_gem
+ end
+ expect(app_gem_path).to exist
+ end
+ end
+ end
+
+ describe "#build_checksum" do
+ it "calculates SHA512 of the content" do
+ FileUtils.mkdir_p(app_gem_dir)
+ File.write(app_gem_path, "")
+ mock_checksum_message app_name, app_version
+ subject.build_checksum(app_gem_path)
+ expect(File.read(app_sha_path).chomp).to eql(Digest::SHA512.hexdigest(""))
+ end
+
+ context "when build was successful" do
+ it "creates .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ subject.build_checksum
+ expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
+ end
+ end
+ context "when building in the current working directory" do
+ it "creates a .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ Dir.chdir app_path do
+ Bundler::GemHelper.new.build_checksum
+ end
+ expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
+ end
+ end
+ context "when building in a location relative to the current working directory" do
+ it "creates a .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ Dir.chdir File.dirname(app_path) do
+ Bundler::GemHelper.new(File.basename(app_path)).build_checksum
+ end
+ expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
+ end
+ end
end
describe "#install_gem" do
@@ -163,7 +226,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "#{app_name} (#{app_version}) installed."
subject.install_gem(nil, :local)
expect(app_gem_path).to exist
- gem_command! :list
+ installed_gems_list
expect(out).to include("#{app_name} (#{app_version})")
end
end
@@ -176,7 +239,7 @@ RSpec.describe Bundler::GemHelper do
FileUtils.touch app_gem_path
app_gem_path
end
- expect { subject.install_gem }.to raise_error(/Couldn't install gem/)
+ expect { subject.install_gem }.to raise_error(/Running `#{gem_bin} install #{app_gem_path}` failed/)
end
end
end
@@ -194,12 +257,11 @@ RSpec.describe Bundler::GemHelper do
end
before do
- Dir.chdir(app_path) do
- `git init`
- `git config user.email "you@example.com"`
- `git config user.name "name"`
- `git config push.default simple`
- end
+ git("init", app_path)
+ git("config user.email \"you@example.com\"", app_path)
+ git("config user.name \"name\"", app_path)
+ git("config commit.gpgsign false", app_path)
+ git("config push.default simple", app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
@@ -213,35 +275,81 @@ RSpec.describe Bundler::GemHelper do
end
it "when there are uncommitted files" do
- Dir.chdir(app_path) { `git add .` }
+ git("add .", app_path)
expect { Rake.application["release"].invoke }.
to raise_error("There are files that need to be committed first.")
end
it "when there is no git remote" do
- Dir.chdir(app_path) { `git commit -a -m "initial commit"` }
+ git("commit -a -m \"initial commit\"", app_path)
expect { Rake.application["release"].invoke }.to raise_error(RuntimeError)
end
end
context "succeeds" do
+ let(:repo) { build_git("foo", bare: true) }
+
before do
- Dir.chdir(gem_repo1) { `git init --bare` }
- Dir.chdir(app_path) do
- `git remote add origin file://#{gem_repo1}`
- `git commit -a -m "initial commit"`
+ git("remote add origin #{repo.path}", app_path)
+ git('commit -a -m "initial commit"', app_path)
+ end
+
+ context "on releasing" do
+ before do
+ mock_build_message app_name, app_version
+ mock_confirm_message "Tagged v#{app_version}."
+ mock_confirm_message "Pushed git commits and release tag."
+
+ git("push -u origin main", app_path)
+ end
+
+ it "calls rubygem_push with proper arguments" do
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
+ end
+
+ it "uses Kernel.system" do
+ cmd = gem_bin.shellsplit
+ expect(Kernel).to receive(:system).with(*cmd, "push", app_gem_path.to_s, "--host", "http://example.org").and_return(true)
+
+ Rake.application["release"].invoke
+ end
+
+ it "also works when releasing from an ambiguous reference" do
+ # Create a branch with the same name as the tag
+ git("checkout -b v#{app_version}", app_path)
+ git("push -u origin v#{app_version}", app_path)
+
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
+ end
+
+ it "also works with releasing from a branch not yet pushed" do
+ git("checkout -b module_function", app_path)
+
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
end
end
- it "on releasing" do
- mock_build_message app_name, app_version
- mock_confirm_message "Tagged v#{app_version}."
- mock_confirm_message "Pushed git commits and tags."
- expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+ context "on releasing with a custom tag prefix" do
+ before do
+ Bundler::GemHelper.tag_prefix = "foo-"
+ mock_build_message app_name, app_version
+ mock_confirm_message "Pushed git commits and release tag."
- Dir.chdir(app_path) { sys_exec("git push -u origin master") }
+ git("push -u origin main", app_path)
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+ end
- Rake.application["release"].invoke
+ it "prepends the custom prefix to the tag" do
+ mock_confirm_message "Tagged foo-v#{app_version}."
+
+ Rake.application["release"].invoke
+ end
end
it "even if tag already exists" do
@@ -249,9 +357,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "Tag v#{app_version} has already been created."
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
- Dir.chdir(app_path) do
- `git tag -a -m \"Version #{app_version}\" v#{app_version}`
- end
+ git("tag -a -m \"Version #{app_version}\" v#{app_version}", app_path)
Rake.application["release"].invoke
end
@@ -264,7 +370,7 @@ RSpec.describe Bundler::GemHelper do
before(:each) do
Rake.application = Rake::Application.new
subject.install
- allow(subject).to receive(:sh)
+ allow(subject).to receive(:sh_with_input)
end
after(:each) do
@@ -272,12 +378,10 @@ RSpec.describe Bundler::GemHelper do
end
before do
- Dir.chdir(app_path) do
- `git init`
- `git config user.email "you@example.com"`
- `git config user.name "name"`
- `git config push.default simple`
- end
+ git("init", app_path)
+ git("config user.email \"you@example.com\"", app_path)
+ git("config user.name \"name\"", app_path)
+ git("config push.gpgsign simple", app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
@@ -286,6 +390,7 @@ RSpec.describe Bundler::GemHelper do
credentials = double("credentials", "file?" => true)
allow(Bundler.user_home).to receive(:join).
with(".gem/credentials").and_return(credentials)
+ allow(Bundler.user_home).to receive(:join).and_call_original
end
describe "success messaging" do
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 01e0232fba..0e1b7c9cc8 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -1,178 +1,162 @@
# frozen_string_literal: true
RSpec.describe Bundler::GemVersionPromoter do
- context "conservative resolver" do
- def versions(result)
- result.flatten.map(&:version).map(&:to_s)
+ let(:gvp) { described_class.new }
+
+ # Rightmost (highest array index) in result is most preferred.
+ # Leftmost (lowest array index) in result is least preferred.
+ # `build_candidates` has all versions of gem in index.
+ # `build_spec` is the version currently in the .lock file.
+ #
+ # In default (not strict) mode, all versions in the index will
+ # be returned, allowing Bundler the best chance to resolve all
+ # dependencies, but sometimes resulting in upgrades that some
+ # would not consider conservative.
+
+ describe "#sort_versions" do
+ def build_candidates(versions)
+ versions.map do |v|
+ Bundler::Resolver::Candidate.new(v)
+ end
end
- def make_instance(*args)
- @gvp = Bundler::GemVersionPromoter.new(*args).tap do |gvp|
- gvp.class.class_eval { public :filter_dep_specs, :sort_dep_specs }
- end
+ def build_package(name, version, unlock)
+ Bundler::Resolver::Package.new(name, [], locked_specs: Bundler::SpecSet.new(build_spec(name, version)), unlock: unlock)
end
- def unlocking(options)
- make_instance(Bundler::SpecSet.new([]), ["foo"]).tap do |p|
- p.level = options[:level] if options[:level]
- p.strict = options[:strict] if options[:strict]
- end
+ def sorted_versions(candidates:, current:, unlock: true)
+ gvp.sort_versions(
+ build_package("foo", current, unlock),
+ build_candidates(candidates)
+ ).flatten.map(&:version).map(&:to_s)
end
- def keep_locked(options)
- make_instance(Bundler::SpecSet.new([]), ["bar"]).tap do |p|
- p.level = options[:level] if options[:level]
- p.strict = options[:strict] if options[:strict]
- end
+ it "numerically sorts versions" do
+ versions = sorted_versions(candidates: %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0], current: "1.7.8")
+ expect(versions).to eq %w[1.8.0 1.7.15 1.7.9 1.7.8 1.7.7]
end
- def build_spec_groups(name, versions)
- versions.map do |v|
- Bundler::Resolver::SpecGroup.new(build_spec(name, v))
+ context "with no options" do
+ it "defaults to level=:major, strict=false, pre=false" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[2.1.0 2.0.1 1.0.0 0.9.0 0.3.1 0.3.0 0.2.0]
end
end
- # Rightmost (highest array index) in result is most preferred.
- # Leftmost (lowest array index) in result is least preferred.
- # `build_spec_groups` has all versions of gem in index.
- # `build_spec` is the version currently in the .lock file.
- #
- # In default (not strict) mode, all versions in the index will
- # be returned, allowing Bundler the best chance to resolve all
- # dependencies, but sometimes resulting in upgrades that some
- # would not consider conservative.
- context "filter specs (strict) level patch" do
- it "when keeping build_spec, keep current, next release" do
- keep_locked(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.9 1.7.8]
- end
+ context "when strict" do
+ before { gvp.strict = true }
- it "when unlocking prefer next release first" do
- unlocking(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.8 1.7.9]
- end
+ context "when level is major" do
+ before { gvp.level = :major }
- it "when unlocking keep current when already at latest release" do
- unlocking(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]),
- build_spec("foo", "1.7.9").first
- )
- expect(versions(res)).to eq %w[1.7.9]
+ it "keeps downgrades" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[2.1.0 2.0.1 1.0.0 0.9.0 0.3.1 0.3.0 0.2.0]
+ end
end
- end
- context "filter specs (strict) level minor" do
- it "when unlocking favor next releases, remove minor and major increases" do
- unlocking(:level => :minor)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0]
+ context "when level is minor" do
+ before { gvp.level = :minor }
+
+ it "sorts highest minor within same major in first position" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[0.9.0 0.3.1 0.3.0 1.0.0 2.1.0 2.0.1 0.2.0]
+ end
end
- it "when keep locked, keep current, then favor next release, remove minor and major increases" do
- keep_locked(:level => :minor)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0]
+ context "when level is patch" do
+ before { gvp.level = :patch }
+
+ it "sorts highest patch within same minor in first position" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[0.3.1 0.3.0 0.9.0 1.0.0 2.0.1 2.1.0 0.2.0]
+ end
end
end
- context "sort specs (not strict) level patch" do
- it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do
- keep_locked(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]),
- build_spec("foo", "1.7.7").first
- )
- expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7]
- end
+ context "when not strict" do
+ before { gvp.strict = false }
- it "when unlocking favor next release, then current over minor increase" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9]
+ context "when level is major" do
+ before { gvp.level = :major }
+
+ it "orders by version" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[2.1.0 2.0.1 1.0.0 0.9.0 0.3.1 0.3.0 0.2.0]
+ end
end
- it "when unlocking do proper integer comparison, not string" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15]
+ context "when level is minor" do
+ before { gvp.level = :minor }
+
+ it "favors minor upgrades, then patch upgrades, then major upgrades, then downgrades" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[0.9.0 0.3.1 0.3.0 1.0.0 2.1.0 2.0.1 0.2.0]
+ end
end
- it "leave current when unlocking but already at latest release" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]),
- build_spec("foo", "1.7.9").first
- )
- expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9]
+ context "when level is patch" do
+ before { gvp.level = :patch }
+
+ it "favors patch upgrades, then minor upgrades, then major upgrades, then downgrades" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], current: "0.3.0")
+ expect(versions).to eq %w[0.3.1 0.3.0 0.9.0 1.0.0 2.0.1 2.1.0 0.2.0]
+ end
end
end
- context "sort specs (not strict) level minor" do
- it "when unlocking favor next release, then minor increase over current" do
- unlocking(:level => :minor)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0]
+ context "when pre" do
+ before { gvp.pre = true }
+
+ it "sorts regardless of prerelease status" do
+ versions = sorted_versions(candidates: %w[1.7.7.pre 1.8.0 1.8.1.pre 1.8.1 2.0.0.pre 2.0.0], current: "1.8.0")
+ expect(versions).to eq %w[2.0.0 2.0.0.pre 1.8.1 1.8.1.pre 1.8.0 1.7.7.pre]
end
end
- context "level error handling" do
- subject { Bundler::GemVersionPromoter.new }
+ context "when not pre" do
+ before { gvp.pre = false }
- it "should raise if not major, minor or patch is passed" do
- expect { subject.level = :minjor }.to raise_error ArgumentError
+ it "deprioritizes prerelease gems" do
+ versions = sorted_versions(candidates: %w[1.7.7.pre 1.8.0 1.8.1.pre 1.8.1 2.0.0.pre 2.0.0], current: "1.8.0")
+ expect(versions).to eq %w[2.0.0 1.8.1 1.8.0 2.0.0.pre 1.8.1.pre 1.7.7.pre]
end
+ end
- it "should raise if invalid classes passed" do
- [123, nil].each do |value|
- expect { subject.level = value }.to raise_error ArgumentError
- end
+ context "when locking and not major" do
+ before { gvp.level = :minor }
+
+ it "keeps the current version first" do
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.1.0 2.0.1], current: "0.3.0", unlock: [])
+ expect(versions.first).to eq("0.3.0")
end
+ end
+ end
- it "should accept major, minor patch symbols" do
- [:major, :minor, :patch].each do |value|
- subject.level = value
- expect(subject.level).to eq value
- end
+ describe "#level=" do
+ subject { described_class.new }
+
+ it "should raise if not major, minor or patch is passed" do
+ expect { subject.level = :minjor }.to raise_error ArgumentError
+ end
+
+ it "should raise if invalid classes passed" do
+ [123, nil].each do |value|
+ expect { subject.level = value }.to raise_error ArgumentError
end
+ end
- it "should accept major, minor patch strings" do
- %w[major minor patch].each do |value|
- subject.level = value
- expect(subject.level).to eq value.to_sym
- end
+ it "should accept major, minor patch symbols" do
+ [:major, :minor, :patch].each do |value|
+ subject.level = value
+ expect(subject.level).to eq value
end
end
- context "debug output" do
- it "should not kerblooie on its own debug output" do
- gvp = unlocking(:level => :patch)
- dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby")
- result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0]))
- expect(result.class).to eq Array
+ it "should accept major, minor patch strings" do
+ %w[major minor patch].each do |value|
+ subject.level = value
+ expect(subject.level).to eq value.to_sym
end
end
end
diff --git a/spec/bundler/bundler/installer/gem_installer_spec.rb b/spec/bundler/bundler/installer/gem_installer_spec.rb
index 7340a3acc0..dbd4e1d2c8 100644
--- a/spec/bundler/bundler/installer/gem_installer_spec.rb
+++ b/spec/bundler/bundler/installer/gem_installer_spec.rb
@@ -3,26 +3,44 @@
require "bundler/installer/gem_installer"
RSpec.describe Bundler::GemInstaller do
- let(:installer) { instance_double("Installer") }
+ let(:definition) { instance_double("Definition", locked_gems: nil) }
+ let(:installer) { instance_double("Installer", definition: definition) }
let(:spec_source) { instance_double("SpecSource") }
- let(:spec) { instance_double("Specification", :name => "dummy", :version => "0.0.1", :loaded_from => "dummy", :source => spec_source) }
+ let(:spec) { instance_double("Specification", name: "dummy", version: "0.0.1", loaded_from: "dummy", source: spec_source) }
+ let(:base_options) { { force: false, local: false, previous_spec: nil } }
subject { described_class.new(spec, installer) }
context "spec_settings is nil" do
- it "invokes install method with empty build_args", :rubygems => ">= 2" do
- allow(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => [])
+ it "invokes install method with empty build_args" do
+ allow(spec_source).to receive(:install).with(
+ spec,
+ base_options.merge(build_args: [])
+ )
subject.install_from_spec
end
end
context "spec_settings is build option" do
- it "invokes install method with build_args", :rubygems => ">= 2" do
- allow(Bundler.settings).to receive(:[]).with(:bin)
- allow(Bundler.settings).to receive(:[]).with(:inline)
- allow(Bundler.settings).to receive(:[]).with(:forget_cli_options)
+ it "invokes install method with build_args" do
+ allow(Bundler.settings).to receive(:[])
allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy")
- expect(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy"])
+ expect(spec_source).to receive(:install).with(
+ spec,
+ base_options.merge(build_args: ["--with-dummy-config=dummy"])
+ )
+ subject.install_from_spec
+ end
+ end
+
+ context "spec_settings is build option with spaces" do
+ it "invokes install method with build_args" do
+ allow(Bundler.settings).to receive(:[])
+ allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy --with-another-dummy-config")
+ expect(spec_source).to receive(:install).with(
+ spec,
+ base_options.merge(build_args: ["--with-dummy-config=dummy", "--with-another-dummy-config"])
+ )
subject.install_from_spec
end
end
diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb
index ace5c1a23a..49bcb5310b 100644
--- a/spec/bundler/bundler/installer/parallel_installer_spec.rb
+++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb
@@ -1,47 +1,79 @@
# frozen_string_literal: true
require "bundler/installer/parallel_installer"
+require "bundler/rubygems_gem_installer"
+require "rubygems/remote_fetcher"
+require "bundler"
RSpec.describe Bundler::ParallelInstaller do
- let(:installer) { instance_double("Installer") }
- let(:all_specs) { [] }
- let(:size) { 1 }
- let(:standalone) { false }
- let(:force) { false }
-
- subject { described_class.new(installer, all_specs, size, standalone, force) }
-
- context "when dependencies that are not on the overall installation list are the only ones not installed" do
- let(:all_specs) do
- [
- build_spec("alpha", "1.0") {|s| s.runtime "a", "1" },
- ].flatten
+ describe "priority queue" do
+ before do
+ require "support/artifice/compact_index"
+
+ @previous_client = Gem::Request::ConnectionPools.client
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+ Gem::RemoteFetcher.fetcher.close_all
+
+ build_repo2 do
+ build_gem "gem_with_extension", &:add_c_extension
+ build_gem "gem_without_extension"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "gem_with_extension"
+ gem "gem_without_extension"
+ G
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ gem_with_extension (1.0)
+ gem_without_extension (1.0)
+
+ DEPENDENCIES
+ gem_with_extension
+ gem_without_extension
+ L
+
+ @old_ui = Bundler.ui
+ Bundler.ui = Bundler::UI::Silent.new
end
- it "prints a warning" do
- expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
-Your lockfile was created by an old Bundler that left some things out.
-You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile.
-The missing gems are:
-* a depended upon by alpha
- W
- subject.check_for_corrupt_lockfile
+ after do
+ Bundler.ui = @old_ui
+ Gem::Request::ConnectionPools.client = @previous_client
+ Artifice.deactivate
end
- context "when size > 1" do
- let(:size) { 500 }
-
- it "prints a warning and sets size to 1" do
- expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
-Your lockfile was created by an old Bundler that left some things out.
-Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing 500 at a time.
-You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile.
-The missing gems are:
-* a depended upon by alpha
- W
- subject.check_for_corrupt_lockfile
- expect(subject.size).to eq(1)
+ let(:definition) do
+ allow(Bundler).to receive(:root) { bundled_app }
+
+ definition = Bundler::Definition.build(bundled_app.join("Gemfile"), bundled_app.join("Gemfile.lock"), false)
+ definition.tap(&:setup_domain!)
+ end
+ let(:installer) { Bundler::Installer.new(bundled_app, definition) }
+
+ it "queues native extensions in priority" do
+ parallel_installer = Bundler::ParallelInstaller.new(installer, definition.specs, 2, false, true)
+ worker_pool = parallel_installer.send(:worker_pool)
+ expected = 6 # Enqueue to download bundler and the 2 gems. Enqueue to install Bundler and the 2 gems.
+
+ expect(worker_pool).to receive(:enq).exactly(expected).times.and_wrap_original do |original_enq, spec, opts|
+ unless opts.nil? # Enqueued for download, no priority
+ if spec.name == "gem_with_extension"
+ expect(opts).to eq({ priority: true })
+ else
+ expect(opts).to eq({ priority: false })
+ end
+ end
+
+ opts ||= {}
+ original_enq.call(spec, **opts)
end
+
+ parallel_installer.call
end
end
end
diff --git a/spec/bundler/bundler/installer/spec_installation_spec.rb b/spec/bundler/bundler/installer/spec_installation_spec.rb
index a9cf09a372..57868766d9 100644
--- a/spec/bundler/bundler/installer/spec_installation_spec.rb
+++ b/spec/bundler/bundler/installer/spec_installation_spec.rb
@@ -3,14 +3,17 @@
require "bundler/installer/parallel_installer"
RSpec.describe Bundler::ParallelInstaller::SpecInstallation do
- let!(:dep) do
- a_spec = Object.new
- def a_spec.name
- "I like tests"
- end
- a_spec
+ def build_spec(name, extensions: [])
+ spec = Object.new
+ spec.define_singleton_method(:name) { name }
+ spec.define_singleton_method(:full_name) { "#{name}-1.0" }
+ spec.define_singleton_method(:extensions) { extensions }
+ spec.define_singleton_method(:dependencies) { [] }
+ spec
end
+ let!(:dep) { build_spec("I like tests") }
+
describe "#ready_to_enqueue?" do
context "when in enqueued state" do
it "is falsey" do
@@ -35,27 +38,51 @@ RSpec.describe Bundler::ParallelInstaller::SpecInstallation do
end
describe "#dependencies_installed?" do
- context "when all dependencies are installed" do
- it "returns true" do
- dependencies = []
- dependencies << instance_double("SpecInstallation", :spec => "alpha", :name => "alpha", :installed? => true, :all_dependencies => [], :type => :production)
- dependencies << instance_double("SpecInstallation", :spec => "beta", :name => "beta", :installed? => true, :all_dependencies => [], :type => :production)
- all_specs = dependencies + [instance_double("SpecInstallation", :spec => "gamma", :name => "gamma", :installed? => false, :all_dependencies => [], :type => :production)]
+ it "returns true when all dependencies are installed" do
+ alpha = described_class.new(build_spec("alpha"))
+ alpha.dependencies = []
+
+ beta = described_class.new(build_spec("beta"))
+ beta.dependencies = [alpha]
+
+ gamma = described_class.new(build_spec("gamma"))
+ gamma.dependencies = [beta]
+
+ expect(gamma.dependencies_installed?({})).to be_falsey
+ expect(gamma.dependencies_installed?({ "beta" => true })).to be_falsey
+ expect(gamma.dependencies_installed?({ "alpha" => true, "beta" => true })).to be_truthy
+ end
+ end
+
+ describe "#ready_to_install?" do
+ context "when spec has no extensions" do
+ it "returns true regardless of dependencies" do
+ beta = described_class.new(build_spec("beta"))
+ beta.dependencies = []
+
spec = described_class.new(dep)
- allow(spec).to receive(:all_dependencies).and_return(dependencies)
- expect(spec.dependencies_installed?(all_specs)).to be_truthy
+ spec.state = :downloaded
+ spec.dependencies = [beta]
+
+ expect(spec.ready_to_install?({})).to be_truthy
end
end
- context "when all dependencies are not installed" do
- it "returns false" do
- dependencies = []
- dependencies << instance_double("SpecInstallation", :spec => "alpha", :name => "alpha", :installed? => false, :all_dependencies => [], :type => :production)
- dependencies << instance_double("SpecInstallation", :spec => "beta", :name => "beta", :installed? => true, :all_dependencies => [], :type => :production)
- all_specs = dependencies + [instance_double("SpecInstallation", :spec => "gamma", :name => "gamma", :installed? => false, :all_dependencies => [], :type => :production)]
- spec = described_class.new(dep)
- allow(spec).to receive(:all_dependencies).and_return(dependencies)
- expect(spec.dependencies_installed?(all_specs)).to be_falsey
+ context "when spec has extensions" do
+ it "returns true when all dependencies are installed" do
+ alpha = described_class.new(build_spec("alpha"))
+ alpha.dependencies = []
+
+ beta = described_class.new(build_spec("beta"))
+ beta.dependencies = [alpha]
+
+ gamma = described_class.new(build_spec("gamma", extensions: ["ext/Rakefile"]))
+ gamma.state = :downloaded
+ gamma.dependencies = [beta]
+
+ expect(gamma.ready_to_install?({})).to be_falsey
+ expect(gamma.ready_to_install?({ "beta" => true })).to be_falsey
+ expect(gamma.ready_to_install?({ "alpha" => true, "beta" => true })).to be_truthy
end
end
end
diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb
index 3a6d61336f..7364ab98e5 100644
--- a/spec/bundler/bundler/lockfile_parser_spec.rb
+++ b/spec/bundler/bundler/lockfile_parser_spec.rb
@@ -3,7 +3,7 @@
require "bundler/lockfile_parser"
RSpec.describe Bundler::LockfileParser do
- let(:lockfile_contents) { strip_whitespace(<<-L) }
+ let(:lockfile_contents) { <<~L }
GIT
remote: https://github.com/alloy/peiji-san.git
revision: eca485d8dc95f12aaec1a434b49d295c7e91844b
@@ -22,6 +22,9 @@ RSpec.describe Bundler::LockfileParser do
peiji-san!
rake
+ CHECKSUMS
+ rake (10.3.2) sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8
+
RUBY VERSION
ruby 2.1.3p242
@@ -33,13 +36,13 @@ RSpec.describe Bundler::LockfileParser do
it "returns the attributes" do
attributes = described_class.sections_in_lockfile(lockfile_contents)
expect(attributes).to contain_exactly(
- "BUNDLED WITH", "DEPENDENCIES", "GEM", "GIT", "PLATFORMS", "RUBY VERSION"
+ "BUNDLED WITH", "CHECKSUMS", "DEPENDENCIES", "GEM", "GIT", "PLATFORMS", "RUBY VERSION"
)
end
end
describe ".unknown_sections_in_lockfile" do
- let(:lockfile_contents) { strip_whitespace(<<-L) }
+ let(:lockfile_contents) { <<~L }
UNKNOWN ATTR
UNKNOWN ATTR 2
@@ -60,7 +63,7 @@ RSpec.describe Bundler::LockfileParser do
it "returns the same as > 1.0" do
expect(subject).to contain_exactly(
- described_class::BUNDLED, described_class::RUBY, described_class::PLUGIN
+ described_class::BUNDLED, described_class::CHECKSUMS, described_class::RUBY, described_class::PLUGIN
)
end
end
@@ -70,7 +73,7 @@ RSpec.describe Bundler::LockfileParser do
it "returns the same as for the release version" do
expect(subject).to contain_exactly(
- described_class::RUBY, described_class::PLUGIN
+ described_class::CHECKSUMS, described_class::RUBY, described_class::PLUGIN
)
end
end
@@ -108,16 +111,25 @@ RSpec.describe Bundler::LockfileParser do
end
let(:specs) do
[
- Bundler::LazySpecification.new("peiji-san", v("1.2.0"), rb),
- Bundler::LazySpecification.new("rake", v("10.3.2"), rb),
+ Bundler::LazySpecification.new("peiji-san", v("1.2.0"), Gem::Platform::RUBY),
+ Bundler::LazySpecification.new("rake", v("10.3.2"), Gem::Platform::RUBY),
]
end
- let(:platforms) { [rb] }
+ let(:platforms) { [Gem::Platform::RUBY] }
let(:bundler_version) { Gem::Version.new("1.12.0.rc.2") }
let(:ruby_version) { "ruby 2.1.3p242" }
+ let(:lockfile_path) { Bundler.default_lockfile.relative_path_from(Dir.pwd) }
+ let(:rake_sha256_checksum) do
+ Bundler::Checksum.from_lock(
+ "sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8",
+ "#{lockfile_path}:20:17"
+ )
+ end
+ let(:rake_checksums) { [rake_sha256_checksum] }
shared_examples_for "parsing" do
it "parses correctly" do
+ expect(subject.valid?).to be(true)
expect(subject.sources).to eq sources
expect(subject.dependencies).to eq dependencies
expect(subject.specs).to eq specs
@@ -125,6 +137,9 @@ RSpec.describe Bundler::LockfileParser do
expect(subject.platforms).to eq platforms
expect(subject.bundler_version).to eq bundler_version
expect(subject.ruby_version).to eq ruby_version
+ rake_spec = specs.last
+ checksums = subject.sources.last.checksum_store.to_lock(specs.last)
+ expect(checksums).to eq("#{rake_spec.lock_name} #{rake_checksums.map(&:to_lock).sort.join(",")}")
end
end
@@ -149,5 +164,140 @@ RSpec.describe Bundler::LockfileParser do
let(:lockfile_contents) { super().sub("peiji-san!", "peiji-san!\n foo: bar") }
include_examples "parsing"
end
+
+ context "when the checksum is urlsafe base64 encoded" do
+ let(:lockfile_contents) do
+ super().sub(
+ "sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8",
+ "sha256=gUgow08TFdfnt-gpUYRXfMTpabrWFWrAadAtY_WNgug="
+ )
+ end
+ include_examples "parsing"
+ end
+
+ context "when the checksum is of an unknown algorithm" do
+ let(:rake_sha512_checksum) do
+ Bundler::Checksum.from_lock(
+ "sha512=pVDn9GLmcFkz8vj1ueiVxj5uGKkAyaqYjEX8zG6L5O4BeVg3wANaKbQdpj/B82Nd/MHVszy6polHcyotUdwilQ==",
+ "#{lockfile_path}:20:17"
+ )
+ end
+ let(:lockfile_contents) do
+ super().sub(
+ "sha256=",
+ "sha512=pVDn9GLmcFkz8vj1ueiVxj5uGKkAyaqYjEX8zG6L5O4BeVg3wANaKbQdpj/B82Nd/MHVszy6polHcyotUdwilQ==,sha256="
+ )
+ end
+ let(:rake_checksums) { [rake_sha256_checksum, rake_sha512_checksum] }
+ include_examples "parsing"
+ end
+
+ context "when the content does not contain any recognized lockfile sections" do
+ let(:lockfile_contents) { "hello world\nlorem ipsum\n" }
+
+ it "does not raise, is not valid, and deprecates" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
+ /does not appear to be a valid lockfile.*future version of Bundler/m
+ )
+ parser = described_class.new(lockfile_contents)
+ expect(parser.valid?).to be(false)
+ expect(parser.specs).to eq([])
+ expect(parser.dependencies).to eq({})
+ end
+
+ it "does not raise when strict: true, and still deprecates" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
+ /does not appear to be a valid lockfile.*future version of Bundler/m
+ )
+ parser = described_class.new(lockfile_contents, strict: true)
+ expect(parser.valid?).to be(false)
+ expect(parser.specs).to eq([])
+ expect(parser.dependencies).to eq({})
+ end
+ end
+
+ context "when the content looks like a Gemfile DSL" do
+ let(:lockfile_contents) { <<~G }
+ source "https://rubygems.org"
+ gem "rake"
+ G
+
+ it "does not raise, is not valid, and deprecates" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
+ /does not appear to be a valid lockfile.*future version of Bundler/m
+ )
+ parser = described_class.new(lockfile_contents)
+ expect(parser.valid?).to be(false)
+ expect(parser.specs).to eq([])
+ expect(parser.dependencies).to eq({})
+ end
+
+ it "does not raise when strict: true, and still deprecates" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
+ /does not appear to be a valid lockfile.*future version of Bundler/m
+ )
+ parser = described_class.new(lockfile_contents, strict: true)
+ expect(parser.valid?).to be(false)
+ expect(parser.specs).to eq([])
+ expect(parser.dependencies).to eq({})
+ end
+ end
+
+ context "when the content is empty" do
+ let(:lockfile_contents) { "" }
+
+ it "does not raise and is valid" do
+ expect { subject }.not_to raise_error
+ expect(subject.valid?).to be(true)
+ end
+ end
+
+ context "when lockfile_path is given" do
+ it "uses the provided path in error messages instead of looking up Bundler.default_lockfile" do
+ expect(Bundler::SharedHelpers).not_to receive(:relative_lockfile_path)
+ parser = described_class.new(lockfile_contents, lockfile_path: "custom/path.lock")
+ expect(parser.valid?).to be(true)
+ rake_spec = parser.specs.last
+ checksums = parser.sources.last.checksum_store.to_lock(rake_spec)
+ expected_checksum = Bundler::Checksum.from_lock(
+ "sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8",
+ "custom/path.lock:20:17"
+ )
+ expect(checksums).to eq("#{rake_spec.lock_name} #{expected_checksum.to_lock}")
+ end
+
+ it "raises with the provided path when the lockfile contains merge conflicts" do
+ expect do
+ described_class.new("<<<<<<<\n", lockfile_path: "custom/path.lock")
+ end.to raise_error(Bundler::LockfileError, %r{custom/path\.lock contains merge conflicts})
+ end
+ end
+
+ context "when CHECKSUMS has duplicate checksums in the lockfile that don't match" do
+ let(:bad_checksum) { "sha256=c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11" }
+ let(:lockfile_contents) { super().split(/(?<=CHECKSUMS\n)/m).insert(1, " rake (10.3.2) #{bad_checksum}\n").join }
+
+ it "raises a security error" do
+ expect { subject }.to raise_error(Bundler::SecurityError) do |e|
+ expect(e.message).to match <<~MESSAGE
+ Bundler found mismatched checksums. This is a potential security risk.
+ rake (10.3.2) #{bad_checksum}
+ from the lockfile CHECKSUMS at #{lockfile_path}:20:17
+ rake (10.3.2) #{rake_sha256_checksum.to_lock}
+ from the lockfile CHECKSUMS at #{lockfile_path}:21:17
+
+ To resolve this issue you can either:
+ 1. remove the matching checksum in #{lockfile_path}:21:17
+ 2. run `bundle install`
+ or if you are sure that the new checksum from the lockfile CHECKSUMS at #{lockfile_path}:21:17 is correct:
+ 1. remove the matching checksum in #{lockfile_path}:20:17
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ MESSAGE
+ end
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/mirror_spec.rb b/spec/bundler/bundler/mirror_spec.rb
index acd0895f2f..ba1c6ed413 100644
--- a/spec/bundler/bundler/mirror_spec.rb
+++ b/spec/bundler/bundler/mirror_spec.rb
@@ -36,12 +36,12 @@ RSpec.describe Bundler::Settings::Mirror do
it "takes a string for the uri but returns an uri object" do
mirror.uri = "http://localhost:9292"
- expect(mirror.uri).to eq(URI("http://localhost:9292"))
+ expect(mirror.uri).to eq(Gem::URI("http://localhost:9292"))
end
it "takes an uri object for the uri" do
- mirror.uri = URI("http://localhost:9293")
- expect(mirror.uri).to eq(URI("http://localhost:9293"))
+ mirror.uri = Gem::URI("http://localhost:9293")
+ expect(mirror.uri).to eq(Gem::URI("http://localhost:9293"))
end
context "without a uri" do
@@ -145,7 +145,7 @@ RSpec.describe Bundler::Settings::Mirror do
end
RSpec.describe Bundler::Settings::Mirrors do
- let(:localhost_uri) { URI("http://localhost:9292") }
+ let(:localhost_uri) { Gem::URI("http://localhost:9292") }
context "with a just created mirror" do
let(:mirrors) do
@@ -260,7 +260,7 @@ RSpec.describe Bundler::Settings::Mirrors do
before { mirrors.parse("mirror.all.fallback_timeout", "true") }
it "returns the source uri, not localhost" do
- expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/"))
+ expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/"))
end
end
end
@@ -270,7 +270,7 @@ RSpec.describe Bundler::Settings::Mirrors do
context "without a fallback timeout" do
it "returns the uri that is not mirrored" do
- expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/"))
+ expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/"))
end
it "returns localhost for rubygems.org" do
@@ -282,11 +282,11 @@ RSpec.describe Bundler::Settings::Mirrors do
before { mirrors.parse("mirror.http://rubygems.org/.fallback_timeout", "true") }
it "returns the uri that is not mirrored" do
- expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/"))
+ expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/"))
end
it "returns rubygems.org for rubygems.org" do
- expect(mirrors.for("http://rubygems.org/").uri).to eq(URI("http://rubygems.org/"))
+ expect(mirrors.for("http://rubygems.org/").uri).to eq(Gem::URI("http://rubygems.org/"))
end
end
end
@@ -298,13 +298,15 @@ RSpec.describe Bundler::Settings::TCPSocketProbe do
context "with a listening TCP Server" do
def with_server_and_mirror
- server = TCPServer.new("127.0.0.1", 0)
- mirror = Bundler::Settings::Mirror.new("http://localhost:#{server.addr[1]}", 1)
+ server = TCPServer.new("0.0.0.0", 0)
+ mirror = Bundler::Settings::Mirror.new("http://0.0.0.0:#{server.addr[1]}", 1)
yield server, mirror
server.close unless server.closed?
end
- it "probes the server correctly", :ruby_repo do
+ it "probes the server correctly" do
+ skip "obscure error" if Gem.win_platform?
+
with_server_and_mirror do |server, mirror|
expect(server.closed?).to be_falsey
expect(probe.replies?(mirror)).to be_truthy
diff --git a/spec/bundler/bundler/override_spec.rb b/spec/bundler/bundler/override_spec.rb
new file mode 100644
index 0000000000..ad8be75520
--- /dev/null
+++ b/spec/bundler/bundler/override_spec.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+
+RSpec.describe "MatchMetadata override-aware checks" do
+ let(:spec_class) do
+ Class.new do
+ include Bundler::MatchMetadata
+ attr_accessor :name
+ def initialize(name, ruby_req, rubygems_req)
+ @name = name
+ @required_ruby_version = ruby_req
+ @required_rubygems_version = rubygems_req
+ end
+ end
+ end
+
+ it "matches_current_metadata? ignores overrides (strict path)" do
+ spec = spec_class.new("rails", Gem::Requirement.new("< #{Gem.ruby_version}"), Gem::Requirement.default)
+ overrides = [Bundler::Override.new("rails", :required_ruby_version, :ignore_upper)]
+ # Strict method MUST NOT apply overrides; guards SelfManager and other generic callers.
+ expect(spec.matches_current_metadata?).to be(false)
+ expect(spec.matches_current_metadata_with_overrides?(overrides)).to be(true)
+ end
+
+ it "matches_current_ruby_with_overrides? returns the strict result for an empty override list" do
+ spec = spec_class.new("rails", Gem::Requirement.new(">= #{Gem.ruby_version}"), Gem::Requirement.default)
+ expect(spec.matches_current_ruby_with_overrides?([])).to be(true)
+ expect(spec.matches_current_ruby_with_overrides?(nil)).to be(true)
+ end
+
+ it "matches_current_rubygems_with_overrides? honors :all override" do
+ spec = spec_class.new("rails", Gem::Requirement.default, Gem::Requirement.new("< #{Gem.rubygems_version}"))
+ overrides = [Bundler::Override.new(:all, :required_rubygems_version, :ignore_upper)]
+ expect(spec.matches_current_rubygems_with_overrides?(overrides)).to be(true)
+ end
+end
+
+RSpec.describe "LazySpecification override propagation" do
+ let(:overrides) { [Bundler::Override.new("rails", :required_ruby_version, :ignore_upper)] }
+
+ it "carries overrides forward from a source LazySpec via from_spec" do
+ src = Bundler::LazySpecification.new("rails", "8.0", Gem::Platform::RUBY)
+ src.overrides = overrides
+ derived = Bundler::LazySpecification.from_spec(src)
+ expect(derived.overrides).to eq(overrides)
+ end
+
+ it "does not call respond_to? on the source spec, avoiding gemspec lazy load" do
+ # If from_spec used respond_to?(:overrides), a RemoteSpec source would
+ # force-load the backing gemspec. Use a stand-in object whose
+ # respond_to? raises to prove it is never asked.
+ src = Object.new
+ src.define_singleton_method(:name) { "rails" }
+ src.define_singleton_method(:version) { Gem::Version.new("8.0") }
+ src.define_singleton_method(:platform) { Gem::Platform::RUBY }
+ src.define_singleton_method(:source) { nil }
+ src.define_singleton_method(:runtime_dependencies) { [] }
+ src.define_singleton_method(:required_ruby_version) { Gem::Requirement.default }
+ src.define_singleton_method(:required_rubygems_version) { Gem::Requirement.default }
+ src.define_singleton_method(:respond_to?) {|*| raise "from_spec must not call respond_to?" }
+ expect { Bundler::LazySpecification.from_spec(src) }.not_to raise_error
+ end
+end
+
+RSpec.describe Bundler::Override do
+ describe ".find_for" do
+ it "returns the matching override by target and field" do
+ a = described_class.new("rails", :version, ">= 8.0")
+ b = described_class.new("nokogiri", :version, :ignore_upper)
+ expect(described_class.find_for([a, b], "rails", :version)).to be(a)
+ end
+
+ it "returns nil when no override matches the target" do
+ a = described_class.new("rails", :version, ">= 8.0")
+ expect(described_class.find_for([a], "sinatra", :version)).to be_nil
+ end
+
+ it "returns nil when no override matches the field" do
+ a = described_class.new("rails", :version, ">= 8.0")
+ expect(described_class.find_for([a], "rails", :required_ruby_version)).to be_nil
+ end
+
+ it "returns nil for an empty overrides list" do
+ expect(described_class.find_for([], "rails", :version)).to be_nil
+ end
+
+ it "falls back to an :all override on the same field" do
+ a = described_class.new(:all, :required_ruby_version, :ignore_upper)
+ expect(described_class.find_for([a], "rails", :required_ruby_version)).to be(a)
+ end
+
+ it "prefers a per-gem override over a matching :all override" do
+ per_gem = described_class.new("rails", :required_ruby_version, ">= 3.4")
+ all_target = described_class.new(:all, :required_ruby_version, :ignore_upper)
+ expect(described_class.find_for([all_target, per_gem], "rails", :required_ruby_version)).to be(per_gem)
+ end
+
+ it "does not fall back to :all when the field differs" do
+ a = described_class.new(:all, :required_ruby_version, :ignore_upper)
+ expect(described_class.find_for([a], "rails", :required_rubygems_version)).to be_nil
+ end
+ end
+
+ describe "#apply_to" do
+ context "when operation is a version spec string" do
+ it "replaces the existing requirement entirely" do
+ override = described_class.new("rails", :version, ">= 8.0")
+ result = override.apply_to(Gem::Requirement.new(">= 1.0", "< 2.0"))
+ expect(result).to eq(Gem::Requirement.new(">= 8.0"))
+ end
+
+ it "ignores the existing requirement regardless of its content" do
+ override = described_class.new("rails", :version, "= 1.0")
+ result = override.apply_to(Gem::Requirement.new(">= 99.0"))
+ expect(result).to eq(Gem::Requirement.new("= 1.0"))
+ end
+ end
+
+ context "when operation is :ignore_upper" do
+ it "removes < and <= operators" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ result = override.apply_to(Gem::Requirement.new(">= 1.0", "< 2.0"))
+ expect(result).to eq(Gem::Requirement.new(">= 1.0"))
+ end
+
+ it "keeps >, >=, = operators" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ result = override.apply_to(Gem::Requirement.new("> 1.0", "<= 2.0"))
+ expect(result).to eq(Gem::Requirement.new("> 1.0"))
+ end
+
+ it "converts ~> to >= preserving the lower bound" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ result = override.apply_to(Gem::Requirement.new("~> 1.5"))
+ expect(result).to eq(Gem::Requirement.new(">= 1.5"))
+ end
+
+ it "preserves != exclusion constraints" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ result = override.apply_to(Gem::Requirement.new(">= 1.0", "!= 1.5.0", "< 2.0"))
+ expect(result).to eq(Gem::Requirement.new(">= 1.0", "!= 1.5.0"))
+ end
+
+ it "returns the default requirement when only upper bounds remain" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ result = override.apply_to(Gem::Requirement.new("< 2.0"))
+ expect(result).to eq(Gem::Requirement.default)
+ end
+
+ it "returns the default requirement when the input is nil" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ expect(override.apply_to(nil)).to eq(Gem::Requirement.default)
+ end
+
+ it "returns the default requirement when the input is already the default" do
+ override = described_class.new("rails", :version, :ignore_upper)
+ expect(override.apply_to(Gem::Requirement.default)).to eq(Gem::Requirement.default)
+ end
+ end
+
+ context "when operation is nil" do
+ it "returns the default requirement" do
+ override = described_class.new("rails", :version, nil)
+ result = override.apply_to(Gem::Requirement.new(">= 1.0", "< 2.0"))
+ expect(result).to eq(Gem::Requirement.default)
+ end
+ end
+
+ context "when operation is unsupported" do
+ it "raises ArgumentError" do
+ override = described_class.new("rails", :version, 42)
+ expect { override.apply_to(Gem::Requirement.default) }.to raise_error(ArgumentError, /unsupported override operation/)
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/plugin/api/source_spec.rb b/spec/bundler/bundler/plugin/api/source_spec.rb
index 2c50ff56a4..ae02e08bea 100644
--- a/spec/bundler/bundler/plugin/api/source_spec.rb
+++ b/spec/bundler/bundler/plugin/api/source_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe Bundler::Plugin::API::Source do
context "to_lock" do
it "returns the string with remote and type" do
- expected = strip_whitespace <<-L
+ expected = <<~L
PLUGIN SOURCE
remote: #{uri}
type: #{type}
@@ -67,7 +67,7 @@ RSpec.describe Bundler::Plugin::API::Source do
end
it "includes them" do
- expected = strip_whitespace <<-L
+ expected = <<~L
PLUGIN SOURCE
remote: #{uri}
type: #{type}
@@ -79,4 +79,10 @@ RSpec.describe Bundler::Plugin::API::Source do
end
end
end
+
+ describe "to_s" do
+ it "returns the string with type and uri" do
+ expect(source.to_s).to eq("plugin source for spec_type with uri uri://to/test")
+ end
+ end
end
diff --git a/spec/bundler/bundler/plugin/dsl_spec.rb b/spec/bundler/bundler/plugin/dsl_spec.rb
index be23db3bba..235a549735 100644
--- a/spec/bundler/bundler/plugin/dsl_spec.rb
+++ b/spec/bundler/bundler/plugin/dsl_spec.rb
@@ -23,16 +23,16 @@ RSpec.describe Bundler::Plugin::DSL do
it "adds #source with :type to list and also inferred_plugins list" do
expect(dsl).to receive(:plugin).with("bundler-source-news").once
- dsl.source("some_random_url", :type => "news") {}
+ dsl.source("some_random_url", type: "news") {}
expect(dsl.inferred_plugins).to eq(["bundler-source-news"])
end
- it "registers a source type plugin only once for multiple declataions" do
+ it "registers a source type plugin only once for multiple declarations" do
expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once
- dsl.source("some_random_url", :type => "news") {}
- dsl.source("another_random_url", :type => "news") {}
+ dsl.source("some_random_url", type: "news") {}
+ dsl.source("another_random_url", type: "news") {}
end
end
end
diff --git a/spec/bundler/bundler/plugin/events_spec.rb b/spec/bundler/bundler/plugin/events_spec.rb
index b09e915682..77e5fdb74c 100644
--- a/spec/bundler/bundler/plugin/events_spec.rb
+++ b/spec/bundler/bundler/plugin/events_spec.rb
@@ -2,10 +2,24 @@
RSpec.describe Bundler::Plugin::Events do
context "plugin events" do
+ before do
+ @old_constants = Bundler::Plugin::Events.constants.map {|name| [name, Bundler::Plugin::Events.const_get(name)] }
+ Bundler::Plugin::Events.send :reset
+ end
+
+ after do
+ Bundler::Plugin::Events.send(:reset)
+ Hash[@old_constants].each do |name, value|
+ Bundler::Plugin::Events.send(:define, name, value)
+ end
+ end
+
describe "#define" do
it "raises when redefining a constant" do
+ Bundler::Plugin::Events.send(:define, :TEST_EVENT, "foo")
+
expect do
- Bundler::Plugin::Events.send(:define, :GEM_BEFORE_INSTALL_ALL, "another-value")
+ Bundler::Plugin::Events.send(:define, :TEST_EVENT, "bar")
end.to raise_error(ArgumentError)
end
diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb
index ca3476ea2a..a28934269b 100644
--- a/spec/bundler/bundler/plugin/index_spec.rb
+++ b/spec/bundler/bundler/plugin/index_spec.rb
@@ -4,7 +4,8 @@ RSpec.describe Bundler::Plugin::Index do
Index = Bundler::Plugin::Index
before do
- gemfile ""
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ gemfile "source 'https://gem.repo1'"
path = lib_path(plugin_name)
index.register_plugin("new-plugin", path.to_s, [path.join("lib").to_s], commands, sources, hooks)
end
@@ -21,7 +22,7 @@ RSpec.describe Bundler::Plugin::Index do
expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name))
end
- it "load_paths is available for retrival" do
+ it "load_paths is available for retrieval" do
expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s])
end
@@ -86,7 +87,24 @@ RSpec.describe Bundler::Plugin::Index do
expect(new_index.hook_plugins("after-bar")).to eq([plugin_name])
end
- context "that are not registered", :focused do
+ it "only registers a gem once for an event" do
+ path = lib_path(plugin_name)
+ index.register_plugin(plugin_name,
+ path.to_s,
+ [path.join("lib").to_s],
+ commands,
+ sources,
+ hooks + hooks)
+ expect(index.hook_plugins("after-bar")).to eq([plugin_name])
+ end
+
+ it "is gone after unregistration" do
+ expect(index.index_file.read).to include("after-bar:\n - \"new-plugin\"\n")
+ index.unregister_plugin(plugin_name)
+ expect(index.index_file.read).to_not include("after-bar:\n - \n")
+ end
+
+ context "that are not registered" do
let(:file) { double("index-file") }
before do
@@ -106,11 +124,11 @@ RSpec.describe Bundler::Plugin::Index do
describe "global index" do
before do
- Dir.chdir(tmp) do
- Bundler::Plugin.reset!
- path = lib_path("gplugin")
- index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], [])
- end
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil)
+
+ Bundler::Plugin.reset!
+ path = lib_path("gplugin")
+ index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], [])
end
it "skips sources" do
@@ -122,7 +140,7 @@ RSpec.describe Bundler::Plugin::Index do
describe "after conflict" do
let(:commands) { ["foo"] }
let(:sources) { ["bar"] }
- let(:hooks) { ["hoook"] }
+ let(:hooks) { ["thehook"] }
shared_examples "it cleans up" do
it "the path" do
@@ -138,7 +156,7 @@ RSpec.describe Bundler::Plugin::Index do
end
it "the hook" do
- expect(index.hook_plugins("xhoook")).to be_empty
+ expect(index.hook_plugins("xthehook")).to be_empty
end
end
@@ -146,7 +164,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["xbar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["xbar"], ["xthehook"])
end.to raise_error(Index::CommandConflict)
end
@@ -157,7 +175,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["xfoo"], ["bar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["xfoo"], ["bar"], ["xthehook"])
end.to raise_error(Index::SourceConflict)
end
@@ -168,7 +186,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["bar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["bar"], ["xthehook"])
end.to raise_error(Index::CommandConflict)
end
@@ -176,11 +194,82 @@ RSpec.describe Bundler::Plugin::Index do
end
end
- describe "readonly disk without home" do
- it "ignores being unable to create temp home dir" do
- expect_any_instance_of(Bundler::Plugin::Index).to receive(:global_index_file).
- and_raise(Bundler::GenericSystemCallError.new("foo", "bar"))
- Bundler::Plugin::Index.new
+ describe "relative plugin paths" do
+ let(:plugin_name) { "relative-plugin" }
+
+ before do
+ Bundler::Plugin.reset!
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+
+ plugin_root = Bundler::Plugin.root
+ FileUtils.mkdir_p(plugin_root)
+
+ path = plugin_root.join(plugin_name)
+ FileUtils.mkdir_p(path.join("lib"))
+
+ index.register_plugin(plugin_name, path.to_s, [path.join("lib").to_s], [], [], [])
+ end
+
+ it "stores plugin paths relative to the plugin root" do
+ require "yaml"
+ data = YAML.load_file(index.index_file)
+
+ expect(data["plugin_paths"][plugin_name]).to eq(plugin_name)
+ expect(data["load_paths"][plugin_name]).to eq([File.join(plugin_name, "lib")])
+ end
+
+ it "expands relative paths to absolute on load" do
+ require "bundler/yaml_serializer"
+
+ plugin_root = Bundler::Plugin.root
+
+ relative_index = {
+ "commands" => {},
+ "hooks" => {},
+ "load_paths" => { plugin_name => [File.join(plugin_name, "lib")] },
+ "plugin_paths" => { plugin_name => plugin_name },
+ "sources" => {},
+ }
+
+ File.open(index.index_file, "w") {|f| f.puts Bundler::YAMLSerializer.dump(relative_index) }
+
+ new_index = Index.new
+ expect(new_index.plugin_path(plugin_name)).to eq(plugin_root.join(plugin_name))
+ expect(new_index.load_paths(plugin_name)).to eq([plugin_root.join(plugin_name, "lib").to_s])
+ end
+
+ it "keeps paths outside the plugin root as absolute" do
+ outside_path = tmp.join("outside", "external-plugin")
+ FileUtils.mkdir_p(outside_path.join("lib"))
+
+ index.register_plugin("external-plugin", outside_path.to_s, [outside_path.join("lib").to_s], [], [], [])
+
+ require "yaml"
+ data = YAML.load_file(index.index_file)
+
+ expect(data["plugin_paths"]["external-plugin"]).to eq(outside_path.to_s)
+ expect(data["load_paths"]["external-plugin"]).to eq([outside_path.join("lib").to_s])
+ end
+
+ it "reads legacy index files with absolute paths" do
+ require "bundler/yaml_serializer"
+
+ plugin_root = Bundler::Plugin.root
+ absolute_path = plugin_root.join(plugin_name).to_s
+
+ legacy_index = {
+ "commands" => {},
+ "hooks" => {},
+ "load_paths" => { plugin_name => [File.join(absolute_path, "lib")] },
+ "plugin_paths" => { plugin_name => absolute_path },
+ "sources" => {},
+ }
+
+ File.open(index.index_file, "w") {|f| f.puts Bundler::YAMLSerializer.dump(legacy_index) }
+
+ new_index = Index.new
+ expect(new_index.plugin_path(plugin_name)).to eq(Pathname.new(absolute_path))
+ expect(new_index.load_paths(plugin_name)).to eq([File.join(absolute_path, "lib")])
end
end
end
diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb
index f8bf8450c9..c200a98afa 100644
--- a/spec/bundler/bundler/plugin/installer_spec.rb
+++ b/spec/bundler/bundler/plugin/installer_spec.rb
@@ -3,15 +3,10 @@
RSpec.describe Bundler::Plugin::Installer do
subject(:installer) { Bundler::Plugin::Installer.new }
- before do
- # allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(Pathname.new("/Gemfile"))
- end
-
describe "cli install" do
it "uses Gem.sources when non of the source is provided" do
sources = double(:sources)
- Bundler.settings # initialize it before we have to touch rubygems.ext_lock
- allow(Bundler).to receive_message_chain("rubygems.sources") { sources }
+ allow(Gem).to receive(:sources) { sources }
allow(installer).to receive(:install_rubygems).
with("new-plugin", [">= 0"], sources).once
@@ -25,7 +20,15 @@ RSpec.describe Bundler::Plugin::Installer do
allow(installer).to receive(:install_git).
and_return("new-plugin" => spec)
- expect(installer.install(["new-plugin"], :git => "https://some.ran/dom")).
+ expect(installer.install(["new-plugin"], git: "https://some.ran/dom")).
+ to eq("new-plugin" => spec)
+ end
+
+ it "returns the installed spec after installing local git plugins" do
+ allow(installer).to receive(:install_git).
+ and_return("new-plugin" => spec)
+
+ expect(installer.install(["new-plugin"], git: "/phony/path/repo")).
to eq("new-plugin" => spec)
end
@@ -33,7 +36,7 @@ RSpec.describe Bundler::Plugin::Installer do
allow(installer).to receive(:install_rubygems).
and_return("new-plugin" => spec)
- expect(installer.install(["new-plugin"], :source => "https://some.ran/dom")).
+ expect(installer.install(["new-plugin"], source: "https://some.ran/dom")).
to eq("new-plugin" => spec)
end
end
@@ -44,17 +47,47 @@ RSpec.describe Bundler::Plugin::Installer do
build_plugin "re-plugin"
build_plugin "ma-plugin"
end
+
+ @previous_ui = Bundler.ui
+ Bundler.ui = Bundler::UI::Silent.new
+ end
+
+ after do
+ Bundler.ui = @previous_ui
end
context "git plugins" do
before do
- build_git "ga-plugin", :path => lib_path("ga-plugin") do |s|
+ build_git "ga-plugin", path: lib_path("ga-plugin") do |s|
+ s.write "plugins.rb"
+ end
+ end
+
+ let(:result) do
+ installer.install(["ga-plugin"], git: lib_path("ga-plugin").to_s)
+ end
+
+ it "returns the installed spec after installing" do
+ spec = result["ga-plugin"]
+ expect(spec.full_name).to eq "ga-plugin-1.0"
+ end
+
+ it "has expected full_gem_path" do
+ rev = revision_for(lib_path("ga-plugin"))
+ expect(result["ga-plugin"].full_gem_path).
+ to eq(Bundler::Plugin.root.join("bundler", "gems", "ga-plugin-#{rev[0..11]}").to_s)
+ end
+ end
+
+ context "local git plugins" do
+ before do
+ build_git "ga-plugin", path: lib_path("ga-plugin") do |s|
s.write "plugins.rb"
end
end
let(:result) do
- installer.install(["ga-plugin"], :git => "file://#{lib_path("ga-plugin")}")
+ installer.install(["ga-plugin"], git: lib_path("ga-plugin").to_s)
end
it "returns the installed spec after installing" do
@@ -62,7 +95,7 @@ RSpec.describe Bundler::Plugin::Installer do
expect(spec.full_name).to eq "ga-plugin-1.0"
end
- it "has expected full gem path" do
+ it "has expected full_gem_path" do
rev = revision_for(lib_path("ga-plugin"))
expect(result["ga-plugin"].full_gem_path).
to eq(Bundler::Plugin.root.join("bundler", "gems", "ga-plugin-#{rev[0..11]}").to_s)
@@ -71,14 +104,14 @@ RSpec.describe Bundler::Plugin::Installer do
context "rubygems plugins" do
let(:result) do
- installer.install(["re-plugin"], :source => "file://#{gem_repo2}")
+ installer.install(["re-plugin"], source: file_uri_for(gem_repo2))
end
it "returns the installed spec after installing " do
expect(result["re-plugin"]).to be_kind_of(Bundler::RemoteSpecification)
end
- it "has expected full_gem)path" do
+ it "has expected full_gem_path" do
expect(result["re-plugin"].full_gem_path).
to eq(global_plugin_gem("re-plugin-1.0").to_s)
end
@@ -86,7 +119,7 @@ RSpec.describe Bundler::Plugin::Installer do
context "multiple plugins" do
let(:result) do
- installer.install(["re-plugin", "ma-plugin"], :source => "file://#{gem_repo2}")
+ installer.install(["re-plugin", "ma-plugin"], source: file_uri_for(gem_repo2))
end
it "returns the installed spec after installing " do
@@ -94,7 +127,7 @@ RSpec.describe Bundler::Plugin::Installer do
expect(result["ma-plugin"]).to be_kind_of(Bundler::RemoteSpecification)
end
- it "has expected full_gem)path" do
+ it "has expected full_gem_path" do
expect(result["re-plugin"].full_gem_path).to eq(global_plugin_gem("re-plugin-1.0").to_s)
expect(result["ma-plugin"].full_gem_path).to eq(global_plugin_gem("ma-plugin-1.0").to_s)
end
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index 9266fad1eb..b379594c6f 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -9,11 +9,11 @@ RSpec.describe Bundler::Plugin do
let(:spec2) { double(:spec2) }
before do
- build_lib "new-plugin", :path => lib_path("new-plugin") do |s|
+ build_lib "new-plugin", path: lib_path("new-plugin") do |s|
s.write "plugins.rb"
end
- build_lib "another-plugin", :path => lib_path("another-plugin") do |s|
+ build_lib "another-plugin", path: lib_path("another-plugin") do |s|
s.write "plugins.rb"
end
@@ -32,6 +32,29 @@ RSpec.describe Bundler::Plugin do
allow(index).to receive(:register_plugin)
end
+ describe "list command" do
+ context "when no plugins are installed" do
+ before { allow(index).to receive(:installed_plugins) { [] } }
+ it "outputs no plugins installed" do
+ expect(Bundler.ui).to receive(:info).with("No plugins installed")
+ subject.list
+ end
+ end
+
+ context "with installed plugins" do
+ before do
+ allow(index).to receive(:installed_plugins) { %w[plug1 plug2] }
+ allow(index).to receive(:plugin_commands).with("plug1") { %w[c11 c12] }
+ allow(index).to receive(:plugin_commands).with("plug2") { %w[c21 c22] }
+ end
+ it "list plugins followed by commands" do
+ expected_output = "plug1\n-----\n c11\n c12\n\nplug2\n-----\n c21\n c22\n\n"
+ expect(Bundler.ui).to receive(:info).with(expected_output)
+ subject.list
+ end
+ end
+ end
+
describe "install command" do
let(:opts) { { "version" => "~> 1.0", "source" => "foo" } }
@@ -42,6 +65,8 @@ RSpec.describe Bundler::Plugin do
end
it "passes the name and options to installer" do
+ allow(index).to receive(:up_to_date?).
+ with(spec)
allow(installer).to receive(:install).with(["new-plugin"], opts) do
{ "new-plugin" => spec }
end.once
@@ -50,6 +75,8 @@ RSpec.describe Bundler::Plugin do
end
it "validates the installed plugin" do
+ allow(index).to receive(:up_to_date?).
+ with(spec)
allow(subject).
to receive(:validate_plugin!).with(lib_path("new-plugin")).once
@@ -57,6 +84,8 @@ RSpec.describe Bundler::Plugin do
end
it "registers the plugin with index" do
+ allow(index).to receive(:up_to_date?).
+ with(spec)
allow(index).to receive(:register_plugin).
with("new-plugin", lib_path("new-plugin").to_s, [lib_path("new-plugin").join("lib").to_s], []).once
subject.install ["new-plugin"], opts
@@ -73,6 +102,7 @@ RSpec.describe Bundler::Plugin do
end.once
allow(subject).to receive(:validate_plugin!).twice
+ allow(index).to receive(:up_to_date?).twice
allow(index).to receive(:register_plugin).twice
subject.install ["new-plugin", "another-plugin"], opts
end
@@ -82,11 +112,12 @@ RSpec.describe Bundler::Plugin do
describe "evaluate gemfile for plugins" do
let(:definition) { double("definition") }
let(:builder) { double("builder") }
- let(:gemfile) { bundled_app("Gemfile") }
+ let(:gemfile) { bundled_app_gemfile }
before do
allow(Plugin::DSL).to receive(:new) { builder }
allow(builder).to receive(:eval_gemfile).with(gemfile)
+ allow(builder).to receive(:check_primary_source_safety)
allow(builder).to receive(:to_definition) { definition }
allow(builder).to receive(:inferred_plugins) { [] }
end
@@ -107,7 +138,7 @@ RSpec.describe Bundler::Plugin do
end
before do
- allow(index).to receive(:installed?) { nil }
+ allow(index).to receive(:up_to_date?) { nil }
allow(definition).to receive(:dependencies) { [Bundler::Dependency.new("new-plugin", ">=0"), Bundler::Dependency.new("another-plugin", ">=0")] }
allow(installer).to receive(:install_definition) { plugin_specs }
end
@@ -194,7 +225,7 @@ RSpec.describe Bundler::Plugin do
end
end
- describe "#source_from_lock" do
+ describe "#from_lock" do
it "returns instance of registered class initialized with locked opts" do
opts = { "type" => "l_source", "remote" => "xyz", "other" => "random" }
allow(index).to receive(:source_plugin).with("l_source") { "plugin_name" }
@@ -205,25 +236,28 @@ RSpec.describe Bundler::Plugin do
expect(SClass).to receive(:new).
with(hash_including("type" => "l_source", "uri" => "xyz", "other" => "random")) { s_instance }
- expect(subject.source_from_lock(opts)).to be(s_instance)
+ expect(subject.from_lock(opts)).to be(s_instance)
end
end
describe "#root" do
context "in app dir" do
before do
- gemfile ""
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "returns plugin dir in app .bundle path" do
- expect(subject.root).to eq(bundled_app.join(".bundle/plugin"))
+ expect(subject.root).to eq(bundled_app(".bundle/plugin"))
end
end
context "outside app dir" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil)
+ end
+
it "returns plugin dir in global bundle path" do
- Dir.chdir tmp
- expect(subject.root).to eq(home.join(".bundle/plugin"))
+ expect(subject.root).to eq(home(".bundle/plugin"))
end
end
end
@@ -241,22 +275,30 @@ RSpec.describe Bundler::Plugin do
describe "#hook" do
before do
path = lib_path("foo-plugin")
- build_lib "foo-plugin", :path => path do |s|
+ build_lib "foo-plugin", path: path do |s|
s.write "plugins.rb", code
end
+ @old_constants = Bundler::Plugin::Events.constants.map {|name| [name, Bundler::Plugin::Events.const_get(name)] }
Bundler::Plugin::Events.send(:reset)
- Bundler::Plugin::Events.send(:define, :EVENT_1, "event-1")
- Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2")
+ Bundler::Plugin::Events.send(:define, :EVENT1, "event-1")
+ Bundler::Plugin::Events.send(:define, :EVENT2, "event-2")
- allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1).
- and_return(["foo-plugin"])
- allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2).
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT1).
+ and_return(["foo-plugin", "", nil])
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT2).
and_return(["foo-plugin"])
allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path)
allow(index).to receive(:load_paths).with("foo-plugin").and_return([])
end
+ after do
+ Bundler::Plugin::Events.send(:reset)
+ Hash[@old_constants].each do |name, value|
+ Bundler::Plugin::Events.send(:define, name, value)
+ end
+ end
+
let(:code) { <<-RUBY }
Bundler::Plugin::API.hook("event-1") { puts "hook for event 1" }
RUBY
@@ -268,41 +310,58 @@ RSpec.describe Bundler::Plugin do
end
it "executes the hook" do
- out = capture(:stdout) do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1)
- end.strip
-
- expect(out).to eq("hook for event 1")
+ expect do
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
+ end.to output("hook for event 1\n").to_stdout
end
context "single plugin declaring more than one hook" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) {}
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_2) {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT1) {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT2) {}
puts "loaded"
RUBY
it "evals plugins.rb once" do
- out = capture(:stdout) do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1)
- Plugin.hook(Bundler::Plugin::Events::EVENT_2)
- end.strip
-
- expect(out).to eq("loaded")
+ expect do
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
+ Plugin.hook(Bundler::Plugin::Events::EVENT2)
+ end.to output("loaded\n").to_stdout
end
end
context "a block is passed" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) { |&blk| blk.call }
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT1) { |&blk| blk.call }
RUBY
it "is passed to the hook" do
- out = capture(:stdout) do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1) { puts "win" }
- end.strip
+ expect do
+ Plugin.hook(Bundler::Plugin::Events::EVENT1) { puts "win" }
+ end.to output("win\n").to_stdout
+ end
+ end
+
+ context "the plugin load_path is invalid" do
+ before do
+ allow(index).to receive(:load_paths).with("foo-plugin").
+ and_return(["invalid-file-name1", "invalid-file-name2"])
+ end
+
+ it "outputs a useful warning" do
+ msg =
+ "The following plugin paths don't exist: invalid-file-name1, invalid-file-name2.\n\n" \
+ "This can happen if the plugin was " \
+ "installed with a different version of Ruby that has since been uninstalled.\n\n" \
+ "If you would like to reinstall the plugin, run:\n\n" \
+ "bundler plugin uninstall foo-plugin && bundler plugin install foo-plugin\n\n" \
+ "Continuing without installing plugin foo-plugin.\n"
+
+ expect(Bundler.ui).to receive(:warn).with(msg)
+
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
- expect(out).to eq("win")
+ expect(subject.loaded?("foo-plugin")).to be_falsey
end
end
end
diff --git a/spec/bundler/bundler/psyched_yaml_spec.rb b/spec/bundler/bundler/psyched_yaml_spec.rb
deleted file mode 100644
index d5d68c5cc3..0000000000
--- a/spec/bundler/bundler/psyched_yaml_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/psyched_yaml"
-
-RSpec.describe "Bundler::YamlLibrarySyntaxError" do
- it "is raised on YAML parse errors" do
- expect { YAML.parse "{foo" }.to raise_error(Bundler::YamlLibrarySyntaxError)
- end
-end
diff --git a/spec/bundler/bundler/remote_specification_spec.rb b/spec/bundler/bundler/remote_specification_spec.rb
index 8115e026d8..f35b231d58 100644
--- a/spec/bundler/bundler/remote_specification_spec.rb
+++ b/spec/bundler/bundler/remote_specification_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Bundler::RemoteSpecification do
end
describe "#fetch_platform" do
- let(:remote_spec) { double(:remote_spec, :platform => "jruby") }
+ let(:remote_spec) { double(:remote_spec, platform: "jruby") }
before { allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec) }
@@ -45,7 +45,7 @@ RSpec.describe Bundler::RemoteSpecification do
let(:platform) { "jruby" }
it "should return the spec name, version, and platform" do
- expect(subject.full_name).to eq("foo-1.0.0-jruby")
+ expect(subject.full_name).to eq("foo-1.0.0-java")
end
end
end
@@ -113,7 +113,7 @@ RSpec.describe Bundler::RemoteSpecification do
context "comparing a non sortable object" do
let(:other) { Object.new }
- let(:remote_spec) { double(:remote_spec, :platform => "jruby") }
+ let(:remote_spec) { double(:remote_spec, platform: "jruby") }
before do
allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
@@ -127,8 +127,8 @@ RSpec.describe Bundler::RemoteSpecification do
end
describe "#__swap__" do
- let(:spec) { double(:spec, :dependencies => []) }
- let(:new_spec) { double(:new_spec, :dependencies => [], :runtime_dependencies => []) }
+ let(:spec) { double(:spec, dependencies: []) }
+ let(:new_spec) { double(:new_spec, dependencies: [], runtime_dependencies: []) }
before { subject.instance_variable_set(:@_remote_specification, spec) }
@@ -157,7 +157,7 @@ RSpec.describe Bundler::RemoteSpecification do
describe "method missing" do
context "and is present in Gem::Specification" do
- let(:remote_spec) { double(:remote_spec, :authors => "abcd") }
+ let(:remote_spec) { double(:remote_spec, authors: "abcd") }
before do
allow(subject).to receive(:_remote_specification).and_return(remote_spec)
@@ -172,7 +172,7 @@ RSpec.describe Bundler::RemoteSpecification do
describe "respond to missing?" do
context "and is present in Gem::Specification" do
- let(:remote_spec) { double(:remote_spec, :authors => "abcd") }
+ let(:remote_spec) { double(:remote_spec, authors: "abcd") }
before do
allow(subject).to receive(:_remote_specification).and_return(remote_spec)
diff --git a/spec/bundler/bundler/resolver/candidate_spec.rb b/spec/bundler/bundler/resolver/candidate_spec.rb
new file mode 100644
index 0000000000..aefad3316e
--- /dev/null
+++ b/spec/bundler/bundler/resolver/candidate_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Resolver::Candidate do
+ it "compares fine" do
+ version1 = described_class.new("1.12.5", priority: -1)
+ version2 = described_class.new("1.12.5", priority: 1)
+
+ expect(version2 > version1).to be true
+
+ version1 = described_class.new("1.12.5")
+ version2 = described_class.new("1.12.5")
+
+ expect(version2 == version1).to be true
+
+ version1 = described_class.new("1.12.5", priority: 1)
+ version2 = described_class.new("1.12.5", priority: -1)
+
+ expect(version2 < version1).to be true
+ end
+end
diff --git a/spec/bundler/bundler/resolver/cooldown_spec.rb b/spec/bundler/bundler/resolver/cooldown_spec.rb
new file mode 100644
index 0000000000..37ec158cba
--- /dev/null
+++ b/spec/bundler/bundler/resolver/cooldown_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Resolver do
+ let(:resolver) { described_class.allocate }
+
+ def remote(cooldown:)
+ instance_double(Bundler::Source::Rubygems::Remote, effective_cooldown: cooldown)
+ end
+
+ def spec(created_at:, remote:, name: "myrack", version: "1.0.0")
+ Struct.new(:name, :version, :created_at, :remote).new(name, Gem::Version.new(version), created_at, remote)
+ end
+
+ describe "#filter_cooldown" do
+ let(:now) { Time.now }
+
+ context "with a 7-day cooldown" do
+ let(:r) { remote(cooldown: 7) }
+
+ it "rejects versions published within the window" do
+ recent = spec(version: "1.1.0", created_at: now - (2 * 86_400), remote: r)
+ old = spec(version: "1.0.0", created_at: now - (30 * 86_400), remote: r)
+
+ expect(resolver.send(:filter_cooldown, [recent, old])).to eq([old])
+ end
+
+ it "keeps versions published exactly at the threshold" do
+ boundary = spec(created_at: now - (7 * 86_400), remote: r)
+
+ expect(resolver.send(:filter_cooldown, [boundary])).to eq([boundary])
+ end
+
+ it "leaves rolling-delay history intact" do
+ # 7-day cooldown with frequent releases must still expose an older candidate.
+ in_cooldown = spec(version: "1.2.0", created_at: now - 86_400, remote: r)
+ also_in_cooldown = spec(version: "1.1.0", created_at: now - (3 * 86_400), remote: r)
+ eligible = spec(version: "1.0.0", created_at: now - (10 * 86_400), remote: r)
+
+ result = resolver.send(:filter_cooldown, [in_cooldown, also_in_cooldown, eligible])
+
+ expect(result).to eq([eligible])
+ end
+
+ it "drops every spec sharing an excluded [name, version] tuple" do
+ # The cooldown check is by version, not per-spec: a StubSpecification for an
+ # in-cooldown release would otherwise slip through on local install paths.
+ endpoint = spec(version: "2.0.0", created_at: now - 86_400, remote: r)
+ local_stub = Struct.new(:name, :version).new("myrack", Gem::Version.new("2.0.0"))
+ eligible = spec(version: "1.0.0", created_at: now - (30 * 86_400), remote: r)
+
+ result = resolver.send(:filter_cooldown, [endpoint, local_stub, eligible])
+
+ expect(result).to eq([eligible])
+ end
+
+ it "keeps stub-only versions that no endpoint marks as in cooldown" do
+ # If no remote spec carries created_at for a version, cooldown cannot judge it;
+ # the stub stays in.
+ local_only = Struct.new(:name, :version).new("myrack", Gem::Version.new("2.0.0"))
+ eligible = spec(version: "1.0.0", created_at: now - (30 * 86_400), remote: r)
+
+ result = resolver.send(:filter_cooldown, [local_only, eligible])
+
+ expect(result).to eq([local_only, eligible])
+ end
+ end
+
+ context "when created_at is missing (blank metadata)" do
+ it "keeps the spec regardless of cooldown" do
+ s = spec(created_at: nil, remote: remote(cooldown: 7))
+
+ expect(resolver.send(:filter_cooldown, [s])).to eq([s])
+ end
+ end
+
+ context "when the remote has no cooldown" do
+ it "keeps every spec" do
+ s = spec(created_at: now - 3600, remote: remote(cooldown: nil))
+
+ expect(resolver.send(:filter_cooldown, [s])).to eq([s])
+ end
+ end
+
+ context "when cooldown is 0" do
+ it "keeps every spec (escape hatch)" do
+ s = spec(created_at: now - 3600, remote: remote(cooldown: 0))
+
+ expect(resolver.send(:filter_cooldown, [s])).to eq([s])
+ end
+ end
+
+ context "when the spec does not respond to created_at" do
+ it "keeps the spec" do
+ bare = Struct.new(:version).new("1.0.0")
+
+ expect(resolver.send(:filter_cooldown, [bare])).to eq([bare])
+ end
+ end
+
+ context "when the spec has no remote" do
+ it "keeps the spec" do
+ s = spec(created_at: now - 86_400, remote: nil)
+
+ expect(resolver.send(:filter_cooldown, [s])).to eq([s])
+ end
+ end
+
+ it "returns the same array when input is empty" do
+ expect(resolver.send(:filter_cooldown, [])).to eq([])
+ end
+ end
+
+ describe "#cooldown_hint" do
+ let(:now) { Time.now }
+ let(:r) { remote(cooldown: 7) }
+
+ it "returns nil when no spec is excluded" do
+ expect(resolver.send(:cooldown_hint, [])).to be_nil
+ end
+
+ it "returns nil when every spec is outside the cooldown window" do
+ eligible = [spec(created_at: now - (30 * 86_400), remote: r)]
+
+ expect(resolver.send(:cooldown_hint, eligible)).to be_nil
+ end
+
+ it "mentions the count and the bypass flag for one excluded version" do
+ excluded = [spec(created_at: now - 86_400, remote: r)]
+
+ hint = resolver.send(:cooldown_hint, excluded)
+
+ expect(hint).to match(/1 version excluded by the cooldown setting/)
+ expect(hint).to match(/--cooldown 0/)
+ end
+
+ it "uses plural wording when multiple versions are excluded" do
+ excluded = %w[1.0.0 1.1.0 1.2.0].map {|v| spec(version: v, created_at: now - 86_400, remote: r) }
+
+ expect(resolver.send(:cooldown_hint, excluded)).to match(/3 versions excluded/)
+ end
+
+ it "counts each unique version once even when multiple spec instances share it" do
+ duplicates = Array.new(3) { spec(created_at: now - 86_400, remote: r) }
+
+ expect(resolver.send(:cooldown_hint, duplicates)).to match(/1 version excluded/)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/retry_spec.rb b/spec/bundler/bundler/retry_spec.rb
index b893580d72..5c84d0bea5 100644
--- a/spec/bundler/bundler/retry_spec.rb
+++ b/spec/bundler/bundler/retry_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Bundler::Retry do
end
it "returns the first valid result" do
- jobs = [proc { raise "foo" }, proc { :bar }, proc { raise "foo" }]
+ jobs = [proc { raise "job 1 failed" }, proc { :bar }, proc { raise "job 2 failed" }]
attempts = 0
result = Bundler::Retry.new(nil, nil, 3).attempt do
attempts += 1
@@ -68,7 +68,7 @@ RSpec.describe Bundler::Retry do
it "print error message with newlines" do
allow(Bundler.ui).to receive(:debug?).and_return(false)
expect(Bundler.ui).to receive(:info).with("").twice
- expect(Bundler.ui).to receive(:warn).with(failure_message, false)
+ expect(Bundler.ui).to receive(:warn).with(failure_message, true)
expect do
Bundler::Retry.new("test", [], 1).attempt do
@@ -78,4 +78,113 @@ RSpec.describe Bundler::Retry do
end
end
end
+
+ context "exponential backoff" do
+ it "can be disabled by setting base_delay to 0" do
+ attempts = 0
+ expect do
+ Bundler::Retry.new("test", [], 2, base_delay: 0).attempt do
+ attempts += 1
+ raise "error"
+ end
+ end.to raise_error(StandardError)
+
+ # Verify no sleep was called (implicitly - if sleep was called, timing would be different)
+ expect(attempts).to eq(3)
+ end
+
+ it "is enabled by default with 1 second base delay" do
+ original_base_delay = Bundler::Retry.default_base_delay
+ Bundler::Retry.default_base_delay = 1.0
+
+ attempts = 0
+ sleep_times = []
+
+ allow_any_instance_of(Bundler::Retry).to receive(:sleep) do |_instance, delay|
+ sleep_times << delay
+ end
+
+ expect do
+ Bundler::Retry.new("test", [], 2, jitter: 0).attempt do
+ attempts += 1
+ raise "error"
+ end
+ end.to raise_error(StandardError)
+
+ expect(attempts).to eq(3)
+ expect(sleep_times.length).to eq(2)
+ # First retry: 1.0 * 2^0 = 1.0
+ expect(sleep_times[0]).to eq(1.0)
+ # Second retry: 1.0 * 2^1 = 2.0
+ expect(sleep_times[1]).to eq(2.0)
+ ensure
+ Bundler::Retry.default_base_delay = original_base_delay
+ end
+
+ it "sleeps with exponential backoff when base_delay is set" do
+ attempts = 0
+ sleep_times = []
+
+ allow_any_instance_of(Bundler::Retry).to receive(:sleep) do |_instance, delay|
+ sleep_times << delay
+ end
+
+ expect do
+ Bundler::Retry.new("test", [], 2, base_delay: 1.0, jitter: 0).attempt do
+ attempts += 1
+ raise "error"
+ end
+ end.to raise_error(StandardError)
+
+ expect(attempts).to eq(3)
+ expect(sleep_times.length).to eq(2)
+ # First retry: 1.0 * 2^0 = 1.0
+ expect(sleep_times[0]).to eq(1.0)
+ # Second retry: 1.0 * 2^1 = 2.0
+ expect(sleep_times[1]).to eq(2.0)
+ end
+
+ it "respects max_delay" do
+ sleep_times = []
+
+ allow_any_instance_of(Bundler::Retry).to receive(:sleep) do |_instance, delay|
+ sleep_times << delay
+ end
+
+ expect do
+ Bundler::Retry.new("test", [], 3, base_delay: 10.0, max_delay: 15.0, jitter: 0).attempt do
+ raise "error"
+ end
+ end.to raise_error(StandardError)
+
+ # First retry: 10.0 * 2^0 = 10.0
+ expect(sleep_times[0]).to eq(10.0)
+ # Second retry: 10.0 * 2^1 = 20.0, capped at 15.0
+ expect(sleep_times[1]).to eq(15.0)
+ # Third retry: 10.0 * 2^2 = 40.0, capped at 15.0
+ expect(sleep_times[2]).to eq(15.0)
+ end
+
+ it "adds jitter to delay" do
+ sleep_times = []
+
+ allow_any_instance_of(Bundler::Retry).to receive(:sleep) do |_instance, delay|
+ sleep_times << delay
+ end
+
+ expect do
+ Bundler::Retry.new("test", [], 2, base_delay: 1.0, jitter: 0.5).attempt do
+ raise "error"
+ end
+ end.to raise_error(StandardError)
+
+ expect(sleep_times.length).to eq(2)
+ # First retry should be between 1.0 and 1.5 (base + jitter)
+ expect(sleep_times[0]).to be >= 1.0
+ expect(sleep_times[0]).to be <= 1.5
+ # Second retry should be between 2.0 and 2.5
+ expect(sleep_times[1]).to be >= 2.0
+ expect(sleep_times[1]).to be <= 2.5
+ end
+ end
end
diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb
index bc1ca98457..45a37c5795 100644
--- a/spec/bundler/bundler/ruby_dsl_spec.rb
+++ b/spec/bundler/bundler/ruby_dsl_spec.rb
@@ -7,28 +7,37 @@ RSpec.describe Bundler::RubyDsl do
include Bundler::RubyDsl
attr_reader :ruby_version
+ attr_accessor :gemfile
end
let(:dsl) { MockDSL.new }
let(:ruby_version) { "2.0.0" }
+ let(:ruby_version_arg) { ruby_version }
let(:version) { "2.0.0" }
let(:engine) { "jruby" }
let(:engine_version) { "9000" }
let(:patchlevel) { "100" }
let(:options) do
- { :patchlevel => patchlevel,
- :engine => engine,
- :engine_version => engine_version }
+ { patchlevel: patchlevel,
+ engine: engine,
+ engine_version: engine_version }
end
+ let(:project_root) { Pathname.new("/path/to/project") }
+ let(:gemfile) { project_root.join("Gemfile") }
+ before { allow(Bundler).to receive(:root).and_return(project_root) }
let(:invoke) do
proc do
- args = Array(ruby_version) + [options]
+ args = []
+ args << ruby_version_arg if ruby_version_arg
+ args << options
+
dsl.ruby(*args)
end
end
subject do
+ dsl.gemfile = gemfile
invoke.call
dsl.ruby_version
end
@@ -59,10 +68,19 @@ RSpec.describe Bundler::RubyDsl do
it_behaves_like "it stores the ruby version"
end
+ context "with a preview version" do
+ let(:ruby_version) { "3.3.0-preview2" }
+
+ it "stores the version" do
+ expect(subject.versions).to eq(Array("3.3.0.preview2"))
+ expect(subject.gem_version.version).to eq("3.3.0.preview2")
+ end
+ end
+
context "with two requirements in the same string" do
let(:ruby_version) { ">= 2.0.0, < 3.0" }
it "raises an error" do
- expect { subject }.to raise_error(ArgumentError)
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError)
end
end
@@ -91,5 +109,140 @@ RSpec.describe Bundler::RubyDsl do
it_behaves_like "it stores the ruby version"
end
end
+
+ context "with a file option" do
+ let(:file) { ".ruby-version" }
+ let(:ruby_version_file_path) { gemfile.dirname.join(file) }
+ let(:options) do
+ { file: file,
+ patchlevel: patchlevel,
+ engine: engine,
+ engine_version: engine_version }
+ end
+ let(:ruby_version_arg) { nil }
+ let(:file_content) { "#{version}\n" }
+
+ before do
+ allow(Bundler).to receive(:read_file) do |path|
+ raise Errno::ENOENT, <<~ERROR unless path == ruby_version_file_path
+ #{file} not found in specs:
+ expected: #{ruby_version_file_path}
+ received: #{path}
+ ERROR
+ file_content
+ end
+ end
+
+ it_behaves_like "it stores the ruby version"
+
+ context "with the Gemfile ruby file: path is relative to the Gemfile in a subdir" do
+ let(:gemfile) { project_root.join("subdir", "Gemfile") }
+ let(:file) { "../.ruby-version" }
+ let(:ruby_version_file_path) { gemfile.dirname.join(file) }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with bundler root in a subdir of the project" do
+ let(:project_root) { Pathname.new("/path/to/project/subdir") }
+ let(:gemfile) { project_root.parent.join("Gemfile") }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with the ruby- prefix in the file" do
+ let(:file_content) { "ruby-#{version}\n" }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "and a version" do
+ let(:ruby_version_arg) { version }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::GemfileError, "Do not pass version argument when using :file option")
+ end
+ end
+
+ context "with a @gemset" do
+ let(:file_content) { "ruby-#{version}@gemset\n" }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError, "2.0.0@gemset is not a valid requirement on the Ruby version")
+ end
+ end
+
+ context "with a mise.toml file format" do
+ let(:file) { "mise.toml" }
+ let(:ruby_version_arg) { nil }
+ let(:file_content) do
+ <<~TOML
+ [tools]
+ ruby = #{quote}#{version}#{quote}
+ TOML
+ end
+
+ context "with double quotes" do
+ let(:quote) { '"' }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with single quotes" do
+ let(:quote) { "'" }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with mismatched quotes" do
+ let(:file_content) do
+ <<~TOML
+ [tools]
+ ruby = "#{version}'
+ TOML
+ end
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError, "= is not a valid requirement on the Ruby version")
+ end
+ end
+ end
+
+ context "with a .tool-versions file format" do
+ let(:file) { ".tool-versions" }
+ let(:ruby_version_arg) { nil }
+ let(:file_content) do
+ <<~TOOLS
+ nodejs 18.16.0
+ ruby #{version} # This is a comment
+ pnpm 8.6.12
+ TOOLS
+ end
+
+ it_behaves_like "it stores the ruby version"
+
+ context "with extra spaces and a very cozy comment" do
+ let(:file_content) do
+ <<~TOOLS
+ nodejs 18.16.0
+ ruby #{version}# This is a cozy comment
+ pnpm 8.6.12
+ TOOLS
+ end
+
+ it_behaves_like "it stores the ruby version"
+ end
+ end
+
+ context "when the file does not exist" do
+ let(:ruby_version_file_path) { nil }
+ let(:ruby_version_arg) { nil }
+ let(:file) { "nonexistent.txt" }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::GemfileError, /Could not find version file nonexistent.txt/)
+ end
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/ruby_version_spec.rb b/spec/bundler/bundler/ruby_version_spec.rb
index 46a1b2918b..0d41ec9901 100644
--- a/spec/bundler/bundler/ruby_version_spec.rb
+++ b/spec/bundler/bundler/ruby_version_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
describe "#to_s" do
it "should return info string with the ruby version, patchlevel, engine, and engine version" do
- expect(subject.to_s).to eq("ruby 2.0.0p645 (jruby 2.0.1)")
+ expect(subject.to_s).to eq("ruby 2.0.0 (jruby 2.0.1)")
end
context "no patchlevel" do
@@ -115,7 +115,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
let(:engine) { "ruby" }
it "should return info string with the ruby version and patchlevel" do
- expect(subject.to_s).to eq("ruby 2.0.0p645")
+ expect(subject.to_s).to eq("ruby 2.0.0")
end
end
@@ -137,7 +137,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
end
- context "the versions, pathlevels, engines, and engine_versions match" do
+ shared_examples_for "the versions, engines, and engine_versions match" do
it "should return true" do
expect(subject).to eq(other_ruby_version)
end
@@ -152,7 +152,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
context "the patchlevels do not match" do
let(:other_patchlevel) { "21" }
- it_behaves_like "two ruby versions are not equal"
+ it_behaves_like "the versions, engines, and engine_versions match"
end
context "the engines do not match" do
@@ -228,9 +228,9 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
end
- shared_examples_for "there is a difference in the patchlevels" do
- it "should return a tuple with :patchlevel and the two different patchlevels" do
- expect(ruby_version.diff(other_ruby_version)).to eq([:patchlevel, patchlevel, other_patchlevel])
+ shared_examples_for "even there is a difference in the patchlevels" do
+ it "should return nil" do
+ expect(ruby_version.diff(other_ruby_version)).to be_nil
end
end
@@ -287,10 +287,10 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
it_behaves_like "there is a difference in the engine versions"
end
- context "detects patchlevel discrepancies last" do
+ context "ignores patchlevel discrepancies last" do
let(:other_patchlevel) { "643" }
- it_behaves_like "there is a difference in the patchlevels"
+ it_behaves_like "even there is a difference in the patchlevels"
end
context "successfully matches gem requirements" do
@@ -355,7 +355,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
let(:other_engine) { "ruby" }
let(:other_engine_version) { "2.0.5" }
- it_behaves_like "there is a difference in the patchlevels"
+ it_behaves_like "even there is a difference in the patchlevels"
end
context "successfully detects bad gem requirements with engine versions" do
@@ -389,7 +389,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
context "and comparing with a patchlevel that is not -1" do
let(:other_patchlevel) { "642" }
- it_behaves_like "there is a difference in the patchlevels"
+ it_behaves_like "even there is a difference in the patchlevels"
end
end
end
@@ -399,8 +399,22 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
let(:bundler_system_ruby_version) { subject }
- before do
- Bundler::RubyVersion.instance_variable_set("@ruby_version", nil)
+ around do |example|
+ if Bundler::RubyVersion.instance_variable_defined?("@system")
+ begin
+ old_ruby_version = Bundler::RubyVersion.instance_variable_get("@system")
+ Bundler::RubyVersion.remove_instance_variable("@system")
+ example.run
+ ensure
+ Bundler::RubyVersion.instance_variable_set("@system", old_ruby_version)
+ end
+ else
+ begin
+ example.run
+ ensure
+ Bundler::RubyVersion.remove_instance_variable("@system")
+ end
+ end
end
it "should return an instance of Bundler::RubyVersion" do
@@ -413,66 +427,54 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
describe "#version" do
- it "should return a copy of the value of RUBY_VERSION" do
- expect(subject.versions).to eq([RUBY_VERSION])
- expect(subject.versions.first).to_not be(RUBY_VERSION)
+ it "should return the value of Gem.ruby_version as a string" do
+ expect(subject.versions).to eq([Gem.ruby_version.to_s])
end
end
describe "#engine" do
- context "RUBY_ENGINE is defined" do
- before { stub_const("RUBY_ENGINE", "jruby") }
- before { stub_const("JRUBY_VERSION", "2.1.1") }
+ before { stub_const("RUBY_ENGINE", "jruby") }
+ before { stub_const("RUBY_ENGINE_VERSION", "2.1.1") }
- it "should return a copy of the value of RUBY_ENGINE" do
- expect(subject.engine).to eq("jruby")
- expect(subject.engine).to_not be(RUBY_ENGINE)
- end
- end
-
- context "RUBY_ENGINE is not defined" do
- before { stub_const("RUBY_ENGINE", nil) }
-
- it "should return the string 'ruby'" do
- expect(subject.engine).to eq("ruby")
- end
+ it "should return a copy of the value of RUBY_ENGINE" do
+ expect(subject.engine).to eq("jruby")
+ expect(subject.engine).to_not be(RUBY_ENGINE)
end
end
describe "#engine_version" do
context "engine is ruby" do
before do
- stub_const("RUBY_VERSION", "2.2.4")
+ allow(Gem).to receive(:ruby_version).and_return(Gem::Version.new("2.2.4"))
stub_const("RUBY_ENGINE", "ruby")
end
- it "should return a copy of the value of RUBY_VERSION" do
+ it "should return the value of Gem.ruby_version as a string" do
expect(bundler_system_ruby_version.engine_versions).to eq(["2.2.4"])
- expect(bundler_system_ruby_version.engine_versions.first).to_not be(RUBY_VERSION)
end
end
context "engine is rbx" do
before do
stub_const("RUBY_ENGINE", "rbx")
- stub_const("Rubinius::VERSION", "2.0.0")
+ stub_const("RUBY_ENGINE_VERSION", "2.0.0")
end
- it "should return a copy of the value of Rubinius::VERSION" do
+ it "should return a copy of the value of RUBY_ENGINE_VERSION" do
expect(bundler_system_ruby_version.engine_versions).to eq(["2.0.0"])
- expect(bundler_system_ruby_version.engine_versions.first).to_not be(Rubinius::VERSION)
+ expect(bundler_system_ruby_version.engine_versions.first).to_not be(RUBY_ENGINE_VERSION)
end
end
context "engine is jruby" do
before do
stub_const("RUBY_ENGINE", "jruby")
- stub_const("JRUBY_VERSION", "2.1.1")
+ stub_const("RUBY_ENGINE_VERSION", "2.1.1")
end
- it "should return a copy of the value of JRUBY_VERSION" do
+ it "should return a copy of the value of RUBY_ENGINE_VERSION" do
expect(subject.engine_versions).to eq(["2.1.1"])
- expect(bundler_system_ruby_version.engine_versions.first).to_not be(JRUBY_VERSION)
+ expect(bundler_system_ruby_version.engine_versions.first).to_not be(RUBY_ENGINE_VERSION)
end
end
@@ -494,31 +496,5 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
end
end
-
- describe "#to_gem_version_with_patchlevel" do
- shared_examples_for "the patchlevel is omitted" do
- it "does not include a patch level" do
- expect(subject.to_gem_version_with_patchlevel.to_s).to eq(version)
- end
- end
-
- context "with nil patch number" do
- let(:patchlevel) { nil }
-
- it_behaves_like "the patchlevel is omitted"
- end
-
- context "with negative patch number" do
- let(:patchlevel) { -1 }
-
- it_behaves_like "the patchlevel is omitted"
- end
-
- context "with a valid patch number" do
- it "uses the specified patchlevel as patchlevel" do
- expect(subject.to_gem_version_with_patchlevel.to_s).to eq("#{version}.#{patchlevel}")
- end
- end
- end
end
end
diff --git a/spec/bundler/bundler/rubygems_ext_spec.rb b/spec/bundler/bundler/rubygems_ext_spec.rb
new file mode 100644
index 0000000000..0fc528f78c
--- /dev/null
+++ b/spec/bundler/bundler/rubygems_ext_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "bundler/rubygems_ext"
+
+RSpec.describe Gem::SplitCompactIndexEntryOnFirstColon do
+ # Reproduces the RubyGems < 4.0.13 `Gem::Resolver::APISet::GemParser` that
+ # split each compact index entry on every colon, corrupting metadata values
+ # that themselves contain colons.
+ let(:legacy_parser_class) do
+ Class.new do
+ def parse_dependency(string)
+ dependency = string.split(":")
+ dependency[-1] = dependency[-1].split("&") if dependency.size > 1
+ dependency[0] = -dependency[0]
+ dependency
+ end
+ end
+ end
+
+ before { legacy_parser_class.prepend(described_class) }
+
+ it "preserves colon-bearing metadata values such as created_at timestamps" do
+ parser = legacy_parser_class.new
+
+ expect(parser.send(:parse_dependency, "created_at:2026-05-12T10:00:00Z")).to eq(["created_at", ["2026-05-12T10:00:00Z"]])
+ end
+
+ it "still parses ordinary name:requirement entries" do
+ parser = legacy_parser_class.new
+
+ expect(parser.send(:parse_dependency, "myrack:>= 1.0")).to eq(["myrack", [">= 1.0"]])
+ end
+
+ it "keeps parse_dependency private" do
+ parser = legacy_parser_class.new
+
+ expect { parser.parse_dependency("created_at:x") }.to raise_error(NoMethodError, /private method/)
+ end
+end
diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb
index b1b15d9e5d..a2c63a7ca0 100644
--- a/spec/bundler/bundler/rubygems_integration_spec.rb
+++ b/spec/bundler/bundler/rubygems_integration_spec.rb
@@ -1,10 +1,6 @@
# frozen_string_literal: true
RSpec.describe Bundler::RubygemsIntegration do
- it "uses the same chdir lock as rubygems", :rubygems => "2.1" do
- expect(Bundler.rubygems.ext_lock).to eq(Gem::Ext::Builder::CHDIR_MONITOR)
- end
-
context "#validate" do
let(:spec) do
Gem::Specification.new do |s|
@@ -15,30 +11,18 @@ RSpec.describe Bundler::RubygemsIntegration do
end
subject { Bundler.rubygems.validate(spec) }
- it "skips overly-strict gemspec validation", :rubygems => "< 1.7" do
- expect(spec).to_not receive(:validate)
+ it "validates for resolution" do
+ expect(spec).to receive(:validate_for_resolution)
subject
end
- it "validates with packaging mode disabled", :rubygems => "1.7" do
- expect(spec).to receive(:validate).with(false)
- subject
- end
-
- it "should set a summary to avoid an overly-strict error", :rubygems => "~> 1.7.0" do
- spec.summary = nil
- expect { subject }.not_to raise_error
- expect(spec.summary).to eq("")
- end
-
context "with an invalid spec" do
before do
- expect(spec).to receive(:validate).with(false).
+ expect(spec).to receive(:validate_for_resolution).
and_raise(Gem::InvalidSpecificationException.new("TODO is not an author"))
end
- it "should raise a Gem::InvalidSpecificationException and produce a helpful warning message",
- :rubygems => "1.7" do
+ it "should raise a Gem::InvalidSpecificationException and produce a helpful warning message" do
expect { subject }.to raise_error(Gem::InvalidSpecificationException,
"The gemspec at #{__FILE__} is not valid. "\
"Please fix this gemspec.\nThe validation error was 'TODO is not an author'\n")
@@ -46,69 +30,97 @@ RSpec.describe Bundler::RubygemsIntegration do
end
end
- describe "#configuration" do
- it "handles Gem::SystemExitException errors" do
- allow(Gem).to receive(:configuration) { raise Gem::SystemExitException.new(1) }
- expect { Bundler.rubygems.configuration }.to raise_error(Gem::SystemExitException)
- end
- end
-
- describe "#download_gem", :rubygems => ">= 2.0" do
+ describe "#download_gem" do
let(:bundler_retry) { double(Bundler::Retry) }
- let(:retry) { double("Bundler::Retry") }
- let(:uri) { URI.parse("https://foo.bar") }
- let(:path) { Gem.path.first }
+ let(:cache_dir) { "#{Gem.path.first}/cache" }
let(:spec) do
- spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"),
- Gem::Platform::RUBY, nil)
+ spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2"))
spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s)
spec
end
let(:fetcher) { double("gem_remote_fetcher") }
- it "successfully downloads gem with retries" do
- expect(Bundler.rubygems).to receive(:gem_remote_fetcher).and_return(fetcher)
- expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "https://foo.bar")
- expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/").
- and_return(bundler_retry)
- expect(bundler_retry).to receive(:attempts).and_yield
- expect(fetcher).to receive(:download).with(spec, uri, path)
+ context "when uri is public" do
+ let(:uri) { Gem::URI.parse("https://foo.bar") }
+
+ it "successfully downloads gem with retries" do
+ expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/").
+ and_return(bundler_retry)
+ expect(bundler_retry).to receive(:attempts).and_yield
+ expect(fetcher).to receive(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
+
+ context "when uri contains userinfo part" do
+ let(:uri) { Gem::URI.parse("https://#{userinfo}@foo.bar") }
+
+ context "with user and password" do
+ let(:userinfo) { "user:password" }
+
+ it "successfully downloads gem with retries with filtered log" do
+ expect(Bundler::Retry).to receive(:new).with("download gem from https://user:REDACTED@foo.bar/").
+ and_return(bundler_retry)
+ expect(bundler_retry).to receive(:attempts).and_yield
+ expect(fetcher).to receive(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
+
+ context "with token [as user]" do
+ let(:userinfo) { "token" }
- Bundler.rubygems.download_gem(spec, uri, path)
+ it "successfully downloads gem with retries with filtered log" do
+ expect(Bundler::Retry).to receive(:new).with("download gem from https://REDACTED@foo.bar/").
+ and_return(bundler_retry)
+ expect(bundler_retry).to receive(:attempts).and_yield
+ expect(fetcher).to receive(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
end
end
- describe "#fetch_all_remote_specs", :rubygems => ">= 2.0" do
- let(:uri) { URI("https://example.com") }
+ describe "#fetch_all_remote_specs" do
+ let(:uri) { "https://example.com" }
let(:fetcher) { double("gem_remote_fetcher") }
let(:specs_response) { Marshal.dump(["specs"]) }
let(:prerelease_specs_response) { Marshal.dump(["prerelease_specs"]) }
context "when a rubygems source mirror is set" do
- let(:orig_uri) { URI("http://zombo.com") }
- let(:remote_with_mirror) { double("remote", :uri => uri, :original_uri => orig_uri) }
+ let(:orig_uri) { Gem::URI("http://zombo.com") }
+ let(:remote_with_mirror) { double("remote", uri: uri, original_uri: orig_uri) }
it "sets the 'X-Gemfile-Source' header containing the original source" do
- expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher)
- expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "http://zombo.com").twice
expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response)
expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response)
- result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror)
+ result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror, fetcher)
expect(result).to eq(%w[specs prerelease_specs])
end
end
context "when there is no rubygems source mirror set" do
- let(:remote_no_mirror) { double("remote", :uri => uri, :original_uri => nil) }
+ let(:remote_no_mirror) { double("remote", uri: uri, original_uri: nil) }
it "does not set the 'X-Gemfile-Source' header" do
- expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher)
- expect(fetcher).to_not receive(:headers=)
expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response)
expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response)
- result = Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror)
+ result = Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror, fetcher)
expect(result).to eq(%w[specs prerelease_specs])
end
end
+
+ context "when loading an unexpected class" do
+ let(:remote_no_mirror) { double("remote", uri: uri, original_uri: nil) }
+ let(:unexpected_specs_response) { Marshal.dump(3) }
+
+ it "raises a MarshalError error" do
+ expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(unexpected_specs_response)
+ expect { Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror, fetcher) }.to raise_error(Bundler::MarshalError, /unexpected class/i)
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/settings/validator_spec.rb b/spec/bundler/bundler/settings/validator_spec.rb
index e4ffd89435..b252ba59a0 100644
--- a/spec/bundler/bundler/settings/validator_spec.rb
+++ b/spec/bundler/bundler/settings/validator_spec.rb
@@ -44,14 +44,14 @@ RSpec.describe Bundler::Settings::Validator do
validate!("without", "b:c", "BUNDLE_WITH" => "a")
end.not_to raise_error
- expect { validate!("with", "b:c", "BUNDLE_WITHOUT" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip
+ expect { validate!("with", "b:c", "BUNDLE_WITHOUT" => "c:d") }.to raise_error Bundler::InvalidOption, <<~EOS.strip
Setting `with` to "b:c" failed:
- a group cannot be in both `with` & `without` simultaneously
- `without` is current set to [:c, :d]
- the `c` groups conflict
EOS
- expect { validate!("without", "b:c", "BUNDLE_WITH" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip
+ expect { validate!("without", "b:c", "BUNDLE_WITH" => "c:d") }.to raise_error Bundler::InvalidOption, <<~EOS.strip
Setting `without` to "b:c" failed:
- a group cannot be in both `with` & `without` simultaneously
- `with` is current set to [:c, :d]
@@ -74,7 +74,7 @@ RSpec.describe Bundler::Settings::Validator do
describe "#fail!" do
it "raises with a helpful message" do
- expect { subject.fail!("key", "value", "reason1", "reason2") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip
+ expect { subject.fail!("key", "value", "reason1", "reason2") }.to raise_error Bundler::InvalidOption, <<~EOS.strip
Setting `key` to "value" failed:
- rule description
- reason1
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 1a31493e20..5e1aaaa555 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -6,12 +6,18 @@ RSpec.describe Bundler::Settings do
subject(:settings) { described_class.new(bundled_app) }
describe "#set_local" do
- context "when the local config file is not found" do
+ context "root is nil" do
subject(:settings) { described_class.new(nil) }
- it "raises a GemfileNotFound error with explanation" do
- expect { subject.set_local("foo", "bar") }.
- to raise_error(Bundler::GemfileNotFound, "Could not locate Gemfile")
+ before do
+ allow(Pathname).to receive(:new).and_call_original
+ allow(Pathname).to receive(:new).with(".bundle").and_return home(".bundle")
+ end
+
+ it "works" do
+ subject.set_local("foo", "bar")
+
+ expect(subject["foo"]).to eq("bar")
end
end
end
@@ -27,7 +33,7 @@ RSpec.describe Bundler::Settings do
"gem.mit" => "false",
"gem.test" => "minitest",
"thingy" => <<-EOS.tr("\n", " "),
---asdf --fdsa --ty=oh man i hope this doesnt break bundler because
+--asdf --fdsa --ty=oh man i hope this doesn't break bundler because
that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
--very-important-option=DontDeleteRoo
--very-important-option=DontDeleteRoo
@@ -64,13 +70,10 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "#global_config_file" do
context "when $HOME is not accessible" do
- context "when $TMPDIR is not writable" do
- it "does not raise" do
- expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(FileUtils).to receive(:mkpath).twice.with(File.join(Dir.tmpdir, "bundler", "home")).and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
+ it "does not raise" do
+ expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(subject.send(:global_config_file)).to be_nil
- end
+ expect(subject.send(:global_config_file)).to be_nil
end
end
end
@@ -116,27 +119,37 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
settings.set_local :ssl_verify_mode, "1"
expect(settings[:ssl_verify_mode]).to be 1
end
+
+ it "coerces cooldown to integer" do
+ settings.set_local :cooldown, "7"
+ expect(settings[:cooldown]).to be 7
+ end
end
- context "when it's not possible to write to the file" do
+ context "when it's not possible to create the settings directory" do
it "raises an PermissionError with explanation" do
- expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:local_config_file).dirname).
- and_raise(Errno::EACCES)
+ settings_dir = settings.send(:local_config_file).dirname
+ expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings_dir).
+ and_raise(Errno::EACCES.new(settings_dir.to_s))
expect { settings.set_local :frozen, "1" }.
- to raise_error(Bundler::PermissionError, /config/)
+ to raise_error(Bundler::PermissionError, /#{settings_dir}/)
end
end
end
describe "#temporary" do
it "reset after used" do
- Bundler.settings.set_local :no_install, true
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+
+ Bundler.settings.set_command_option :no_install, true
- Bundler.settings.temporary(:no_install => false) do
+ Bundler.settings.temporary(no_install: false) do
expect(Bundler.settings[:no_install]).to eq false
end
expect(Bundler.settings[:no_install]).to eq true
+
+ Bundler.settings.set_command_option :no_install, nil
end
it "returns the return value of the block" do
@@ -146,23 +159,24 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
context "when called without a block" do
it "leaves the setting changed" do
- Bundler.settings.temporary(:foo => :random)
+ Bundler.settings.temporary(foo: :random)
expect(Bundler.settings[:foo]).to eq "random"
end
it "returns nil" do
- expect(Bundler.settings.temporary(:foo => :bar)).to be_nil
+ expect(Bundler.settings.temporary(foo: :bar)).to be_nil
end
end
end
describe "#set_global" do
- context "when it's not possible to write to the file" do
+ context "when it's not possible to write to create the settings directory" do
it "raises an PermissionError with explanation" do
- expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:global_config_file).dirname).
- and_raise(Errno::EACCES)
+ settings_dir = settings.send(:global_config_file).dirname
+ expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings_dir).
+ and_raise(Errno::EACCES.new(settings_dir.to_s))
expect { settings.set_global(:frozen, "1") }.
- to raise_error(Bundler::PermissionError, %r{\.bundle/config})
+ to raise_error(Bundler::PermissionError, /#{settings_dir}/)
end
end
end
@@ -178,7 +192,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
describe "#mirror_for" do
- let(:uri) { URI("https://rubygems.org/") }
+ let(:uri) { Gem::URI("https://rubygems.org/") }
context "with no configured mirror" do
it "returns the original URI" do
@@ -191,7 +205,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
context "with a configured mirror" do
- let(:mirror_uri) { URI("https://rubygems-mirror.org/") }
+ let(:mirror_uri) { Gem::URI("https://example-mirror.rubygems.org/") }
before { settings.set_local "mirror.https://rubygems.org/", mirror_uri.to_s }
@@ -212,7 +226,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
context "with a file URI" do
- let(:mirror_uri) { URI("file:/foo/BAR/baz/qUx/") }
+ let(:mirror_uri) { Gem::URI("file:/foo/BAR/baz/qUx/") }
it "returns the mirror URI" do
expect(settings.mirror_for(uri)).to eq(mirror_uri)
@@ -230,7 +244,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
describe "#credentials_for" do
- let(:uri) { URI("https://gemserver.example.org/") }
+ let(:uri) { Gem::URI("https://gemserver.example.org/") }
let(:credentials) { "username:password" }
context "with no configured credentials" do
@@ -268,12 +282,12 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
it "normalizes HTTP URIs in mirror configuration" do
- settings.set_local "mirror.http://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.http://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.all).to include("mirror.http://rubygems.org/")
end
it "normalizes HTTPS URIs in mirror configuration" do
- settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.https://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.all).to include("mirror.https://rubygems.org/")
end
@@ -288,9 +302,9 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
it "reads older keys without trailing slashes" do
- settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.https://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.mirror_for("https://rubygems.org/")).to eq(
- URI("http://rubygems-mirror.org/")
+ Gem::URI("http://example-mirror.rubygems.org/")
)
end
@@ -308,19 +322,59 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "BUNDLE_ keys format" do
let(:settings) { described_class.new(bundled_app(".bundle")) }
- it "converts older keys without double dashes" do
- config("BUNDLE_MY__PERSONAL.RACK" => "~/Work/git/rack")
- expect(settings["my.personal.rack"]).to eq("~/Work/git/rack")
+ it "converts older keys without double underscore" do
+ bundle_config("BUNDLE_MY__PERSONAL.MYRACK" => "~/Work/git/myrack")
+ expect(settings["my.personal.myrack"]).to eq("~/Work/git/myrack")
+ end
+
+ it "converts older keys without trailing slashes and double underscore" do
+ bundle_config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://example-mirror.rubygems.org")
+ expect(settings["mirror.https://rubygems.org/"]).to eq("http://example-mirror.rubygems.org")
+ end
+
+ it "ignores commented out keys" do
+ create_file bundled_app(".bundle/config"), <<~C
+ # BUNDLE_MY-PERSONAL-SERVER__ORG: my-personal-server.org
+ C
+
+ expect(Bundler.ui).not_to receive(:warn)
+ expect(settings.all).to be_empty
end
- it "converts older keys without trailing slashes and double dashes" do
- config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://rubygems-mirror.org")
- expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org")
+ it "converts older keys with dashes" do
+ bundle_config("BUNDLE_MY-PERSONAL-SERVER__ORG" => "my-personal-server.org")
+ expect(Bundler.ui).to receive(:warn).with(
+ "Your #{bundled_app(".bundle/config")} config includes `BUNDLE_MY-PERSONAL-SERVER__ORG`, which contains the dash character (`-`).\n" \
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
+ "Please edit #{bundled_app(".bundle/config")} and replace any dashes in configuration keys with a triple underscore (`___`)."
+ )
+ expect(settings["my-personal-server.org"]).to eq("my-personal-server.org")
end
it "reads newer keys format properly" do
- config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org")
- expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org")
+ bundle_config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://example-mirror.rubygems.org")
+ expect(settings["mirror.https://rubygems.org/"]).to eq("http://example-mirror.rubygems.org")
+ end
+ end
+
+ describe "default_cli_command validation" do
+ it "accepts 'install' as a valid value" do
+ expect { settings.set_local("default_cli_command", "install") }.not_to raise_error
+ end
+
+ it "accepts 'cli_help' as a valid value" do
+ expect { settings.set_local("default_cli_command", "cli_help") }.not_to raise_error
+ end
+
+ it "rejects invalid values" do
+ expect { settings.set_local("default_cli_command", "invalid") }.to raise_error(
+ Bundler::InvalidOption,
+ /Setting `default_cli_command` to "invalid" failed:\n - default_cli_command must be either 'install' or 'cli_help'\n - must be one of: install, cli_help/
+ )
+ end
+
+ it "accepts nil values" do
+ expect { settings.set_local("default_cli_command", nil) }.not_to raise_error
end
end
end
diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb
index b66c43fd92..41115aa667 100644
--- a/spec/bundler/bundler/shared_helpers_spec.rb
+++ b/spec/bundler/bundler/shared_helpers_spec.rb
@@ -1,20 +1,19 @@
# frozen_string_literal: true
RSpec.describe Bundler::SharedHelpers do
- let(:ext_lock_double) { double(:ext_lock) }
-
before do
- allow(Bundler.rubygems).to receive(:ext_lock).and_return(ext_lock_double)
- allow(ext_lock_double).to receive(:synchronize) {|&block| block.call }
+ pwd_stub
end
+ let(:pwd_stub) { allow(subject).to receive(:pwd).and_return(bundled_app) }
+
subject { Bundler::SharedHelpers }
describe "#default_gemfile" do
before { ENV["BUNDLE_GEMFILE"] = "/path/Gemfile" }
context "Gemfile is present" do
- let(:expected_gemfile_path) { Pathname.new("/path/Gemfile") }
+ let(:expected_gemfile_path) { Pathname.new("/path/Gemfile").expand_path }
it "returns the Gemfile path" do
expect(subject.default_gemfile).to eq(expected_gemfile_path)
@@ -60,7 +59,7 @@ RSpec.describe Bundler::SharedHelpers do
before { allow(subject).to receive(:default_gemfile).and_return(gemfile_path) }
- it "returns the lock file path" do
+ it "returns the lockfile path" do
expect(subject.default_lockfile).to eq(expected_lockfile_path)
end
end
@@ -74,10 +73,10 @@ RSpec.describe Bundler::SharedHelpers do
end
context ".bundle is global .bundle" do
- let(:global_rubygems_dir) { Pathname.new("#{bundled_app}") }
+ let(:global_rubygems_dir) { Pathname.new(bundled_app) }
before do
- Dir.mkdir ".bundle"
+ Dir.mkdir bundled_app(".bundle")
allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir)
end
@@ -91,7 +90,7 @@ RSpec.describe Bundler::SharedHelpers do
let(:expected_bundle_dir_path) { Pathname.new("#{bundled_app}/.bundle") }
before do
- Dir.mkdir ".bundle"
+ Dir.mkdir bundled_app(".bundle")
allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir)
end
@@ -109,7 +108,8 @@ RSpec.describe Bundler::SharedHelpers do
shared_examples_for "correctly determines whether to return a Gemfile path" do
context "currently in directory with a Gemfile" do
- before { File.new("Gemfile", "w") }
+ before { FileUtils.touch(bundled_app_gemfile) }
+ after { FileUtils.rm(bundled_app_gemfile) }
it "returns path of the bundle Gemfile" do
expect(subject.in_bundle?).to eq("#{bundled_app}/Gemfile")
@@ -147,22 +147,24 @@ RSpec.describe Bundler::SharedHelpers do
describe "#chdir" do
let(:op_block) { proc { Dir.mkdir "nested_dir" } }
- before { Dir.mkdir "chdir_test_dir" }
+ before { Dir.mkdir bundled_app("chdir_test_dir") }
it "executes the passed block while in the specified directory" do
- subject.chdir("chdir_test_dir", &op_block)
- expect(Pathname.new("chdir_test_dir/nested_dir")).to exist
+ subject.chdir(bundled_app("chdir_test_dir"), &op_block)
+ expect(bundled_app("chdir_test_dir/nested_dir")).to exist
end
end
describe "#pwd" do
+ let(:pwd_stub) { nil }
+
it "returns the current absolute path" do
- expect(subject.pwd).to eq(bundled_app)
+ expect(subject.pwd).to eq(git_root.to_s)
end
end
describe "#with_clean_git_env" do
- let(:with_clean_git_env_block) { proc { Dir.mkdir "with_clean_git_env_test_dir" } }
+ let(:with_clean_git_env_block) { proc { Dir.mkdir bundled_app("with_clean_git_env_test_dir") } }
before do
ENV["GIT_DIR"] = "ORIGINAL_ENV_GIT_DIR"
@@ -171,20 +173,20 @@ RSpec.describe Bundler::SharedHelpers do
it "executes the passed block" do
subject.with_clean_git_env(&with_clean_git_env_block)
- expect(Pathname.new("with_clean_git_env_test_dir")).to exist
+ expect(bundled_app("with_clean_git_env_test_dir")).to exist
end
context "when a block is passed" do
let(:with_clean_git_env_block) do
proc do
- Dir.mkdir "git_dir_test_dir" unless ENV["GIT_DIR"].nil?
- Dir.mkdir "git_work_tree_test_dir" unless ENV["GIT_WORK_TREE"].nil?
+ Dir.mkdir bundled_app("git_dir_test_dir") unless ENV["GIT_DIR"].nil?
+ Dir.mkdir bundled_app("git_work_tree_test_dir") unless ENV["GIT_WORK_TREE"].nil?
end end
it "uses a fresh git env for execution" do
subject.with_clean_git_env(&with_clean_git_env_block)
- expect(Pathname.new("git_dir_test_dir")).to_not exist
- expect(Pathname.new("git_work_tree_test_dir")).to_not exist
+ expect(bundled_app("git_dir_test_dir")).to_not exist
+ expect(bundled_app("git_work_tree_test_dir")).to_not exist
end
end
@@ -224,7 +226,7 @@ RSpec.describe Bundler::SharedHelpers do
end
shared_examples_for "ENV['PATH'] gets set correctly" do
- before { Dir.mkdir ".bundle" }
+ before { Dir.mkdir bundled_app(".bundle") }
it "ensures bundle bin path is in ENV['PATH']" do
subject.set_bundle_environment
@@ -236,7 +238,14 @@ RSpec.describe Bundler::SharedHelpers do
shared_examples_for "ENV['RUBYOPT'] gets set correctly" do
it "ensures -rbundler/setup is at the beginning of ENV['RUBYOPT']" do
subject.set_bundle_environment
- expect(ENV["RUBYOPT"].split(" ")).to start_with("-rbundler/setup")
+ expect(ENV["RUBYOPT"].split(" ")).to start_with("-r#{install_path}/bundler/setup")
+ end
+ end
+
+ shared_examples_for "ENV['BUNDLER_SETUP'] gets set correctly" do
+ it "ensures bundler/setup is set in ENV['BUNDLER_SETUP']" do
+ subject.set_bundle_environment
+ expect(ENV["BUNDLER_SETUP"]).to eq("#{source_lib_dir}/bundler/setup")
end
end
@@ -244,28 +253,36 @@ RSpec.describe Bundler::SharedHelpers do
let(:ruby_lib_path) { "stubbed_ruby_lib_dir" }
before do
- allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(ruby_lib_path)
+ allow(subject).to receive(:bundler_ruby_lib).and_return(ruby_lib_path)
end
it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do
subject.set_bundle_environment
- paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR)
- expect(paths).to include(ruby_lib_path)
+ expect(rubylib).to include(ruby_lib_path)
end
end
it "calls the appropriate set methods" do
+ expect(subject).to receive(:set_bundle_variables)
expect(subject).to receive(:set_path)
expect(subject).to receive(:set_rubyopt)
expect(subject).to receive(:set_rubylib)
subject.set_bundle_environment
end
+ it "ignores if bundler_ruby_lib is same as rubylibdir" do
+ allow(subject).to receive(:bundler_ruby_lib).and_return(RbConfig::CONFIG["rubylibdir"])
+
+ subject.set_bundle_environment
+
+ expect(rubylib.count(RbConfig::CONFIG["rubylibdir"])).to eq(0)
+ end
+
it "exits if bundle path contains the unix-like path separator" do
if Gem.respond_to?(:path_separator)
allow(Gem).to receive(:path_separator).and_return(":")
else
- stub_const("File::PATH_SEPARATOR", ":".freeze)
+ stub_const("File::PATH_SEPARATOR", ":")
end
allow(Bundler).to receive(:bundle_path) { Pathname.new("so:me/dir/bin") }
expect { subject.send(:validate_bundle_path) }.to raise_error(
@@ -279,7 +296,7 @@ RSpec.describe Bundler::SharedHelpers do
)
end
- context "with a jruby path_separator regex", :ruby => "1.9" do
+ context "with a jruby path_separator regex" do
# In versions of jruby that supported ruby 1.8, the path separator was the standard File::PATH_SEPARATOR
let(:regex) { Regexp.new("(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):") }
it "does not exit if bundle path is the standard uri path" do
@@ -337,25 +354,46 @@ RSpec.describe Bundler::SharedHelpers do
it "ENV['PATH'] should only contain one instance of bundle bin path" do
subject.set_bundle_environment
- paths = (ENV["PATH"]).split(File::PATH_SEPARATOR)
+ paths = ENV["PATH"].split(File::PATH_SEPARATOR)
expect(paths.count(bundle_path)).to eq(1)
end
end
- context "ENV['RUBYOPT'] does not exist" do
- before { ENV.delete("RUBYOPT") }
+ context "when bundler install path is standard" do
+ let(:install_path) { source_lib_dir }
- it_behaves_like "ENV['RUBYOPT'] gets set correctly"
- end
+ context "ENV['RUBYOPT'] does not exist" do
+ before { ENV.delete("RUBYOPT") }
+
+ it_behaves_like "ENV['RUBYOPT'] gets set correctly"
+ end
- context "ENV['RUBYOPT'] exists without -rbundler/setup" do
- before { ENV["RUBYOPT"] = "-I/some_app_path/lib" }
+ context "ENV['RUBYOPT'] exists without -rbundler/setup" do
+ before { ENV["RUBYOPT"] = "-I/some_app_path/lib" }
- it_behaves_like "ENV['RUBYOPT'] gets set correctly"
+ it_behaves_like "ENV['RUBYOPT'] gets set correctly"
+ end
+
+ context "ENV['RUBYOPT'] exists and contains -rbundler/setup" do
+ before { ENV["RUBYOPT"] = "-rbundler/setup" }
+
+ it_behaves_like "ENV['RUBYOPT'] gets set correctly"
+ end
end
- context "ENV['RUBYOPT'] exists and contains -rbundler/setup" do
- before { ENV["RUBYOPT"] = "-rbundler/setup" }
+ context "when bundler install path contains special characters" do
+ let(:install_path) { "/opt/ruby3.3.0-preview2/lib/ruby/3.3.0+0" }
+
+ before do
+ ENV["RUBYOPT"] = "-r#{install_path}/bundler/setup"
+ allow(File).to receive(:expand_path).and_return("#{install_path}/bundler/setup")
+ allow(Gem).to receive(:bin_path).and_return("#{install_path}/bundler/setup")
+ end
+
+ it "ensures -rbundler/setup is not duplicated" do
+ subject.set_bundle_environment
+ expect(ENV["RUBYOPT"].split(" ").grep(%r{-r.*/bundler/setup}).length).to eq(1)
+ end
it_behaves_like "ENV['RUBYOPT'] gets set correctly"
end
@@ -380,12 +418,13 @@ RSpec.describe Bundler::SharedHelpers do
context "bundle executable in ENV['BUNDLE_BIN_PATH'] does not exist" do
before { ENV["BUNDLE_BIN_PATH"] = "/does/not/exist" }
- before { Bundler.rubygems.replace_bin_path [], [] }
+ before { Bundler.rubygems.replace_bin_path [] }
it "sets BUNDLE_BIN_PATH to the bundle executable file" do
subject.set_bundle_environment
- bundle_exe = ruby_core? ? "../../../../exe/bundle" : "../../../exe/bundle"
- expect(ENV["BUNDLE_BIN_PATH"]).to eq(File.expand_path(bundle_exe, __FILE__))
+ bin_path = ENV["BUNDLE_BIN_PATH"]
+ expect(bin_path).to eq(exedir.join("bundle").to_s)
+ expect(File.exist?(bin_path)).to be true
end
end
@@ -400,8 +439,7 @@ RSpec.describe Bundler::SharedHelpers do
it "ENV['RUBYLIB'] should only contain one instance of bundler's ruby version lib path" do
subject.set_bundle_environment
- paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR)
- expect(paths.count(ruby_lib_path)).to eq(1)
+ expect(rubylib.count(ruby_lib_path)).to eq(1)
end
end
end
@@ -411,13 +449,13 @@ RSpec.describe Bundler::SharedHelpers do
let(:file_op_block) { proc {|path| FileUtils.mkdir_p(path) } }
it "performs the operation in the passed block" do
- subject.filesystem_access("./test_dir", &file_op_block)
- expect(Pathname.new("test_dir")).to exist
+ subject.filesystem_access(bundled_app("test_dir"), &file_op_block)
+ expect(bundled_app("test_dir")).to exist
end
end
context "system throws Errno::EACESS" do
- let(:file_op_block) { proc {|_path| raise Errno::EACCES } }
+ let(:file_op_block) { proc {|_path| raise Errno::EACCES.new("/path") } }
it "raises a PermissionError" do
expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error(
@@ -446,7 +484,7 @@ RSpec.describe Bundler::SharedHelpers do
end
end
- context "system throws Errno::ENOTSUP", :ruby => "1.9" do
+ context "system throws Errno::ENOTSUP" do
let(:file_op_block) { proc {|_path| raise Errno::ENOTSUP } }
it "raises a OperationNotSupportedError" do
@@ -472,33 +510,9 @@ RSpec.describe Bundler::SharedHelpers do
it "raises a GenericSystemCallError" do
expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error(
- Bundler::GenericSystemCallError, /error accessing.+underlying.+Shields down/m
+ Bundler::GenericSystemCallError, /error creating.+underlying.+Shields down/m
)
end
end
end
-
- describe "#const_get_safely" do
- module TargetNamespace
- VALID_CONSTANT = 1
- end
-
- context "when the namespace does have the requested constant" do
- it "returns the value of the requested constant" do
- expect(subject.const_get_safely(:VALID_CONSTANT, TargetNamespace)).to eq(1)
- end
- end
-
- context "when the requested constant is passed as a string" do
- it "returns the value of the requested constant" do
- expect(subject.const_get_safely("VALID_CONSTANT", TargetNamespace)).to eq(1)
- end
- end
-
- context "when the namespace does not have the requested constant" do
- it "returns nil" do
- expect(subject.const_get_safely("INVALID_CONSTANT", TargetNamespace)).to be_nil
- end
- end
- end
end
diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb
index 3a29c97461..1f10ca4b07 100644
--- a/spec/bundler/bundler/source/git/git_proxy_spec.rb
+++ b/spec/bundler/bundler/source/git/git_proxy_spec.rb
@@ -2,83 +2,145 @@
RSpec.describe Bundler::Source::Git::GitProxy do
let(:path) { Pathname("path") }
- let(:uri) { "https://github.com/bundler/bundler.git" }
- let(:ref) { "HEAD" }
+ let(:uri) { "https://github.com/ruby/rubygems.git" }
+ let(:ref) { nil }
+ let(:branch) { nil }
+ let(:tag) { nil }
+ let(:options) { { "ref" => ref, "branch" => branch, "tag" => tag }.compact }
let(:revision) { nil }
let(:git_source) { nil }
- subject { described_class.new(path, uri, ref, revision, git_source) }
+ let(:clone_result) { double(Process::Status, success?: true) }
+ let(:fail_result) { double(Process::Status, success?: false) }
+ let(:base_clone_args) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--depth", "1", "--single-branch"] }
+ let(:base_fetch_args) { ["fetch", "--force", "--quiet", "--no-tags", "--depth", "1"] }
+ subject(:git_proxy) { described_class.new(path, uri, options, revision, git_source) }
+
+ context "with explicit ref" do
+ context "with branch only" do
+ let(:branch) { "main" }
+ it "sets explicit ref to branch" do
+ expect(git_proxy.explicit_ref).to eq(branch)
+ end
+ end
+
+ context "with ref only" do
+ let(:ref) { "HEAD" }
+ it "sets explicit ref to ref" do
+ expect(git_proxy.explicit_ref).to eq(ref)
+ end
+ end
+
+ context "with tag only" do
+ let(:tag) { "v1.0" }
+ it "sets explicit ref to ref" do
+ expect(git_proxy.explicit_ref).to eq(tag)
+ end
+ end
+
+ context "with tag and branch" do
+ let(:tag) { "v1.0" }
+ let(:branch) { "main" }
+ it "raises error" do
+ expect { git_proxy }.to raise_error(Bundler::Source::Git::AmbiguousGitReference)
+ end
+ end
+
+ context "with tag and ref" do
+ let(:tag) { "v1.0" }
+ let(:ref) { "HEAD" }
+ it "raises error" do
+ expect { git_proxy }.to raise_error(Bundler::Source::Git::AmbiguousGitReference)
+ end
+ end
+
+ context "with branch and ref" do
+ let(:branch) { "main" }
+ let(:ref) { "HEAD" }
+ it "honors ref over branch" do
+ expect(git_proxy.explicit_ref).to eq(ref)
+ end
+ end
+ end
context "with configured credentials" do
it "adds username and password to URI" do
- Bundler.settings.temporary(uri => "u:p")
- expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git"))
- subject.checkout
+ Bundler.settings.temporary(uri => "u:p") do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
+ subject.checkout
+ end
end
it "adds username and password to URI for host" do
- Bundler.settings.temporary("github.com" => "u:p")
- expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git"))
- subject.checkout
+ Bundler.settings.temporary("github.com" => "u:p") do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
+ subject.checkout
+ end
end
it "does not add username and password to mismatched URI" do
- Bundler.settings.temporary("https://u:p@github.com/bundler/bundler-mismatch.git" => "u:p")
- expect(subject).to receive(:git_retry).with(match(uri))
- subject.checkout
+ Bundler.settings.temporary("https://u:p@github.com/ruby/rubygems-mismatch.git" => "u:p") do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
+ subject.checkout
+ end
end
it "keeps original userinfo" do
- Bundler.settings.temporary("github.com" => "u:p")
- original = "https://orig:info@github.com/bundler/bundler.git"
- subject = described_class.new(Pathname("path"), original, "HEAD")
- expect(subject).to receive(:git_retry).with(match(original))
- subject.checkout
+ Bundler.settings.temporary("github.com" => "u:p") do
+ original = "https://orig:info@github.com/ruby/rubygems.git"
+ git_proxy = described_class.new(Pathname("path"), original, options)
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", original, path.to_s], nil).and_return(["", "", clone_result])
+ git_proxy.checkout
+ end
end
end
describe "#version" do
context "with a normal version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(described_class).to receive(:full_version).
and_return("git version 1.2.3")
end
it "returns the git version number" do
- expect(subject.version).to eq("1.2.3")
+ expect(git_proxy.version).to eq("1.2.3")
end
it "does not raise an error when passed into Gem::Version.create" do
- expect { Gem::Version.create subject.version }.not_to raise_error
+ expect { Gem::Version.create git_proxy.version }.not_to raise_error
end
end
context "with a OSX version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(described_class).to receive(:full_version).
and_return("git version 1.2.3 (Apple Git-BS)")
end
it "strips out OSX specific additions in the version string" do
- expect(subject.version).to eq("1.2.3")
+ expect(git_proxy.version).to eq("1.2.3")
end
it "does not raise an error when passed into Gem::Version.create" do
- expect { Gem::Version.create subject.version }.not_to raise_error
+ expect { Gem::Version.create git_proxy.version }.not_to raise_error
end
end
context "with a msysgit version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(described_class).to receive(:full_version).
and_return("git version 1.2.3.msysgit.0")
end
it "strips out msysgit specific additions in the version string" do
- expect(subject.version).to eq("1.2.3")
+ expect(git_proxy.version).to eq("1.2.3")
end
it "does not raise an error when passed into Gem::Version.create" do
- expect { Gem::Version.create subject.version }.not_to raise_error
+ expect { Gem::Version.create git_proxy.version }.not_to raise_error
end
end
end
@@ -86,54 +148,206 @@ RSpec.describe Bundler::Source::Git::GitProxy do
describe "#full_version" do
context "with a normal version number" do
before do
- expect(subject).to receive(:git).with("--version").
- and_return("git version 1.2.3")
+ status = double("success?" => true)
+ expect(Open3).to receive(:capture3).with("git", "--version").
+ and_return(["git version 1.2.3", "", status])
end
it "returns the git version number" do
- expect(subject.full_version).to eq("1.2.3")
+ expect(git_proxy.full_version).to eq("1.2.3")
end
end
context "with a OSX version number" do
before do
- expect(subject).to receive(:git).with("--version").
- and_return("git version 1.2.3 (Apple Git-BS)")
+ status = double("success?" => true)
+ expect(Open3).to receive(:capture3).with("git", "--version").
+ and_return(["git version 1.2.3 (Apple Git-BS)", "", status])
end
it "does not strip out OSX specific additions in the version string" do
- expect(subject.full_version).to eq("1.2.3 (Apple Git-BS)")
+ expect(git_proxy.full_version).to eq("1.2.3 (Apple Git-BS)")
end
end
context "with a msysgit version number" do
before do
- expect(subject).to receive(:git).with("--version").
- and_return("git version 1.2.3.msysgit.0")
+ status = double("success?" => true)
+ expect(Open3).to receive(:capture3).with("git", "--version").
+ and_return(["git version 1.2.3.msysgit.0", "", status])
end
it "does not strip out msysgit specific additions in the version string" do
- expect(subject.full_version).to eq("1.2.3.msysgit.0")
+ expect(git_proxy.full_version).to eq("1.2.3.msysgit.0")
end
end
end
- describe "#copy_to" do
- let(:destination) { tmpdir("copy_to_path") }
- let(:submodules) { false }
+ it "doesn't allow arbitrary code execution through Gemfile uris with a leading dash" do
+ gemfile <<~G
+ gem "poc", git: "-u./pay:load.sh"
+ G
+
+ file = bundled_app("pay:load.sh")
+
+ create_file file, <<~RUBY
+ #!/bin/sh
- context "when given a SHA as a revision" do
- let(:revision) { "abcd" * 10 }
+ touch #{bundled_app("canary")}
+ RUBY
+
+ FileUtils.chmod("+x", file)
+
+ bundle :lock, raise_on_error: false
+
+ expect(Pathname.new(bundled_app("canary"))).not_to exist
+ end
+
+ context "URI is HTTP" do
+ let(:uri) { "http://github.com/ruby/rubygems.git" }
+ let(:clone_args_without_depth) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--single-branch"] }
+
+ it "retries clone without --depth when dumb http transport fails" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "dumb http transport does not support shallow capabilities", fail_result])
+ expect(git_proxy).to receive(:capture).with([*clone_args_without_depth, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
+
+ subject.checkout
+ end
+ end
+
+ describe "#installed_to?" do
+ let(:destination) { "install/dir" }
+ let(:destination_dir_exists) { true }
+ let(:children) { ["gem.gemspec", "README.me", ".git", "Rakefile"] }
+
+ before do
+ allow(Dir).to receive(:exist?).with(destination).and_return(destination_dir_exists)
+ allow(Dir).to receive(:children).with(destination).and_return(children)
+ end
+
+ context "when destination dir exists with children other than just .git" do
+ it "returns true" do
+ expect(git_proxy.installed_to?(destination)).to be true
+ end
+ end
+
+ context "when destination dir does not exist" do
+ let(:destination_dir_exists) { false }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+
+ context "when destination dir is empty" do
+ let(:children) { [] }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+
+ context "when destination dir has only .git directory" do
+ let(:children) { [".git"] }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+ end
+
+ describe "#checkout" do
+ context "when the repository isn't cloned" do
+ before do
+ allow(path).to receive(:exist?).and_return(false)
+ end
+
+ it "clones the repository" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+
+ context "when the repository is cloned" do
+ before do
+ allow(path).to receive(:exist?).and_return(true)
+ end
+
+ context "with a locked revision" do
+ let(:revision) { Digest::SHA1.hexdigest("ruby") }
+
+ context "when the revision exists locally" do
+ it "uses the cached revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", revision, dir: path).and_return(true)
+ subject.checkout
+ end
+ end
+
+ context "when the revision doesn't exist locally" do
+ it "fetches the specific revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", revision, dir: path).and_raise(Bundler::GitError)
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{revision}:refs/#{revision}-sha"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+ end
+
+ context "with no explicit ref" do
+ it "fetches the HEAD revision" do
+ parsed_revision = Digest::SHA1.hexdigest("ruby")
+ allow(git_proxy).to receive(:git_local).with("rev-parse", "--abbrev-ref", "HEAD", dir: path).and_return(parsed_revision)
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+
+ context "with a commit ref" do
+ let(:ref) { Digest::SHA1.hexdigest("ruby") }
+
+ context "when the revision exists locally" do
+ it "uses the cached revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", ref, dir: path).and_return(true)
+ subject.checkout
+ end
+ end
+
+ context "when the revision doesn't exist locally" do
+ it "fetches the specific revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", ref, dir: path).and_raise(Bundler::GitError)
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{ref}:refs/#{ref}-sha"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+ end
+
+ context "with a non-commit ref" do
+ let(:ref) { "HEAD" }
+
+ it "fetches all revisions" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--", uri, "refs/*:refs/*"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
- it "fails gracefully when resetting to the revision fails" do
- expect(subject).to receive(:git_retry).with(start_with("clone ")) { destination.mkpath }
- expect(subject).to receive(:git_retry).with(start_with("fetch "))
- expect(subject).to receive(:git).with("reset --hard #{revision}").and_raise(Bundler::Source::Git::GitCommandError, "command")
- expect(subject).not_to receive(:git)
+ context "URI is HTTP" do
+ let(:uri) { "http://github.com/ruby/rubygems.git" }
- expect { subject.copy_to(destination, submodules) }.
- to raise_error(Bundler::Source::Git::MissingGitRevisionError,
- "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?")
+ it "retries fetch without --depth when dumb http transport fails" do
+ parsed_revision = Digest::SHA1.hexdigest("ruby")
+ allow(git_proxy).to receive(:git_local).with("rev-parse", "--abbrev-ref", "HEAD", dir: path).and_return(parsed_revision)
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_fetch_args, "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "dumb http transport does not support shallow capabilities", fail_result])
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
end
end
end
diff --git a/spec/bundler/bundler/source/git_spec.rb b/spec/bundler/bundler/source/git_spec.rb
index f7475a35aa..14e91c6bdc 100644
--- a/spec/bundler/bundler/source/git_spec.rb
+++ b/spec/bundler/bundler/source/git_spec.rb
@@ -14,14 +14,109 @@ RSpec.describe Bundler::Source::Git do
describe "#to_s" do
it "returns a description" do
- expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git"
end
context "when the URI contains credentials" do
let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" }
it "filters credentials" do
- expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git"
+ end
+ end
+
+ context "when the source has a glob specifier" do
+ let(:glob) { "bar/baz/*.gemspec" }
+ let(:options) do
+ { "uri" => uri, "glob" => glob }
+ end
+
+ it "includes it" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (glob: bar/baz/*.gemspec)"
+ end
+ end
+
+ context "when the source has a reference" do
+ let(:git_proxy_stub) do
+ instance_double(Bundler::Source::Git::GitProxy, revision: "123abc", branch: "v1.0.0")
+ end
+ let(:options) do
+ { "uri" => uri, "ref" => "v1.0.0" }
+ end
+
+ before do
+ allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
+ end
+
+ it "includes it" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc)"
+ end
+ end
+
+ context "when the source has both reference and glob specifiers" do
+ let(:git_proxy_stub) do
+ instance_double(Bundler::Source::Git::GitProxy, revision: "123abc", branch: "v1.0.0")
+ end
+ let(:options) do
+ { "uri" => uri, "ref" => "v1.0.0", "glob" => "gems/foo/*.gemspec" }
+ end
+
+ before do
+ allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
+ end
+
+ it "includes both" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc, glob: gems/foo/*.gemspec)"
+ end
+ end
+ end
+
+ describe "#locked_revision_checked_out?" do
+ let(:revision) { "abc" }
+ let(:git_proxy_revision) { revision }
+ let(:git_proxy_installed) { true }
+ let(:git_proxy) { subject.send(:git_proxy) }
+ let(:options) do
+ {
+ "uri" => uri,
+ "revision" => revision,
+ }
+ end
+
+ before do
+ allow(git_proxy).to receive(:revision).and_return(git_proxy_revision)
+ allow(git_proxy).to receive(:installed_to?).with(subject.install_path).and_return(git_proxy_installed)
+ end
+
+ context "when the locked revision is checked out" do
+ it "returns true" do
+ expect(subject.send(:locked_revision_checked_out?)).to be true
+ end
+ end
+
+ context "when no revision is provided" do
+ let(:options) do
+ { "uri" => uri }
+ end
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
+ end
+ end
+
+ context "when the git proxy revision is different than the git revision" do
+ let(:git_proxy_revision) { revision.next }
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
+ end
+ end
+
+ context "when the gem hasn't been installed" do
+ let(:git_proxy_installed) { false }
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
end
end
end
diff --git a/spec/bundler/bundler/source/rubygems/remote_spec.rb b/spec/bundler/bundler/source/rubygems/remote_spec.rb
index 9a7ab42128..27430d4a3b 100644
--- a/spec/bundler/bundler/source/rubygems/remote_spec.rb
+++ b/spec/bundler/bundler/source/rubygems/remote_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
allow(Digest(:MD5)).to receive(:hexdigest).with(duck_type(:to_s)) {|string| "MD5HEX(#{string})" }
end
- let(:uri_no_auth) { URI("https://gems.example.com") }
- let(:uri_with_auth) { URI("https://#{credentials}@gems.example.com") }
+ let(:uri_no_auth) { Gem::URI("https://gems.example.com") }
+ let(:uri_with_auth) { Gem::URI("https://#{credentials}@gems.example.com") }
let(:credentials) { "username:password" }
context "when the original URI has no credentials" do
@@ -22,8 +22,9 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
it "applies configured credentials" do
- Bundler.settings.temporary(uri_no_auth.to_s => credentials)
- expect(remote(uri_no_auth).uri).to eq(uri_with_auth)
+ Bundler.settings.temporary(uri_no_auth.to_s => credentials) do
+ expect(remote(uri_no_auth).uri).to eq(uri_with_auth)
+ end
end
end
@@ -33,8 +34,9 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
it "does not apply given credentials" do
- Bundler.settings.temporary(uri_no_auth.to_s => credentials)
- expect(remote(uri_no_auth).anonymized_uri).to eq(uri_no_auth)
+ Bundler.settings.temporary(uri_no_auth.to_s => credentials) do
+ expect(remote(uri_no_auth).anonymized_uri).to eq(uri_no_auth)
+ end
end
end
@@ -44,8 +46,9 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
it "only applies the given user" do
- Bundler.settings.temporary(uri_no_auth.to_s => credentials)
- expect(remote(uri_no_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)")
+ Bundler.settings.temporary(uri_no_auth.to_s => credentials) do
+ expect(remote(uri_no_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)")
+ end
end
end
end
@@ -86,11 +89,11 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
context "when the original URI has only a username" do
- let(:uri) { URI("https://SeCrEt-ToKeN@gem.fury.io/me/") }
+ let(:uri) { Gem::URI("https://SeCrEt-ToKeN@gem.fury.io/me/") }
describe "#anonymized_uri" do
it "returns the URI without username and password" do
- expect(remote(uri).anonymized_uri).to eq(URI("https://gem.fury.io/me/"))
+ expect(remote(uri).anonymized_uri).to eq(Gem::URI("https://gem.fury.io/me/"))
end
end
@@ -102,11 +105,13 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
context "when a mirror with inline credentials is configured for the URI" do
- let(:uri) { URI("https://rubygems.org/") }
- let(:mirror_uri_with_auth) { URI("https://username:password@rubygems-mirror.org/") }
- let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") }
+ let(:uri) { Gem::URI("https://rubygems.org/") }
+ let(:mirror_uri_with_auth) { Gem::URI("https://username:password@example-mirror.rubygems.org/") }
+ let(:mirror_uri_no_auth) { Gem::URI("https://example-mirror.rubygems.org/") }
+
+ before { Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_with_auth.to_s) }
- before { Bundler.settings.set_local("mirror.https://rubygems.org/", mirror_uri_with_auth.to_s) }
+ after { Bundler.settings.temporary("mirror.https://rubygems.org/" => nil) }
specify "#uri returns the mirror URI with credentials" do
expect(remote(uri).uri).to eq(mirror_uri_with_auth)
@@ -126,15 +131,20 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
context "when a mirror with configured credentials is configured for the URI" do
- let(:uri) { URI("https://rubygems.org/") }
- let(:mirror_uri_with_auth) { URI("https://#{credentials}@rubygems-mirror.org/") }
- let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") }
+ let(:uri) { Gem::URI("https://rubygems.org/") }
+ let(:mirror_uri_with_auth) { Gem::URI("https://#{credentials}@example-mirror.rubygems.org/") }
+ let(:mirror_uri_no_auth) { Gem::URI("https://example-mirror.rubygems.org/") }
before do
Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_no_auth.to_s)
Bundler.settings.temporary(mirror_uri_no_auth.to_s => credentials)
end
+ after do
+ Bundler.settings.temporary("mirror.https://rubygems.org/" => nil)
+ Bundler.settings.temporary(mirror_uri_no_auth.to_s => nil)
+ end
+
specify "#uri returns the mirror URI with credentials" do
expect(remote(uri).uri).to eq(mirror_uri_with_auth)
end
@@ -159,4 +169,39 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
end
end
end
+
+ describe "#cooldown" do
+ it "is nil by default" do
+ expect(remote(uri_no_auth).cooldown).to be_nil
+ end
+
+ it "returns the value passed to the constructor" do
+ r = Bundler::Source::Rubygems::Remote.new(uri_no_auth, cooldown: 7)
+ expect(r.cooldown).to eq(7)
+ end
+ end
+
+ describe "#effective_cooldown" do
+ it "returns the per-remote value when no override is set" do
+ r = Bundler::Source::Rubygems::Remote.new(uri_no_auth, cooldown: 7)
+ expect(r.effective_cooldown).to eq(7)
+ end
+
+ it "returns nil when neither override nor per-remote value is set" do
+ expect(remote(uri_no_auth).effective_cooldown).to be_nil
+ end
+
+ it "settings override per-remote value" do
+ r = Bundler::Source::Rubygems::Remote.new(uri_no_auth, cooldown: 7)
+ Bundler.settings.temporary(cooldown: 14) do
+ expect(r.effective_cooldown).to eq(14)
+ end
+ end
+
+ it "settings override even when per-remote value is absent" do
+ Bundler.settings.temporary(cooldown: 14) do
+ expect(remote(uri_no_auth).effective_cooldown).to eq(14)
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source/rubygems_spec.rb b/spec/bundler/bundler/source/rubygems_spec.rb
index 7c457a7265..feb787498e 100644
--- a/spec/bundler/bundler/source/rubygems_spec.rb
+++ b/spec/bundler/bundler/source/rubygems_spec.rb
@@ -30,4 +30,75 @@ RSpec.describe Bundler::Source::Rubygems do
end
end
end
+
+ describe "#no_remotes?" do
+ context "when no remote provided" do
+ it "returns a truthy value" do
+ expect(described_class.new("remotes" => []).no_remotes?).to be_truthy
+ end
+ end
+
+ context "when a remote provided" do
+ it "returns a falsey value" do
+ expect(described_class.new("remotes" => ["https://rubygems.org"]).no_remotes?).to be_falsey
+ end
+ end
+ end
+
+ describe "#clear_cache" do
+ it "invalidates memoized indexes so subsequent reads rebuild them" do
+ source = described_class.new
+
+ first_specs = source.specs
+ first_installed = source.send(:installed_specs)
+ first_default = source.send(:default_specs)
+ first_cached = source.send(:cached_specs)
+
+ expect(source.specs).to equal(first_specs)
+ expect(source.send(:installed_specs)).to equal(first_installed)
+ expect(source.send(:default_specs)).to equal(first_default)
+ expect(source.send(:cached_specs)).to equal(first_cached)
+
+ source.clear_cache
+
+ expect(source.specs).not_to equal(first_specs)
+ expect(source.send(:installed_specs)).not_to equal(first_installed)
+ expect(source.send(:default_specs)).not_to equal(first_default)
+ expect(source.send(:cached_specs)).not_to equal(first_cached)
+ end
+
+ it "reflects newly-discovered installed gems after clear_cache" do
+ source = described_class.new
+ foo = Gem::Specification.new("foo", "1.0.0")
+ bar = Gem::Specification.new("bar", "1.0.0")
+
+ allow(Bundler.rubygems).to receive(:installed_specs).and_return([foo])
+ expect(source.send(:installed_specs).search("bar")).to be_empty
+
+ allow(Bundler.rubygems).to receive(:installed_specs).and_return([foo, bar])
+ expect(source.send(:installed_specs).search("bar")).to be_empty
+
+ source.clear_cache
+
+ expect(source.send(:installed_specs).search("bar")).not_to be_empty
+ end
+ end
+
+ describe "log debug information" do
+ it "log the time spent downloading and installing a gem" do
+ build_repo2 do
+ build_gem "warning"
+ end
+
+ gemfile_content = <<~G
+ source "https://gem.repo2"
+ gem "warning"
+ G
+
+ stdout = install_gemfile(gemfile_content, env: { "DEBUG" => "1" })
+
+ expect(stdout).to match(/Downloaded warning in: \d+\.\d+s/)
+ expect(stdout).to match(/Installed warning in: \d+\.\d+s/)
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb
index 541a46c6d0..61bd99b063 100644
--- a/spec/bundler/bundler/source_list_spec.rb
+++ b/spec/bundler/bundler/source_list_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Bundler::SourceList do
subject(:source_list) { Bundler::SourceList.new }
- let(:rubygems_aggregate) { Bundler::Source::Rubygems.new }
+ let(:global_rubygems_source) { Bundler::Source::Rubygems.new }
let(:metadata_source) { Bundler::Source::Metadata.new }
describe "adding sources" do
@@ -75,7 +75,7 @@ RSpec.describe Bundler::SourceList do
let(:msg) do
"The git source `git://existing-git.org/path.git` " \
"uses the `git` protocol, which transmits data without encryption. " \
- "Disable this warning with `bundle config git.allow_insecure true`, " \
+ "Disable this warning with `bundle config set --local git.allow_insecure true`, " \
"or switch to the `https` protocol to keep your data secure."
end
@@ -85,7 +85,7 @@ RSpec.describe Bundler::SourceList do
end
it "ignores git protocols on request" do
- Bundler.settings.temporary(:"git.allow_insecure" => true)
+ Bundler.settings.temporary("git.allow_insecure": true)
expect(Bundler.ui).to_not receive(:warn).with(msg)
source_list.add_git_source("uri" => "git://existing-git.org/path.git")
end
@@ -115,20 +115,26 @@ RSpec.describe Bundler::SourceList do
end
end
- describe "#add_rubygems_remote", :bundler => "< 3" do
- let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") }
+ describe "#add_global_rubygems_remote" do
+ let!(:returned_source) { source_list.add_global_rubygems_remote("https://rubygems.org/") }
- it "returns the aggregate rubygems source" do
+ it "returns the global rubygems source" do
expect(returned_source).to be_instance_of(Bundler::Source::Rubygems)
end
- it "adds the provided remote to the beginning of the aggregate source" do
- source_list.add_rubygems_remote("https://othersource.org")
+ it "adds the provided remote to the beginning of the global source" do
+ source_list.add_global_rubygems_remote("https://othersource.org")
expect(returned_source.remotes).to eq [
- URI("https://othersource.org/"),
- URI("https://rubygems.org/"),
+ Gem::URI("https://othersource.org/"),
+ Gem::URI("https://rubygems.org/"),
]
end
+
+ it "records the per-remote cooldown when supplied" do
+ source_list.add_global_rubygems_remote("https://othersource.org", cooldown: 7)
+ expect(returned_source.cooldown_for(Gem::URI("https://othersource.org/"))).to eq(7)
+ expect(returned_source.cooldown_for(Gem::URI("https://rubygems.org/"))).to be_nil
+ end
end
describe "#add_plugin_source" do
@@ -156,21 +162,21 @@ RSpec.describe Bundler::SourceList do
end
describe "#all_sources" do
- it "includes the aggregate rubygems source when rubygems sources have been added" do
+ it "includes the global rubygems source when rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_rubygems_source("remotes" => ["https://rubygems.org"])
source_list.add_path_source("path" => "/path/to/gem")
source_list.add_plugin_source("new_source", "uri" => "https://some.url/a")
- expect(source_list.all_sources).to include rubygems_aggregate
+ expect(source_list.all_sources).to include global_rubygems_source
end
- it "includes the aggregate rubygems source when no rubygems sources have been added" do
+ it "includes the global rubygems source when no rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_path_source("path" => "/path/to/gem")
source_list.add_plugin_source("new_source", "uri" => "https://some.url/a")
- expect(source_list.all_sources).to include rubygems_aggregate
+ expect(source_list.all_sources).to include global_rubygems_source
end
it "returns sources of the same type in the reverse order that they were added" do
@@ -204,7 +210,7 @@ RSpec.describe Bundler::SourceList do
Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]),
- rubygems_aggregate,
+ global_rubygems_source,
metadata_source,
]
end
@@ -212,22 +218,22 @@ RSpec.describe Bundler::SourceList do
describe "#path_sources" do
it "returns an empty array when no path sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_git_source("uri" => "git://host/path.git")
expect(source_list.path_sources).to be_empty
end
it "returns path sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.path_sources).to eq [
@@ -240,7 +246,7 @@ RSpec.describe Bundler::SourceList do
describe "#git_sources" do
it "returns an empty array when no git sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.git_sources).to be_empty
@@ -248,15 +254,15 @@ RSpec.describe Bundler::SourceList do
it "returns git sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.git_sources).to eq [
@@ -269,7 +275,7 @@ RSpec.describe Bundler::SourceList do
describe "#plugin_sources" do
it "returns an empty array when no plugin sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.plugin_sources).to be_empty
@@ -279,13 +285,13 @@ RSpec.describe Bundler::SourceList do
source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git")
source_list.add_git_source("https://new-git.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git")
expect(source_list.plugin_sources).to eq [
@@ -297,19 +303,19 @@ RSpec.describe Bundler::SourceList do
end
describe "#rubygems_sources" do
- it "includes the aggregate rubygems source when rubygems sources have been added" do
+ it "includes the global rubygems source when rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_rubygems_source("remotes" => ["https://rubygems.org"])
source_list.add_path_source("path" => "/path/to/gem")
- expect(source_list.rubygems_sources).to include rubygems_aggregate
+ expect(source_list.rubygems_sources).to include global_rubygems_source
end
- it "returns only the aggregate rubygems source when no rubygems sources have been added" do
+ it "returns only the global rubygems source when no rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_path_source("path" => "/path/to/gem")
- expect(source_list.rubygems_sources).to eq [rubygems_aggregate]
+ expect(source_list.rubygems_sources).to eq [global_rubygems_source]
end
it "returns rubygems sources in the reverse order that they were added" do
@@ -331,7 +337,7 @@ RSpec.describe Bundler::SourceList do
Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]),
- rubygems_aggregate,
+ global_rubygems_source,
]
end
end
@@ -339,7 +345,7 @@ RSpec.describe Bundler::SourceList do
describe "#get" do
context "when it includes an equal source" do
let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) }
- before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") }
+ before { @equal_source = source_list.add_global_rubygems_remote("https://rubygems.org") }
it "returns the equal source" do
expect(source_list.get(rubygems_source)).to be @equal_source
@@ -372,7 +378,7 @@ RSpec.describe Bundler::SourceList do
source_list.add_git_source("uri" => "git://first-git.org/path.git")
end
- it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do
+ it "returns all sources, without combining rubygems sources" do
expect(source_list.lock_sources).to eq [
Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
@@ -382,30 +388,11 @@ RSpec.describe Bundler::SourceList do
Bundler::Source::Path.new("path" => "/first/path/to/gem"),
Bundler::Source::Path.new("path" => "/second/path/to/gem"),
Bundler::Source::Path.new("path" => "/third/path/to/gem"),
- Bundler::Source::Rubygems.new("remotes" => [
- "https://duplicate-rubygems.org",
- "https://first-rubygems.org",
- "https://second-rubygems.org",
- "https://third-rubygems.org",
- ]),
- ]
- end
-
- it "returns all sources, without combining rubygems sources", :bundler => "3" do
- expect(source_list.lock_sources).to eq [
Bundler::Source::Rubygems.new,
Bundler::Source::Rubygems.new("remotes" => ["https://duplicate-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://first-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://second-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]),
- Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"),
- Bundler::Source::Path.new("path" => "/first/path/to/gem"),
- Bundler::Source::Path.new("path" => "/second/path/to/gem"),
- Bundler::Source::Path.new("path" => "/third/path/to/gem"),
- ASourcePlugin.new("uri" => "https://second-plugin.org/random"),
- ASourcePlugin.new("uri" => "https://third-bar.org/foo"),
]
end
end
@@ -460,4 +447,29 @@ RSpec.describe Bundler::SourceList do
source_list.remote!
end
end
+
+ describe "#clear_cache" do
+ let(:rubygems_source) { source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) }
+
+ it "calls #clear_cache on all rubygems sources" do
+ expect(rubygems_source).to receive(:clear_cache)
+ expect(source_list.global_rubygems_source).to receive(:clear_cache)
+ source_list.clear_cache
+ end
+ end
+
+ describe "implicit_global_source?" do
+ context "when a global rubygem source provided" do
+ it "returns a falsy value" do
+ source_list.add_global_rubygems_remote("https://rubygems.org")
+
+ expect(source_list.implicit_global_source?).to be_falsey
+ end
+ end
+ context "when no global rubygem source provided" do
+ it "returns a truthy value" do
+ expect(source_list.implicit_global_source?).to be_truthy
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb
index 9ef8e7e50f..01b57ce9e8 100644
--- a/spec/bundler/bundler/source_spec.rb
+++ b/spec/bundler/bundler/source_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Bundler::Source do
end
describe "#version_message" do
- let(:spec) { double(:spec, :name => "nokogiri", :version => ">= 1.6", :platform => rb) }
+ let(:spec) { double(:spec, name: "nokogiri", version: ">= 1.6", platform: Gem::Platform::RUBY) }
shared_examples_for "the lockfile specs are not relevant" do
it "should return a string with the spec name and version" do
@@ -30,95 +30,105 @@ RSpec.describe Bundler::Source do
end
context "when there are locked gems" do
- let(:locked_gems) { double(:locked_gems) }
-
- before { allow(Bundler).to receive(:locked_gems).and_return(locked_gems) }
-
context "that contain the relevant gem spec" do
- before do
- specs = double(:specs)
- allow(locked_gems).to receive(:specs).and_return(specs)
- allow(specs).to receive(:find).and_return(locked_gem)
- end
-
context "without a version" do
- let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => nil) }
+ let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: nil) }
it_behaves_like "the lockfile specs are not relevant"
end
context "with the same version" do
- let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => ">= 1.6") }
+ let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: ">= 1.6") }
it_behaves_like "the lockfile specs are not relevant"
end
context "with a different version" do
- let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "< 1.5") }
+ let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: "< 1.5") }
- context "with color" do
- before { Bundler.ui = Bundler::UI::Shell.new }
+ context "with color", :no_color_tty do
+ before do
+ allow($stdout).to receive(:tty?).and_return(true)
+ end
it "should return a string with the spec name and version and locked spec version" do
- expect(subject.version_message(spec)).to eq("nokogiri >= 1.6\e[32m (was < 1.5)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri >= 1.6\e[32m (was < 1.5)\e[0m")
end
end
context "without color" do
+ around do |example|
+ with_ui(Bundler::UI::Shell.new("no-color" => true)) do
+ example.run
+ end
+ end
+
it "should return a string with the spec name and version and locked spec version" do
- expect(subject.version_message(spec)).to eq("nokogiri >= 1.6 (was < 1.5)")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri >= 1.6 (was < 1.5)")
end
end
end
context "with a more recent version" do
- let(:spec) { double(:spec, :name => "nokogiri", :version => "1.6.1", :platform => rb) }
- let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "1.7.0") }
+ let(:spec) { double(:spec, name: "nokogiri", version: "1.6.1", platform: Gem::Platform::RUBY) }
+ let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: "1.7.0") }
+
+ context "with color", :no_color_tty do
+ before do
+ allow($stdout).to receive(:tty?).and_return(true)
+ end
+
+ it "should return a string with the locked spec version in yellow" do
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.6.1\e[33m (was 1.7.0)\e[0m")
+ end
+ end
- context "with color" do
- before { Bundler.ui = Bundler::UI::Shell.new }
+ context "without color" do
+ around do |example|
+ with_ui(Bundler::UI::Shell.new("no-color" => true)) do
+ example.run
+ end
+ end
it "should return a string with the locked spec version in yellow" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.6.1\e[33m (was 1.7.0)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.6.1 (was 1.7.0)")
end
end
end
context "with an older version" do
- let(:spec) { double(:spec, :name => "nokogiri", :version => "1.7.1", :platform => rb) }
- let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "1.7.0") }
+ let(:spec) { double(:spec, name: "nokogiri", version: "1.7.1", platform: Gem::Platform::RUBY) }
+ let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: "1.7.0") }
- context "with color" do
- before { Bundler.ui = Bundler::UI::Shell.new }
+ context "with color", :no_color_tty do
+ before do
+ allow($stdout).to receive(:tty?).and_return(true)
+ end
it "should return a string with the locked spec version in green" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.7.1\e[32m (was 1.7.0)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.7.1\e[32m (was 1.7.0)\e[0m")
end
end
- end
- end
- context "that do not contain the relevant gem spec" do
- before do
- specs = double(:specs)
- allow(locked_gems).to receive(:specs).and_return(specs)
- allow(specs).to receive(:find).and_return(nil)
- end
+ context "without color" do
+ around do |example|
+ with_ui(Bundler::UI::Shell.new("no-color" => true)) do
+ example.run
+ end
+ end
- it_behaves_like "the lockfile specs are not relevant"
+ it "should return a string with the locked spec version in yellow" do
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.7.1 (was 1.7.0)")
+ end
+ end
+ end
end
end
-
- context "when there are no locked gems" do
- before { allow(Bundler).to receive(:locked_gems).and_return(nil) }
-
- it_behaves_like "the lockfile specs are not relevant"
- end
end
describe "#can_lock?" do
context "when the passed spec's source is equivalent" do
- let(:spec) { double(:spec, :source => subject) }
+ let(:spec) { double(:spec, source: subject) }
it "should return true" do
expect(subject.can_lock?(spec)).to be_truthy
@@ -126,7 +136,7 @@ RSpec.describe Bundler::Source do
end
context "when the passed spec's source is not equivalent" do
- let(:spec) { double(:spec, :source => double(:other_source)) }
+ let(:spec) { double(:spec, source: double(:other_source)) }
it "should return false" do
expect(subject.can_lock?(spec)).to be_falsey
@@ -151,4 +161,14 @@ RSpec.describe Bundler::Source do
end
end
end
+
+ private
+
+ def with_ui(ui)
+ old_ui = Bundler.ui
+ Bundler.ui = ui
+ yield
+ ensure
+ Bundler.ui = old_ui
+ end
end
diff --git a/spec/bundler/bundler/spec_set_spec.rb b/spec/bundler/bundler/spec_set_spec.rb
index 6fedd38b50..1e1ceadf26 100644
--- a/spec/bundler/bundler/spec_set_spec.rb
+++ b/spec/bundler/bundler/spec_set_spec.rb
@@ -43,23 +43,29 @@ RSpec.describe Bundler::SpecSet do
spec = described_class.new(specs).find_by_name_and_platform("b", platform)
expect(spec).to eq platform_spec
end
- end
- describe "#merge" do
- let(:other_specs) do
- [
- build_spec("f", "1.0"),
- build_spec("g", "2.0"),
- ].flatten
+ it "returns nil when the name is not present" do
+ spec = described_class.new(specs).find_by_name_and_platform("missing", platform)
+ expect(spec).to be_nil
end
- let(:other_spec_set) { described_class.new(other_specs) }
+ it "returns nil when the name exists but no spec is installable on the requested platform" do
+ incompatible_platform = Gem::Platform.new("java")
+ incompatible_spec = build_spec("a", "1.0", incompatible_platform).first
- it "merges the items in each gemspec" do
- new_spec_set = subject.merge(other_spec_set)
- specs = new_spec_set.to_a.map(&:full_name)
- expect(specs).to include("a-1.0")
- expect(specs).to include("f-1.0")
+ spec = described_class.new([incompatible_spec]).find_by_name_and_platform("a", platform)
+ expect(spec).to be_nil
+ end
+
+ it "returns the first installable spec for the given name in insertion order" do
+ later_platform_spec = build_spec("b", "3.0", platform).first
+ specs = [
+ platform_spec,
+ later_platform_spec,
+ ]
+
+ spec = described_class.new(specs).find_by_name_and_platform("b", platform)
+ expect(spec).to eq platform_spec
end
end
@@ -73,5 +79,70 @@ RSpec.describe Bundler::SpecSet do
d-2.0
]
end
+
+ it "puts rake first when present" do
+ specs = [
+ build_spec("a", "1.0") {|s| s.dep "rake", ">= 0" },
+ build_spec("rake", "13.0"),
+ ].flatten
+
+ expect(described_class.new(specs).to_a.map(&:full_name)).to eq %w[
+ rake-13.0
+ a-1.0
+ ]
+ end
+ end
+
+ describe "#complete_platform" do
+ let(:platform) { Gem::Platform.new("x86_64-linux") }
+
+ let(:platform_variant) do
+ build_spec("needs_old_ruby", "1.0", platform).first.tap do |s|
+ s.required_ruby_version = Gem::Requirement.new("< #{Gem.ruby_version}")
+ end
+ end
+
+ let(:lazy_spec) do
+ lazy = Bundler::LazySpecification.new("needs_old_ruby", Gem::Version.new("1.0"), Gem::Platform::RUBY)
+ lazy.required_ruby_version = Gem::Requirement.new("< #{Gem.ruby_version}")
+ source = double("source")
+ source_specs = double("source_specs")
+ allow(source).to receive(:specs).and_return(source_specs)
+ allow(source_specs).to receive(:search).
+ with(["needs_old_ruby", Gem::Version.new("1.0")]).and_return([platform_variant])
+ lazy.source = source
+ lazy
+ end
+
+ it "rejects a platform variant whose strict metadata is incompatible when no override is attached" do
+ set = described_class.new([lazy_spec])
+ expect(set.send(:complete_platform, platform)).to be(false)
+ end
+
+ it "accepts a platform variant when the LazySpec carries an override that allows it" do
+ lazy_spec.overrides = [Bundler::Override.new("needs_old_ruby", :required_ruby_version, :ignore_upper)]
+ set = described_class.new([lazy_spec])
+ expect(set.send(:complete_platform, platform)).to be(true)
+ end
+
+ it "carries overrides onto a synthesized LazySpec so a follow-up complete_platform still honors them" do
+ override = Bundler::Override.new("needs_old_ruby", :required_ruby_version, :ignore_upper)
+ lazy_spec.overrides = [override]
+ second_platform = Gem::Platform.new("aarch64-linux")
+ second_variant = build_spec("needs_old_ruby", "1.0", second_platform).first.tap do |s|
+ s.required_ruby_version = Gem::Requirement.new("< #{Gem.ruby_version}")
+ end
+ allow(lazy_spec.source.specs).to receive(:search).
+ with(["needs_old_ruby", Gem::Version.new("1.0")]).and_return([platform_variant, second_variant])
+
+ set = described_class.new([lazy_spec])
+ expect(set.send(:complete_platform, platform)).to be(true)
+ # The synthesized x86_64-linux variant is now in the set. If lookup
+ # picks it as exemplar for the next platform check, the override list
+ # must still be reachable via its overrides accessor.
+ synthesized = set.to_a.find {|s| s.platform == platform }
+ expect(synthesized.overrides).to eq([override])
+ expect(set.send(:complete_platform, second_platform)).to be(true)
+ end
end
end
diff --git a/spec/bundler/bundler/specifications/foo.gemspec b/spec/bundler/bundler/specifications/foo.gemspec
new file mode 100644
index 0000000000..19b7724e81
--- /dev/null
+++ b/spec/bundler/bundler/specifications/foo.gemspec
@@ -0,0 +1,13 @@
+# rubocop:disable Style/FrozenStringLiteralComment
+# stub: foo 1.0.0 ruby lib
+
+# The first line would be '# -*- encoding: utf-8 -*-' in a real stub gemspec
+
+Gem::Specification.new do |s|
+ s.name = "foo"
+ s.version = "1.0.0"
+ s.loaded_from = __FILE__
+ s.extensions = "ext/foo"
+ s.required_ruby_version = ">= 3.2.0"
+end
+# rubocop:enable Style/FrozenStringLiteralComment
diff --git a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb b/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb
deleted file mode 100644
index 56606a830f..0000000000
--- a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/ssl_certs/certificate_manager"
-
-RSpec.describe Bundler::SSLCerts::CertificateManager do
- let(:rubygems_path) { root }
- let(:stub_cert) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem") }
- let(:rubygems_certs_dir) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org") }
-
- subject { described_class.new(rubygems_path) }
-
- # Pretend bundler root is rubygems root
- before do
- # Backing up rubygems ceriticates
- FileUtils.mv(rubygems_certs_dir, rubygems_certs_dir + ".back") if ruby_core?
-
- FileUtils.mkdir_p(rubygems_certs_dir)
- FileUtils.touch(stub_cert)
- end
-
- after do
- FileUtils.rm_rf(rubygems_certs_dir)
-
- # Restore rubygems certificates
- FileUtils.mv(rubygems_certs_dir + ".back", rubygems_certs_dir) if ruby_core?
- end
-
- describe "#update_from" do
- let(:cert_manager) { double(:cert_manager) }
-
- before { allow(described_class).to receive(:new).with(rubygems_path).and_return(cert_manager) }
-
- it "should update the certs through a new certificate manager" do
- allow(cert_manager).to receive(:update!)
- expect(described_class.update_from!(rubygems_path)).to be_nil
- end
- end
-
- describe "#initialize" do
- it "should set bundler_cert_path as path of the subdir with bundler ssl certs" do
- expect(subject.bundler_cert_path).to eq(File.join(root, "lib/bundler/ssl_certs"))
- end
-
- it "should set bundler_certs as the paths of the bundler ssl certs" do
- expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem"))
- expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem"))
- end
-
- context "when rubygems_path is not nil" do
- it "should set rubygems_certs" do
- expect(subject.rubygems_certs).to include(File.join(root, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem"))
- end
- end
- end
-
- describe "#up_to_date?" do
- context "when bundler certs and rubygems certs are the same" do
- before do
- bundler_certs = Dir[File.join(root.to_s, "lib", "bundler", "ssl_certs", "**", "*.pem")]
- FileUtils.rm(stub_cert)
- FileUtils.cp(bundler_certs, rubygems_certs_dir)
- end
-
- it "should return true" do
- expect(subject).to be_up_to_date
- end
- end
-
- context "when bundler certs and rubygems certs are not the same" do
- it "should return false" do
- expect(subject).to_not be_up_to_date
- end
- end
- end
-
- describe "#update!" do
- context "when certificate manager is not up to date" do
- before do
- allow(subject).to receive(:up_to_date?).and_return(false)
- allow(bundler_fileutils).to receive(:rm)
- allow(bundler_fileutils).to receive(:cp)
- end
-
- it "should remove the current bundler certs" do
- expect(bundler_fileutils).to receive(:rm).with(subject.bundler_certs)
- subject.update!
- end
-
- it "should copy the rubygems certs into bundler certs" do
- expect(bundler_fileutils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path)
- subject.update!
- end
-
- it "should return nil" do
- expect(subject.update!).to be_nil
- end
- end
-
- context "when certificate manager is up to date" do
- before { allow(subject).to receive(:up_to_date?).and_return(true) }
-
- it "should return nil" do
- expect(subject.update!).to be_nil
- end
- end
- end
-
- describe "#connect_to" do
- let(:host) { "http://www.host.com" }
- let(:http) { Net::HTTP.new(host, 443) }
- let(:cert_store) { OpenSSL::X509::Store.new }
- let(:http_header_response) { double(:http_header_response) }
-
- before do
- allow(Net::HTTP).to receive(:new).with(host, 443).and_return(http)
- allow(OpenSSL::X509::Store).to receive(:new).and_return(cert_store)
- allow(http).to receive(:head).with("/").and_return(http_header_response)
- end
-
- it "should use ssl for the http request" do
- expect(http).to receive(:use_ssl=).with(true)
- subject.connect_to(host)
- end
-
- it "use verify peer mode" do
- expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
- subject.connect_to(host)
- end
-
- it "set its cert store as a OpenSSL::X509::Store populated with bundler certs" do
- expect(cert_store).to receive(:add_file).at_least(:once)
- expect(http).to receive(:cert_store=).with(cert_store)
- subject.connect_to(host)
- end
-
- it "return the headers of the request response" do
- expect(subject.connect_to(host)).to eq(http_header_response)
- end
- end
-end
diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb
index 5521d83769..f2faa2ea64 100644
--- a/spec/bundler/bundler/stub_specification_spec.rb
+++ b/spec/bundler/bundler/stub_specification_spec.rb
@@ -1,24 +1,82 @@
# frozen_string_literal: true
RSpec.describe Bundler::StubSpecification do
- let(:gemspec) do
- Gem::Specification.new do |s|
+ let(:with_bundler_stub_spec) do
+ gemspec = Gem::Specification.new do |s|
s.name = "gemname"
s.version = "1.0.0"
s.loaded_from = __FILE__
+ s.extensions = "ext/gemname"
end
- end
- let(:with_bundler_stub_spec) do
described_class.from_stub(gemspec)
end
- if Bundler.rubygems.provides?(">= 2.1")
- describe "#from_stub" do
- it "returns the same stub if already a Bundler::StubSpecification" do
- stub = described_class.from_stub(with_bundler_stub_spec)
- expect(stub).to be(with_bundler_stub_spec)
+ describe "#from_stub" do
+ it "returns the same stub if already a Bundler::StubSpecification" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub).to be(with_bundler_stub_spec)
+ end
+ end
+
+ describe "#gem_build_complete_path" do
+ it "StubSpecification should have equal gem_build_complete_path as Specification" do
+ spec_path = File.join(File.dirname(__FILE__), "specifications", "foo.gemspec")
+ spec = Gem::Specification.load(spec_path)
+ gem_stub = Gem::StubSpecification.new(spec_path, File.dirname(__FILE__),"","")
+
+ stub = described_class.from_stub(gem_stub)
+ expect(stub.gem_build_complete_path).to eq spec.gem_build_complete_path
+ end
+ end
+
+ describe "#manually_installed?" do
+ it "returns true if installed_by_version is nil or 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.manually_installed?).to be true
+ end
+
+ it "returns false if installed_by_version is greater than 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ expect(stub.manually_installed?).to be false
+ end
+ end
+
+ describe "#missing_extensions?" do
+ it "returns false if manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.missing_extensions?).to be false
+ end
+
+ it "returns #{RUBY_ENGINE == "jruby" ? "false" : "true"} if not manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ if RUBY_ENGINE == "jruby"
+ expect(stub.missing_extensions?).to be false
+ else
+ expect(stub.missing_extensions?).to be true
end
end
end
+
+ describe "#activated?" do
+ it "returns true after activation" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+
+ expect(stub.activated?).to be_falsey
+ stub.activated = true
+ expect(stub.activated?).to be true
+ end
+
+ it "returns true after activation if the underlying stub is a `Gem::StubSpecification`" do
+ spec_path = File.join(File.dirname(__FILE__), "specifications", "foo.gemspec")
+ gem_stub = Gem::StubSpecification.new(spec_path, File.dirname(__FILE__),"","")
+ stub = described_class.from_stub(gem_stub)
+
+ expect(stub.activated?).to be_falsey
+ stub.activated = true
+ expect(stub.activated?).to be true
+ end
+ end
end
diff --git a/spec/bundler/bundler/ui/shell_spec.rb b/spec/bundler/bundler/ui/shell_spec.rb
index 951a446aff..83f147191e 100644
--- a/spec/bundler/bundler/ui/shell_spec.rb
+++ b/spec/bundler/bundler/ui/shell_spec.rb
@@ -10,6 +10,13 @@ RSpec.describe Bundler::UI::Shell do
it "prints to stdout" do
expect { subject.info("info") }.to output("info\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.info("info") }.to output("info\n").to_stderr
+ end
+ end
end
describe "#confirm" do
@@ -17,23 +24,22 @@ RSpec.describe Bundler::UI::Shell do
it "prints to stdout" do
expect { subject.confirm("confirm") }.to output("confirm\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.confirm("confirm") }.to output("confirm\n").to_stderr
+ end
+ end
end
describe "#warn" do
before { subject.level = "warn" }
- it "prints to stdout", :bundler => "< 2" do
- expect { subject.warn("warning") }.to output("warning\n").to_stdout
- end
-
- it "prints to stderr", :bundler => "2" do
+ it "prints to stderr, implicitly adding a newline" do
expect { subject.warn("warning") }.to output("warning\n").to_stderr
end
-
- context "when stderr flag is enabled" do
- before { Bundler.settings.temporary(:error_on_stderr => true) }
- it "prints to stderr" do
- expect { subject.warn("warning!") }.to output("warning!\n").to_stderr
- end
+ it "can be told not to emit a newline" do
+ expect { subject.warn("warning", false) }.to output("warning").to_stderr
end
end
@@ -41,33 +47,66 @@ RSpec.describe Bundler::UI::Shell do
it "prints to stdout" do
expect { subject.debug("debug") }.to output("debug\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.debug("debug") }.to output("debug\n").to_stderr
+ end
+ end
end
describe "#error" do
before { subject.level = "error" }
- it "prints to stdout", :bundler => "< 2" do
- expect { subject.error("error!!!") }.to output("error!!!\n").to_stdout
+ it "prints to stderr" do
+ expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr
end
- it "prints to stderr", :bundler => "2" do
- expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr
+ context "when stderr is closed" do
+ it "doesn't report anything" do
+ output = begin
+ result = StringIO.new
+ result.close
+
+ $stderr = result
+
+ subject.error("Something went wrong")
+
+ result.string
+ ensure
+ $stderr = STDERR
+ end
+ expect(output).to_not eq("Something went wrong")
+ end
end
+ end
- context "when stderr flag is enabled" do
- before { Bundler.settings.temporary(:error_on_stderr => true) }
- it "prints to stderr" do
- expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr
+ describe "threads" do
+ it "is thread safe when using with_level" do
+ stop_thr1 = false
+ stop_thr2 = false
+
+ expect(subject.level).to eq("debug")
+
+ thr1 = Thread.new do
+ subject.silence do
+ sleep(0.1) until stop_thr1
+ end
+
+ stop_thr2 = true
end
- context "when stderr is closed" do
- it "doesn't report anything" do
- output = capture(:stderr, :closed => true) do
- subject.error("Something went wrong")
- end
- expect(output).to_not eq("Something went wrong\n")
+ thr2 = Thread.new do
+ subject.silence do
+ stop_thr1 = true
+ sleep(0.1) until stop_thr2
end
end
+
+ [thr1, thr2].each(&:join)
+
+ expect(subject.level).to eq("debug")
end
end
end
diff --git a/spec/bundler/bundler/ui_spec.rb b/spec/bundler/bundler/ui_spec.rb
index 6ef8729277..6df0d2e290 100644
--- a/spec/bundler/bundler/ui_spec.rb
+++ b/spec/bundler/bundler/ui_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe Bundler::UI do
describe Bundler::UI::Silent do
- it "has the same instance methods as Shell", :ruby => ">= 1.9" do
+ it "has the same instance methods as Shell" do
shell = Bundler::UI::Shell
methods = proc do |cls|
cls.instance_methods.map do |i|
@@ -13,7 +13,7 @@ RSpec.describe Bundler::UI do
expect(methods.call(described_class)).to eq(methods.call(shell))
end
- it "has the same instance class as Shell", :ruby => ">= 1.9" do
+ it "has the same instance class as Shell" do
shell = Bundler::UI::Shell
methods = proc do |cls|
cls.methods.map do |i|
diff --git a/spec/bundler/bundler/uri_credentials_filter_spec.rb b/spec/bundler/bundler/uri_credentials_filter_spec.rb
index fe52d16306..641f0addb4 100644
--- a/spec/bundler/bundler/uri_credentials_filter_spec.rb
+++ b/spec/bundler/bundler/uri_credentials_filter_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Bundler::URICredentialsFilter do
let(:credentials) { "oauth_token:x-oauth-basic@" }
it "returns the uri without the oauth token" do
- expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://x-oauth-basic@github.com/company/private-repo").to_s)
+ expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://x-oauth-basic@github.com/company/private-repo").to_s)
end
it_behaves_like "original type of uri is maintained"
@@ -26,7 +26,17 @@ RSpec.describe Bundler::URICredentialsFilter do
let(:credentials) { "oauth_token:x@" }
it "returns the uri without the oauth token" do
- expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://x@github.com/company/private-repo").to_s)
+ expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://x@github.com/company/private-repo").to_s)
+ end
+
+ it_behaves_like "original type of uri is maintained"
+ end
+
+ context "specified without empty username" do
+ let(:credentials) { "oauth_token@" }
+
+ it "returns the uri without the oauth token" do
+ expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://github.com/company/private-repo").to_s)
end
it_behaves_like "original type of uri is maintained"
@@ -37,7 +47,7 @@ RSpec.describe Bundler::URICredentialsFilter do
let(:credentials) { "username1:hunter3@" }
it "returns the uri without the password" do
- expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://username1@github.com/company/private-repo").to_s)
+ expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://username1@github.com/company/private-repo").to_s)
end
it_behaves_like "original type of uri is maintained"
@@ -55,7 +65,7 @@ RSpec.describe Bundler::URICredentialsFilter do
end
context "uri is a uri object" do
- let(:uri) { URI("https://#{credentials}github.com/company/private-repo") }
+ let(:uri) { Gem::URI("https://#{credentials}github.com/company/private-repo") }
it_behaves_like "sensitive credentials in uri are filtered out"
end
@@ -90,7 +100,7 @@ RSpec.describe Bundler::URICredentialsFilter do
describe "#credential_filtered_string" do
let(:str_to_filter) { "This is a git message containing a uri #{uri}!" }
let(:credentials) { "" }
- let(:uri) { URI("https://#{credentials}github.com/company/private-repo") }
+ let(:uri) { Gem::URI("https://#{credentials}github.com/company/private-repo") }
context "with a uri that contains credentials" do
let(:credentials) { "oauth_token:x-oauth-basic@" }
diff --git a/spec/bundler/bundler/uri_normalizer_spec.rb b/spec/bundler/bundler/uri_normalizer_spec.rb
new file mode 100644
index 0000000000..1308e86014
--- /dev/null
+++ b/spec/bundler/bundler/uri_normalizer_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::URINormalizer do
+ describe ".normalize_suffix" do
+ context "when trailing_slash is true" do
+ it "adds a trailing slash when missing" do
+ expect(described_class.normalize_suffix("https://example.com", trailing_slash: true)).to eq("https://example.com/")
+ end
+
+ it "keeps the trailing slash when present" do
+ expect(described_class.normalize_suffix("https://example.com/", trailing_slash: true)).to eq("https://example.com/")
+ end
+ end
+
+ context "when trailing_slash is false" do
+ it "removes a trailing slash when present" do
+ expect(described_class.normalize_suffix("https://example.com/", trailing_slash: false)).to eq("https://example.com")
+ end
+
+ it "keeps the value unchanged when no trailing slash exists" do
+ expect(described_class.normalize_suffix("https://example.com", trailing_slash: false)).to eq("https://example.com")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/vendored_persistent_spec.rb b/spec/bundler/bundler/vendored_persistent_spec.rb
deleted file mode 100644
index 338431c4a6..0000000000
--- a/spec/bundler/bundler/vendored_persistent_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-require "bundler/vendored_persistent"
-
-RSpec.describe Bundler::PersistentHTTP do
- describe "#warn_old_tls_version_rubygems_connection" do
- let(:uri) { "https://index.rubygems.org" }
- let(:connection) { instance_double(subject.http_class) }
- let(:tls_version) { "TLSv1.2" }
- let(:socket) { double("Socket") }
- let(:socket_io) { double("SocketIO") }
-
- before do
- allow(connection).to receive(:use_ssl?).and_return(!tls_version.nil?)
- allow(socket).to receive(:io).and_return(socket_io)
- connection.instance_variable_set(:@socket, socket)
-
- if tls_version
- allow(socket_io).to receive(:ssl_version).and_return(tls_version)
- end
- end
-
- shared_examples_for "does not warn" do
- it "does not warn" do
- allow(Bundler.ui).to receive(:warn).never
- subject.warn_old_tls_version_rubygems_connection(URI(uri), connection)
- end
- end
-
- shared_examples_for "does warn" do |*expected|
- it "warns" do
- expect(Bundler.ui).to receive(:warn).with(*expected)
- subject.warn_old_tls_version_rubygems_connection(URI(uri), connection)
- end
- end
-
- context "an HTTPS uri with TLSv1.2" do
- include_examples "does not warn"
- end
-
- context "without SSL" do
- let(:tls_version) { nil }
-
- include_examples "does not warn"
- end
-
- context "without a socket" do
- let(:socket) { nil }
-
- include_examples "does not warn"
- end
-
- context "with a different TLD" do
- let(:uri) { "https://foo.bar" }
- include_examples "does not warn"
-
- context "and an outdated TLS version" do
- let(:tls_version) { "TLSv1" }
- include_examples "does not warn"
- end
- end
-
- context "with a nonsense TLS version" do
- let(:tls_version) { "BlahBlah2.0Blah" }
- include_examples "does not warn"
- end
-
- context "with an outdated TLS version" do
- let(:tls_version) { "TLSv1" }
- include_examples "does warn",
- "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \
- "Starting in January 2018, RubyGems.org will refuse connection requests from these very old versions of OpenSSL. " \
- "If you will need to continue installing gems after January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.",
- :wrap => true
- end
- end
-end
diff --git a/spec/bundler/bundler/version_ranges_spec.rb b/spec/bundler/bundler/version_ranges_spec.rb
deleted file mode 100644
index ccbb9285d5..0000000000
--- a/spec/bundler/bundler/version_ranges_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/version_ranges"
-
-RSpec.describe Bundler::VersionRanges do
- describe ".empty?" do
- shared_examples_for "empty?" do |exp, *req|
- it "returns #{exp} for #{req}" do
- r = Gem::Requirement.new(*req)
- ranges = described_class.for(r)
- expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty"
- end
- end
-
- include_examples "empty?", false
- include_examples "empty?", false, "!= 1"
- include_examples "empty?", false, "!= 1", "= 2"
- include_examples "empty?", false, "!= 1", "> 1"
- include_examples "empty?", false, "!= 1", ">= 1"
- include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1"
- include_examples "empty?", false, "= 1", ">= 1", "<= 1"
- include_examples "empty?", false, "= 1", "~> 1"
- include_examples "empty?", false, ">= 0.z", "= 0"
- include_examples "empty?", false, ">= 0"
- include_examples "empty?", false, ">= 1.0.0", "< 2.0.0"
- include_examples "empty?", false, "~> 1"
- include_examples "empty?", false, "~> 2.0", "~> 2.1"
- include_examples "empty?", true, "!= 1", "< 2", "> 2"
- include_examples "empty?", true, "!= 1", "<= 1", ">= 1"
- include_examples "empty?", true, "< 2", "> 2"
- include_examples "empty?", true, "= 1", "!= 1"
- include_examples "empty?", true, "= 1", "= 2"
- include_examples "empty?", true, "= 1", "~> 2"
- include_examples "empty?", true, ">= 0", "<= 0.a"
- include_examples "empty?", true, "~> 2.0", "~> 3"
- end
-end
diff --git a/spec/bundler/bundler/worker_spec.rb b/spec/bundler/bundler/worker_spec.rb
index 2e5642709d..2ad2845e37 100644
--- a/spec/bundler/bundler/worker_spec.rb
+++ b/spec/bundler/bundler/worker_spec.rb
@@ -19,4 +19,71 @@ RSpec.describe Bundler::Worker do
end
end
end
+
+ describe "priority queue" do
+ it "process elements from the priority queue first" do
+ processed_elements = []
+
+ function = proc do |element, _|
+ processed_elements << element
+ end
+
+ worker = described_class.new(1, "Spec Worker", function)
+ worker.instance_variable_set(:@threads, []) # Prevent the enqueueing from starting work.
+ worker.enq("Normal element")
+ worker.enq("Priority element", priority: true)
+ worker.send(:create_threads)
+
+ worker.stop
+
+ expect(processed_elements).to eq(["Priority element", "Normal element"])
+ end
+ end
+
+ describe "handling interrupts" do
+ let(:status) do
+ pid = Process.fork do
+ $stderr.reopen File.new("/dev/null", "w")
+ Signal.trap "INT", previous_interrupt_handler
+ subject.enq "a"
+ subject.stop unless interrupt_before_stopping
+ Process.kill "INT", Process.pid
+ end
+
+ Process.wait2(pid).last
+ end
+
+ before do
+ skip "requires Process.fork" unless Process.respond_to?(:fork)
+ end
+
+ context "when interrupted before stopping" do
+ let(:interrupt_before_stopping) { true }
+ let(:previous_interrupt_handler) { ->(*) { exit 0 } }
+
+ it "aborts" do
+ expect(status.exitstatus).to eq(1)
+ end
+ end
+
+ context "when interrupted after stopping" do
+ let(:interrupt_before_stopping) { false }
+
+ context "when the previous interrupt handler was the default" do
+ let(:previous_interrupt_handler) { "DEFAULT" }
+
+ it "uses the default interrupt handler" do
+ expect(status).to be_signaled
+ end
+ end
+
+ context "when the previous interrupt handler was customized" do
+ let(:previous_interrupt_handler) { ->(*) { exit 42 } }
+
+ it "restores the custom interrupt handler after stopping" do
+ expect(status.exitstatus).to eq(42)
+ end
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb
index 1241c74bbf..9ff1579b76 100644
--- a/spec/bundler/bundler/yaml_serializer_spec.rb
+++ b/spec/bundler/bundler/yaml_serializer_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Bundler::YAMLSerializer do
it "works for simple hash" do
hash = { "Q" => "Where does Thursday come before Wednesday? In the dictionary. :P" }
- expected = strip_whitespace <<-YAML
+ expected = <<~YAML
---
Q: "Where does Thursday come before Wednesday? In the dictionary. :P"
YAML
@@ -24,7 +24,7 @@ RSpec.describe Bundler::YAMLSerializer do
},
}
- expected = strip_whitespace <<-YAML
+ expected = <<~YAML
---
nice-one:
read_ahead: "All generalizations are false, including this one"
@@ -45,7 +45,7 @@ RSpec.describe Bundler::YAMLSerializer do
},
}
- expected = strip_whitespace <<-YAML
+ expected = <<~YAML
---
nested_hash:
contains_array:
@@ -57,11 +57,24 @@ RSpec.describe Bundler::YAMLSerializer do
expect(serializer.dump(hash)).to eq(expected)
end
+
+ it "handles empty array" do
+ hash = {
+ "empty_array" => [],
+ }
+
+ expected = <<~YAML
+ ---
+ empty_array: []
+ YAML
+
+ expect(serializer.dump(hash)).to eq(expected)
+ end
end
describe "#load" do
it "works for simple hash" do
- yaml = strip_whitespace <<-YAML
+ yaml = <<~YAML
---
Jon: "Air is free dude!"
Jack: "Yes.. until you buy a bag of chips!"
@@ -76,7 +89,7 @@ RSpec.describe Bundler::YAMLSerializer do
end
it "works for nested hash" do
- yaml = strip_whitespace <<-YAML
+ yaml = <<~YAML
---
baa:
baa: "black sheep"
@@ -98,15 +111,15 @@ RSpec.describe Bundler::YAMLSerializer do
end
it "handles colon in key/value" do
- yaml = strip_whitespace <<-YAML
- BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: http://rubygems-mirror.org
+ yaml = <<~YAML
+ BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: http://example-mirror.rubygems.org
YAML
- expect(serializer.load(yaml)).to eq("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org")
+ expect(serializer.load(yaml)).to eq("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://example-mirror.rubygems.org")
end
it "handles arrays inside hashes" do
- yaml = strip_whitespace <<-YAML
+ yaml = <<~YAML
---
nested_hash:
contains_array:
@@ -127,7 +140,7 @@ RSpec.describe Bundler::YAMLSerializer do
end
it "handles windows-style CRLF line endings" do
- yaml = strip_whitespace(<<-YAML).gsub("\n", "\r\n")
+ yaml = <<~YAML.gsub("\n", "\r\n")
---
nested_hash:
contains_array:
@@ -148,6 +161,34 @@ RSpec.describe Bundler::YAMLSerializer do
expect(serializer.load(yaml)).to eq(hash)
end
+
+ it "handles empty array" do
+ yaml = <<~YAML
+ ---
+ empty_array: []
+ YAML
+
+ hash = {
+ "empty_array" => [],
+ }
+
+ expect(serializer.load(yaml)).to eq(hash)
+ end
+
+ it "skip commented out words" do
+ yaml = <<~YAML
+ ---
+ foo: bar
+ buzz: foo # bar
+ YAML
+
+ hash = {
+ "foo" => "bar",
+ "buzz" => "foo",
+ }
+
+ expect(serializer.load(yaml)).to eq(hash)
+ end
end
describe "against yaml lib" do
diff --git a/spec/bundler/cache/cache_path_spec.rb b/spec/bundler/cache/cache_path_spec.rb
index 69d3809964..2a280ea858 100644
--- a/spec/bundler/cache/cache_path_spec.rb
+++ b/spec/bundler/cache/cache_path_spec.rb
@@ -3,30 +3,30 @@
RSpec.describe "bundle package" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
context "with --cache-path" do
it "caches gems at given path" do
- bundle :package, "cache-path" => "vendor/cache-foo"
- expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ bundle :cache, "cache-path" => "vendor/cache-foo"
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
context "with config cache_path" do
it "caches gems at given path" do
- bundle "config cache_path vendor/cache-foo"
- bundle :package
- expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ bundle_config "cache_path vendor/cache-foo"
+ bundle :cache
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
context "with absolute --cache-path" do
it "caches gems at given path" do
- bundle :package, "cache-path" => "/tmp/cache-foo"
- expect(bundled_app("/tmp/cache-foo/rack-1.0.0.gem")).to exist
+ bundle :cache, "cache-path" => bundled_app("vendor/cache-foo")
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
end
diff --git a/spec/bundler/cache/gems_spec.rb b/spec/bundler/cache/gems_spec.rb
index 4a0b953830..198279d84c 100644
--- a/spec/bundler/cache/gems_spec.rb
+++ b/spec/bundler/cache/gems_spec.rb
@@ -4,22 +4,23 @@ RSpec.describe "bundle cache" do
shared_examples_for "when there are only gemsources" do
before :each do
gemfile <<-G
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- system_gems "rack-1.0.0", :path => :bundle_path
- bundle! :cache
+ system_gems "myrack-1.0.0", path: path
+ bundle :cache
end
it "copies the .gem file to vendor/cache" do
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "uses the cache as a source when installing gems" do
- build_gem "omg", :path => bundled_app("vendor/cache")
+ build_gem "omg", path: bundled_app("vendor/cache")
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "omg"
G
@@ -27,131 +28,167 @@ RSpec.describe "bundle cache" do
end
it "uses the cache as a source when installing gems with --local" do
- system_gems [], :path => :bundle_path
+ system_gems [], path: default_bundle_path
bundle "install --local"
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "does not reinstall gems from the cache if they exist on the system" do
- build_gem "rack", "1.0.0", :path => bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "does not reinstall gems from the cache if they exist in the bundle" do
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- build_gem "rack", "1.0.0", :path => bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- bundle! :install, :local => true
- expect(the_bundle).to include_gems("rack 1.0.0")
+ bundle :install, local: true
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "creates a lockfile" do
- cache_gems "rack-1.0.0"
+ cache_gems "myrack-1.0.0"
gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
end
context "using system gems" do
- before { bundle! "config path.system true" }
+ before { bundle_config "path.system true" }
+ let(:path) { system_gem_path }
it_behaves_like "when there are only gemsources"
end
context "installing into a local path" do
- before { bundle! "config path ./.bundle" }
+ before { bundle_config "path ./.bundle" }
+ let(:path) { local_gem_path }
it_behaves_like "when there are only gemsources"
end
- describe "when there is a built-in gem", :ruby => "2.0" do
+ describe "when there is a built-in gem", :ruby_repo do
+ let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" }
+
before :each do
- build_repo2 do
- build_gem "builtin_gem", "1.0.2"
+ build_gem "json", default_json_version, to_system: true, default: true
+ end
+
+ context "when a remote gem is available for caching" do
+ before do
+ build_repo2 do
+ build_gem "json", default_json_version
+ end
end
- build_gem "builtin_gem", "1.0.2", :to_system => true do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
+ it "uses remote gems when installing" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true
+ expect(out).to include("Installing json #{default_json_version}")
end
- FileUtils.rm("#{system_gem_path}/cache/builtin_gem-1.0.2.gem")
- end
+ it "does not use remote gems when installing with --local flag" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true, local: true
+ expect(out).to include("Using json #{default_json_version}")
+ end
- it "uses builtin gems when installing to system gems" do
- bundle! "config path.system true"
- install_gemfile %(gem 'builtin_gem', '1.0.2')
- expect(the_bundle).to include_gems("builtin_gem 1.0.2")
- end
+ it "does not use remote gems when installing with --prefer-local flag" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true, "prefer-local": true
+ expect(out).to include("Using json #{default_json_version}")
+ end
- it "caches remote and builtin gems" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'builtin_gem', '1.0.2'
- gem 'rack', '1.0.0'
- G
+ it "caches remote and builtin gems" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'json', '#{default_json_version}'
+ gem 'myrack', '1.0.0'
+ G
- bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/builtin_gem-1.0.2.gem")).to exist
- end
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
+ end
+
+ it "caches builtin gems when cache_all_platforms is set" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "json"
+ G
+
+ bundle_config "cache_all_platforms true"
- it "doesn't make remote request after caching the gem" do
- build_gem "builtin_gem_2", "1.0.2", :path => bundled_app("vendor/cache") do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
+ bundle :cache
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
end
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'builtin_gem_2', '1.0.2'
- G
+ it "doesn't make remote request after caching the gem" do
+ build_gem "builtin_gem_2", "1.0.2", path: bundled_app("vendor/cache"), default: true
- bundle "install --local"
- expect(the_bundle).to include_gems("builtin_gem_2 1.0.2")
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'builtin_gem_2', '1.0.2'
+ G
+
+ bundle "install --local"
+ expect(the_bundle).to include_gems("builtin_gem_2 1.0.2")
+ end
end
- it "errors if the builtin gem isn't available to cache" do
- bundle! "config path.system true"
+ context "when a remote gem is not available for caching" do
+ it "warns, but uses builtin gems when installing to system gems" do
+ bundle_config "path.system true"
+ install_gemfile %(source "https://gem.repo1"; gem 'json', '#{default_json_version}'), verbose: true
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
+ expect(out).to include("Using json #{default_json_version}")
+ end
- install_gemfile <<-G
- gem 'builtin_gem', '1.0.2'
- G
+ it "errors when explicitly caching" do
+ bundle_config "path.system true"
- bundle :cache
- expect(exitstatus).to_not eq(0) if exitstatus
- expect(out).to include("builtin_gem-1.0.2 is built in to Ruby, and can't be cached")
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'json', '#{default_json_version}'
+ G
+
+ bundle :cache, raise_on_error: false
+ expect(last_command).to be_failure
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
+ end
end
end
describe "when there are also git sources" do
before do
build_git "foo"
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
@@ -161,49 +198,57 @@ RSpec.describe "bundle cache" do
system_gems []
bundle "install --local"
- expect(the_bundle).to include_gems("rack 1.0.0", "foo 1.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", "foo 1.0")
end
it "should not explode if the lockfile is not present" do
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
bundle :cache
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
end
describe "when previously cached" do
- before :each do
+ let :setup_main_repo do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
gem "actionpack"
G
bundle :cache
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
expect(cached_gem("actionpack-2.3.2")).to exist
expect(cached_gem("activesupport-2.3.2")).to exist
end
it "re-caches during install" do
- cached_gem("rack-1.0.0").rmtree
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
bundle :install
expect(out).to include("Updating files in vendor/cache")
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
end
it "adds and removes when gems are updated" do
- update_repo2
- bundle "update", :all => bundle_update_requires_all?
- expect(cached_gem("rack-1.2")).to exist
- expect(cached_gem("rack-1.0.0")).not_to exist
+ setup_main_repo
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+ end
+
+ bundle "update", all: true
+ expect(cached_gem("myrack-1.2")).to exist
+ expect(cached_gem("myrack-1.0.0")).not_to exist
end
it "adds new gems and dependencies" do
+ setup_main_repo
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails"
G
expect(cached_gem("rails-2.3.2")).to exist
@@ -211,24 +256,26 @@ RSpec.describe "bundle cache" do
end
it "removes .gems for removed gems and dependencies" do
+ setup_main_repo
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
expect(cached_gem("actionpack-2.3.2")).not_to exist
expect(cached_gem("activesupport-2.3.2")).not_to exist
end
it "removes .gems when gem changes to git source" do
- build_git "rack"
+ setup_main_repo
+ build_git "myrack"
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo2"
+ gem "myrack", :git => "#{lib_path("myrack-1.0")}"
gem "actionpack"
G
- expect(cached_gem("rack-1.0.0")).not_to exist
+ expect(cached_gem("myrack-1.0.0")).not_to exist
expect(cached_gem("actionpack-2.3.2")).to exist
expect(cached_gem("activesupport-2.3.2")).to exist
end
@@ -236,7 +283,7 @@ RSpec.describe "bundle cache" do
it "doesn't remove gems that are for another platform" do
simulate_platform "java" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "platform_specific"
G
@@ -244,37 +291,111 @@ RSpec.describe "bundle cache" do
expect(cached_gem("platform_specific-1.0-java")).to exist
end
- simulate_new_machine
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
+ pristine_system_gems
+
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- expect(cached_gem("platform_specific-1.0-#{Bundler.local_platform}")).to exist
- expect(cached_gem("platform_specific-1.0-java")).to exist
+ expect(cached_gem("platform_specific-1.0-x86-darwin-100")).to exist
+ expect(cached_gem("platform_specific-1.0-java")).to exist
+ end
end
- it "doesn't remove gems with mismatched :rubygems_version or :date" do
- cached_gem("rack-1.0.0").rmtree
- build_gem "rack", "1.0.0",
- :path => bundled_app("vendor/cache"),
- :rubygems_version => "1.3.2"
- simulate_new_machine
+ it "doesn't remove gems cached gems that don't match their remote counterparts, but also refuses to install and prints an error" do
+ setup_main_repo
+ cached_myrack = cached_gem("myrack-1.0.0")
+ FileUtils.rm_rf cached_myrack
+ build_gem "myrack", "1.0.0",
+ path: cached_myrack.parent,
+ rubygems_version: "1.3.2"
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
+
+ FileUtils.rm bundled_app_lock
+ bundle :install, raise_on_error: false
+
+ expect(err).to eq <<~E.strip
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_to_lock(gem_repo2, "myrack", "1.0.0")}
+ from the API at https://gem.repo2/
+ #{checksum_from_package(cached_myrack, "myrack", "1.0.0")}
+ from the gem at #{cached_myrack}
+
+ If you trust the API at https://gem.repo2/, to resolve this issue you can:
+ 1. remove the gem at #{cached_myrack}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+
+ expect(cached_gem("myrack-1.0.0")).to exist
+ end
+
+ it "raises an error when a cached gem is altered and produces a different checksum than the remote gem" do
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache")
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+ #{checksums}
+ L
+
+ bundle :install, raise_on_error: false
+ expect(exitstatus).to eq(37)
+ expect(err).to include("Bundler found mismatched checksums.")
+ expect(err).to include("1. remove the gem at #{cached_gem("myrack-1.0.0")}")
+
+ expect(cached_gem("myrack-1.0.0")).to exist
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
bundle :install
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
+ end
+
+ it "installs a modified gem with a non-matching checksum when the API implementation does not provide checksums" do
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache")
+ pristine_system_gems
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+ L
+
+ bundle :install, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(cached_gem("myrack-1.0.0")).to exist
end
it "handles directories and non .gem files in the cache" do
+ setup_main_repo
bundled_app("vendor/cache/foo").mkdir
File.open(bundled_app("vendor/cache/bar"), "w") {|f| f.write("not a gem") }
bundle :cache
end
it "does not say that it is removing gems when it isn't actually doing so" do
+ setup_main_repo
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
bundle "install"
@@ -282,9 +403,10 @@ RSpec.describe "bundle cache" do
end
it "does not warn about all if it doesn't have any git/path dependency" do
+ setup_main_repo
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
expect(out).not_to match(/\-\-all/)
@@ -292,9 +414,10 @@ RSpec.describe "bundle cache" do
it "should install gems with the name bundler in them (that aren't bundler)" do
build_gem "foo-bundler", "1.0",
- :path => bundled_app("vendor/cache")
+ path: bundled_app("vendor/cache")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo-bundler"
G
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 33387dbbb2..f0976ecac7 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -12,203 +12,500 @@ RSpec.describe "git base name" do
end
end
-%w[cache package].each do |cmd|
- RSpec.describe "bundle #{cmd} with git" do
- it "copies repository to vendor cache and uses it" do
- git = build_git "foo"
- ref = git.ref_for("master", 11)
+RSpec.describe "bundle cache with git" do
+ it "does not copy repository to vendor cache when cache_all set to false" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
- bundle "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
+ bundle_config "cache_all false"
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).not_to exist
- FileUtils.rm_rf lib_path("foo-1.0")
- expect(the_bundle).to include_gems "foo 1.0"
- end
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
- it "copies repository to vendor cache and uses it even when installed with bundle --path" do
- git = build_git "foo"
- ref = git.ref_for("master", 11)
+ it "copies repository to vendor cache and uses it" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
- bundle "install --path vendor/bundle"
- bundle "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
+ FileUtils.rm_r lib_path("foo-1.0")
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
+ it "copies repository to vendor cache and uses it even when configured with `path`" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
+
+ FileUtils.rm_r lib_path("foo-1.0")
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
- FileUtils.rm_rf lib_path("foo-1.0")
- expect(the_bundle).to include_gems "foo 1.0"
+ it "runs twice without exploding" do
+ build_git "foo"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :cache
+ bundle :cache
+
+ expect(out).to include "Updating files in vendor/cache"
+ FileUtils.rm_r lib_path("foo-1.0")
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
+ it "tracks updates" do
+ git = build_git "foo"
+ old_ref = git.ref_for("main", 11)
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :cache
+
+ update_git "foo" do |s|
+ s.write "lib/foo.rb", "puts :CACHE"
end
- it "runs twice without exploding" do
- build_git "foo"
+ ref = git.ref_for("main", 11)
+ expect(ref).not_to eq(old_ref)
+
+ bundle "update", all: true
+ bundle :cache
- install_gemfile! <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist
+
+ FileUtils.rm_r lib_path("foo-1.0")
+ run "require 'foo'"
+ expect(out).to eq("CACHE")
+ end
- bundle! "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
- bundle! "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ it "tracks updates when specifying the gem" do
+ git = build_git "foo"
+ old_ref = git.ref_for("main", 11)
- expect(last_command.stdout).to include "Updating files in vendor/cache"
- FileUtils.rm_rf lib_path("foo-1.0")
- expect(the_bundle).to include_gems "foo 1.0"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :cache
+
+ update_git "foo" do |s|
+ s.write "lib/foo.rb", "puts :CACHE"
end
- it "tracks updates" do
- git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
+ expect(ref).not_to eq(old_ref)
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ bundle "update foo"
- bundle "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist
- update_git "foo" do |s|
- s.write "lib/foo.rb", "puts :CACHE"
- end
+ FileUtils.rm_r lib_path("foo-1.0")
+ run "require 'foo'"
+ expect(out).to eq("CACHE")
+ end
- ref = git.ref_for("master", 11)
- expect(ref).not_to eq(old_ref)
+ it "uses the local repository to generate the cache" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
- bundle! "update", :all => bundle_update_requires_all?
- bundle! "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :main
+ G
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
- expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist
+ bundle %(config set local.foo #{lib_path("foo-1.0")})
+ bundle "install"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/foo-invalid-#{ref}")).to exist
- FileUtils.rm_rf lib_path("foo-1.0")
- run! "require 'foo'"
- expect(out).to eq("CACHE")
+ # Updating the local still uses the local.
+ update_git "foo" do |s|
+ s.write "lib/foo.rb", "puts :LOCAL"
end
- it "tracks updates when specifying the gem" do
- git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ run "require 'foo'"
+ expect(out).to eq("LOCAL")
+ end
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ it "can use gems after copying install folder to a different machine with git not installed" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle_config "path vendor/bundle"
+ bundle :install
+
+ pristine_system_gems
+ with_path_as "" do
+ bundle_config "deployment true"
+ bundle "install --local"
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+ end
- bundle! cmd, forgotten_command_line_options([:all, :cache_all] => true)
+ it "can install after bundle cache without cloning remote repositories" do
+ build_git "foo"
- update_git "foo" do |s|
- s.write "lib/foo.rb", "puts :CACHE"
- end
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
- ref = git.ref_for("master", 11)
- expect(ref).not_to eq(old_ref)
+ pristine_system_gems
+ bundle_config "frozen true"
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
- bundle "update foo"
+ it "can install after bundle cache without cloning remote repositories even without the original cache" do
+ build_git "foo"
- expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
- expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
+
+ pristine_system_gems
+ bundle_config "frozen true"
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "can install after bundle cache without cloning remote repositories with only git tracked files" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
- FileUtils.rm_rf lib_path("foo-1.0")
- run "require 'foo'"
- expect(out).to eq("CACHE")
+ pristine_system_gems
+ bundle_config "frozen true"
+
+ # Remove untracked files (including the empty refs dir in the cache)
+ Dir.chdir(bundled_app) do
+ system(*%W[git init --quiet])
+ system(*%W[git add --all])
+ system(*%W[git clean -d --force --quiet])
end
- it "uses the local repository to generate the cache" do
- git = build_git "foo"
- ref = git.ref_for("master", 11)
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
- gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master
- G
+ it "installs properly a bundler 2.5.17-2.5.23 cache as a bare repository without cloning remote repositories" do
+ git = build_git "foo"
- bundle %(config local.foo #{lib_path("foo-1.0")})
- bundle "install"
- bundle "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
- expect(bundled_app("vendor/cache/foo-invalid-#{ref}")).to exist
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle_config "global_gem_cache false"
+ bundle_config "path vendor/bundle"
+ bundle :install
- # Updating the local still uses the local.
- update_git "foo" do |s|
- s.write "lib/foo.rb", "puts :LOCAL"
- end
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+ FileUtils.rm_r bundled_app("vendor/bundle")
+
+ bundle "install --local --verbose"
+ expect(err).to include("Installing from cache in old \"bare repository\" format for compatibility")
+
+ expect(out).to_not include("Fetching")
- run "require 'foo'"
- expect(out).to eq("LOCAL")
+ # leaves old cache alone
+ expect(cache_dir.join("lib/foo.rb")).not_to exist
+ expect(cache_dir.join("HEAD")).to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "migrates a bundler 2.5.17-2.5.23 cache as a bare repository when not running with --local" do
+ git = build_git "foo"
+
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle_config "global_gem_cache false"
+ bundle_config "path vendor/bundle"
+ bundle :install
+
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+ FileUtils.rm_r bundled_app("vendor/bundle")
+
+ bundle "install --verbose"
+ expect(out).to include("Fetching")
+
+ # migrates old cache alone
+ expect(cache_dir.join("lib/foo.rb")).to exist
+ expect(cache_dir.join("HEAD")).not_to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "migrates a bundler 2.5.17-2.5.23 cache as a bare repository when running `bundle cache`, even if gems already installed" do
+ git = build_git "foo"
+
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle_config "global_gem_cache false"
+ bundle_config "path vendor/bundle"
+ bundle :install
+
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+
+ bundle "cache"
+
+ # migrates old cache alone
+ expect(cache_dir.join("lib/foo.rb")).to exist
+ expect(cache_dir.join("HEAD")).not_to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "copies repository to vendor cache, including submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
+ build_git "submodule", "1.0"
+
+ git = build_git "has_submodule", "1.0" do |s|
+ s.add_dependency "submodule"
end
- it "copies repository to vendor cache, including submodules" do
- build_git "submodule", "1.0"
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
- git = build_git "has_submodule", "1.0" do |s|
- s.add_dependency "submodule"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ git "#{lib_path("has_submodule-1.0")}", :submodules => true do
+ gem "has_submodule"
end
+ G
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ ref = git.ref_for("main", 11)
+ bundle :cache
- install_gemfile <<-G
- git "#{lib_path("has_submodule-1.0")}", :submodules => true do
- gem "has_submodule"
- end
- G
+ expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}")).to exist
+ expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}/submodule-1.0")).to exist
+ expect(the_bundle).to include_gems "has_submodule 1.0"
+ end
- ref = git.ref_for("master", 11)
- bundle "#{cmd}", forgotten_command_line_options([:all, :cache_all] => true)
+ it "caches pre-evaluated gemspecs" do
+ git = build_git "foo"
- expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}")).to exist
- expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}/submodule-1.0")).to exist
- expect(the_bundle).to include_gems "has_submodule 1.0"
- end
+ # Insert a gemspec method that shells out
+ spec_lines = lib_path("foo-1.0/foo.gemspec").read.split("\n")
+ spec_lines.insert(-2, "s.description = `echo bob`")
+ update_git("foo") {|s| s.write "foo.gemspec", spec_lines.join("\n") }
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache
- it "displays warning message when detecting git repo in Gemfile", :bundler => "< 2" do
- build_git "foo"
+ ref = git.ref_for("main", 11)
+ gemspec = bundled_app("vendor/cache/foo-1.0-#{ref}/foo.gemspec").read
+ expect(gemspec).to_not match("`echo bob`")
+ end
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ it "can install after bundle cache with git not installed" do
+ build_git "foo"
- bundle "#{cmd}"
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true, :install => false
- expect(out).to include("Your Gemfile contains path and git dependencies.")
+ pristine_system_gems
+ with_path_as "" do
+ bundle_config "deployment true"
+ bundle :install, local: true
+ expect(the_bundle).to include_gem "foo 1.0"
end
+ end
- it "does not display warning message if cache_all is set in bundle config" do
- build_git "foo"
+ it "can install after bundle cache generated with an older Bundler that kept checkouts in the cache" do
+ git = build_git("foo")
+ locked_revision = git.ref_for("main")
+ path_revision = git.ref_for("main", 11)
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
+ git_path = lib_path("foo-1.0")
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- bundle cmd
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{git_path}'
+ G
+ lockfile <<~L
+ GIT
+ remote: #{git_path}/
+ revision: #{locked_revision}
+ specs:
+ foo (1.0)
- expect(out).not_to include("Your Gemfile contains path and git dependencies.")
- end
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
- it "caches pre-evaluated gemspecs" do
- git = build_git "foo"
+ DEPENDENCIES
+ foo!
- # Insert a gemspec method that shells out
- spec_lines = lib_path("foo-1.0/foo.gemspec").read.split("\n")
- spec_lines.insert(-2, "s.description = `echo bob`")
- update_git("foo") {|s| s.write "foo.gemspec", spec_lines.join("\n") }
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
+ # Simulate an old incorrect situation where vendor/cache would be the install location of git gems
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r git_path, bundled_app("vendor/cache/foo-1.0-#{path_revision}")
+ FileUtils.rm_r bundled_app("vendor/cache/foo-1.0-#{path_revision}/.git")
+
+ bundle :install, env: { "BUNDLE_DEPLOYMENT" => "true", "BUNDLE_CACHE_ALL" => "true" }
+ end
- ref = git.ref_for("master", 11)
- gemspec = bundled_app("vendor/cache/foo-1.0-#{ref}/foo.gemspec").read
- expect(gemspec).to_not match("`echo bob`")
+ it "respects the --no-install flag" do
+ git = build_git "foo", &:add_c_extension
+ ref = git.ref_for("main", 11)
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ # The algorithm for the cache location for a git checkout is
+ # in Bundle::Source::Git#cache_path
+ cache_path_name = "foo-1.0-#{Digest(:SHA1).hexdigest(lib_path("foo-1.0").to_s)}"
+
+ # Run this test twice. This is because materially different codepaths
+ # will get hit the second time around.
+ # The first time, Bundler::Sources::Git#install_path is set to the system
+ # wide cache directory bundler/gems; the second time, it's set to the
+ # vendor/cache directory. We don't want the native extension to appear in
+ # either of these places, so run the `bundle cache` command twice.
+ 2.times do
+ bundle :cache, "all-platforms" => true, :install => false
+
+ # it did _NOT_ actually install the gem - neither in $GEM_HOME (bundler 2 mode),
+ # nor in .bundle (bundler 4 mode)
+ expect(Pathname.new(File.join(default_bundle_path, "gems/foo-1.0-#{ref}"))).to_not exist
+ # it _did_ cache the gem in vendor/
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ # it did _NOT_ build the gems extensions in the vendor/ dir
+ expect(Dir[bundled_app("vendor/cache/foo-1.0-#{ref}/lib/foo_c*")]).to be_empty
+ # it _did_ cache the git checkout
+ expect(default_cache_path("git", cache_path_name)).to exist
+ # And the checkout is a bare checkout
+ expect(default_cache_path("git", cache_path_name, "HEAD")).to exist
+ end
+
+ # Subsequently installing the gem should compile it.
+ # _currently_, the gem gets compiled in vendor/cache, and vendor/cache is added
+ # to the $LOAD_PATH for git extensions, so it all kind of "works". However, in the
+ # future we would like to stop adding vendor/cache to the $LOAD_PATH for git extensions
+ # and instead treat them identically to normal gems (where the gem install location,
+ # not the cache location, is added to $LOAD_PATH).
+ # Verify that the compilation worked and the result is in $LOAD_PATH by simply attempting
+ # to require it; that should make sure this spec does not break if the load path behaviour
+ # is changed.
+ bundle :install, local: true
+ ruby <<~R, raise_on_error: false
+ require 'bundler/setup'
+ require 'foo_c'
+ R
+ expect(last_command).to_not be_failure
+ end
+
+ it "doesn't fail when git gem has extensions and an empty cache folder is present before bundle install" do
+ build_git "puma" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.executables = "puma"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/puma.rb", "w") do |f|
+ f.puts "PUMA = 'YES'"
+ end
+ end
+ RUBY
end
+
+ FileUtils.mkdir_p(bundled_app("vendor/cache"))
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "puma", :git => "#{lib_path("puma-1.0")}"
+ G
+
+ bundle "exec puma"
+
+ expect(out).to eq("YES")
end
end
diff --git a/spec/bundler/cache/path_spec.rb b/spec/bundler/cache/path_spec.rb
index 12be2dbcf8..42648aea1f 100644
--- a/spec/bundler/cache/path_spec.rb
+++ b/spec/bundler/cache/path_spec.rb
@@ -1,139 +1,121 @@
# frozen_string_literal: true
-%w[cache package].each do |cmd|
- RSpec.describe "bundle #{cmd} with path" do
- it "is no-op when the path is within the bundle" do
- build_lib "foo", :path => bundled_app("lib/foo")
-
- install_gemfile <<-G
- gem "foo", :path => '#{bundled_app("lib/foo")}'
- G
-
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
- expect(the_bundle).to include_gems "foo 1.0"
- end
-
- it "copies when the path is outside the bundle " do
- build_lib "foo"
-
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+RSpec.describe "bundle cache with path" do
+ it "is no-op when the path is within the bundle" do
+ build_lib "foo", path: bundled_app("lib/foo")
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{bundled_app("lib/foo")}'
+ G
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- expect(bundled_app("vendor/cache/foo-1.0")).to exist
- expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file
+ it "copies when the path is outside the bundle " do
+ build_lib "foo"
- FileUtils.rm_rf lib_path("foo-1.0")
- expect(the_bundle).to include_gems "foo 1.0"
- end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
- it "copies when the path is outside the bundle and the paths intersect" do
- libname = File.basename(Dir.pwd) + "_gem"
- libpath = File.join(File.dirname(Dir.pwd), libname)
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
+ expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file
- build_lib libname, :path => libpath
-
- install_gemfile <<-G
- gem "#{libname}", :path => '#{libpath}'
- G
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- expect(bundled_app("vendor/cache/#{libname}")).to exist
- expect(bundled_app("vendor/cache/#{libname}/.bundlecache")).to be_file
+ it "copies when the path is outside the bundle and the paths intersect" do
+ libname = File.basename(bundled_app) + "_gem"
+ libpath = File.join(File.dirname(bundled_app), libname)
- FileUtils.rm_rf libpath
- expect(the_bundle).to include_gems "#{libname} 1.0"
- end
+ build_lib libname, path: libpath
- it "updates the path on each cache" do
- build_lib "foo"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "#{libname}", :path => '#{libpath}'
+ G
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+ bundle :cache
+ expect(bundled_app("vendor/cache/#{libname}")).to exist
+ expect(bundled_app("vendor/cache/#{libname}/.bundlecache")).to be_file
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
+ expect(the_bundle).to include_gems "#{libname} 1.0"
+ end
- build_lib "foo" do |s|
- s.write "lib/foo.rb", "puts :CACHE"
- end
+ it "updates the path on each cache" do
+ build_lib "foo"
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
- expect(bundled_app("vendor/cache/foo-1.0")).to exist
- FileUtils.rm_rf lib_path("foo-1.0")
+ bundle :cache
- run "require 'foo'"
- expect(out).to eq("CACHE")
+ build_lib "foo" do |s|
+ s.write "lib/foo.rb", "puts :CACHE"
end
- it "removes stale entries cache" do
- build_lib "foo"
+ bundle :cache
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
-
- install_gemfile <<-G
- gem "bar", :path => '#{lib_path("bar-1.0")}'
- G
-
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- expect(bundled_app("vendor/cache/bar-1.0")).not_to exist
- end
+ run "require 'foo'"
+ expect(out).to eq("CACHE")
+ end
- it "raises a warning without --all", :bundler => "< 3" do
- build_lib "foo"
+ it "removes stale entries cache" do
+ build_lib "foo"
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
- bundle cmd
- expect(out).to match(/please pass the \-\-all flag/)
- expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
- end
+ bundle :cache
- it "stores the given flag" do
- build_lib "foo"
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+ build_lib "bar"
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- build_lib "bar"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "bar", :path => '#{lib_path("bar-1.0")}'
+ G
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- gem "bar", :path => '#{lib_path("bar-1.0")}'
- G
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
+ end
- bundle cmd
- expect(bundled_app("vendor/cache/bar-1.0")).to exist
- end
+ it "does not cache path gems if cache_all is set to false" do
+ build_lib "foo"
- it "can rewind chosen configuration" do
- build_lib "foo"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
+ bundle_config "cache_all false"
- install_gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- G
+ bundle :cache
+ expect(err).to be_empty
+ expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
+ end
- bundle cmd, forgotten_command_line_options([:all, :cache_all] => true)
- build_lib "baz"
+ it "caches path gems by default" do
+ build_lib "foo"
- gemfile <<-G
- gem "foo", :path => '#{lib_path("foo-1.0")}'
- gem "baz", :path => '#{lib_path("baz-1.0")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
- bundle "#{cmd} --no-all"
- expect(bundled_app("vendor/cache/baz-1.0")).not_to exist
- end
+ bundle :cache
+ expect(err).to be_empty
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
end
end
diff --git a/spec/bundler/cache/platform_spec.rb b/spec/bundler/cache/platform_spec.rb
index c0622a3c94..71c0eaee8e 100644
--- a/spec/bundler/cache/platform_spec.rb
+++ b/spec/bundler/cache/platform_spec.rb
@@ -3,10 +3,10 @@
RSpec.describe "bundle cache with multiple platforms" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
platforms :mri, :rbx do
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
end
platforms :jruby do
@@ -16,9 +16,9 @@ RSpec.describe "bundle cache with multiple platforms" do
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
activesupport (2.3.5)
PLATFORMS
@@ -26,24 +26,24 @@ RSpec.describe "bundle cache with multiple platforms" do
java
DEPENDENCIES
- rack (1.0.0)
+ myrack (1.0.0)
activesupport (2.3.5)
G
- cache_gems "rack-1.0.0", "activesupport-2.3.5"
+ cache_gems "myrack-1.0.0", "activesupport-2.3.5"
end
it "ensures that a successful bundle install does not delete gems for other platforms" do
- bundle! "install"
+ bundle "install"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
end
it "ensures that a successful bundle update does not delete gems for other platforms" do
- bundle! "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
end
end
diff --git a/spec/bundler/commands/add_spec.rb b/spec/bundler/commands/add_spec.rb
index 9f11adbcf8..162650f2e5 100644
--- a/spec/bundler/commands/add_spec.rb
+++ b/spec/bundler/commands/add_spec.rb
@@ -9,209 +9,440 @@ RSpec.describe "bundle add" do
build_gem "bar", "0.12.3"
build_gem "cat", "0.12.3.pre"
build_gem "dog", "1.1.3.pre"
+ build_gem "lemur", "3.1.1.pre.2023.1.1"
end
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ build_git "foo", "2.0"
+
+ gemfile <<-G
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
G
end
context "when no gems are specified" do
it "shows error" do
- bundle "add"
+ bundle "add", raise_on_error: false
- expect(last_command.bundler_err).to include("Please specify gems to add")
+ expect(err).to include("Please specify gems to add")
+ end
+ end
+
+ context "when Gemfile is empty, and frozen mode is set" do
+ it "shows error" do
+ gemfile 'source "https://gem.repo2"'
+ bundle "add bar", raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
+
+ expect(err).to include("Frozen mode is set, but there's no lockfile")
end
end
describe "without version specified" do
- it "version requirement becomes ~> major.minor.patch when resolved version is < 1.0" do
+ it "version requirement becomes >= major.minor.patch when resolved version is < 1.0" do
bundle "add 'bar'"
- expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/)
+ expect(bundled_app_gemfile.read).to match(/gem "bar", ">= 0.12.3"/)
expect(the_bundle).to include_gems "bar 0.12.3"
end
- it "version requirement becomes ~> major.minor when resolved version is > 1.0" do
+ it "version requirement becomes >= major.minor when resolved version is > 1.0" do
bundle "add 'baz'"
- expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/)
+ expect(bundled_app_gemfile.read).to match(/gem "baz", ">= 1.2"/)
expect(the_bundle).to include_gems "baz 1.2.3"
end
- it "version requirement becomes ~> major.minor.patch.pre when resolved version is < 1.0" do
+ it "version requirement becomes >= major.minor.patch.pre when resolved version is < 1.0" do
bundle "add 'cat'"
- expect(bundled_app("Gemfile").read).to match(/gem "cat", "~> 0.12.3.pre"/)
+ expect(bundled_app_gemfile.read).to match(/gem "cat", ">= 0.12.3.pre"/)
expect(the_bundle).to include_gems "cat 0.12.3.pre"
end
- it "version requirement becomes ~> major.minor.pre when resolved version is > 1.0.pre" do
+ it "version requirement becomes >= major.minor.pre when resolved version is >= 1.0.pre" do
bundle "add 'dog'"
- expect(bundled_app("Gemfile").read).to match(/gem "dog", "~> 1.1.pre"/)
+ expect(bundled_app_gemfile.read).to match(/gem "dog", ">= 1.1.pre"/)
expect(the_bundle).to include_gems "dog 1.1.3.pre"
end
+
+ it "version requirement becomes >= major.minor.pre.tail when resolved version has a very long tail pre version" do
+ bundle "add 'lemur'"
+ # the trailing pre purposely matches the release version to ensure that subbing the release doesn't change the pre.version"
+ expect(bundled_app_gemfile.read).to match(/gem "lemur", ">= 3.1.pre.2023.1.1"/)
+ expect(the_bundle).to include_gems "lemur 3.1.1.pre.2023.1.1"
+ end
end
describe "with --version" do
it "adds dependency of specified version and runs install" do
bundle "add 'foo' --version='~> 1.0'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 1.0"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 1.0"/)
expect(the_bundle).to include_gems "foo 1.1"
end
it "adds multiple version constraints when specified" do
requirements = ["< 3.0", "> 1.0"]
bundle "add 'foo' --version='#{requirements.join(", ")}'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(", ")}/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
+ describe "with --require" do
+ it "adds the require param for the gem" do
+ bundle "add 'foo' --require=foo/engine"
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo",(?: .*,) require: "foo\/engine"})
+ end
+
+ it "converts false to a boolean" do
+ bundle "add 'foo' --require=false"
+ expect(bundled_app_gemfile.read).to match(/gem "foo",(?: .*,) require: false/)
+ end
+ end
+
describe "with --group" do
it "adds dependency for the specified group" do
bundle "add 'foo' --group='development'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :group => :development/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2.0", group: :development/)
expect(the_bundle).to include_gems "foo 2.0"
end
it "adds dependency to more than one group" do
bundle "add 'foo' --group='development, test'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :groups => \[:development, :test\]/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2.0", groups: \[:development, :test\]/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
describe "with --source" do
it "adds dependency with specified source" do
- bundle "add 'foo' --source='file://#{gem_repo2}'"
+ bundle "add 'foo' --source='https://gem.repo2'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", ">= 2.0", source: "https://gem.repo2"})
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --path" do
+ it "adds dependency with specified path" do
+ bundle "add 'foo' --path='#{lib_path("foo-2.0")}'"
+
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2.0", path: "#{lib_path("foo-2.0")}"/)
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --git" do
+ it "adds dependency with specified git source" do
+ bundle "add foo --git=#{lib_path("foo-2.0")}"
+
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2.0", git: "#{lib_path("foo-2.0")}"/)
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --git and --branch" do
+ before do
+ update_git "foo", "2.0", branch: "test"
+ end
+
+ it "adds dependency with specified git source and branch" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --branch=test"
- expect(bundled_app("Gemfile").read).to match(%r{gem "foo", "~> 2.0", :source => "file:\/\/#{gem_repo2}"})
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2.0", git: "#{lib_path("foo-2.0")}", branch: "test"/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
+ describe "with --git and --ref" do
+ it "adds dependency with specified git source and branch" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --ref=#{revision_for(lib_path("foo-2.0"))}"
+
+ expect(bundled_app_gemfile.read).to match(/gem "foo", ">= 2\.0", git: "#{lib_path("foo-2.0")}", ref: "#{revision_for(lib_path("foo-2.0"))}"/)
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --github" do
+ before do
+ build_git "rake", "13.0"
+ git("config --global url.file://#{lib_path("rake-13.0")}.insteadOf https://github.com/ruby/rake.git")
+ end
+
+ it "adds dependency with specified github source" do
+ bundle "add rake --github=ruby/rake"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake"})
+ end
+
+ it "adds dependency with specified github source and branch" do
+ bundle "add rake --github=ruby/rake --branch=main"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake", branch: "main"})
+ end
+
+ it "adds dependency with specified github source and ref" do
+ ref = revision_for(lib_path("rake-13.0"))
+ bundle "add rake --github=ruby/rake --ref=#{ref}"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake", ref: "#{ref}"})
+ end
+
+ it "adds dependency with specified github source and glob" do
+ bundle "add rake --github=ruby/rake --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake", glob: "\.\/\*\.gemspec"})
+ end
+
+ it "adds dependency with specified github source, branch and glob" do
+ bundle "add rake --github=ruby/rake --branch=main --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake", branch: "main", glob: "\.\/\*\.gemspec"})
+ end
+
+ it "adds dependency with specified github source, ref and glob" do
+ ref = revision_for(lib_path("rake-13.0"))
+ bundle "add rake --github=ruby/rake --ref=#{ref} --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", ">= 13\.\d+", github: "ruby\/rake", ref: "#{ref}", glob: "\.\/\*\.gemspec"})
+ end
+ end
+
+ describe "with --git and --glob" do
+ it "adds dependency with specified git source" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", ">= 2.0", git: "#{lib_path("foo-2.0")}", glob: "\./\*\.gemspec"})
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --git and --branch and --glob" do
+ before do
+ update_git "foo", "2.0", branch: "test"
+ end
+
+ it "adds dependency with specified git source and branch" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --branch=test --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", ">= 2.0", git: "#{lib_path("foo-2.0")}", branch: "test", glob: "\./\*\.gemspec"})
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --git and --ref and --glob" do
+ it "adds dependency with specified git source and branch" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --ref=#{revision_for(lib_path("foo-2.0"))} --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", ">= 2\.0", git: "#{lib_path("foo-2.0")}", ref: "#{revision_for(lib_path("foo-2.0"))}", glob: "\./\*\.gemspec"})
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with mismatched pair in --git/--github, --branch/--ref" do
+ describe "with --git and --github" do
+ it "throws error" do
+ bundle "add 'foo' --git x --github y", raise_on_error: false
+
+ expect(err).to include("You cannot specify `--git` and `--github` at the same time.")
+ end
+ end
+
+ describe "with --branch and --ref with --git" do
+ it "throws error" do
+ bundle "add 'foo' --branch x --ref y --git file://git", raise_on_error: false
+
+ expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.")
+ end
+ end
+
+ describe "with --branch but without --git or --github" do
+ it "throws error" do
+ bundle "add 'foo' --branch x", raise_on_error: false
+
+ expect(err).to include("You cannot specify `--branch` unless `--git` or `--github` is specified.")
+ end
+ end
+
+ describe "with --ref but without --git or --github" do
+ it "throws error" do
+ bundle "add 'foo' --ref y", raise_on_error: false
+
+ expect(err).to include("You cannot specify `--ref` unless `--git` or `--github` is specified.")
+ end
+ end
+ end
+
describe "with --skip-install" do
it "adds gem to Gemfile but is not installed" do
bundle "add foo --skip-install --version=2.0"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "= 2.0"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "= 2.0"/)
expect(the_bundle).to_not include_gems "foo 2.0"
end
end
it "using combination of short form options works like long form" do
- bundle "add 'foo' -s='file://#{gem_repo2}' -g='development' -v='~>1.0'"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 1.0", :group => :development, :source => "file://#{gem_repo2}")
+ bundle "add 'foo' -s='https://gem.repo2' -g='development' -v='~>1.0'"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 1.0", group: :development, source: "https://gem.repo2")
expect(the_bundle).to include_gems "foo 1.1"
end
it "shows error message when version is not formatted correctly" do
- bundle "add 'foo' -v='~>1 . 0'"
- expect(out).to match("Invalid gem requirement pattern '~>1 . 0'")
+ bundle "add 'foo' -v='~>1 . 0'", raise_on_error: false
+ expect(err).to match("Invalid gem requirement pattern '~>1 . 0'")
end
it "shows error message when gem cannot be found" do
- bundle "add 'werk_it'"
- expect(out).to match("Could not find gem 'werk_it' in")
+ bundle_config "force_ruby_platform true"
+ bundle "add 'werk_it'", raise_on_error: false
+ expect(err).to match("Could not find gem 'werk_it' in")
- bundle "add 'werk_it' -s='file://#{gem_repo2}'"
- expect(out).to match("Could not find gem 'werk_it' in rubygems repository")
+ bundle "add 'werk_it' -s='https://gem.repo2'", raise_on_error: false
+ expect(err).to match("Could not find gem 'werk_it' in rubygems repository")
end
it "shows error message when source cannot be reached" do
- bundle "add 'baz' --source='http://badhostasdf'"
- expect(out).to include("Could not reach host badhostasdf. Check your network connection and try again.")
+ bundle "add 'baz' --source='http://badhostasdf'", raise_on_error: false, artifice: "fail"
+ expect(err).to include("Could not reach host badhostasdf. Check your network connection and try again.")
- bundle "add 'baz' --source='file://does/not/exist'"
- expect(out).to include("Could not fetch specs from file://does/not/exist/")
+ bundle "add 'baz' --source='file://does/not/exist'", raise_on_error: false
+ expect(err).to include("Could not fetch specs from file://does/not/exist/")
end
describe "with --optimistic" do
- it "adds optimistic version" do
- bundle! "add 'foo' --optimistic"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", ">= 2.0")
+ it "ignores option" do
+ bundle "add 'foo' --optimistic"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", ">= 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
+ describe "with --pessimistic" do
+ it "adds pessimistic version" do
+ bundle "add 'foo' --pessimistic"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 2.0")
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --quiet option" do
+ it "is quiet when there are no warnings" do
+ bundle "add 'foo' --quiet"
+ expect(out).to be_empty
+ expect(err).to be_empty
+ end
+
+ it "still displays warning and errors" do
+ create_file("add_with_warning.rb", <<~RUBY)
+ require "#{lib_dir}/bundler"
+ require "#{lib_dir}/bundler/cli"
+ require "#{lib_dir}/bundler/cli/add"
+
+ module RunWithWarning
+ def run
+ super
+ rescue
+ Bundler.ui.warn "This is a warning"
+ raise
+ end
+ end
+
+ Bundler::CLI::Add.prepend(RunWithWarning)
+ RUBY
+
+ bundle "add 'non-existing-gem' --quiet", raise_on_error: false, env: { "RUBYOPT" => "-r#{bundled_app("add_with_warning.rb")}" }
+ expect(out).to be_empty
+ expect(err).to include("Could not find gem 'non-existing-gem'")
+ expect(err).to include("This is a warning")
+ end
+ end
+
describe "with --strict option" do
it "adds strict version" do
- bundle! "add 'foo' --strict"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "= 2.0")
+ bundle "add 'foo' --strict"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "= 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
describe "with no option" do
- it "adds pessimistic version" do
- bundle! "add 'foo'"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 2.0")
+ it "adds optimistic version" do
+ bundle "add 'foo'"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", ">= 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
- describe "with --optimistic and --strict" do
+ describe "with --pessimistic and --strict" do
it "throws error" do
- bundle "add 'foo' --strict --optimistic"
+ bundle "add 'foo' --strict --pessimistic", raise_on_error: false
- expect(out).to include("You can not specify `--strict` and `--optimistic` at the same time")
+ expect(err).to include("You cannot specify `--strict` and `--pessimistic` at the same time")
end
end
context "multiple gems" do
it "adds multiple gems to gemfile" do
- bundle! "add bar baz"
+ bundle "add bar baz"
- expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/)
- expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/)
+ expect(bundled_app_gemfile.read).to match(/gem "bar", ">= 0.12.3"/)
+ expect(bundled_app_gemfile.read).to match(/gem "baz", ">= 1.2"/)
end
it "throws error if any of the specified gems are present in the gemfile with different version" do
- bundle "add weakling bar"
+ bundle "add weakling bar", raise_on_error: false
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).to include("You specified: weakling (~> 0.0.1) and weakling (>= 0).")
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: weakling (~> 0.0.1) and weakling (>= 0).")
end
end
describe "when a gem is added which is already specified in Gemfile with version" do
it "shows an error when added with different version requirement" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", "1.0"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
G
- bundle "add 'rack' --version=1.1"
+ bundle "add 'myrack' --version=1.1", raise_on_error: false
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("If you want to update the gem version, run `bundle update myrack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
end
it "shows error when added without version requirements" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", "1.0"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
G
- bundle "add 'rack'"
+ bundle "add 'myrack'", raise_on_error: false
- expect(out).to include("Gem already added.")
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).not_to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ expect(err).to include("Gem already added.")
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).not_to include("If you want to update the gem version, run `bundle update myrack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
end
end
describe "when a gem is added which is already specified in Gemfile without version" do
it "shows an error when added with different version requirement" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
- bundle "add 'rack' --version=1.1"
+ bundle "add 'myrack' --version=1.1", raise_on_error: false
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("If you want to update the gem version, run `bundle update myrack`.")
+ expect(err).not_to include("You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ end
+ end
+
+ describe "when a gem is added and cache exists" do
+ it "caches all new dependencies added for the specified gem" do
+ bundle :cache
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).to include("If you want to update the gem version, run `bundle update rack`.")
- expect(out).not_to include("You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
+ bundle "add 'myrack' --version=1.0.0"
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
end
end
diff --git a/spec/bundler/commands/binstubs_spec.rb b/spec/bundler/commands/binstubs_spec.rb
index 7f2e81c099..af4d24a9e8 100644
--- a/spec/bundler/commands/binstubs_spec.rb
+++ b/spec/bundler/commands/binstubs_spec.rb
@@ -4,267 +4,95 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem exists in the lockfile" do
it "sets up the binstub" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
end
it "does not install other binstubs" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "rails"
G
bundle "binstubs rails"
- expect(bundled_app("bin/rackup")).not_to exist
+ expect(bundled_app("bin/myrackup")).not_to exist
expect(bundled_app("bin/rails")).to exist
end
it "does install multiple binstubs" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "rails"
G
- bundle "binstubs rails rack"
+ bundle "binstubs rails myrack"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
expect(bundled_app("bin/rails")).to exist
end
it "allows installing all binstubs" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "rails"
G
- bundle! :binstubs, :all => true
+ bundle :binstubs, all: true
expect(bundled_app("bin/rails")).to exist
expect(bundled_app("bin/rake")).to exist
end
- it "displays an error when used without any gem" do
+ it "allows installing binstubs for all platforms" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs"
- expect(exitstatus).to eq(1) if exitstatus
- expect(out).to include("`bundle binstubs` needs at least one gem to run.")
+ bundle "binstubs myrack --all-platforms"
+
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(bundled_app("bin/myrackup.cmd")).to exist
end
- it "displays an error when used with --all and gems" do
+ it "displays an error when used without any gem" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack", :all => true
- expect(last_command).to be_failure
- expect(last_command.bundler_err).to include("Cannot specify --all with specific gems")
- end
-
- context "when generating bundle binstub outside bundler" do
- it "should abort" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- bundle "binstubs rack"
-
- File.open("bin/bundle", "wb") do |file|
- file.print "OMG"
- end
-
- sys_exec "bin/rackup"
-
- expect(last_command.stderr).to include("was not generated by Bundler")
- end
+ bundle "binstubs", raise_on_error: false
+ expect(exitstatus).to eq(1)
+ expect(err).to include("`bundle binstubs` needs at least one gem to run.")
end
- context "the bundle binstub" do
- before do
- if system_bundler_version == :bundler
- system_gems :bundler
- elsif system_bundler_version
- build_repo4 do
- build_gem "bundler", system_bundler_version do |s|
- s.executables = "bundle"
- s.bindir = "exe"
- s.write "exe/bundle", "puts %(system bundler #{system_bundler_version}\\n\#{ARGV.inspect})"
- end
- end
- system_gems "bundler-#{system_bundler_version}", :gem_repo => gem_repo4
- end
- build_repo2 do
- build_gem "prints_loaded_gems", "1.0" do |s|
- s.executables = "print_loaded_gems"
- s.bindir = "exe"
- s.write "exe/print_loaded_gems", <<-R
- specs = Gem.loaded_specs.values.reject {|s| Bundler.rubygems.spec_default_gem?(s) }
- puts specs.map(&:full_name).sort.inspect
- R
- end
- end
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
- gem "rack"
- gem "prints_loaded_gems"
- G
- bundle! "binstubs bundler rack prints_loaded_gems"
- end
-
- # When environment has a same version of bundler as default gems.
- # `system_gems "bundler-x.y.z"` will detect system binstub.
- # We need to avoid it by virtual version of bundler.
- let(:system_bundler_version) { Gem::Version.new(Bundler::VERSION).bump.to_s }
-
- context "when system bundler was used" do
- # Support master branch of bundler
- if ENV["BUNDLER_SPEC_SUB_VERSION"]
- let(:system_bundler_version) { Bundler::VERSION }
- end
-
- before do
- gemfile <<-G
- source "file:///Users/colby/Projects/bundler/tmp/gems/remote2"
- gem "rack"
- gem "prints_loaded_gems"
- G
-
- lockfile <<-G
- GEM
- remote: file:///Users/colby/Projects/bundler/tmp/gems/remote2/
- specs:
- prints_loaded_gems (1.0)
- rack (1.2)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- prints_loaded_gems
- rack
-
- BUNDLED WITH
- #{system_bundler_version}
- G
- end
-
- it "runs bundler" do
- sys_exec! "#{bundled_app("bin/bundle")} install"
- expect(out).to eq %(system bundler #{system_bundler_version}\n["install"])
- end
- end
-
- context "when BUNDLER_VERSION is set" do
- let(:system_bundler_version) { Bundler::VERSION }
-
- it "runs the correct version of bundler" do
- sys_exec "BUNDLER_VERSION='999.999.999' #{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (999.999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
- end
- end
-
- context "when a lockfile exists with a locked bundler version" do
- let(:system_bundler_version) { Bundler::VERSION }
-
- it "runs the correct version of bundler when the version is newer" do
- lockfile lockfile.gsub(system_bundler_version, "999.999.999")
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (999.999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
- end
-
- it "runs the correct version of bundler when the version is older" do
- simulate_bundler_version "55"
- lockfile lockfile.gsub(system_bundler_version, "44.0")
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (44.0) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '44.0'`")
- end
-
- it "runs the correct version of bundler when the version is a pre-release" do
- simulate_bundler_version "55"
- lockfile lockfile.gsub(system_bundler_version, "2.12.0.a")
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (2.12.0.a) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '2.12.0.a'`")
- end
- end
-
- context "when update --bundler is called" do
- before { lockfile.gsub(system_bundler_version, "1.1.1") }
-
- it "calls through to the latest bundler version" do
- sys_exec! "#{bundled_app("bin/bundle")} update --bundler"
- expect(last_command.stdout).to eq %(system bundler #{system_bundler_version}\n["update", "--bundler"])
- end
-
- it "calls through to the explicit bundler version" do
- sys_exec "#{bundled_app("bin/bundle")} update --bundler=999.999.999"
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (999.999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
- end
- end
-
- context "without a lockfile" do
- it "falls back to the latest installed bundler" do
- FileUtils.rm bundled_app("Gemfile.lock")
- sys_exec! bundled_app("bin/bundle").to_s
- expect(out).to eq "system bundler #{system_bundler_version}\n[]"
- end
- end
-
- context "using another binstub" do
- let(:system_bundler_version) { :bundler }
- it "loads all gems" do
- sys_exec! bundled_app("bin/print_loaded_gems").to_s
- # RG < 2.0.14 didn't have a `Gem::Specification#default_gem?`
- # This is dirty detection for old RG versions.
- if File.dirname(Bundler.load.specs["bundler"][0].loaded_from) =~ %r{specifications/default}
- expect(out).to eq %(["prints_loaded_gems-1.0", "rack-1.2"])
- else
- expect(out).to eq %(["bundler-#{Bundler::VERSION}", "prints_loaded_gems-1.0", "rack-1.2"])
- end
- end
-
- context "when requesting a different bundler version" do
- before { lockfile lockfile.gsub(Bundler::VERSION, "999.999.999") }
+ it "displays an error when used with --all and gems" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
- it "attempts to load that version", :ruby_repo do
- sys_exec bundled_app("bin/rackup").to_s
- expect(exitstatus).to eq(42) if exitstatus
- expect(last_command.stderr).to include("Activating bundler (999.999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
- end
- end
- end
+ bundle "binstubs myrack", all: true, raise_on_error: false
+ expect(last_command).to be_failure
+ expect(err).to include("Cannot specify --all with specific gems")
end
it "installs binstubs from git gems" do
FileUtils.mkdir_p(lib_path("foo/bin"))
FileUtils.touch(lib_path("foo/bin/foo"))
- build_git "foo", "1.0", :path => lib_path("foo") do |s|
+ build_git "foo", "1.0", path: lib_path("foo") do |s|
s.executables = %w[foo]
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo")}"
G
@@ -276,10 +104,11 @@ RSpec.describe "bundle binstubs <gem>" do
it "installs binstubs from path gems" do
FileUtils.mkdir_p(lib_path("foo/bin"))
FileUtils.touch(lib_path("foo/bin/foo"))
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.executables = %w[foo]
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -291,26 +120,25 @@ RSpec.describe "bundle binstubs <gem>" do
it "sets correct permissions for binstubs" do
with_umask(0o002) do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
- binary = bundled_app("bin/rackup")
- expect(File.stat(binary).mode.to_s(8)).to eq("100775")
+ bundle "binstubs myrack"
+ binary = bundled_app("bin/myrackup")
+ expect(File.stat(binary).mode.to_s(8)).to eq(Gem.win_platform? ? "100644" : "100775")
end
end
context "when using --shebang" do
- it "sets the specified shebang for the the binstub" do
+ it "sets the specified shebang for the binstub" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack --shebang jruby"
-
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env jruby\n")
+ bundle "binstubs myrack --shebang jruby"
+ expect(File.readlines(bundled_app("bin/myrackup")).first).to eq("#!/usr/bin/env jruby\n")
end
end
end
@@ -318,64 +146,83 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem doesn't exist" do
it "displays an error with correct status" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
- bundle "binstubs doesnt_exist"
+ bundle "binstubs doesnt_exist", raise_on_error: false
- expect(exitstatus).to eq(7) if exitstatus
- expect(out).to include("Could not find gem 'doesnt_exist'.")
+ expect(exitstatus).to eq(7)
+ expect(err).to include("Could not find gem 'doesnt_exist'.")
end
end
- context "--path" do
- it "sets the binstubs dir" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- bundle "binstubs rack --path exec"
-
- expect(bundled_app("exec/rackup")).to exist
+ context "with the binstubs dir configured" do
+ before do
+ bundle_config "bin exec"
end
- it "setting is saved for bundle install", :bundler => "< 3" do
+ it "creates the binstubs in the configured dir" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rails"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle! "binstubs rack", forgotten_command_line_options([:path, :bin] => "exec")
- bundle! :install
+ bundle "binstubs myrack"
- expect(bundled_app("exec/rails")).to exist
+ expect(bundled_app("exec/myrackup")).to exist
end
end
context "with --standalone option" do
before do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "rails"
G
end
it "generates a standalone binstub" do
- bundle! "binstubs rack --standalone"
- expect(bundled_app("bin/rackup")).to exist
+ bundle "binstubs myrack --standalone"
+ expect(bundled_app("bin/myrackup")).to exist
end
it "generates a binstub that does not depend on rubygems or bundler" do
- bundle! "binstubs rack --standalone"
- expect(File.read(bundled_app("bin/rackup"))).to_not include("Gem.bin_path")
+ bundle "binstubs myrack --standalone"
+ expect(File.read(bundled_app("bin/myrackup"))).to_not include("Gem.bin_path")
+ end
+
+ it "generates a standalone binstub at the given path when configured" do
+ bundle_config "bin foo"
+ bundle "binstubs myrack --standalone"
+ expect(bundled_app("foo/myrackup")).to exist
end
- context "when specified --path option" do
- it "generates a standalone binstub at the given path" do
- bundle! "binstubs rack --standalone --path foo"
- expect(bundled_app("foo/rackup")).to exist
+ context "when specified --all-platforms option" do
+ it "generates standalone binstubs for all platforms" do
+ bundle "binstubs myrack --standalone --all-platforms"
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(bundled_app("bin/myrackup.cmd")).to exist
+ end
+ end
+
+ context "when the gem is bundler" do
+ it "warns without generating a standalone binstub" do
+ bundle "binstubs bundler --standalone"
+ expect(bundled_app("bin/bundle")).not_to exist
+ expect(bundled_app("bin/bundler")).not_to exist
+ expect(err).to include("Sorry, Bundler can only be run via RubyGems.")
+ end
+ end
+
+ context "when specified --all option" do
+ it "generates standalone binstubs for all gems except bundler" do
+ bundle "binstubs --standalone --all"
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(bundled_app("bin/rails")).to exist
+ expect(bundled_app("bin/bundle")).not_to exist
+ expect(bundled_app("bin/bundler")).not_to exist
+ expect(err).not_to include("Sorry, Bundler can only be run via RubyGems.")
end
end
end
@@ -383,39 +230,39 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the bin already exists" do
it "doesn't overwrite and warns" do
FileUtils.mkdir_p(bundled_app("bin"))
- File.open(bundled_app("bin/rackup"), "wb") do |file|
+ File.open(bundled_app("bin/myrackup"), "wb") do |file|
file.print "OMG"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- expect(bundled_app("bin/rackup")).to exist
- expect(File.read(bundled_app("bin/rackup"))).to eq("OMG")
- expect(out).to include("Skipped rackup")
- expect(out).to include("overwrite skipped stubs, use --force")
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(File.read(bundled_app("bin/myrackup"))).to eq("OMG")
+ expect(err).to include("Skipped myrackup")
+ expect(err).to include("overwrite skipped stubs, use --force")
end
context "when using --force" do
it "overwrites the binstub" do
FileUtils.mkdir_p(bundled_app("bin"))
- File.open(bundled_app("bin/rackup"), "wb") do |file|
+ File.open(bundled_app("bin/myrackup"), "wb") do |file|
file.print "OMG"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack --force"
+ bundle "binstubs myrack --force"
- expect(bundled_app("bin/rackup")).to exist
- expect(File.read(bundled_app("bin/rackup"))).not_to eq("OMG")
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(File.read(bundled_app("bin/myrackup"))).not_to eq("OMG")
end
end
end
@@ -423,58 +270,64 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem has no bins" do
it "suggests child gems if they have bins" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack-obama"
G
- bundle "binstubs rack-obama"
- expect(out).to include("rack-obama has no executables")
- expect(out).to include("rack has: rackup")
+ bundle "binstubs myrack-obama"
+ expect(err).to include("myrack-obama has no executables")
+ expect(err).to include("myrack has: myrackup")
end
it "works if child gems don't have bins" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "actionpack"
G
bundle "binstubs actionpack"
- expect(out).to include("no executables for the gem actionpack")
+ expect(err).to include("no executables for the gem actionpack")
end
it "works if the gem has development dependencies" do
+ build_repo2 do
+ build_gem "with_development_dependency" do |s|
+ s.add_development_dependency "activesupport", "= 2.3.5"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "with_development_dependency"
G
bundle "binstubs with_development_dependency"
- expect(out).to include("no executables for the gem with_development_dependency")
+ expect(err).to include("no executables for the gem with_development_dependency")
end
end
context "when BUNDLE_INSTALL is specified" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "config auto_install 1"
- bundle "binstubs rack"
- expect(out).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle_config "auto_install 1"
+ bundle "binstubs myrack"
+ expect(out).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does nothing when already up to date" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "config auto_install 1"
- bundle "binstubs rack", :env => { "BUNDLE_INSTALL" => 1 }
- expect(out).not_to include("Installing rack 1.0.0")
+ bundle_config "auto_install 1"
+ bundle "binstubs myrack", env: { "BUNDLE_INSTALL" => "1" }
+ expect(out).not_to include("Installing myrack 1.0.0")
end
end
end
diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb
new file mode 100644
index 0000000000..e223d07f7f
--- /dev/null
+++ b/spec/bundler/commands/cache_spec.rb
@@ -0,0 +1,620 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle cache" do
+ it "doesn't update the cache multiple times, even if it already exists" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+ end
+
+ context "with --gemfile" do
+ it "finds the gemfile" do
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle "cache --gemfile=NotGemfile"
+
+ ENV["BUNDLE_GEMFILE"] = "NotGemfile"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+ end
+
+ context "with cache_all configured" do
+ context "without a gemspec" do
+ it "caches all dependencies except bundler itself" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ gem 'bundler'
+ D
+
+ bundle_config "cache_all true"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
+ end
+ end
+
+ context "with a gemspec" do
+ context "that has the same name as the gem" do
+ before do
+ File.open(bundled_app("mygem.gemspec"), "w") do |f|
+ f.write <<-G
+ Gem::Specification.new do |s|
+ s.name = "mygem"
+ s.version = "0.1.1"
+ s.summary = ""
+ s.authors = ["gem author"]
+ s.add_development_dependency "nokogiri", "=1.4.2"
+ end
+ G
+ end
+ end
+
+ it "caches all dependencies except bundler and the gemspec specified gem" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ gemspec
+ D
+
+ bundle_config "cache_all true"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
+ expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
+ expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
+ end
+ end
+
+ context "that has a different name as the gem" do
+ before do
+ File.open(bundled_app("mygem_diffname.gemspec"), "w") do |f|
+ f.write <<-G
+ Gem::Specification.new do |s|
+ s.name = "mygem"
+ s.version = "0.1.1"
+ s.summary = ""
+ s.authors = ["gem author"]
+ s.add_development_dependency "nokogiri", "=1.4.2"
+ end
+ G
+ end
+ end
+
+ it "caches all dependencies except bundler and the gemspec specified gem" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ gemspec
+ D
+
+ bundle_config "cache_all true"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
+ expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
+ expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
+ end
+ end
+ end
+
+ context "with multiple gemspecs" do
+ before do
+ File.open(bundled_app("mygem.gemspec"), "w") do |f|
+ f.write <<-G
+ Gem::Specification.new do |s|
+ s.name = "mygem"
+ s.version = "0.1.1"
+ s.summary = ""
+ s.authors = ["gem author"]
+ s.add_development_dependency "nokogiri", "=1.4.2"
+ end
+ G
+ end
+ File.open(bundled_app("mygem_client.gemspec"), "w") do |f|
+ f.write <<-G
+ Gem::Specification.new do |s|
+ s.name = "mygem_test"
+ s.version = "0.1.1"
+ s.summary = ""
+ s.authors = ["gem author"]
+ s.add_development_dependency "weakling", "=0.0.3"
+ end
+ G
+ end
+ end
+
+ it "caches all dependencies except bundler and the gemspec specified gems" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ gemspec :name => 'mygem'
+ gemspec :name => 'mygem_test'
+ D
+
+ bundle_config "cache_all true"
+ bundle :cache
+
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
+ expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
+ expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
+ expect(bundled_app("vendor/cache/mygem_test-0.1.1.gem")).to_not exist
+ expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
+ end
+ end
+ end
+
+ context "with --no-install" do
+ it "puts the gems in vendor/cache but does not install them" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ D
+
+ bundle "cache --no-install"
+
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "does not prevent installing gems with bundle install" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack'
+ D
+
+ bundle "cache --no-install"
+ bundle "install"
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "does not prevent installing gems with bundle update" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ D
+
+ bundle "cache --no-install"
+ bundle "update --all"
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+ end
+
+ context "with --all-platforms" do
+ it "puts the gems in vendor/cache even for other rubies" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack', :platforms => [:ruby_20, :windows_20]
+ D
+
+ bundle "cache --all-platforms"
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "prints a warn when using legacy windows rubies" do
+ gemfile <<-D
+ source "https://gem.repo1"
+ gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20]
+ D
+
+ bundle "cache --all-platforms", raise_on_error: false
+ expect(err).to include("will be removed in the future")
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "does not attempt to install gems in without groups" do
+ build_repo4 do
+ build_gem "uninstallable", "2.0" do |s|
+ s.add_development_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", "task(:default) { raise 'CANNOT INSTALL' }"
+ end
+ end
+
+ bundle_config "without wo"
+ install_gemfile <<-G, artifice: "compact_index_extra_api"
+ source "https://main.repo"
+ gem "myrack"
+ group :wo do
+ gem "weakling"
+ gem "uninstallable", :source => "https://main.repo/extra"
+ end
+ G
+
+ bundle :cache, "all-platforms" => true, artifice: "compact_index_extra_api"
+ expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
+ expect(bundled_app("vendor/cache/uninstallable-2.0.gem")).to exist
+ expect(the_bundle).to include_gem "myrack 1.0"
+ expect(the_bundle).not_to include_gems "weakling", "uninstallable"
+
+ bundle_config "without wo"
+ bundle :install, artifice: "compact_index_extra_api"
+ expect(the_bundle).to include_gem "myrack 1.0"
+ expect(the_bundle).not_to include_gems "weakling"
+ end
+
+ it "does not fail to cache gems in excluded groups when there's a lockfile but gems not previously installed" do
+ bundle_config "without wo"
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ group :wo do
+ gem "weakling"
+ end
+ G
+
+ bundle :lock
+ bundle :cache, "all-platforms" => true
+ expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
+ end
+ end
+
+ context "with frozen configured" do
+ let(:app_cache) { bundled_app("vendor/cache") }
+
+ before do
+ bundle_config "frozen true"
+ end
+
+ it "tries to install but fails when the lockfile is out of sync" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ myrack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ bundle :cache, raise_on_error: false
+ expect(exitstatus).to eq(16)
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have deleted from the Gemfile")
+ expect(err).to include("* myrack-obama")
+ bundle "env"
+ expect(out).to include("frozen")
+ end
+
+ it "caches gems without installing when lockfile is in sync, and --no-install is passed, even if vendor/cache directory is initially empty" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ FileUtils.mkdir_p app_cache
+
+ bundle "cache --no-install"
+ expect(out).not_to include("Installing myrack 1.0.0")
+ expect(out).to include("Fetching myrack 1.0.0")
+ expect(app_cache.join("myrack-1.0.0.gem")).to exist
+ end
+
+ it "completes a partial cache when lockfile is in sync, even if the already cached gem is no longer available remotely" do
+ build_repo4 do
+ build_gem "foo", "1.0.0"
+ end
+
+ build_gem "bar", "1.0.0", path: bundled_app("vendor/cache")
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ gem "bar"
+ G
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0.0)
+ bar (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "cache --no-install"
+ expect(out).to include("Fetching foo 1.0.0")
+ expect(out).not_to include("Fetching bar 1.0.0")
+ expect(app_cache.join("foo-1.0.0.gem")).to exist
+ expect(app_cache.join("bar-1.0.0.gem")).to exist
+ end
+ end
+
+ context "with gems with extensions" do
+ before do
+ build_repo2 do
+ build_gem "racc", "2.0" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", "task(:default) { puts 'INSTALLING myrack' }"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "racc"
+ G
+ end
+
+ it "installs them properly from cache to a different path" do
+ bundle "cache"
+ bundle_config "path vendor/bundle"
+ bundle "install --local"
+ end
+ end
+end
+
+RSpec.describe "bundle install with gem sources" do
+ describe "when cached and locked" do
+ it "does not hit the remote at all" do
+ build_repo2
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle :cache
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
+
+ bundle "install --local"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "does not hit the remote at all in frozen mode" do
+ build_repo2
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle :cache
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
+
+ bundle_config "deployment true"
+ bundle_config "path vendor/bundle"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "does not hit the remote at all in non frozen mode either" do
+ build_repo2
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle :cache
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
+
+ bundle_config "path vendor/bundle"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "does not hit the remote at all when cache_all_platforms configured" do
+ build_repo2
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle :cache
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
+
+ bundle_config "cache_all_platforms true"
+ bundle_config "path vendor/bundle"
+ bundle "install --local"
+ expect(out).not_to include("Fetching gem metadata")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "uses cached gems for secondary sources when cache_all_platforms configured" do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "foo", "1.0.0" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "foo"
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0.0-x86_64-linux)
+ foo (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle_config "cache_all_platforms true"
+ bundle_config "path vendor/bundle"
+ bundle :cache, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ # simulate removal of all remote gems
+ empty_repo4
+
+ # delete compact index cache
+ FileUtils.rm_r home(".bundle/cache/compact_index")
+
+ bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(the_bundle).to include_gems "foo 1.0.0 x86_64-linux"
+ end
+ end
+
+ it "does not reinstall already-installed gems" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ bundle :cache
+
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "raise 'omg'"
+ end
+
+ bundle :install
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems "myrack 1.0"
+ end
+
+ it "ignores cached gems for the wrong platform" do
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+ bundle :cache
+ end
+
+ pristine_system_gems
+
+ bundle_config "force_ruby_platform true"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+ expect(the_bundle).to include_gems("platform_specific 1.0 ruby")
+ end
+
+ it "keeps gems that are locked and cached for the current platform, even if incompatible with the current ruby" do
+ build_repo4 do
+ build_gem "bcrypt_pbkdf", "1.1.1"
+ build_gem "bcrypt_pbkdf", "1.1.1" do |s|
+ s.platform = "arm64-darwin"
+ s.required_ruby_version = "< #{current_ruby_minor}"
+ end
+ end
+
+ app_cache = bundled_app("vendor/cache")
+ FileUtils.mkdir_p app_cache
+ FileUtils.cp gem_repo4("gems/bcrypt_pbkdf-1.1.1-arm64-darwin.gem"), app_cache
+ FileUtils.cp gem_repo4("gems/bcrypt_pbkdf-1.1.1.gem"), app_cache
+
+ bundle_config "cache_all_platforms true"
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bcrypt_pbkdf (1.1.1)
+ bcrypt_pbkdf (1.1.1-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+ ruby
+
+ DEPENDENCIES
+ bcrypt_pbkdf
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-23" do
+ install_gemfile <<~G, verbose: true
+ source "https://gem.repo4"
+ gem "bcrypt_pbkdf"
+ G
+
+ expect(out).to include("Updating files in vendor/cache")
+ expect(err).to be_empty
+ expect(app_cache.join("bcrypt_pbkdf-1.1.1-arm64-darwin.gem")).to exist
+ expect(app_cache.join("bcrypt_pbkdf-1.1.1.gem")).to exist
+ end
+ end
+
+ it "does not update the cache if --no-cache is passed" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ bundled_app("vendor/cache").mkpath
+ expect(bundled_app("vendor/cache").children).to be_empty
+
+ bundle "install --no-cache"
+ expect(bundled_app("vendor/cache").children).to be_empty
+ end
+ end
+end
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index 890f4b1356..7fe6897ae3 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -3,163 +3,198 @@
RSpec.describe "bundle check" do
it "returns success when the Gemfile is satisfied" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
bundle :check
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "works with the --gemfile flag when not in the directory" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- Dir.chdir tmp
- bundle "check --gemfile bundled_app/Gemfile"
+ bundle "check --gemfile bundled_app/Gemfile", dir: tmp
expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "creates a Gemfile.lock by default if one does not exist" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "check"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "does not create a Gemfile.lock if --dry-run was passed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "check --dry-run"
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
end
- it "prints a generic error if the missing gems are unresolvable" do
- system_gems ["rails-2.3.2"]
+ it "prints an error that shows missing gems" do
+ system_gems ["rails-2.3.2"], path: default_bundle_path
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- bundle :check
- expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.")
+ bundle :check, raise_on_error: false
+ expect(err).to include("The following gems are missing")
+ expect(err).to include(" * rake (#{rake_version})")
+ expect(err).to include(" * actionpack (2.3.2)")
+ expect(err).to include(" * activerecord (2.3.2)")
+ expect(err).to include(" * actionmailer (2.3.2)")
+ expect(err).to include(" * activeresource (2.3.2)")
+ expect(err).to include(" * activesupport (2.3.2)")
+ expect(err).to include("Install missing gems with `bundle install`")
end
- it "prints a generic error if a Gemfile.lock does not exist and a toplevel dependency does not exist" do
+ it "prints an error that shows missing gems if a Gemfile.lock does not exist and a toplevel dependency is missing" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- bundle :check
- expect(exitstatus).to be > 0 if exitstatus
- expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.")
+ bundle :check, raise_on_error: false
+ expect(exitstatus).to be > 0
+ expect(err).to include("The following gems are missing")
+ expect(err).to include(" * rails (2.3.2)")
+ expect(err).to include(" * rake (#{rake_version})")
+ expect(err).to include(" * actionpack (2.3.2)")
+ expect(err).to include(" * activerecord (2.3.2)")
+ expect(err).to include(" * actionmailer (2.3.2)")
+ expect(err).to include(" * activeresource (2.3.2)")
+ expect(err).to include(" * activesupport (2.3.2)")
+ expect(err).to include("Install missing gems with `bundle install`")
end
- it "prints a generic message if you changed your lockfile" do
+ it "prints a generic error if gem git source is not checked out" do
+ build_git "foo", path: lib_path("foo")
+
+ bundle_config "path vendor/bundle"
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rails'
+ source "https://gem.repo1"
+ gem "foo", git: "#{lib_path("foo")}"
G
+
+ FileUtils.rm_r bundled_app("vendor/bundle")
+ bundle :check, raise_on_error: false
+ expect(exitstatus).to eq 1
+ expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
+ end
+
+ it "prints a generic message if you changed your lockfile" do
+ build_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rails_fail'
+ source "https://gem.repo2"
+ gem 'rails'
G
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "rails"
- gem "rails_fail"
+ gem "rails_pinned_to_old_activesupport"
G
- bundle :check
- expect(out).to include("Bundler can't satisfy your Gemfile's dependencies.")
+ bundle :check, raise_on_error: false
+ expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
- it "remembers --without option from install", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
+ it "uses the without setting" do
+ bundle_config "without foo"
+ install_gemfile <<-G
+ source "https://gem.repo1"
group :foo do
- gem "rack"
+ gem "myrack"
end
G
- bundle! "install --without foo"
- bundle! "check"
+ bundle "check"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
- it "uses the without setting" do
- bundle! "config without foo"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- group :foo do
- gem "rack"
- end
+ it "ensures that gems are actually installed and not just cached" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :group => :foo
G
- bundle! "check"
- expect(out).to include("The Gemfile's dependencies are satisfied")
- end
+ bundle_config "without foo"
+ bundle :install
- it "ensures that gems are actually installed and not just cached" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :group => :foo
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, forgotten_command_line_options(:without => "foo")
+ bundle "check", raise_on_error: false
+ expect(err).to include("* myrack (1.0.0)")
+ expect(exitstatus).to eq(1)
+ end
+ it "ensures that gems are actually installed and not just cached in applications' cache" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "check"
- expect(out).to include("* rack (1.0.0)")
- expect(exitstatus).to eq(1) if exitstatus
+ bundle_config "path vendor/bundle"
+ bundle :cache
+
+ uninstall_gem("myrack", env: { "GEM_HOME" => vendored_gems.to_s })
+
+ bundle "check", raise_on_error: false
+ expect(err).to include("* myrack (1.0.0)")
+ expect(exitstatus).to eq(1)
end
it "ignores missing gems restricted to other platforms" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
platforms :#{not_local_tag} do
gem "activesupport"
end
G
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
#{not_local}
DEPENDENCIES
- rack
+ myrack
activesupport
G
@@ -169,28 +204,28 @@ RSpec.describe "bundle check" do
it "works with env conditionals" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
env :NOT_GOING_TO_BE_SET do
gem "activesupport"
end
G
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
#{not_local}
DEPENDENCIES
- rack
+ myrack
activesupport
G
@@ -199,130 +234,341 @@ RSpec.describe "bundle check" do
end
it "outputs an error when the default Gemfile is not found" do
- bundle :check
- expect(exitstatus).to eq(10) if exitstatus
- expect(out).to include("Could not locate Gemfile")
+ bundle :check, raise_on_error: false
+ expect(exitstatus).to eq(10)
+ expect(err).to include("Could not locate Gemfile")
end
it "does not output fatal error message" do
- bundle :check
- expect(exitstatus).to eq(10) if exitstatus
- expect(out).not_to include("Unfortunately, a fatal error has occurred. ")
+ bundle :check, raise_on_error: false
+ expect(exitstatus).to eq(10)
+ expect(err).not_to include("Unfortunately, a fatal error has occurred. ")
end
- it "should not crash when called multiple times on a new machine" do
- gemfile <<-G
- gem 'rails', '3.0.0.beta3'
- gem 'paperclip', :git => 'git://github.com/thoughtbot/paperclip.git'
+ it "fails when there's no lockfile and frozen is set" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo"
G
- simulate_new_machine
- bundle "check"
- last_out = out
- 3.times do
+ bundle_config "deployment true"
+ bundle "install"
+ FileUtils.rm(bundled_app_lock)
+
+ bundle :check, raise_on_error: false
+ expect(last_command).to be_failure
+ end
+
+ describe "when locked" do
+ before :each do
+ system_gems "myrack-1.0.0"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+ end
+
+ it "returns success when the Gemfile is satisfied" do
+ bundle :install
bundle :check
- expect(out).to eq(last_out)
+ expect(out).to include("The Gemfile's dependencies are satisfied")
+ end
+
+ it "shows what is missing with the current Gemfile if it is not satisfied" do
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
+ bundle :check, raise_on_error: false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* myrack (1.0")
end
end
- it "fails when there's no lock file and frozen is set" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "foo"
- G
+ describe "when locked with multiple dependents with different requirements" do
+ before :each do
+ build_repo4 do
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack", ">= 1.0"
+ end
+ build_gem "also_depends_on_myrack" do |s|
+ s.add_dependency "myrack", "~> 1.0"
+ end
+ build_gem "myrack"
+ end
- bundle! "install", forgotten_command_line_options(:deployment => true)
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "depends_on_myrack"
+ gem "also_depends_on_myrack"
+ G
- bundle :check
- expect(last_command).to be_failure
+ bundle "lock"
+ end
+
+ it "shows what is missing with the current Gemfile without duplications" do
+ bundle :check, raise_on_error: false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* myrack (1.0").once
+ end
end
- context "--path", :bundler => "< 3" do
- before do
+ describe "when locked under multiple platforms" do
+ before :each do
+ build_repo4 do
+ build_gem "myrack"
+ end
+
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
+ source "https://gem.repo4"
+ gem "myrack"
G
- bundle "install --path vendor/bundle"
- FileUtils.rm_rf(bundled_app(".bundle"))
- end
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
- it "returns success" do
- bundle! "check --path vendor/bundle"
- expect(out).to include("The Gemfile's dependencies are satisfied")
+ PLATFORMS
+ ruby
+ #{local_platform}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
- it "should write to .bundle/config", :bundler => "< 3" do
- bundle "check --path vendor/bundle"
- bundle! "check"
+ it "shows what is missing with the current Gemfile without duplications" do
+ bundle :check, raise_on_error: false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* myrack (1.0").once
end
end
- context "--path vendor/bundle after installing gems in the default directory" do
- it "returns false" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
+ describe "when using only scoped rubygems sources" do
+ before do
+ gemfile <<~G
+ source "https://gem.repo2"
+ source "https://gem.repo1" do
+ gem "myrack"
+ end
G
+ end
- bundle "check --path vendor/bundle"
- expect(exitstatus).to eq(1) if exitstatus
- expect(out).to match(/The following gems are missing/)
+ it "returns success when the Gemfile is satisfied" do
+ system_gems "myrack-1.0.0", path: default_bundle_path
+ bundle :check, artifice: "compact_index"
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
end
- describe "when locked" do
- before :each do
- system_gems "rack-1.0.0"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0"
+ describe "when using only scoped rubygems sources with indirect dependencies" do
+ before do
+ build_repo4 do
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack"
+ end
+
+ build_gem "myrack"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo1"
+ source "https://gem.repo4" do
+ gem "depends_on_myrack"
+ end
G
end
- it "returns success when the Gemfile is satisfied" do
- bundle :install
- bundle :check
- expect(exitstatus).to eq(0) if exitstatus
+ it "returns success when the Gemfile is satisfied and generates a correct lockfile" do
+ system_gems "depends_on_myrack-1.0", "myrack-1.0", gem_repo: gem_repo4, path: default_bundle_path
+ bundle :check, artifice: "compact_index"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "depends_on_myrack", "1.0"
+ c.checksum gem_repo4, "myrack", "1.0"
+ end
+
expect(out).to include("The Gemfile's dependencies are satisfied")
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ depends_on_myrack (1.0)
+ myrack
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ depends_on_myrack!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
+ end
- it "shows what is missing with the current Gemfile if it is not satisfied" do
- simulate_new_machine
- bundle :check
- expect(out).to match(/The following gems are missing/)
- expect(out).to include("* rack (1.0")
+ context "with gemspec directive and scoped sources" do
+ before do
+ build_repo4 do
+ build_gem "awesome_print"
+ end
+
+ build_repo2 do
+ build_gem "dex-dispatch-engine"
+ end
+
+ build_lib("bundle-check-issue", path: tmp("bundle-check-issue")) do |s|
+ s.write "Gemfile", <<-G
+ source "https://localgemserver.test"
+
+ gemspec
+
+ source "https://localgemserver.test/extra" do
+ gem "dex-dispatch-engine"
+ end
+ G
+
+ s.add_dependency "awesome_print"
+ end
+
+ bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, dir: tmp("bundle-check-issue")
+ end
+
+ it "does not corrupt lockfile when changing version" do
+ version_file = tmp("bundle-check-issue/bundle-check-issue.gemspec")
+ File.write(version_file, File.read(version_file).gsub(/s\.version = .+/, "s.version = '9999'"))
+
+ bundle "check --verbose", dir: tmp("bundle-check-issue")
+
+ lockfile = File.read(tmp("bundle-check-issue/Gemfile.lock"))
+
+ checksums = checksums_section_when_enabled(lockfile) do |c|
+ c.checksum gem_repo4, "awesome_print", "1.0"
+ c.no_checksum "bundle-check-issue", "9999"
+ c.checksum gem_repo2, "dex-dispatch-engine", "1.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ bundle-check-issue (9999)
+ awesome_print
+
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ awesome_print (1.0)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ dex-dispatch-engine (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ bundle-check-issue!
+ dex-dispatch-engine!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with scoped and unscoped sources" do
+ it "does not corrupt lockfile" do
+ build_repo2 do
+ build_gem "foo"
+ build_gem "wadus"
+ build_gem("baz") {|s| s.add_dependency "wadus" }
+ end
+
+ build_repo4 do
+ build_gem "bar"
+ end
+
+ bundle_config "path.system true"
+
+ # Add all gems to ensure all gems are installed so that a bundle check
+ # would be successful
+ install_gemfile(<<-G, artifice: "compact_index_extra")
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gem "foo"
+ gem "baz"
+ G
+
+ original_lockfile = lockfile
+
+ # Remove "baz" gem from the Gemfile, and bundle install again to generate
+ # a functional lockfile with no "baz" dependency or "wadus" transitive
+ # dependency
+ install_gemfile(<<-G, artifice: "compact_index_extra")
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gem "foo"
+ G
+
+ # Add back "baz" gem back to the Gemfile, but _crucially_ we do not perform a
+ # bundle install
+ gemfile(gemfile + 'gem "baz"')
+
+ bundle :check, verbose: true
+
+ # Bundle check should succeed and restore the lockfile to its original
+ # state
+ expect(lockfile).to eq(original_lockfile)
end
end
describe "BUNDLED WITH" do
def lock_with(bundler_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
L
if bundler_version
- lock += "\n BUNDLED WITH\n #{bundler_version}\n"
+ lock += "\nBUNDLED WITH\n #{bundler_version}\n"
end
lock
end
before do
+ bundle_config "path vendor/bundle"
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -330,24 +576,25 @@ RSpec.describe "bundle check" do
it "does not change the lock" do
lockfile lock_with(nil)
bundle :check
- lockfile_should_be lock_with(nil)
+ expect(lockfile).to eq lock_with(nil)
end
end
context "is newer" do
- it "does not change the lock but warns" do
+ it "does not change the lock and does not warn" do
lockfile lock_with(Bundler::VERSION.succ)
- bundle! :check
- expect(last_command.bundler_err).to include("the running version of Bundler (#{Bundler::VERSION}) is older than the version that created the lockfile (#{Bundler::VERSION.succ})")
- lockfile_should_be lock_with(Bundler::VERSION.succ)
+ bundle :check
+ expect(err).to be_empty
+ expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
context "is older" do
it "does not change the lock" do
- lockfile lock_with("1.10.1")
+ system_gems "bundler-1.18.0"
+ lockfile lock_with("1.18.0")
bundle :check
- lockfile_should_be lock_with("1.10.1")
+ expect(lockfile).to eq lock_with("1.18.0")
end
end
end
diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb
index 158d58d67c..c77859d378 100644
--- a/spec/bundler/commands/clean_spec.rb
+++ b/spec/bundler/commands/clean_spec.rb
@@ -19,108 +19,116 @@ RSpec.describe "bundle clean" do
it "removes unused gems that are different" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
G
- bundle! "install"
+ bundle "install"
- bundle! :clean
+ bundle :clean
expect(out).to include("Removing foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0"
should_not_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes old version of gem if unused" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
gem "foo"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
gem "foo"
G
bundle "install"
bundle :clean
- expect(out).to include("Removing rack (0.9.1)")
+ expect(out).to include("Removing myrack (0.9.1)")
- should_have_gems "foo-1.0", "rack-1.0.0"
- should_not_have_gems "rack-0.9.1"
+ should_have_gems "foo-1.0", "myrack-1.0.0"
+ should_not_have_gems "myrack-0.9.1"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes new version of gem if unused" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
gem "foo"
G
- bundle! "update rack"
+ bundle "update myrack"
- bundle! :clean
+ bundle :clean
- expect(out).to include("Removing rack (1.0.0)")
+ expect(out).to include("Removing myrack (1.0.0)")
- should_have_gems "foo-1.0", "rack-0.9.1"
- should_not_have_gems "rack-1.0.0"
+ should_have_gems "foo-1.0", "myrack-0.9.1"
+ should_not_have_gems "myrack-1.0.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes gems in bundle without groups" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
group :test_group do
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
end
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
- bundle "install", forgotten_command_line_options(:without => "test_group")
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ bundle_config "without test_group"
+ bundle "install"
bundle :clean
- expect(out).to include("Removing rack (1.0.0)")
+ expect(out).to include("Removing myrack (1.0.0)")
should_have_gems "foo-1.0"
- should_not_have_gems "rack-1.0.0"
+ should_not_have_gems "myrack-1.0.0"
- expect(vendored_gems("bin/rackup")).to_not exist
+ expect(vendored_gems("bin/myrackup")).to_not exist
end
it "does not remove cached git dir if it's being used" do
@@ -129,43 +137,45 @@ RSpec.describe "bundle clean" do
git_path = lib_path("foo-1.0")
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
bundle :clean
digest = Digest(:SHA1).hexdigest(git_path.to_s)
- cache_path = Bundler.bundler_major_version < 3 ? vendored_gems("cache/bundler/git/foo-1.0-#{digest}") : home(".bundle/cache/git/foo-1.0-#{digest}")
+ cache_path = vendored_gems("cache/bundler/git/foo-1.0-#{digest}")
expect(cache_path).to exist
end
it "removes unused git gems" do
- build_git "foo", :path => lib_path("foo")
+ build_git "foo", path: lib_path("foo")
git_path = lib_path("foo")
revision = revision_for(git_path)
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle "install"
@@ -173,60 +183,90 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (#{revision[0..11]})")
- expect(vendored_gems("gems/rack-1.0.0")).to exist
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).not_to exist
digest = Digest(:SHA1).hexdigest(git_path.to_s)
expect(vendored_gems("cache/bundler/git/foo-#{digest}")).not_to exist
- expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
+ expect(vendored_gems("specifications/myrack-1.0.0.gemspec")).to exist
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
- it "removes old git gems" do
- build_git "foo-bar", :path => lib_path("foo-bar")
+ it "keeps used git gems even if installed to a symlinked location" do
+ build_git "foo", path: lib_path("foo")
+ git_path = lib_path("foo")
+ revision = revision_for(git_path)
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack", "1.0.0"
+ git "#{git_path}", :ref => "#{revision}" do
+ gem "foo"
+ end
+ G
+
+ FileUtils.mkdir_p(bundled_app("real-path"))
+ File.symlink(bundled_app("real-path"), bundled_app("symlink-path"))
+
+ bundle_config "path #{bundled_app("symlink-path")}"
+ bundle "install"
+
+ bundle :clean
+
+ expect(out).not_to include("Removing foo (#{revision[0..11]})")
+
+ expect(bundled_app("symlink-path/#{Bundler.ruby_scope}/bundler/gems/foo-#{revision[0..11]}")).to exist
+ end
+
+ it "removes old git gems on bundle update" do
+ build_git "foo-bar", path: lib_path("foo-bar")
revision = revision_for(lib_path("foo-bar"))
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{lib_path("foo-bar")}" do
gem "foo-bar"
end
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
- update_git "foo", :path => lib_path("foo-bar")
+ update_git "foo-bar", path: lib_path("foo-bar")
revision2 = revision_for(lib_path("foo-bar"))
- bundle! "update", :all => bundle_update_requires_all?
- bundle! :clean
+ bundle "update", all: true
+ bundle :clean
expect(out).to include("Removing foo-bar (#{revision[0..11]})")
- expect(vendored_gems("gems/rack-1.0.0")).to exist
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision[0..11]}")).not_to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision2[0..11]}")).to exist
- expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
+ expect(vendored_gems("specifications/myrack-1.0.0.gemspec")).to exist
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "does not remove nested gems in a git repo" do
- build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport")
- build_git "rails", "3.0", :path => lib_path("rails") do |s|
+ build_lib "activesupport", "3.0", path: lib_path("rails/activesupport")
+ build_git "rails", "3.0", path: lib_path("rails") do |s|
s.add_dependency "activesupport", "= 3.0"
end
revision = revision_for(lib_path("rails"))
gemfile <<-G
+ source "https://gem.repo1"
gem "activesupport", :git => "#{lib_path("rails")}", :ref => '#{revision}'
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
bundle :clean
expect(out).to include("")
@@ -234,21 +274,23 @@ RSpec.describe "bundle clean" do
end
it "does not remove git sources that are in without groups" do
- build_git "foo", :path => lib_path("foo")
+ build_git "foo", path: lib_path("foo")
git_path = lib_path("foo")
revision = revision_for(git_path)
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
group :test do
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
end
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :without => "test")
+ bundle_config "path vendor/bundle"
+ bundle_config "without test"
+ bundle "install"
bundle :clean
@@ -260,134 +302,127 @@ RSpec.describe "bundle clean" do
it "does not blow up when using without groups" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
group :development do
gem "foo"
end
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :without => "development")
+ bundle_config "path vendor/bundle"
+ bundle_config "without development"
+ bundle "install"
bundle :clean
- expect(exitstatus).to eq(0) if exitstatus
end
it "displays an error when used without --path" do
- bundle! "config path.system true"
+ bundle_config "path.system true"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- bundle :clean
+ bundle :clean, raise_on_error: false
- expect(exitstatus).to eq(15) if exitstatus
- expect(out).to include("--force")
+ expect(exitstatus).to eq(15)
+ expect(err).to include("--force")
end
# handling bundle clean upgrade path from the pre's
it "removes .gem/.gemspec file even if there's no corresponding gem dir" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
G
bundle "install"
- FileUtils.rm(vendored_gems("bin/rackup"))
- FileUtils.rm_rf(vendored_gems("gems/thin-1.0"))
- FileUtils.rm_rf(vendored_gems("gems/rack-1.0.0"))
+ FileUtils.rm(vendored_gems("bin/myrackup"))
+ FileUtils.rm_r(vendored_gems("gems/thin-1.0"))
+ FileUtils.rm_r(vendored_gems("gems/myrack-1.0.0"))
bundle :clean
- should_not_have_gems "thin-1.0", "rack-1.0"
+ should_not_have_gems "thin-1.0", "myrack-1.0"
should_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).not_to exist
+ expect(vendored_gems("bin/myrackup")).not_to exist
end
it "does not call clean automatically when using system gems" do
- bundle! "config path.system true"
+ bundle_config "path.system true"
- bundle! :config
-
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
-
- gem "thin"
- gem "rack"
- G
-
- bundle! "info thin"
-
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
-
- gem "rack"
- G
-
- sys_exec! "gem list"
- expect(out).to include("rack (1.0.0)").and include("thin (1.0)")
- end
-
- it "--clean should override the bundle setting on install", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "thin"
- gem "rack"
+ gem "myrack"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => true)
- gemfile <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- bundle "install"
- should_have_gems "rack-1.0.0"
- should_not_have_gems "thin-1.0"
+ installed_gems_list
+ expect(out).to include("myrack (1.0.0)").and include("thin (1.0)")
end
- it "--clean should override the bundle setting on update", :bundler => "< 3" do
+ it "does not clean on bundle update when path has not been set" do
build_repo2
- gemfile <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => true)
update_repo2 do
build_gem "foo", "1.0.1"
end
- bundle! "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
- should_have_gems "foo-1.0.1"
- should_not_have_gems "foo-1.0"
+ files = Pathname.glob(default_bundle_path("*", "*"))
+ files.map! {|f| f.to_s.sub(default_bundle_path.to_s, "") }
+ expected_files = %W[
+ /bin/bundle
+ /bin/bundler
+ /cache/bundler-#{Bundler::VERSION}.gem
+ /cache/foo-1.0.1.gem
+ /cache/foo-1.0.gem
+ /gems/bundler-#{Bundler::VERSION}
+ /gems/foo-1.0
+ /gems/foo-1.0.1
+ /specifications/bundler-#{Bundler::VERSION}.gemspec
+ /specifications/foo-1.0.1.gemspec
+ /specifications/foo-1.0.gemspec
+ ]
+ expected_files += ["/bin/bundle.bat", "/bin/bundler.bat"] if Gem.win_platform?
+
+ expect(files.sort).to eq(expected_files.sort)
end
- it "automatically cleans when path has not been set", :bundler => "3" do
+ it "will automatically clean on bundle update when path has not been set", bundler: "5" do
build_repo2
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "foo"
G
@@ -396,10 +431,10 @@ RSpec.describe "bundle clean" do
build_gem "foo", "1.0.1"
end
- bundle! "update", :all => true
+ bundle "update", all: true
- files = Pathname.glob(bundled_app(".bundle", Bundler.ruby_scope, "*", "*"))
- files.map! {|f| f.to_s.sub(bundled_app(".bundle", Bundler.ruby_scope).to_s, "") }
+ files = Pathname.glob(local_gem_path("*", "*"))
+ files.map! {|f| f.to_s.sub(local_gem_path.to_s, "") }
expect(files.sort).to eq %w[
/cache/foo-1.0.1.gem
/gems/foo-1.0.1
@@ -407,90 +442,92 @@ RSpec.describe "bundle clean" do
]
end
- it "does not clean automatically on --path" do
+ it "does not clean automatically when path configured" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
- gem "rack"
+ gem "myrack"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle "install"
- should_have_gems "rack-1.0.0", "thin-1.0"
+ should_have_gems "myrack-1.0.0", "thin-1.0"
end
- it "does not clean on bundle update with --path" do
+ it "does not clean on bundle update when path configured" do
build_repo2
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
- bundle! :update, :all => bundle_update_requires_all?
+ bundle :update, all: true
should_have_gems "foo-1.0", "foo-1.0.1"
end
- it "does not clean on bundle update when using --system" do
- bundle! "config path.system true"
+ it "does not clean on bundle update when installing to system gems" do
+ bundle_config "path.system true"
build_repo2
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "foo"
G
- bundle! "install"
+ bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
- bundle! :update, :all => bundle_update_requires_all?
+ bundle :update, all: true
- sys_exec! "gem list"
+ installed_gems_list
expect(out).to include("foo (1.0.1, 1.0)")
end
it "cleans system gems when --force is used" do
- bundle! "config path.system true"
+ bundle_config "path.system true"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
- gem "rack"
+ gem "myrack"
G
bundle :install
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle :install
bundle "clean --force"
expect(out).to include("Removing foo (1.0)")
- sys_exec "gem list"
+ installed_gems_list
expect(out).not_to include("foo (1.0)")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
- describe "when missing permissions" do
+ describe "when missing permissions", :permissions do
before { ENV["BUNDLE_PATH__SYSTEM"] = "true" }
let(:system_cache_path) { system_gem_path("cache") }
after do
@@ -498,30 +535,30 @@ RSpec.describe "bundle clean" do
end
it "returns a helpful error message" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
- gem "rack"
+ gem "myrack"
G
bundle :install
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle :install
FileUtils.chmod(0o500, system_cache_path)
- bundle :clean, :force => true
+ bundle :clean, force: true, raise_on_error: false
- expect(out).to include(system_gem_path.to_s)
- expect(out).to include("grant write permissions")
+ expect(err).to include(system_gem_path.to_s)
+ expect(err).to include("grant write permissions")
- sys_exec "gem list"
+ installed_gems_list
expect(out).to include("foo (1.0)")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
end
@@ -530,23 +567,23 @@ RSpec.describe "bundle clean" do
revision = revision_for(lib_path("foo-1.0"))
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
# mimic 7 length git revisions in Gemfile.lock
- gemfile_lock = File.read(bundled_app("Gemfile.lock")).split("\n")
+ gemfile_lock = File.read(bundled_app_lock).split("\n")
gemfile_lock.each_with_index do |line, index|
gemfile_lock[index] = line[0..(11 + 7)] if line.include?(" revision:")
end
- File.open(bundled_app("Gemfile.lock"), "w") do |file|
- file.print gemfile_lock.join("\n")
- end
+ lockfile(bundled_app_lock, gemfile_lock.join("\n"))
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
bundle :clean
@@ -556,10 +593,9 @@ RSpec.describe "bundle clean" do
end
it "when using --force on system gems, it doesn't remove binaries" do
- bundle! "config path.system true"
+ bundle_config "path.system true"
- build_repo2
- update_repo2 do
+ build_repo2 do
build_gem "bindir" do |s|
s.bindir = "exe"
s.executables = "foo"
@@ -567,7 +603,7 @@ RSpec.describe "bundle clean" do
end
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "bindir"
G
@@ -577,11 +613,28 @@ RSpec.describe "bundle clean" do
sys_exec "foo"
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("1.0")
end
- it "doesn't blow up on path gems without a .gempsec" do
+ it "when using --force, it doesn't remove default gem binaries" do
+ default_irb_version = ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", raise_on_error: false
+ skip "irb isn't a default gem" if default_irb_version.empty?
+
+ # simulate executable for default gem
+ build_gem "irb", default_irb_version, to_system: true, default: true do |s|
+ s.executables = "irb"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ G
+
+ bundle "clean --force", env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+
+ expect(out).not_to include("Removing irb")
+ end
+
+ it "doesn't blow up on path gems without a .gemspec" do
relative_path = "vendor/private_gems/bar-1.0"
absolute_path = bundled_app(relative_path)
FileUtils.mkdir_p("#{absolute_path}/lib/bar")
@@ -590,28 +643,31 @@ RSpec.describe "bundle clean" do
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
gem "bar", "1.0", :path => "#{relative_path}"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
- bundle! :clean
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ bundle :clean
end
it "doesn't remove gems in dry-run mode with path set" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -623,54 +679,56 @@ RSpec.describe "bundle clean" do
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0", "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "doesn't remove gems in dry-run mode with no path set" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
G
bundle :install
- bundle "configuration --delete path"
-
bundle "clean --dry-run"
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0", "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "doesn't store dry run as a config setting" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
- bundle "config dry_run false"
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
+ bundle_config "dry_run false"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -682,68 +740,72 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (1.0)")
expect(out).not_to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0"
should_not_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle", :clean => false)
+ bundle_config "path vendor/bundle"
+ bundle_config "clean false"
+ bundle "install"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "weakling"
G
- bundle! "config auto_install 1"
- bundle! :clean
+ bundle_config "auto_install 1"
+ bundle :clean
expect(out).to include("Installing weakling 0.0.3")
- should_have_gems "thin-1.0", "rack-1.0.0", "weakling-0.0.3"
+ should_have_gems "thin-1.0", "myrack-1.0.0", "weakling-0.0.3"
should_not_have_gems "foo-1.0"
end
- it "doesn't remove extensions artifacts from bundled git gems after clean", :ruby_repo, :rubygems => "2.2" do
+ it "doesn't remove extensions artifacts from bundled git gems after clean" do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
expect(vendored_gems("bundler/gems/extensions")).to exist
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
- bundle! :clean
- expect(out).to eq("")
+ bundle :clean
+ expect(out).to be_empty
expect(vendored_gems("bundler/gems/extensions")).to exist
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
end
- it "removes extension directories", :ruby_repo, :rubygems => "2.2" do
+ it "removes extension directories" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "very_simple_binary"
gem "simple_binary"
G
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle "install"
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/extensions/*/*/very_simple_binary-1.0").first
@@ -755,17 +817,120 @@ RSpec.describe "bundle clean" do
expect(simple_binary_extensions_dir).to exist
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "thin"
gem "simple_binary"
G
- bundle! "install"
- bundle! :clean
+ bundle "install"
+ bundle :clean
expect(out).to eq("Removing very_simple_binary (1.0)")
expect(very_simple_binary_extensions_dir).not_to exist
expect(simple_binary_extensions_dir).to exist
end
+
+ it "removes git extension directories" do
+ build_git "very_simple_git_binary", &:add_c_extension
+
+ revision = revision_for(lib_path("very_simple_git_binary-1.0"))
+ short_revision = revision[0..11]
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "thin"
+ gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
+ G
+
+ bundle_config "path vendor/bundle"
+ bundle "install"
+
+ very_simple_binary_extensions_dir =
+ Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
+
+ expect(very_simple_binary_extensions_dir).to exist
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
+ G
+
+ bundle "install"
+ bundle :clean
+ expect(out).to include("Removing thin (1.0)")
+ expect(very_simple_binary_extensions_dir).to exist
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ bundle "install"
+ bundle :clean
+ expect(out).to eq("Removing very_simple_git_binary-1.0 (#{short_revision})")
+
+ expect(very_simple_binary_extensions_dir).not_to exist
+ end
+
+ it "keeps git extension directories when excluded by group" do
+ build_git "very_simple_git_binary", &:add_c_extension
+
+ revision = revision_for(lib_path("very_simple_git_binary-1.0"))
+ short_revision = revision[0..11]
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ group :development do
+ gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
+ end
+ G
+
+ bundle :lock
+ bundle_config "without development"
+ bundle_config "path vendor/bundle"
+ bundle "install", verbose: true
+ bundle :clean
+
+ very_simple_binary_extensions_dir =
+ Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
+
+ expect(very_simple_binary_extensions_dir).to be_nil
+ end
+
+ it "does not remove the bundler version currently running" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ G
+
+ bundle_config "path vendor/bundle"
+ bundle "install"
+
+ version = Bundler.gem_version.to_s
+ # Simulate that the locked bundler version is installed in the bundle path
+ # by creating the gem directory and gemspec (as would happen after bundle install with that version)
+ Pathname(vendored_gems("cache/bundler-#{version}.gem")).tap do |path|
+ FileUtils.touch(path)
+ end
+ FileUtils.touch(vendored_gems("gems/bundler-#{version}"))
+ Pathname(vendored_gems("specifications/bundler-#{version}.gemspec")).tap do |path|
+ path.write(<<~GEMSPEC)
+ Gem::Specification.new do |s|
+ s.name = "bundler"
+ s.version = "#{version}"
+ s.authors = ["bundler team"]
+ s.summary = "The best way to manage your application's dependencies"
+ end
+ GEMSPEC
+ end
+
+ should_have_gems "bundler-#{version}"
+
+ bundle :clean
+
+ should_have_gems "bundler-#{version}"
+ end
end
diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb
index 9e49357465..e8ab32ca5d 100644
--- a/spec/bundler/commands/config_spec.rb
+++ b/spec/bundler/commands/config_spec.rb
@@ -1,18 +1,11 @@
# frozen_string_literal: true
RSpec.describe ".bundle/config" do
- before :each do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0.0"
- G
- end
-
describe "config" do
- before { bundle "config foo bar" }
+ before { bundle "config set foo bar" }
it "prints a detailed report of local and user configuration" do
- bundle "config"
+ bundle "config list"
expect(out).to include("Settings are listed in order of priority. The top value will be used")
expect(out).to include("foo\nSet for the current user")
@@ -21,69 +14,136 @@ RSpec.describe ".bundle/config" do
context "given --parseable flag" do
it "prints a minimal report of local and user configuration" do
- bundle "config --parseable"
+ bundle "config list --parseable"
expect(out).to include("foo=bar")
end
context "with global config" do
it "prints config assigned to local scope" do
- bundle "config --local foo bar2"
- bundle "config --parseable"
+ bundle "config set --local foo bar2"
+ bundle "config list --parseable"
expect(out).to include("foo=bar2")
end
end
context "with env overwrite" do
it "prints config with env" do
- bundle "config --parseable", :env => { "BUNDLE_FOO" => "bar3" }
+ bundle "config list --parseable", env: { "BUNDLE_FOO" => "bar3" }
expect(out).to include("foo=bar3")
end
end
end
end
- describe "BUNDLE_APP_CONFIG" do
+ describe "location with a gemfile" do
+ before :each do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
+
+ it "is local by default" do
+ bundle "config set foo bar"
+ expect(bundled_app(".bundle/config")).to exist
+ expect(home(".bundle/config")).not_to exist
+ end
+
it "can be moved with an environment variable" do
ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
expect(bundled_app(".bundle")).not_to exist
expect(tmp("foo/bar/config")).to exist
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "can provide a relative path with the environment variable" do
FileUtils.mkdir_p bundled_app("omg")
- Dir.chdir bundled_app("omg")
ENV["BUNDLE_APP_CONFIG"] = "../foo"
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle "install", dir: bundled_app("omg")
expect(bundled_app(".bundle")).not_to exist
expect(bundled_app("../foo/config")).to exist
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", dir: bundled_app("omg")
+ end
+ end
+
+ describe "location without a gemfile" do
+ it "is global by default" do
+ bundle "config set foo bar"
+ expect(bundled_app(".bundle/config")).not_to exist
+ expect(home(".bundle/config")).to exist
+ end
+
+ it "does not list global settings as local" do
+ bundle "config set --global foo bar"
+ bundle "config list", dir: home
+
+ expect(out).to include("for the current user")
+ expect(out).not_to include("for your local app")
+ end
+
+ it "works with an absolute path" do
+ ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
+ bundle "config set --local path vendor/bundle"
+
+ expect(bundled_app(".bundle")).not_to exist
+ expect(tmp("foo/bar/config")).to exist
+ end
+ end
+
+ describe "config location" do
+ let(:bundle_user_config) { File.join(Dir.home, ".config/bundler") }
+
+ before do
+ Dir.mkdir File.dirname(bundle_user_config)
+ end
+
+ it "can be configured through BUNDLE_USER_CONFIG" do
+ bundle "config set path vendor", env: { "BUNDLE_USER_CONFIG" => bundle_user_config }
+ bundle "config get path", env: { "BUNDLE_USER_CONFIG" => bundle_user_config }
+ expect(out).to include("Set for the current user (#{bundle_user_config}): \"vendor\"")
+ end
+
+ context "when not explicitly configured, but BUNDLE_USER_HOME set" do
+ let(:bundle_user_home) { bundled_app(".bundle").to_s }
+
+ it "uses the right location" do
+ bundle "config set path vendor", env: { "BUNDLE_USER_HOME" => bundle_user_home }
+ bundle "config get path", env: { "BUNDLE_USER_HOME" => bundle_user_home }
+ expect(out).to include("Set for the current user (#{bundle_user_home}/config): \"vendor\"")
+ end
end
end
describe "global" do
- before(:each) { bundle :install }
+ before(:each) do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
it "is the default" do
- bundle "config foo global"
+ bundle "config set foo global"
run "puts Bundler.settings[:foo]"
expect(out).to eq("global")
end
it "can also be set explicitly" do
- bundle! "config --global foo global"
- run! "puts Bundler.settings[:foo]"
+ bundle "config set --global foo global"
+ run "puts Bundler.settings[:foo]"
expect(out).to eq("global")
end
it "has lower precedence than local" do
- bundle "config --local foo local"
+ bundle "config set --local foo local"
- bundle "config --global foo global"
+ bundle "config set --global foo global"
expect(out).to match(/Your application has set foo to "local"/)
run "puts Bundler.settings[:foo]"
@@ -91,30 +151,28 @@ RSpec.describe ".bundle/config" do
end
it "has lower precedence than env" do
- begin
- ENV["BUNDLE_FOO"] = "env"
+ ENV["BUNDLE_FOO"] = "env"
- bundle "config --global foo global"
- expect(out).to match(/You have a bundler environment variable for foo set to "env"/)
+ bundle "config set --global foo global"
+ expect(out).to match(/You have a bundler environment variable for foo set to "env"/)
- run "puts Bundler.settings[:foo]"
- expect(out).to eq("env")
- ensure
- ENV.delete("BUNDLE_FOO")
- end
+ run "puts Bundler.settings[:foo]"
+ expect(out).to eq("env")
+ ensure
+ ENV.delete("BUNDLE_FOO")
end
it "can be deleted" do
- bundle "config --global foo global"
- bundle "config --delete foo"
+ bundle "config set --global foo global"
+ bundle "config unset foo"
run "puts Bundler.settings[:foo] == nil"
expect(out).to eq("true")
end
it "warns when overriding" do
- bundle "config --global foo previous"
- bundle "config --global foo global"
+ bundle "config set --global foo previous"
+ bundle "config set --global foo global"
expect(out).to match(/You are replacing the current global value of foo/)
run "puts Bundler.settings[:foo]"
@@ -122,8 +180,8 @@ RSpec.describe ".bundle/config" do
end
it "does not warn when using the same value twice" do
- bundle "config --global foo value"
- bundle "config --global foo value"
+ bundle "config set --global foo value"
+ bundle "config set --global foo value"
expect(out).not_to match(/You are replacing the current global value of foo/)
run "puts Bundler.settings[:foo]"
@@ -131,22 +189,22 @@ RSpec.describe ".bundle/config" do
end
it "expands the path at time of setting" do
- bundle "config --global local.foo .."
+ bundle "config set --global local.foo .."
run "puts Bundler.settings['local.foo']"
- expect(out).to eq(File.expand_path(Dir.pwd + "/.."))
+ expect(out).to eq(File.expand_path(bundled_app.to_s + "/.."))
end
it "saves with parseable option" do
- bundle "config --global --parseable foo value"
+ bundle "config set --global --parseable foo value"
expect(out).to eq("foo=value")
run "puts Bundler.settings['foo']"
expect(out).to eq("value")
end
context "when replacing a current value with the parseable flag" do
- before { bundle "config --global foo value" }
+ before { bundle "config set --global foo value" }
it "prints the current value in a parseable format" do
- bundle "config --global --parseable foo value2"
+ bundle "config set --global --parseable foo value2"
expect(out).to eq "foo=value2"
run "puts Bundler.settings['foo']"
expect(out).to eq("value2")
@@ -155,37 +213,40 @@ RSpec.describe ".bundle/config" do
end
describe "local" do
- before(:each) { bundle :install }
+ before(:each) do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
it "can also be set explicitly" do
- bundle "config --local foo local"
+ bundle "config set --local foo local"
run "puts Bundler.settings[:foo]"
expect(out).to eq("local")
end
it "has higher precedence than env" do
- begin
- ENV["BUNDLE_FOO"] = "env"
- bundle "config --local foo local"
-
- run "puts Bundler.settings[:foo]"
- expect(out).to eq("local")
- ensure
- ENV.delete("BUNDLE_FOO")
- end
+ ENV["BUNDLE_FOO"] = "env"
+ bundle "config set --local foo local"
+
+ run "puts Bundler.settings[:foo]"
+ expect(out).to eq("local")
+ ensure
+ ENV.delete("BUNDLE_FOO")
end
it "can be deleted" do
- bundle "config --local foo local"
- bundle "config --delete foo"
+ bundle "config set --local foo local"
+ bundle "config unset foo"
run "puts Bundler.settings[:foo] == nil"
expect(out).to eq("true")
end
it "warns when overriding" do
- bundle "config --local foo previous"
- bundle "config --local foo local"
+ bundle "config set --local foo previous"
+ bundle "config set --local foo local"
expect(out).to match(/You are replacing the current local value of foo/)
run "puts Bundler.settings[:foo]"
@@ -193,14 +254,14 @@ RSpec.describe ".bundle/config" do
end
it "expands the path at time of setting" do
- bundle "config --local local.foo .."
+ bundle "config set --local local.foo .."
run "puts Bundler.settings['local.foo']"
- expect(out).to eq(File.expand_path(Dir.pwd + "/.."))
+ expect(out).to eq(File.expand_path(bundled_app.to_s + "/.."))
end
it "can be deleted with parseable option" do
- bundle "config --local foo value"
- bundle "config --delete --parseable foo"
+ bundle "config set --local foo value"
+ bundle "config unset --parseable foo"
expect(out).to eq ""
run "puts Bundler.settings['foo'] == nil"
expect(out).to eq("true")
@@ -208,7 +269,12 @@ RSpec.describe ".bundle/config" do
end
describe "env" do
- before(:each) { bundle :install }
+ before(:each) do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
it "can set boolean properties via the environment" do
ENV["BUNDLE_FROZEN"] = "true"
@@ -247,39 +313,45 @@ RSpec.describe ".bundle/config" do
describe "parseable option" do
it "prints an empty string" do
- bundle "config foo --parseable"
+ bundle "config get foo --parseable", raise_on_error: false
expect(out).to eq ""
+ expect(last_command).to be_failure
end
it "only prints the value of the config" do
- bundle "config foo local"
- bundle "config foo --parseable"
+ bundle "config set foo local"
+ bundle "config get foo --parseable"
expect(out).to eq "foo=local"
end
it "can print global config" do
- bundle "config --global bar value"
- bundle "config bar --parseable"
+ bundle "config set --global bar value"
+ bundle "config get bar --parseable"
expect(out).to eq "bar=value"
end
it "prefers local config over global" do
- bundle "config --local bar value2"
- bundle "config --global bar value"
- bundle "config bar --parseable"
+ bundle "config set --local bar value2"
+ bundle "config set --global bar value"
+ bundle "config get bar --parseable"
expect(out).to eq "bar=value2"
end
end
describe "gem mirrors" do
- before(:each) { bundle :install }
+ before(:each) do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
it "configures mirrors using keys with `mirror.`" do
- bundle "config --local mirror.http://gems.example.org http://gem-mirror.example.org"
+ bundle "config set --local mirror.http://gems.example.org http://gem-mirror.example.org"
run(<<-E)
Bundler.settings.gem_mirrors.each do |k, v|
puts "\#{k} => \#{v}"
@@ -287,36 +359,42 @@ end
E
expect(out).to eq("http://gems.example.org/ => http://gem-mirror.example.org/")
end
+
+ it "allows configuring fallback timeout for each mirror, and does not duplicate configs", rubygems: ">= 3.5.12" do
+ bundle "config set --global mirror.https://rubygems.org.fallback_timeout 1"
+ bundle "config set --global mirror.https://rubygems.org.fallback_timeout 2"
+ expect(File.read(home(".bundle/config"))).to include("BUNDLE_MIRROR").once
+ end
end
describe "quoting" do
- before(:each) { gemfile "# no gems" }
+ before(:each) { gemfile "source 'https://gem.repo1'" }
let(:long_string) do
"--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
"--with-xslt-dir=/usr/pkg"
end
it "saves quotes" do
- bundle "config foo something\\'"
+ bundle "config set foo something\\'"
run "puts Bundler.settings[:foo]"
expect(out).to eq("something'")
end
- it "doesn't return quotes around values", :ruby => "1.9" do
- bundle "config foo '1'"
- run "puts Bundler.settings.send(:global_config_file).read"
+ it "doesn't return quotes around values" do
+ bundle "config set foo '1'"
+ run "puts Bundler.settings.send(:local_config_file).read"
expect(out).to include('"1"')
run "puts Bundler.settings[:foo]"
expect(out).to eq("1")
end
- it "doesn't duplicate quotes around values", :if => (RUBY_VERSION >= "2.1") do
+ it "doesn't duplicate quotes around values" do
bundled_app(".bundle").mkpath
File.open(bundled_app(".bundle/config"), "w") do |f|
f.write 'BUNDLE_FOO: "$BUILD_DIR"'
end
- bundle "config bar baz"
+ bundle "config set bar baz"
run "puts Bundler.settings.send(:local_config_file).read"
# Starting in Ruby 2.1, YAML automatically adds double quotes
@@ -325,12 +403,12 @@ E
end
it "doesn't duplicate quotes around long wrapped values" do
- bundle "config foo #{long_string}"
+ bundle "config set foo #{long_string}"
run "puts Bundler.settings[:foo]"
expect(out).to eq(long_string)
- bundle "config bar baz"
+ bundle "config set bar baz"
run "puts Bundler.settings[:foo]"
expect(out).to eq(long_string)
@@ -338,7 +416,12 @@ E
end
describe "very long lines" do
- before(:each) { bundle :install }
+ before(:each) do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ G
+ end
let(:long_string) do
"--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
@@ -351,34 +434,213 @@ E
end
it "doesn't wrap values" do
- bundle "config foo #{long_string}"
+ bundle "config set foo #{long_string}"
run "puts Bundler.settings[:foo]"
expect(out).to match(long_string)
end
it "can read wrapped unquoted values" do
- bundle "config foo #{long_string_without_special_characters}"
+ bundle "config set foo #{long_string_without_special_characters}"
run "puts Bundler.settings[:foo]"
expect(out).to match(long_string_without_special_characters)
end
end
+
+ describe "commented out settings with urls" do
+ before do
+ bundle "config set #mirror.https://rails-assets.org http://localhost:9292"
+ end
+
+ it "does not make bundler crash and ignores the configuration" do
+ bundle "config list --parseable"
+
+ expect(out).to be_empty
+ expect(err).to be_empty
+
+ ruby(<<~RUBY)
+ require "bundler"
+ print Bundler.settings.mirror_for("https://rails-assets.org")
+ RUBY
+ expect(out).to eq("https://rails-assets.org/")
+ expect(err).to be_empty
+
+ bundle "config set mirror.all http://localhost:9293"
+ ruby(<<~RUBY)
+ require "bundler"
+ print Bundler.settings.mirror_for("https://rails-assets.org")
+ RUBY
+ expect(out).to eq("http://localhost:9293/")
+ expect(err).to be_empty
+ end
+ end
+
+ describe "subcommands" do
+ it "list" do
+ bundle "config list", env: { "BUNDLE_FOO" => "bar" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nfoo\nSet via BUNDLE_FOO: \"bar\""
+
+ bundle "config list", env: { "BUNDLE_FOO" => "bar" }, parseable: true
+ expect(out).to eq "foo=bar"
+ end
+
+ it "list with credentials" do
+ bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\""
+
+ bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
+ expect(out).to eq "gems.myserver.com=user:password"
+ end
+
+ it "list with API token credentials" do
+ bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\""
+
+ bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "gems.myserver.com=api_token:x-oauth-basic"
+ end
+
+ it "get" do
+ ENV["BUNDLE_BAR"] = "bar_val"
+
+ bundle "config get foo", raise_on_error: false
+ expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(last_command).to be_failure
+
+ ENV["BUNDLE_FOO"] = "foo_val"
+
+ bundle "config get foo --parseable"
+ expect(out).to eq "foo=foo_val"
+
+ bundle "config get foo"
+ expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nSet via BUNDLE_FOO: \"foo_val\""
+ end
+
+ it "set" do
+ bundle "config set foo 1"
+ expect(out).to eq ""
+
+ bundle "config set --local foo 2"
+ expect(out).to eq ""
+
+ bundle "config set --global foo 3"
+ expect(out).to eq "Your application has set foo to \"2\". This will override the global value you are currently setting"
+
+ bundle "config set --parseable --local foo 4"
+ expect(out).to eq "foo=4"
+
+ bundle "config set --local foo 4.1"
+ expect(out).to eq "You are replacing the current local value of foo, which is currently \"4\""
+
+ bundle "config set --global --local foo 5", raise_on_error: false
+ expect(last_command).to be_failure
+ expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time."
+ end
+
+ it "unset" do
+ bundle "config unset foo"
+ expect(out).to eq ""
+
+ bundle "config set foo 1"
+ bundle "config unset foo --parseable"
+ expect(out).to eq ""
+
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
+
+ bundle "config unset foo"
+ expect(out).to eq ""
+ expect(bundle("config get foo", raise_on_error: false)).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(last_command).to be_failure
+
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
+
+ bundle "config unset foo --local"
+ expect(out).to eq ""
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for the current user (#{home(".bundle/config")}): \"2\""
+ bundle "config unset foo --global"
+ expect(out).to eq ""
+ expect(bundle("config get foo", raise_on_error: false)).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(last_command).to be_failure
+
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
+
+ bundle "config unset foo --global"
+ expect(out).to eq ""
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for your local app (#{bundled_app(".bundle/config")}): \"1\""
+ bundle "config unset foo --local"
+ expect(out).to eq ""
+ expect(bundle("config get foo", raise_on_error: false)).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(last_command).to be_failure
+
+ bundle "config unset foo --local --global", raise_on_error: false
+ expect(last_command).to be_failure
+ expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time."
+ end
+ end
end
RSpec.describe "setting gemfile via config" do
+ context "when a default Gemfile exists" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ gemfile bundled_app("foo/bar_gemfile"), <<-G
+ source "https://gem.repo1"
+ G
+ end
+
+ it "reports the local gemfile setting without promoting it to the environment" do
+ bundle "config set gemfile foo/bar_gemfile"
+
+ bundle "config list"
+ expect(out).to include("Set for your local app (#{bundled_app(".bundle/config")}): \"foo/bar_gemfile\"")
+ expect(out).not_to include("Set via BUNDLE_GEMFILE")
+ end
+
+ it "unsets the local gemfile setting from the app config" do
+ bundle "config set gemfile foo/bar_gemfile"
+
+ bundle "config unset gemfile"
+ bundle "config get gemfile", raise_on_error: false
+
+ expect(out).to include("You have not configured a value for `gemfile`")
+ expect(File.read(bundled_app(".bundle/config"))).not_to include("BUNDLE_GEMFILE")
+ end
+ end
+
context "when only the non-default Gemfile exists" do
it "persists the gemfile location to .bundle/config" do
- File.open(bundled_app("NotGemfile"), "w") do |f|
- f.write <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
- G
- end
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
- bundle "config --local gemfile #{bundled_app("NotGemfile")}"
- expect(File.exist?(".bundle/config")).to eq(true)
+ bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
+ expect(File.exist?(bundled_app(".bundle/config"))).to eq(true)
- bundle "config"
+ bundle "config list"
expect(out).to include("NotGemfile")
end
end
end
+
+RSpec.describe "setting lockfile via config" do
+ it "persists the lockfile location to .bundle/config" do
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
+ bundle "config set --local lockfile #{bundled_app("ReallyNotGemfile.lock")}"
+ expect(File.exist?(bundled_app(".bundle/config"))).to eq(true)
+
+ bundle "config list"
+ expect(out).to include("NotGemfile")
+ expect(out).to include("ReallyNotGemfile.lock")
+ end
+end
diff --git a/spec/bundler/commands/console_spec.rb b/spec/bundler/commands/console_spec.rb
index 05b0a6c1e4..a44f607546 100644
--- a/spec/bundler/commands/console_spec.rb
+++ b/spec/bundler/commands/console_spec.rb
@@ -1,106 +1,214 @@
# frozen_string_literal: true
-RSpec.describe "bundle console", :bundler => "< 3" do
+RSpec.describe "bundle console", readline: true do
before :each do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
- G
- end
+ build_repo2 do
+ # A minimal fake pry console
+ build_gem "pry" do |s|
+ s.write "lib/pry.rb", <<-RUBY
+ class Pry
+ class << self
+ def toplevel_binding
+ unless defined?(@toplevel_binding) && @toplevel_binding
+ TOPLEVEL_BINDING.eval %{
+ def self.__pry__; binding; end
+ Pry.instance_variable_set(:@toplevel_binding, __pry__)
+ class << self; undef __pry__; end
+ }
+ end
+ @toplevel_binding.eval('private')
+ @toplevel_binding
+ end
+
+ def __pry__
+ while line = gets
+ begin
+ puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1')
+ rescue Exception => e
+ puts "\#{e.class}: \#{e.message}"
+ puts e.backtrace.first
+ end
+ end
+ end
+ alias start __pry__
+ end
+ end
+ RUBY
+ end
- it "starts IRB with the default group loaded" do
- bundle "console" do |input, _, _|
- input.puts("puts RACK")
- input.puts("exit")
+ build_dummy_irb
end
- expect(out).to include("0.9.1")
end
- it "uses IRB as default console" do
- bundle "console" do |input, _, _|
- input.puts("__method__")
- input.puts("exit")
+ context "when the library requires a non-existent file" do
+ before do
+ build_lib "loadfuuu", "1.0.0" do |s|
+ s.write "lib/loadfuuu.rb", "require_relative 'loadfuuu/bar'"
+ s.write "lib/loadfuuu/bar.rb", "require 'not-in-bundle'"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ path "#{lib_path}" do
+ gem "loadfuuu", require: true
+ end
+ G
end
- expect(out).to include(":irb_binding")
- end
- it "starts another REPL if configured as such" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "pry"
- G
- bundle "config console pry"
+ it "does not show the bug report template" do
+ bundle("console", raise_on_error: false) do |input, _, _|
+ input.puts("exit")
+ end
- bundle "console" do |input, _, _|
- input.puts("__method__")
- input.puts("exit")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
end
- expect(out).to include(":__pry__")
end
- it "falls back to IRB if the other REPL isn't available" do
- bundle "config console pry"
- # make sure pry isn't there
+ context "when the library references a non-existent constant" do
+ before do
+ build_lib "loadfuuu", "1.0.0" do |s|
+ s.write "lib/loadfuuu.rb", "Some::NonExistent::Constant"
+ end
- bundle "console" do |input, _, _|
- input.puts("__method__")
- input.puts("exit")
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ path "#{lib_path}" do
+ gem "loadfuuu", require: true
+ end
+ G
end
- expect(out).to include(":irb_binding")
- end
- it "doesn't load any other groups" do
- bundle "console" do |input, _, _|
- input.puts("puts ACTIVESUPPORT")
- input.puts("exit")
+ it "does not show the bug report template" do
+ bundle("console", raise_on_error: false) do |input, _, _|
+ input.puts("exit")
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
end
- expect(out).to include("NameError")
end
- describe "when given a group" do
- it "loads the given group" do
- bundle "console test" do |input, _, _|
- input.puts("puts ACTIVESUPPORT")
+ context "when the library does not have any errors" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
+ gem "activesupport", :group => :test
+ gem "myrack_middleware", :group => :development
+ G
+ end
+
+ it "starts IRB with the default group loaded" do
+ bundle "console" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ expect(out).to include("0.9.1")
+ end
+
+ it "uses IRB as default console" do
+ skip "Does not work in a ruby-core context if irb is in the default $LOAD_PATH because it enables the real IRB, not our dummy one" if ruby_core? && Gem.ruby_version < Gem::Version.new("3.5.0.a")
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
input.puts("exit")
end
- expect(out).to include("2.3.5")
+ expect(out).to include("__irb__")
end
- it "loads the default group" do
- bundle "console test" do |input, _, _|
- input.puts("puts RACK")
+ it "starts another REPL if configured as such" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "pry"
+ G
+ bundle_config "console pry"
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
input.puts("exit")
end
- expect(out).to include("0.9.1")
+ expect(out).to include(":__pry__")
end
- it "doesn't load other groups" do
- bundle "console test" do |input, _, _|
- input.puts("puts RACK_MIDDLEWARE")
+ it "falls back to IRB if the other REPL isn't available" do
+ skip "Does not work in a ruby-core context if irb is in the default $LOAD_PATH because it enables the real IRB, not our dummy one" if ruby_core? && Gem.ruby_version < Gem::Version.new("3.5.0.a")
+
+ bundle_config "console pry"
+ # make sure pry isn't there
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
+ input.puts("exit")
+ end
+ expect(out).to include("__irb__")
+ end
+
+ it "does not try IRB twice if no console is configured and IRB is not available" do
+ create_file("irb.rb", "raise LoadError, 'irb is not available'")
+
+ bundle("console", env: { "RUBYOPT" => "-I#{bundled_app} #{ENV["RUBYOPT"]}" }, raise_on_error: false) do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
+ input.puts("exit")
+ end
+ expect(err).not_to include("falling back to irb")
+ expect(err).to include("irb is not available")
+ end
+
+ it "doesn't load any other groups" do
+ bundle "console" do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
input.puts("exit")
end
expect(out).to include("NameError")
end
- end
- it "performs an automatic bundle install" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
- gem "foo"
- G
-
- bundle "config auto_install 1"
- bundle :console do |input, _, _|
- input.puts("puts 'hello'")
- input.puts("exit")
+ describe "when given a group" do
+ it "loads the given group" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
+ input.puts("exit")
+ end
+ expect(out).to include("2.3.5")
+ end
+
+ it "loads the default group" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ expect(out).to include("0.9.1")
+ end
+
+ it "doesn't load other groups" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts MYRACK_MIDDLEWARE")
+ input.puts("exit")
+ end
+ expect(out).to include("NameError")
+ end
+ end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
+ gem "activesupport", :group => :test
+ gem "myrack_middleware", :group => :development
+ gem "foo"
+ G
+
+ bundle_config "auto_install 1"
+ bundle :console do |input, _, _|
+ input.puts("puts 'hello'")
+ input.puts("exit")
+ end
+ expect(out).to include("Installing foo 1.0")
+ expect(out).to include("hello")
+ expect(the_bundle).to include_gems "foo 1.0"
end
- expect(out).to include("Installing foo 1.0")
- expect(out).to include("hello")
- expect(the_bundle).to include_gems "foo 1.0"
end
end
diff --git a/spec/bundler/commands/doctor_spec.rb b/spec/bundler/commands/doctor_spec.rb
index 5260e6cb36..d350b4b3d1 100644
--- a/spec/bundler/commands/doctor_spec.rb
+++ b/spec/bundler/commands/doctor_spec.rb
@@ -4,17 +4,18 @@ require "find"
require "stringio"
require "bundler/cli"
require "bundler/cli/doctor"
+require "bundler/cli/doctor/diagnose"
RSpec.describe "bundle doctor" do
before(:each) do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
@stdout = StringIO.new
- [:error, :warn].each do |method|
+ [:error, :warn, :info].each do |method|
allow(Bundler.ui).to receive(method).and_wrap_original do |m, message|
m.call message
@stdout.puts message
@@ -22,89 +23,163 @@ RSpec.describe "bundle doctor" do
end
end
+ it "succeeds on a sane installation" do
+ bundle :doctor
+ end
+
context "when all files in home are readable/writable" do
before(:each) do
stat = double("stat")
unwritable_file = double("file")
- allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] }
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:writable?).and_call_original
+ allow(File).to receive(:readable?).and_call_original
+ allow(File).to receive(:exist?).with(unwritable_file).and_return(true)
allow(File).to receive(:stat).with(unwritable_file) { stat }
allow(stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(unwritable_file) { true }
allow(File).to receive(:readable?).with(unwritable_file) { true }
+
+ # The following lines are for `Gem::PathSupport#initialize`.
+ allow(File).to receive(:exist?).with(Gem.default_dir)
+ allow(File).to receive(:writable?).with(Gem.default_dir)
+ allow(File).to receive(:writable?).with(File.expand_path("..", Gem.default_dir))
end
- it "exits with no message if the installed gem has no C extensions" do
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
- expect(@stdout.string).to be_empty
+ it "exits with a success message if the installed gem has no C extensions" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).to include("No issues")
end
- it "exits with no message if the installed gem's C extension dylib breakage is fine" do
- doctor = Bundler::CLI::Doctor.new({})
- expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
+ it "exits with a success message if the installed gem's C extension dylib breakage is fine" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
- allow(File).to receive(:exist?).and_call_original
- allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true)
- expect { doctor.run }.not_to(raise_error, @stdout.string)
- expect(@stdout.string).to be_empty
+ allow(doctor).to receive(:lookup_with_fiddle).with("/usr/lib/libSystem.dylib").and_return(false)
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).to include("No issues")
+ end
+
+ it "parses otool output correctly" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:`).with("/usr/bin/otool -L fake").and_return("/home/gem/ruby/3.4.3/gems/blake3-rb-1.5.4.4/lib/digest/blake3/blake3_ext.bundle:\n\t (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)")
+ expect(doctor.dylibs_darwin("fake")).to eq(["/usr/lib/libSystem.B.dylib"])
end
it "exits with a message if one of the linked libraries is missing" do
- doctor = Bundler::CLI::Doctor.new({})
- expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
- allow(File).to receive(:exist?).and_call_original
- allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false)
- expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string
+ allow(doctor).to receive(:lookup_with_fiddle).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(true)
+ expect { doctor.run }.to raise_error(Bundler::ProductionError, <<~E.strip), @stdout.string
The following gems are missing OS dependencies:
* bundler: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
- * rack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
+ * myrack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
E
end
end
+ context "when home contains broken symlinks" do
+ before(:each) do
+ @broken_symlink = double("file")
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@broken_symlink] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(@broken_symlink) { false }
+ end
+
+ it "exits with an error if home contains files that are not readable/writable" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).to include(
+ "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{@broken_symlink}"
+ )
+ expect(@stdout.string).not_to include("No issues")
+ end
+ end
+
context "when home contains files that are not readable/writable" do
before(:each) do
@stat = double("stat")
@unwritable_file = double("file")
- allow(Find).to receive(:find).with(Bundler.home.to_s) { [@unwritable_file] }
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:writable?).and_call_original
+ allow(File).to receive(:readable?).and_call_original
+ allow(File).to receive(:exist?).with(@unwritable_file) { true }
allow(File).to receive(:stat).with(@unwritable_file) { @stat }
end
- it "exits with an error if home contains files that are not readable/writable" do
+ it "exits with an error if home contains files that are not readable" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(@stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(@unwritable_file) { false }
allow(File).to receive(:readable?).with(@unwritable_file) { false }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are not readable/writable by the current user. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are not readable by the current user. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
- context "when home contains files that are not owned by the current process" do
+ it "exits without an error if home contains files that are not writable" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ allow(@stat).to receive(:uid) { Process.uid }
+ allow(File).to receive(:writable?).with(@unwritable_file) { false }
+ allow(File).to receive(:readable?).with(@unwritable_file) { true }
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).not_to include(
+ "Files exist in the Bundler home that are not readable by the current user. These files are:\n - #{@unwritable_file}"
+ )
+ expect(@stdout.string).to include("No issues")
+ end
+
+ context "when home contains files that are not owned by the current process", :permissions do
before(:each) do
allow(@stat).to receive(:uid) { 0o0000 }
end
it "exits with an error if home contains files that are not readable/writable and are not owned by the current user" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { false }
allow(File).to receive(:readable?).with(@unwritable_file) { false }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are owned by another user, and are not readable/writable. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are owned by another user, and are not readable. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
it "exits with a warning if home contains files that are read/write but not owned by current user" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { true }
allow(File).to receive(:readable?).with(@unwritable_file) { true }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are owned by another user, but are still readable/writable. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are owned by another user, but are still readable. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
end
end
+
+ context "when home contains filenames with special characters" do
+ it "escape filename before command execute" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:`).with("/usr/bin/otool -L \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")
+ doctor.dylibs_darwin('$(date) "\'\.bundle')
+ expect(doctor).to receive(:`).with("/usr/bin/ldd \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")
+ doctor.dylibs_ldd('$(date) "\'\.bundle')
+ end
+ end
end
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 76841dcff6..aa35685be8 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -1,73 +1,127 @@
# frozen_string_literal: true
RSpec.describe "bundle exec" do
- let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] }
- before :each do
- system_gems(system_gems_to_install, :path => :bundle_path)
- end
-
it "works with --gemfile flag" do
- create_file "CustomGemfile", <<-G
- gem "rack", "1.0.0"
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
+
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
- bundle "exec --gemfile CustomGemfile rackup"
+ bundle "exec --gemfile CustomGemfile myrackup"
expect(out).to eq("1.0.0")
end
it "activates the correct gem" do
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ G
+
+ bundle "exec myrackup"
+ expect(out).to eq("0.9.1")
+ end
+
+ it "works and prints no warnings when HOME is not writable" do
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
+
gemfile <<-G
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- bundle "exec rackup"
+ bundle "exec myrackup", env: { "HOME" => "/" }
expect(out).to eq("0.9.1")
+ expect(err).to be_empty
end
it "works when the bins are in ~/.bundle" do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("1.0.0")
end
- it "works when running from a random directory", :ruby_repo do
+ it "works when running from a random directory" do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec 'cd #{tmp("gems")} && rackup'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
- expect(out).to include("1.0.0")
+ expect(out).to eq("1.0.0")
end
it "works when exec'ing something else" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
bundle "exec echo exec"
expect(out).to eq("exec")
end
it "works when exec'ing to ruby" do
- install_gemfile 'gem "rack"'
- bundle "exec ruby -e 'puts %{hi}'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
+ bundle "exec ruby -e 'puts %{hi}'"
expect(out).to eq("hi")
end
+ it "works when exec'ing to rubygems" do
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
+ bundle "exec #{gem_cmd} --version"
+ expect(out).to eq(Gem::VERSION)
+ end
+
+ it "works when exec'ing to rubygems through sh -c" do
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
+ bundle "exec sh -c '#{gem_cmd} --version'"
+ expect(out).to eq(Gem::VERSION)
+ end
+
+ it "works when exec'ing back to bundler to run a remote resolve" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ G
+
+ bundle "exec bundle lock", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+
+ expect(out).to include("Writing lockfile")
+ end
+
+ it "respects custom process title when loading through ruby" do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
+ script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility = <<~'RUBY'
+ Process.setproctitle("1-2-3-4-5-6-7")
+ puts `ps -ocommand= -p#{$$}`
+ RUBY
+ gemfile "Gemfile", "source \"https://gem.repo1\""
+ create_file "a.rb", script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility
+ bundle "exec ruby a.rb"
+ expect(out).to eq("1-2-3-4-5-6-7")
+ end
+
it "accepts --verbose" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
bundle "exec --verbose echo foobar"
expect(out).to eq("foobar")
end
it "passes --verbose to command if it is given after the command" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
bundle "exec echo --verbose"
expect(out).to eq("--verbose")
end
it "handles --keep-file-descriptors" do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
require "tempfile"
command = Tempfile.new("io-test")
@@ -78,40 +132,35 @@ RSpec.describe "bundle exec" do
else
require 'tempfile'
io = Tempfile.new("io-test-fd")
- args = %W[#{Gem.ruby} -I#{lib} #{bindir.join("bundle")} exec --keep-file-descriptors #{Gem.ruby} #{command.path} \#{io.to_i}]
- args << { io.to_i => io } if RUBY_VERSION >= "2.0"
+ args = %W[#{Gem.ruby} -I#{lib_dir} #{bindir.join("bundle")} exec --keep-file-descriptors #{Gem.ruby} #{command.path} \#{io.to_i}]
+ args << { io.to_i => io }
exec(*args)
end
G
- install_gemfile ""
- with_env_vars "RUBYOPT" => "-r#{spec_dir.join("support/hax")}" do
- sys_exec "#{Gem.ruby} #{command.path}"
- end
-
- if Bundler.current_ruby.ruby_2?
- expect(out).to eq("")
- else
- expect(out).to eq("Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec.")
- end
+ install_gemfile "source \"https://gem.repo1\""
+ in_bundled_app "#{Gem.ruby} #{command.path}"
- expect(err).to lack_errors
+ expect(out).to be_empty
+ expect(err).to be_empty
end
it "accepts --keep-file-descriptors" do
- install_gemfile ""
+ install_gemfile "source \"https://gem.repo1\""
bundle "exec --keep-file-descriptors echo foobar"
- expect(err).to lack_errors
+ expect(err).to be_empty
end
it "can run a command named --verbose" do
- install_gemfile 'gem "rack"'
- File.open("--verbose", "w") do |f|
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
+ File.open(bundled_app("--verbose"), "w") do |f|
f.puts "#!/bin/sh"
f.puts "echo foobar"
end
- File.chmod(0o744, "--verbose")
+ File.chmod(0o744, bundled_app("--verbose"))
with_path_as(".") do
bundle "exec -- --verbose"
end
@@ -120,136 +169,225 @@ RSpec.describe "bundle exec" do
it "handles different versions in different bundles" do
build_repo2 do
- build_gem "rack_two", "1.0.0" do |s|
- s.executables = "rackup"
+ build_gem "myrack_two", "1.0.0" do |s|
+ s.executables = "myrackup"
end
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- Dir.chdir bundled_app2 do
- install_gemfile bundled_app2("Gemfile"), <<-G
- source "file://#{gem_repo2}"
- gem "rack_two", "1.0.0"
- G
- end
+ install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
+ source "https://gem.repo2"
+ gem "myrack_two", "1.0.0"
+ G
- bundle! "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("0.9.1")
- Dir.chdir bundled_app2 do
- bundle! "exec rackup"
- expect(out).to eq("1.0.0")
+ bundle "exec myrackup", dir: bundled_app2
+ expect(out).to eq("1.0.0")
+ end
+
+ context "with default gems" do
+ # TODO: Switch to ERB::VERSION once Ruby 3.4 support is dropped, so all
+ # supported rubies include an `erb` gem version where `ERB::VERSION` is
+ # public
+ let(:default_erb_version) { ruby "require 'erb/version'; puts ERB.const_get(:VERSION)" }
+
+ context "when not specified in Gemfile" do
+ before do
+ install_gemfile "source \"https://gem.repo1\""
+ end
+
+ it "uses version provided by ruby" do
+ bundle "exec erb --version"
+
+ expect(stdboth).to eq(default_erb_version)
+ end
+ end
+
+ context "when specified in Gemfile directly" do
+ let(:specified_erb_version) { "2.0.0" }
+
+ before do
+ build_repo2 do
+ build_gem "erb", specified_erb_version do |s|
+ s.executables = "erb"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "erb", "#{specified_erb_version}"
+ G
+ end
+
+ it "uses version specified" do
+ bundle "exec erb --version"
+
+ expect(stdboth).to eq(specified_erb_version)
+ end
+ end
+
+ context "when specified in Gemfile indirectly" do
+ let(:indirect_erb_version) { "2.0.0" }
+
+ before do
+ build_repo2 do
+ build_gem "erb", indirect_erb_version do |s|
+ s.executables = "erb"
+ end
+
+ build_gem "gem_depending_on_old_erb" do |s|
+ s.add_dependency "erb", indirect_erb_version
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "gem_depending_on_old_erb"
+ G
+ end
+
+ it "uses resolved version" do
+ bundle "exec erb --version"
+
+ expect(stdboth).to eq(indirect_erb_version)
+ end
+ end
+ end
+
+ it "warns about executable conflicts" do
+ build_repo2 do
+ build_gem "myrack_two", "1.0.0" do |s|
+ s.executables = "myrackup"
+ end
end
+
+ bundle_config_global "path.system true"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ G
+
+ install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
+ source "https://gem.repo2"
+ gem "myrack_two", "1.0.0"
+ G
+
+ bundle "exec myrackup"
+
+ expect(last_command.stderr).to eq(
+ "Bundler is using a binstub that was created for a different gem (myrack).\n" \
+ "You should run `bundle binstub myrack_two` to work around a system/bundle conflict."
+ )
end
it "handles gems installed with --without" do
- install_gemfile <<-G, forgotten_command_line_options(:without => "middleware")
- source "file://#{gem_repo1}"
- gem "rack" # rack 0.9.1 and 1.0 exist
+ bundle_config "without middleware"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack" # myrack 0.9.1 and 1.0 exist
group :middleware do
- gem "rack_middleware" # rack_middleware depends on rack 0.9.1
+ gem "myrack_middleware" # myrack_middleware depends on myrack 0.9.1
end
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("0.9.1")
- expect(the_bundle).not_to include_gems "rack_middleware 1.0"
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
end
it "does not duplicate already exec'ed RUBYOPT" do
+ create_file("echoopt", "#!/usr/bin/env ruby\nprint ENV['RUBYOPT']")
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- rubyopt = ENV["RUBYOPT"]
- rubyopt = "-rbundler/setup #{rubyopt}"
+ bundler_setup_opt = "-r#{lib_dir}/bundler/setup"
+
+ rubyopt = opt_add(bundler_setup_opt, ENV["RUBYOPT"])
- bundle "exec 'echo $RUBYOPT'"
- expect(out).to have_rubyopts(rubyopt)
+ bundle "exec echoopt"
+ expect(out.split(" ").count(bundler_setup_opt)).to eq(1)
- bundle "exec 'echo $RUBYOPT'", :env => { "RUBYOPT" => rubyopt }
- expect(out).to have_rubyopts(rubyopt)
+ bundle "exec echoopt", env: { "RUBYOPT" => rubyopt }
+ expect(out.split(" ").count(bundler_setup_opt)).to eq(1)
end
it "does not duplicate already exec'ed RUBYLIB" do
+ create_file("echolib", "#!/usr/bin/env ruby\nprint ENV['RUBYLIB']")
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
rubylib = ENV["RUBYLIB"]
- rubylib = "#{rubylib}".split(File::PATH_SEPARATOR).unshift "#{bundler_path}"
+ rubylib = rubylib.to_s.split(File::PATH_SEPARATOR).unshift lib_dir.to_s
rubylib = rubylib.uniq.join(File::PATH_SEPARATOR)
- bundle "exec 'echo $RUBYLIB'"
+ bundle "exec echolib"
expect(out).to include(rubylib)
- bundle "exec 'echo $RUBYLIB'", :env => { "RUBYLIB" => rubylib }
+ bundle "exec echolib", env: { "RUBYLIB" => rubylib }
expect(out).to include(rubylib)
end
it "errors nicely when the argument doesn't exist" do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec foobarbaz"
- expect(exitstatus).to eq(127) if exitstatus
- expect(out).to include("bundler: command not found: foobarbaz")
- expect(out).to include("Install missing gem executables with `bundle install`")
+ bundle "exec foobarbaz", raise_on_error: false
+ expect(exitstatus).to eq(127)
+ expect(err).to include("bundler: command not found: foobarbaz")
+ expect(err).to include("Install missing gem executables with `bundle install`")
end
it "errors nicely when the argument is not executable" do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec touch foo"
- bundle "exec ./foo"
- expect(exitstatus).to eq(126) if exitstatus
- expect(out).to include("bundler: not executable: ./foo")
+ bundled_app("foo").write("")
+ bundle "exec ./foo", raise_on_error: false
+ expect(exitstatus).to eq(126)
+ expect(err).to include("bundler: not executable: ./foo")
end
it "errors nicely when no arguments are passed" do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec"
- expect(exitstatus).to eq(128) if exitstatus
- expect(out).to include("bundler: exec needs a command to run")
+ bundle "exec", raise_on_error: false
+ expect(exitstatus).to eq(128)
+ expect(err).to include("bundler: exec needs a command to run")
end
- it "raises a helpful error when exec'ing to something outside of the bundle", :ruby_repo, :rubygems => ">= 2.5.2" do
- bundle! "config clean false" # want to keep the rackup binstub
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "with_license"
- G
- [true, false].each do |l|
- bundle! "config disable_exec_load #{l}"
- bundle "exec rackup"
- expect(last_command.stderr).to include "can't find executable rackup for gem rack. rack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?"
- end
- end
+ it "raises a helpful error when exec'ing to something outside of the bundle" do
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
- # Different error message on old RG versions (before activate_bin_path) because they
- # called `Kernel#gem` directly
- it "raises a helpful error when exec'ing to something outside of the bundle", :rubygems => "< 2.5.2" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "with_license"
+ bundle_config "clean false" # want to keep the myrackup binstub
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo"
G
[true, false].each do |l|
- bundle! "config disable_exec_load #{l}"
- bundle "exec rackup", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
- expect(last_command.stderr).to include "rack is not part of the bundle. Add it to your Gemfile."
+ bundle_config "disable_exec_load #{l}"
+ bundle "exec myrackup", raise_on_error: false
+ expect(err).to include "can't find executable myrackup for gem myrack. myrack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?"
end
end
@@ -261,14 +399,14 @@ RSpec.describe "bundle exec" do
describe "when #{exec} is used" do
before(:each) do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
create_file("print_args", <<-'RUBY')
#!/usr/bin/env ruby
puts "args: #{ARGV.inspect}"
RUBY
- bundled_app("print_args").chmod(0o755)
end
it "shows executable's man page when --help is after the executable" do
@@ -289,6 +427,7 @@ RSpec.describe "bundle exec" do
it "shows executable's man page when the executable has a -" do
FileUtils.mv(bundled_app("print_args"), bundled_app("docker-template"))
+ FileUtils.mv(bundled_app("print_args.bat"), bundled_app("docker-template.bat")) if Gem.win_platform?
bundle "#{exec} docker-template build discourse --help"
expect(out).to eq('args: ["build", "discourse", "--help"]')
end
@@ -305,70 +444,71 @@ RSpec.describe "bundle exec" do
it "shows bundle-exec's man page when --help is between exec and the executable" do
with_fake_man do
- bundle "#{exec} --help cat"
+ bundle "#{exec} --help echo"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when --help is before exec" do
with_fake_man do
bundle "--help #{exec}"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when -h is before exec" do
with_fake_man do
bundle "-h #{exec}"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when --help is after exec" do
with_fake_man do
bundle "#{exec} --help"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when -h is after exec" do
with_fake_man do
bundle "#{exec} -h"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
end
end
end
describe "with gem executables" do
- describe "run from a random directory", :ruby_repo do
+ describe "run from a random directory" do
before(:each) do
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
it "works when unlocked" do
- bundle "exec 'cd #{tmp("gems")} && rackup'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
expect(out).to eq("1.0.0")
- expect(out).to include("1.0.0")
end
it "works when locked" do
expect(the_bundle).to be_locked
- bundle "exec 'cd #{tmp("gems")} && rackup'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
- expect(out).to include("1.0.0")
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
+ expect(out).to eq("1.0.0")
end
end
describe "from gems bundled via :path" do
before(:each) do
- build_lib "fizz", :path => home("fizz") do |s|
+ build_lib "fizz", path: home("fizz") do |s|
s.executables = "fizz"
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "fizz", :path => "#{File.expand_path(home("fizz"))}"
G
end
@@ -393,6 +533,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "fizz_git", :git => "#{lib_path("fizz_git-1.0")}"
G
end
@@ -411,11 +552,12 @@ RSpec.describe "bundle exec" do
describe "from gems bundled via :git with no gemspec" do
before(:each) do
- build_git "fizz_no_gemspec", :gemspec => false do |s|
+ build_git "fizz_no_gemspec", gemspec: false do |s|
s.executables = "fizz_no_gemspec"
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "fizz_no_gemspec", "1.0", :git => "#{lib_path("fizz_no_gemspec-1.0")}"
G
end
@@ -435,18 +577,61 @@ RSpec.describe "bundle exec" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo"
G
- bundle "config auto_install 1"
- bundle "exec rackup"
+ bundle_config "auto_install 1"
+ bundle "exec myrackup", artifice: "compact_index"
expect(out).to include("Installing foo 1.0")
end
- describe "with gems bundled via :path with invalid gemspecs", :ruby_repo do
- it "outputs the gemspec validation errors", :rubygems => ">= 1.7.2" do
+ it "performs an automatic bundle install with git gems" do
+ build_git "foo" do |s|
+ s.executables = "foo"
+ end
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+
+ bundle_config "auto_install 1"
+ bundle "exec foo", artifice: "compact_index"
+ expect(out).to include("Fetching myrack 0.9.1")
+ expect(out).to include("Fetching #{lib_path("foo-1.0")}")
+ expect(out.lines).to end_with("1.0")
+ end
+
+ it "loads the correct optparse when `auto_install` is set, and optparse is a dependency" do
+ build_repo4 do
+ build_gem "fastlane", "2.192.0" do |s|
+ s.executables = "fastlane"
+ s.add_dependency "optparse", "~> 999.999.999"
+ end
+
+ build_gem "optparse", "999.999.998"
+ build_gem "optparse", "999.999.999"
+ end
+
+ system_gems "optparse-999.999.998", gem_repo: gem_repo4
+
+ bundle_config "auto_install 1"
+ bundle_config "path vendor/bundle"
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "fastlane"
+ G
+
+ bundle "exec fastlane", artifice: "compact_index"
+ expect(out).to include("Installing optparse 999.999.999")
+ expect(out).to include("2.192.0")
+ end
+
+ describe "with gems bundled via :path with invalid gemspecs" do
+ it "outputs the gemspec validation errors" do
build_lib "foo"
gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s
@@ -457,24 +642,28 @@ RSpec.describe "bundle exec" do
s.version = '1.0'
s.summary = 'TODO: Add summary'
s.authors = 'Me'
+ s.rubygems_version = nil
end
G
end
- install_gemfile <<-G
+ gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- bundle "exec irb"
+ bundle "exec erb", raise_on_error: false
expect(err).to match("The gemspec at #{lib_path("foo-1.0").join("foo.gemspec")} is not valid")
- expect(err).to match('"TODO" is not a summary')
+ expect(err).to match(/missing value for attribute rubygems_version|rubygems_version must not be nil/)
end
end
describe "with gems bundled for deployment" do
it "works when calling bundler from another script" do
gemfile <<-G
+ source "https://gem.repo1"
+
module Monkey
def bin_path(a,b,c)
raise Gem::GemNotFoundException.new('Fail')
@@ -482,70 +671,124 @@ RSpec.describe "bundle exec" do
end
Bundler.rubygems.extend(Monkey)
G
- bundle "install --deployment"
- bundle "exec ruby -e '`#{bindir.join("bundler")} -v`; puts $?.success?'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle_config "path.system true"
+ bundle "install"
+ bundle "exec ruby -e '`bundle -v`; puts $?.success?'", env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(out).to match("true")
end
end
+ describe "bundle exec gem uninstall" do
+ before do
+ build_repo4 do
+ build_gem "foo"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+ end
+
+ it "works" do
+ bundle "exec #{gem_cmd} uninstall foo"
+ expect(out).to eq("Successfully uninstalled foo-1.0")
+ end
+ end
+
+ describe "running gem commands in presence of rubygems plugins" do
+ before do
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.write "lib/rubygems_plugin.rb", "puts 'FAIL'"
+ end
+ end
+
+ system_gems "foo-1.0", path: default_bundle_path, gem_repo: gem_repo4
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ G
+ end
+
+ it "does not load plugins outside of the bundle" do
+ bundle "exec #{gem_cmd} -v"
+ expect(out).not_to include("FAIL")
+ end
+ end
+
context "`load`ing a ruby file instead of `exec`ing" do
let(:path) { bundled_app("ruby_executable") }
let(:shebang) { "#!/usr/bin/env ruby" }
- let(:executable) { <<-RUBY.gsub(/^ */, "").strip }
+ let(:executable) { <<~RUBY.strip }
#{shebang}
- require "rack"
+ require "myrack"
puts "EXEC: \#{caller.grep(/load/).empty? ? 'exec' : 'load'}"
puts "ARGS: \#{$0} \#{ARGV.join(' ')}"
- puts "RACK: \#{RACK}"
- process_title = `ps -o args -p \#{Process.pid}`.split("\n", 2).last.strip
+ puts "MYRACK: \#{MYRACK}"
+ if Gem.win_platform?
+ process_title = "ruby"
+ else
+ process_title = `ps -o args -p \#{Process.pid}`.split("\n", 2).last.strip
+ end
puts "PROCESS: \#{process_title}"
RUBY
before do
- path.open("w") {|f| f << executable }
- path.chmod(0o755)
+ create_file(bundled_app(path), executable)
install_gemfile <<-G
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
let(:exec) { "EXEC: load" }
let(:args) { "ARGS: #{path} arg1 arg2" }
- let(:rack) { "RACK: 1.0.0" }
+ let(:myrack) { "MYRACK: 1.0.0" }
let(:process) do
- title = "PROCESS: #{path}"
- title += " arg1 arg2" if RUBY_VERSION >= "2.1"
- title
+ if Gem.win_platform?
+ "PROCESS: ruby"
+ else
+ "PROCESS: #{path} arg1 arg2"
+ end
end
let(:exit_code) { 0 }
- let(:expected) { [exec, args, rack, process].join("\n") }
+ let(:expected) { [exec, args, myrack, process].join("\n") }
let(:expected_err) { "" }
- subject { bundle "exec #{path} arg1 arg2", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" } }
+ subject { bundle "exec #{path} arg1 arg2", raise_on_error: false }
- shared_examples_for "it runs" do
- it "like a normally executed executable" do
- subject
- expect(exitstatus).to eq(exit_code) if exitstatus
- expect(last_command.stderr).to eq(expected_err)
- expect(last_command.stdout).to eq(expected)
- end
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
end
- it_behaves_like "it runs"
-
context "the executable exits explicitly" do
let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" }
context "with exit 0" do
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "with exit 99" do
let(:exit_code) { 99 }
- it_behaves_like "it runs"
+
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
end
@@ -553,21 +796,22 @@ RSpec.describe "bundle exec" do
let(:executable) do
ex = super()
ex << "\n"
- if LessThanProc.with(RUBY_VERSION).call("1.9")
- # Ruby < 1.9 needs a flush for a exit by signal, later
- # rubies do not
- ex << "STDOUT.flush\n"
- end
ex << "raise SignalException, 'SIGTERM'\n"
ex
end
- let(:expected_err) { ENV["TRAVIS"] ? "Terminated" : "" }
+ let(:expected_err) { "" }
let(:exit_code) do
- # signal mask 128 + plus signal 15 -> TERM
- # this is specified by C99
- 128 + 15
+ exit_status_for_signal(Signal.list["TERM"])
+ end
+
+ it "runs" do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
end
- it_behaves_like "it runs"
end
context "the executable is empty" do
@@ -576,84 +820,146 @@ RSpec.describe "bundle exec" do
let(:exit_code) { 0 }
let(:expected_err) { "#{path} is empty" }
let(:expected) { "" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ # it's empty, so `create_file` won't add executable permission and bat scripts on Windows
+ bundled_app(path).chmod(0o755)
+ path.sub_ext(".bat").write <<~SCRIPT if Gem.win_platform?
+ @ECHO OFF
+ @"ruby.exe" "%~dpn0" %*
+ SCRIPT
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "the executable raises" do
let(:executable) { super() << "\nraise 'ERROR'" }
let(:exit_code) { 1 }
let(:expected_err) do
- "bundler: failed to load command: #{path} (#{path})" \
- "\nRuntimeError: ERROR\n #{path}:10:in `<top (required)>'"
+ /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:[0-9]+:in [`']<top \(required\)>': ERROR \(RuntimeError\)/
+ end
+
+ it "runs like a normally executed executable" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to match(expected_err)
+ expect(out).to eq(expected)
end
- it_behaves_like "it runs"
end
context "the executable raises an error without a backtrace" do
let(:executable) { super() << "\nclass Err < Exception\ndef backtrace; end;\nend\nraise Err" }
let(:exit_code) { 1 }
- let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\nErr: Err" }
+ let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\n#{system_gem_path("bin/bundle")}: Err (Err)" }
let(:expected) { super() }
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
- context "when the file uses the current ruby shebang", :ruby_repo do
+ context "when the file uses the current ruby shebang" do
let(:shebang) { "#!#{Gem.ruby}" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
- context "when Bundler.setup fails", :bundler => "< 3" do
+ context "when Bundler.setup fails" do
before do
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
+
gemfile <<-G
- gem 'rack', '2'
+ source "https://gem.repo1"
+ gem 'myrack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
end
let(:exit_code) { Bundler::GemNotFound.new.status_code }
- let(:expected) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile.\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
+ let(:expected) { "" }
+ let(:expected_err) { <<~EOS.strip }
+ Could not find gem 'myrack (= 2)' in locally installed gems.
+
+ The source contains the following gems matching 'myrack':
+ * myrack-0.9.1
+ * myrack-1.0.0
+ Run `bundle install` to install missing gems.
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
- context "when Bundler.setup fails", :bundler => "3" do
+ context "when Bundler.setup fails and Gemfile is not the default" do
before do
- gemfile <<-G
- gem 'rack', '2'
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo1"
+ gem 'myrack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
+ ENV["BUNDLE_GEMFILE"] = "CustomGemfile"
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil
end
let(:exit_code) { Bundler::GemNotFound.new.status_code }
- let(:expected) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in locally installed gems.
-The source contains 'rack' at: 1.0.0\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
- EOS
+ let(:expected) { "" }
- it_behaves_like "it runs"
+ it "prints proper suggestion" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to include("Run `bundle install --gemfile CustomGemfile` to install missing gems.")
+ expect(out).to eq(expected)
+ end
end
context "when the executable exits non-zero via at_exit" do
let(:executable) { super() + "\n\nat_exit { $! ? raise($!) : exit(1) }" }
let(:exit_code) { 1 }
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when disable_exec_load is set" do
let(:exec) { "EXEC: exec" }
- let(:process) { "PROCESS: ruby #{path} arg1 arg2" }
+ let(:process) do
+ if Gem.win_platform?
+ "PROCESS: ruby"
+ else
+ "PROCESS: ruby #{path} arg1 arg2"
+ end
+ end
before do
- bundle "config disable_exec_load true"
+ bundle_config "disable_exec_load true"
end
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "regarding $0 and __FILE__" do
@@ -663,31 +969,50 @@ The source contains 'rack' at: 1.0.0\e[0m
puts "__FILE__: #{__FILE__.inspect}"
RUBY
- let(:expected) { super() + <<-EOS.chomp }
+ context "when the path is absolute" do
+ let(:expected) { super() + <<~EOS.chomp }
-$0: #{path.to_s.inspect}
-__FILE__: #{path.to_s.inspect}
- EOS
+ $0: #{path.to_s.inspect}
+ __FILE__: #{path.to_s.inspect}
+ EOS
- it_behaves_like "it runs"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
+ end
context "when the path is relative" do
let(:path) { super().relative_path_from(bundled_app) }
+ let(:expected) { super() + <<~EOS.chomp }
- if LessThanProc.with(RUBY_VERSION).call("1.9")
- pending "relative paths have ./ __FILE__"
- else
- it_behaves_like "it runs"
+ $0: #{path.to_s.inspect}
+ __FILE__: #{path.to_s.inspect}
+ EOS
+
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
end
end
context "when the path is relative with a leading ./" do
- let(:path) { Pathname.new("./#{super().relative_path_from(Pathname.pwd)}") }
-
- if LessThanProc.with(RUBY_VERSION).call("< 1.9")
- pending "relative paths with ./ have absolute __FILE__"
- else
- it_behaves_like "it runs"
+ let(:path) { Pathname.new("./#{super().relative_path_from(bundled_app)}") }
+ let(:expected) { super() + <<~EOS.chomp }
+
+ $0: #{path.to_s.inspect}
+ __FILE__: #{File.expand_path(path, bundled_app).inspect}
+ EOS
+
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
end
end
end
@@ -695,29 +1020,31 @@ __FILE__: #{path.to_s.inspect}
context "signal handling" do
let(:test_signals) do
open3_reserved_signals = %w[CHLD CLD PIPE]
- reserved_signals = %w[SEGV BUS ILL FPE VTALRM KILL STOP EXIT]
+ reserved_signals = %w[SEGV BUS ILL FPE ABRT IOT VTALRM KILL STOP EXIT]
bundler_signals = %w[INT]
Signal.list.keys - (bundler_signals + reserved_signals + open3_reserved_signals)
end
context "signals being trapped by bundler" do
- let(:executable) { strip_whitespace <<-RUBY }
+ let(:executable) { <<~RUBY }
#{shebang}
begin
Thread.new do
puts 'Started' # For process sync
STDOUT.flush
sleep 1 # ignore quality_spec
- raise "Didn't receive INT at all"
+ raise RuntimeError, "Didn't receive expected INT"
end.join
rescue Interrupt
puts "foo"
end
RUBY
- it "receives the signal", :ruby => ">= 1.9.3" do
- bundle!("exec #{path}") do |_, o, thr|
+ it "receives the signal" do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
+ bundle("exec #{path}") do |_, o, thr|
o.gets # Consumes 'Started' and ensures that thread has started
Process.kill("INT", thr.pid)
end
@@ -727,7 +1054,7 @@ __FILE__: #{path.to_s.inspect}
end
context "signals not being trapped by bunder" do
- let(:executable) { strip_whitespace <<-RUBY }
+ let(:executable) { <<~RUBY }
#{shebang}
signals = #{test_signals.inspect}
@@ -738,11 +1065,13 @@ __FILE__: #{path.to_s.inspect}
RUBY
it "makes sure no unexpected signals are restored to DEFAULT" do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
test_signals.each do |n|
Signal.trap(n, "IGNORE")
end
- bundle!("exec #{path}")
+ bundle("exec #{path}")
expect(out).to eq(test_signals.count.to_s)
end
@@ -751,72 +1080,192 @@ __FILE__: #{path.to_s.inspect}
end
context "nested bundle exec" do
- let(:system_gems_to_install) { super() << :bundler }
-
- context "with shared gems disabled" do
+ context "when bundle in a local path" do
before do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, :system_bundler => true, :path => "vendor/bundler"
+ bundle_config "path vendor/bundler"
+ bundle :install
end
- it "overrides disable_shared_gems so bundler can be found" do
- skip "bundler 1.16.x is not support with Ruby 2.6 on Travis CI" if RUBY_VERSION >= "2.6"
-
+ it "correctly shells out" do
file = bundled_app("file_that_bundle_execs.rb")
- create_file(file, <<-RB)
+ create_file(file, <<-RUBY)
#!#{Gem.ruby}
puts `bundle exec echo foo`
- RB
+ RUBY
file.chmod(0o777)
- bundle! "exec #{file}", :system_bundler => true
+ bundle "exec #{file}", env: { "PATH" => path }
expect(out).to eq("foo")
end
end
+ context "when Kernel.require uses extra monkeypatches" do
+ before do
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
+
+ install_gemfile "source \"https://gem.repo1\""
+ end
+
+ it "does not undo the monkeypatches" do
+ karafka = bundled_app("bin/karafka")
+ create_file(karafka, <<~RUBY)
+ #!#{Gem.ruby}
+
+ module Kernel
+ module_function
+
+ alias_method :require_before_extra_monkeypatches, :require
+
+ def require(path)
+ puts "requiring \#{path} used the monkeypatch"
+
+ require_before_extra_monkeypatches(path)
+ end
+ end
+
+ Bundler.setup(:default)
+
+ require "foo"
+ RUBY
+ karafka.chmod(0o777)
+
+ foreman = bundled_app("bin/foreman")
+ create_file(foreman, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundle exec bin/karafka`
+ RUBY
+ foreman.chmod(0o777)
+
+ bundle "exec #{foreman}"
+ expect(out).to eq("requiring foo used the monkeypatch")
+ end
+ end
+
+ context "when gemfile and path are configured", :ruby_repo do
+ before do
+ build_repo2 do
+ build_gem "rails", "6.1.0" do |s|
+ s.executables = "rails"
+ end
+ end
+
+ bundle_config "path vendor/bundle"
+ bundle_config "gemfile gemfiles/myrack_6_1.gemfile"
+
+ gemfile(bundled_app("gemfiles/myrack_6_1.gemfile"), <<~RUBY)
+ source "https://gem.repo2"
+
+ gem "rails", "6.1.0"
+ RUBY
+
+ # A Gemfile needs to be in the root to trick bundler's root resolution
+ gemfile "source 'https://gem.repo1'"
+
+ bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ end
+
+ it "can still find gems after a nested subprocess" do
+ script = bundled_app("bin/myscript")
+
+ create_file(script, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundle exec rails`
+ RUBY
+
+ script.chmod(0o777)
+
+ bundle "exec #{script}"
+
+ expect(err).to be_empty
+ expect(out).to eq("6.1.0")
+ end
+
+ it "can still find gems after a nested subprocess when using bundler (with a final r) executable" do
+ script = bundled_app("bin/myscript")
+
+ create_file(script, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundler exec rails`
+ RUBY
+
+ script.chmod(0o777)
+
+ bundle "exec #{script}"
+
+ expect(err).to be_empty
+ expect(out).to eq("6.1.0")
+ end
+ end
+
context "with a system gem that shadows a default gem" do
let(:openssl_version) { "99.9.9" }
- let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil }
it "only leaves the default gem in the stdlib available" do
- skip "openssl isn't a default gem" if expected.empty?
+ default_openssl_version = ruby "require 'openssl'; puts OpenSSL::VERSION"
+
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
- install_gemfile! "" # must happen before installing the broken system gem
+ install_gemfile "source \"https://gem.repo1\"" # must happen before installing the broken system gem
build_repo4 do
build_gem "openssl", openssl_version do |s|
- s.write("lib/openssl.rb", <<-RB)
- raise "custom openssl should not be loaded, it's not in the gemfile!"
- RB
+ s.write("lib/openssl.rb", <<-RUBY)
+ raise ArgumentError, "custom openssl should not be loaded"
+ RUBY
end
end
- system_gems(:bundler, "openssl-#{openssl_version}", :gem_repo => gem_repo4)
+ system_gems("openssl-#{openssl_version}", gem_repo: gem_repo4)
file = bundled_app("require_openssl.rb")
- create_file(file, <<-RB)
+ create_file(file, <<-RUBY)
#!/usr/bin/env ruby
require "openssl"
puts OpenSSL::VERSION
warn Gem.loaded_specs.values.map(&:full_name)
- RB
+ RUBY
file.chmod(0o777)
+ env = { "PATH" => path }
aggregate_failures do
- expect(bundle!("exec #{file}", :artifice => nil)).to eq(expected)
- expect(bundle!("exec bundle exec #{file}", :artifice => nil)).to eq(expected)
- expect(bundle!("exec ruby #{file}", :artifice => nil)).to eq(expected)
- # Ignore expectaion for default bundler gem conflict.
- unless ENV["BUNDLER_SPEC_SUB_VERSION"]
- expect(run!(file.read, :artifice => nil)).to eq(expected)
- end
+ expect(bundle("exec #{file}", env: env)).to eq(default_openssl_version)
+ expect(bundle("exec bundle exec #{file}", env: env)).to eq(default_openssl_version)
+ expect(bundle("exec ruby #{file}", env: env)).to eq(default_openssl_version)
+ expect(run(file.read, artifice: nil, env: env)).to eq(default_openssl_version)
end
+ skip "ruby_core has openssl and rubygems in the same folder, and this test needs rubygems require but default openssl not in a directly added entry in $LOAD_PATH" if ruby_core?
# sanity check that we get the newer, custom version without bundler
- sys_exec("#{Gem.ruby} #{file}")
- expect(last_command.stderr).to include("custom openssl should not be loaded")
+ sys_exec "#{Gem.ruby} #{file}", env: env, raise_on_error: false
+ expect(err).to include("custom openssl should not be loaded")
+ end
+ end
+
+ context "with a git gem that includes extensions", :ruby_repo do
+ before do
+ build_git "simple_git_binary", &:add_c_extension
+ bundle_config "path .bundle"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "simple_git_binary", :git => '#{lib_path("simple_git_binary-1.0")}'
+ G
+ end
+
+ it "allows calling bundle install" do
+ bundle "exec bundle install"
+ end
+
+ it "allows calling bundle install after removing gem.build_complete" do
+ FileUtils.rm_r Dir[bundled_app(".bundle/**/gem.build_complete")]
+ bundle "exec #{Gem.ruby} -S bundle install"
end
end
end
diff --git a/spec/bundler/commands/fund_spec.rb b/spec/bundler/commands/fund_spec.rb
new file mode 100644
index 0000000000..5883b8a63a
--- /dev/null
+++ b/spec/bundler/commands/fund_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle fund" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+
+ build_gem "gem_with_dependent_funding", "1.0" do |s|
+ s.add_dependency "has_funding"
+ end
+ end
+ end
+
+ it "prints fund information for all gems in the bundle" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding")
+ expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("myrack-obama")
+ end
+
+ it "does not consider fund information for gem dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'gem_with_dependent_funding'
+ G
+
+ bundle "fund"
+
+ expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("gem_with_dependent_funding")
+ end
+
+ it "does not consider fund information for uninstalled optional dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ group :whatever, optional: true do
+ gem 'has_funding_and_other_metadata'
+ end
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("has_funding_and_other_metadata")
+ expect(out).to_not include("myrack-obama")
+ end
+
+ it "considers fund information for installed optional dependencies" do
+ bundle_config "with whatever"
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ group :whatever, optional: true do
+ gem 'has_funding_and_other_metadata'
+ end
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding")
+ expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("myrack-obama")
+ end
+
+ it "prints message if none of the gems have fund information" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'myrack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("None of the installed gems you directly depend on are looking for funding.")
+ end
+
+ describe "with --group option" do
+ it "prints fund message for only specified group gems" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata', :group => :development
+ gem 'has_funding'
+ G
+
+ bundle "fund --group development"
+ expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding")
+ expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ end
+ end
+end
diff --git a/spec/bundler/commands/help_spec.rb b/spec/bundler/commands/help_spec.rb
index 56b1b6f722..f9ad9fff14 100644
--- a/spec/bundler/commands/help_spec.rb
+++ b/spec/bundler/commands/help_spec.rb
@@ -1,42 +1,37 @@
# frozen_string_literal: true
RSpec.describe "bundle help" do
- # RubyGems 1.4+ no longer load gem plugins so this test is no longer needed
- it "complains if older versions of bundler are installed", :rubygems => "< 1.4" do
- system_gems "bundler-0.8.1"
-
- bundle "help"
- expect(err).to include("older than 0.9")
- expect(err).to include("running `gem cleanup bundler`.")
- end
-
- it "uses mann when available" do
+ it "uses man when available" do
with_fake_man do
bundle "help gemfile"
end
- expect(out).to eq(%(["#{root}/man/gemfile.5"]))
+ expect(out).to eq(%(["#{man_dir}/gemfile.5"]))
end
- it "prefixes bundle commands with bundle- when finding the groff files" do
+ it "prefixes bundle commands with bundle- when finding the man files" do
with_fake_man do
bundle "help install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
- it "simply outputs the txt file when there is no man on the path" do
- with_path_as("") do
- bundle "help install"
+ it "prexifes bundle commands with bundle- and resolves aliases when finding the man files" do
+ with_fake_man do
+ bundle "help package"
end
- expect(out).to match(/BUNDLE-INSTALL/)
+ expect(out).to eq(%(["#{man_dir}/bundle-cache.1"]))
end
- it "still outputs the old help for commands that do not have man pages yet" do
- bundle "help version"
- expect(out).to include("Prints the bundler's version information")
+ it "simply outputs the human readable file when there is no man on the path" do
+ with_path_as("") do
+ bundle "help install"
+ end
+ expect(out).to match(/bundle-install/)
end
it "looks for a binary and executes it with --help option if it's named bundler-<task>" do
+ skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform?
+
File.open(tmp("bundler-testtasks"), "w", 0o755) do |f|
f.puts "#!/usr/bin/env ruby\nputs ARGV.join(' ')\n"
end
@@ -45,7 +40,6 @@ RSpec.describe "bundle help" do
bundle "help testtasks"
end
- expect(exitstatus).to be_zero if exitstatus
expect(out).to eq("--help")
end
@@ -53,46 +47,46 @@ RSpec.describe "bundle help" do
with_fake_man do
bundle "install --help"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the --help flag is used before the command" do
with_fake_man do
bundle "--help install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the -h flag is used before the command" do
with_fake_man do
bundle "-h install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the -h flag is used after the command" do
with_fake_man do
bundle "install -h"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "has helpful output when using --help flag for a non-existent command" do
with_fake_man do
- bundle "instill -h"
+ bundle "instill -h", raise_on_error: false
end
- expect(out).to include('Could not find command "instill".')
+ expect(err).to include('Could not find command "instill".')
end
it "is called when only using the --help flag" do
with_fake_man do
bundle "--help"
end
- expect(out).to eq(%(["#{root}/man/bundle.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle.1"]))
with_fake_man do
bundle "-h"
end
- expect(out).to eq(%(["#{root}/man/bundle.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle.1"]))
end
end
diff --git a/spec/bundler/commands/info_spec.rb b/spec/bundler/commands/info_spec.rb
index a9ab8fc210..a26b1696fb 100644
--- a/spec/bundler/commands/info_spec.rb
+++ b/spec/bundler/commands/info_spec.rb
@@ -1,40 +1,118 @@
# frozen_string_literal: true
RSpec.describe "bundle info" do
- context "info from specific gem in gemfile" do
+ context "with a standard Gemfile" do
before do
+ build_repo2 do
+ build_gem "has_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "rails"
+ gem "has_metadata"
+ gem "thin"
G
end
- it "prints information about the current gem" do
+ it "creates a Gemfile.lock when invoked with a gem name" do
+ FileUtils.rm(bundled_app_lock)
+
+ bundle "info rails"
+
+ expect(bundled_app_lock).to exist
+ end
+
+ it "prints information if gem exists in bundle" do
bundle "info rails"
expect(out).to include "* rails (2.3.2)
\tSummary: This is just a fake gem for testing
-\tHomepage: http://example.com"
- expect(out).to match(%r{Path\: .*\/rails\-2\.3\.2})
+\tHomepage: http://example.com
+\tPath: #{default_bundle_path("gems", "rails-2.3.2")}"
end
- context "given a gem that is not installed" do
- it "prints missing gem error" do
- bundle "info foo"
- expect(out).to eq "Could not find gem 'foo'."
- end
+ it "prints path if gem exists in bundle" do
+ bundle "info rails --path"
+ expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
+ end
+
+ it "prints the path to the running bundler" do
+ bundle "info bundler --path"
+ expect(out).to eq(root.to_s)
+ end
+
+ it "prints gem version if exists in bundle" do
+ bundle "info rails --version"
+ expect(out).to eq("2.3.2")
+ end
+
+ it "doesn't claim that bundler is missing, even if using a custom path without bundler there" do
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ bundle "info bundler"
+ expect(out).to include("\tPath: #{root}")
+ expect(err).not_to match(/The gem bundler is missing/i)
+ end
+
+ it "complains if gem not in bundle" do
+ bundle "info missing", raise_on_error: false
+ expect(err).to eq("Could not find gem 'missing'.")
+ end
+
+ it "warns if path does not exist on disk, but specification is there" do
+ FileUtils.rm_r(default_bundle_path("gems", "rails-2.3.2"))
+
+ bundle "info rails --path"
+
+ expect(err).to include("The gem rails is missing.")
+ expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
+
+ bundle "info rail --path"
+ expect(err).to include("The gem rails is missing.")
+ expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
+
+ bundle "info rails"
+ expect(err).to include("The gem rails is missing.")
+ expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- context "given a default gem shippped in ruby", :ruby_repo do
- it "prints information about the default gem", :if => (RUBY_VERSION >= "2.0") do
- bundle "info rdoc"
- expect(out).to include("* rdoc")
+ context "given a default gem shipped in ruby", :ruby_repo do
+ it "prints information about the default gem" do
+ bundle "info json"
+ expect(out).to include("* json")
expect(out).to include("Default Gem: yes")
end
end
+ context "given a gem with metadata" do
+ it "prints the gem metadata" do
+ bundle "info has_metadata"
+ expect(out).to include "* has_metadata (1.0)
+\tSummary: This is just a fake gem for testing
+\tHomepage: http://example.com
+\tDocumentation: https://www.example.info/gems/bestgemever/0.0.1
+\tSource Code: https://example.com/user/bestgemever
+\tWiki: https://example.com/user/bestgemever/wiki
+\tChangelog: https://example.com/user/bestgemever/CHANGELOG.md
+\tBug Tracker: https://example.com/user/bestgemever/issues
+\tMailing List: https://groups.example.com/bestgemever
+\tPath: #{default_bundle_path("gems", "has_metadata-1.0")}"
+ end
+ end
+
context "when gem does not have homepage" do
before do
- build_repo1 do
+ build_repo2 do
build_gem "rails", "2.3.2" do |s|
s.executables = "rails"
s.summary = "Just another test gem"
@@ -47,11 +125,125 @@ RSpec.describe "bundle info" do
end
end
- context "given --path option" do
- it "prints the path to the gem" do
+ context "when gem has a reverse dependency on any version" do
+ it "prints the details" do
+ bundle "info myrack"
+
+ expect(out).to include("Reverse Dependencies: \n\t\tthin (1.0) depends on myrack (>= 0)")
+ end
+ end
+
+ context "when gem has a reverse dependency on a specific version" do
+ it "prints the details" do
+ bundle "info actionpack"
+
+ expect(out).to include("Reverse Dependencies: \n\t\trails (2.3.2) depends on actionpack (= 2.3.2)")
+ end
+ end
+
+ context "when gem has no reverse dependencies" do
+ it "excludes the reverse dependencies field from the output" do
bundle "info rails"
- expect(out).to match(%r{.*\/rails\-2\.3\.2})
+
+ expect(out).not_to include("Reverse Dependencies:")
end
end
end
+
+ context "with a git repo in the Gemfile" do
+ before :each do
+ @git = build_git "foo", "1.0"
+ end
+
+ it "prints out git info" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+ expect(the_bundle).to include_gems "foo 1.0"
+
+ bundle "info foo"
+ expect(out).to include("foo (1.0 #{@git.ref_for("main", 6)}")
+ end
+
+ it "prints out branch names other than main" do
+ update_git "foo", branch: "omg" do |s|
+ s.write "lib/foo.rb", "FOO = '1.0.omg'"
+ end
+ @revision = revision_for(lib_path("foo-1.0"))[0...6]
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
+ G
+ expect(the_bundle).to include_gems "foo 1.0.omg"
+
+ bundle "info foo"
+ expect(out).to include("foo (1.0 #{@git.ref_for("omg", 6)}")
+ end
+
+ it "doesn't print the branch when tied to a ref" do
+ sha = revision_for(lib_path("foo-1.0"))
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{sha}"
+ G
+
+ bundle "info foo"
+ expect(out).to include("foo (1.0 #{sha[0..6]})")
+ end
+
+ it "handles when a version is a '-' prerelease" do
+ @git = build_git("foo", "1.0.0-beta.1", path: lib_path("foo"))
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", "1.0.0-beta.1", :git => "#{lib_path("foo")}"
+ G
+ expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1"
+
+ bundle "info foo"
+ expect(out).to include("foo (1.0.0.pre.beta.1")
+ end
+ end
+
+ context "with a valid regexp for gem name" do
+ it "presents alternatives", :readline do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
+ G
+
+ bundle "info rac"
+ expect(out).to match(/\A1 : myrack\n2 : myrack-obama\n0 : - exit -(\n>|\z)/)
+ end
+ end
+
+ context "with an invalid regexp for gem name" do
+ it "does not find the gem" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ G
+
+ invalid_regexp = "[]"
+
+ bundle "info #{invalid_regexp}", raise_on_error: false
+ expect(err).to include("Could not find gem '#{invalid_regexp}'.")
+ end
+ end
+
+ context "with without configured" do
+ it "does not find the gem, but gives a helpful error" do
+ bundle_config "without test"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", group: :test
+ G
+
+ bundle "info rails", raise_on_error: false
+ expect(err).to include("Could not find gem 'rails', because it's in the group 'test', configured to be ignored.")
+ end
+ end
end
diff --git a/spec/bundler/commands/init_spec.rb b/spec/bundler/commands/init_spec.rb
index 8a8f0effa0..989d6fa812 100644
--- a/spec/bundler/commands/init_spec.rb
+++ b/spec/bundler/commands/init_spec.rb
@@ -1,63 +1,61 @@
# frozen_string_literal: true
RSpec.describe "bundle init" do
- it "generates a Gemfile", :bundler => "< 3" do
- bundle! :init
+ it "generates a Gemfile" do
+ bundle :init
expect(out).to include("Writing new Gemfile")
- expect(bundled_app("Gemfile")).to be_file
+ expect(bundled_app_gemfile).to be_file
end
- it "generates a gems.rb", :bundler => "3" do
- bundle! :init
- expect(out).to include("Writing new gems.rb")
- expect(bundled_app("gems.rb")).to be_file
- end
-
- context "when a Gemfile already exists", :bundler => "< 3" do
- before do
- create_file "Gemfile", <<-G
- gem "rails"
- G
+ context "with a template with permission flags not matching current process umask" do
+ let(:template_file) do
+ gemfile = Bundler.preferred_gemfile_name
+ templates_dir.join(gemfile)
end
- it "does not change existing Gemfiles" do
- expect { bundle :init }.not_to change { File.read(bundled_app("Gemfile")) }
+ let(:target_dir) { bundled_app("init_permissions_test") }
+
+ around do |example|
+ old_chmod = File.stat(template_file).mode
+ FileUtils.chmod(old_chmod | 0o111, template_file) # chmod +x
+ example.run
+ FileUtils.chmod(old_chmod, template_file)
end
- it "notifies the user that an existing Gemfile already exists" do
- bundle :init
- expect(out).to include("Gemfile already exists")
+ it "honours the current process umask when generating from a template" do
+ FileUtils.mkdir(target_dir)
+ bundle :init, dir: target_dir
+ generated_mode = File.stat(File.join(target_dir, "Gemfile")).mode & 0o111
+ expect(generated_mode).to be_zero
end
end
- context "when gems.rb already exists", :bundler => ">= 3" do
+ context "when a Gemfile already exists" do
before do
- create_file("gems.rb", <<-G)
+ gemfile <<-G
gem "rails"
G
end
it "does not change existing Gemfiles" do
- expect { bundle :init }.not_to change { File.read(bundled_app("gems.rb")) }
+ expect { bundle :init, raise_on_error: false }.not_to change { File.read(bundled_app_gemfile) }
end
- it "notifies the user that an existing gems.rb already exists" do
- bundle :init
- expect(out).to include("gems.rb already exists")
+ it "notifies the user that an existing Gemfile already exists" do
+ bundle :init, raise_on_error: false
+ expect(err).to include("Gemfile already exists")
end
end
- context "when a Gemfile exists in a parent directory", :bundler => "< 3" do
+ context "when a Gemfile exists in a parent directory" do
let(:subdir) { "child_dir" }
it "lets users generate a Gemfile in a child directory" do
- bundle! :init
+ bundle :init
FileUtils.mkdir bundled_app(subdir)
- Dir.chdir bundled_app(subdir) do
- bundle! :init
- end
+ bundle :init, dir: bundled_app(subdir)
expect(out).to include("Writing new Gemfile")
expect(bundled_app("#{subdir}/Gemfile")).to be_file
@@ -67,61 +65,38 @@ RSpec.describe "bundle init" do
context "when the dir is not writable by the current user" do
let(:subdir) { "child_dir" }
- it "notifies the user that it can not write to it" do
+ it "notifies the user that it cannot write to it" do
FileUtils.mkdir bundled_app(subdir)
# chmod a-w it
mode = File.stat(bundled_app(subdir)).mode ^ 0o222
FileUtils.chmod mode, bundled_app(subdir)
- Dir.chdir bundled_app(subdir) do
- bundle :init
- end
+ bundle :init, dir: bundled_app(subdir), raise_on_error: false
- expect(out).to include("directory is not writable")
+ expect(err).to include("directory is not writable")
expect(Dir[bundled_app("#{subdir}/*")]).to be_empty
end
end
- context "when a gems.rb file exists in a parent directory", :bundler => ">= 3" do
- let(:subdir) { "child_dir" }
-
- it "lets users generate a Gemfile in a child directory" do
- bundle! :init
-
- FileUtils.mkdir bundled_app(subdir)
-
- Dir.chdir bundled_app(subdir) do
- bundle! :init
- end
-
- expect(out).to include("Writing new gems.rb")
- expect(bundled_app("#{subdir}/gems.rb")).to be_file
- end
- end
-
- context "given --gemspec option", :bundler => "< 3" do
- let(:spec_file) { tmp.join("test.gemspec") }
+ context "given --gemspec option" do
+ let(:spec_file) { tmp("test.gemspec") }
it "should generate from an existing gemspec" do
File.open(spec_file, "w") do |file|
file << <<-S
Gem::Specification.new do |s|
s.name = 'test'
- s.add_dependency 'rack', '= 1.0.1'
+ s.add_dependency 'myrack', '= 1.0.1'
s.add_development_dependency 'rspec', '1.2'
end
S
end
- bundle :init, :gemspec => spec_file
+ bundle :init, gemspec: spec_file
- gemfile = if Bundler::VERSION[0, 2].to_i < 3
- bundled_app("Gemfile").read
- else
- bundled_app("gems.rb").read
- end
+ gemfile = bundled_app_gemfile.read
expect(gemfile).to match(%r{source 'https://rubygems.org'})
- expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1)
+ expect(gemfile.scan(/gem "myrack", "= 1.0.1"/).size).to eq(1)
expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1)
expect(gemfile.scan(/group :development/).size).to eq(1)
end
@@ -137,24 +112,62 @@ RSpec.describe "bundle init" do
S
end
- bundle :init, :gemspec => spec_file
- expect(last_command.bundler_err).to include("There was an error while loading `test.gemspec`")
+ bundle :init, gemspec: spec_file, raise_on_error: false
+ expect(err).to include("There was an error while loading `test.gemspec`")
end
end
end
context "when init_gems_rb setting is enabled" do
- before { bundle "config init_gems_rb true" }
+ before { bundle_config "init_gems_rb true" }
- context "given --gemspec option", :bundler => "< 3" do
- let(:spec_file) { tmp.join("test.gemspec") }
+ it "generates a gems.rb" do
+ bundle :init
+ expect(out).to include("Writing new gems.rb")
+ expect(bundled_app("gems.rb")).to be_file
+ end
+
+ context "when gems.rb already exists" do
+ before do
+ gemfile("gems.rb", <<-G)
+ gem "rails"
+ G
+ end
+
+ it "does not change existing Gemfiles" do
+ expect { bundle :init, raise_on_error: false }.not_to change { File.read(bundled_app("gems.rb")) }
+ end
+
+ it "notifies the user that an existing gems.rb already exists" do
+ bundle :init, raise_on_error: false
+ expect(err).to include("gems.rb already exists")
+ end
+ end
+
+ context "when a gems.rb file exists in a parent directory" do
+ let(:subdir) { "child_dir" }
+
+ it "lets users generate a Gemfile in a child directory" do
+ bundle :init
+
+ FileUtils.mkdir bundled_app(subdir)
+
+ bundle :init, dir: bundled_app(subdir)
+
+ expect(out).to include("Writing new gems.rb")
+ expect(bundled_app("#{subdir}/gems.rb")).to be_file
+ end
+ end
+
+ context "given --gemspec option" do
+ let(:spec_file) { tmp("test.gemspec") }
before do
File.open(spec_file, "w") do |file|
file << <<-S
Gem::Specification.new do |s|
s.name = 'test'
- s.add_dependency 'rack', '= 1.0.1'
+ s.add_dependency 'myrack', '= 1.0.1'
s.add_development_dependency 'rspec', '1.2'
end
S
@@ -162,20 +175,33 @@ RSpec.describe "bundle init" do
end
it "should generate from an existing gemspec" do
- bundle :init, :gemspec => spec_file
+ bundle :init, gemspec: spec_file
gemfile = bundled_app("gems.rb").read
expect(gemfile).to match(%r{source 'https://rubygems.org'})
- expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1)
+ expect(gemfile.scan(/gem "myrack", "= 1.0.1"/).size).to eq(1)
expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1)
expect(gemfile.scan(/group :development/).size).to eq(1)
end
it "prints message to user" do
- bundle :init, :gemspec => spec_file
+ bundle :init, gemspec: spec_file
expect(out).to include("Writing new gems.rb")
end
end
end
+
+ describe "using the --gemfile" do
+ it "should use the --gemfile value to name the gemfile" do
+ custom_gemfile_name = "NiceGemfileName"
+
+ bundle :init, gemfile: custom_gemfile_name
+
+ expect(out).to include("Writing new #{custom_gemfile_name}")
+ used_template = File.read("#{source_root}/lib/bundler/templates/Gemfile")
+ generated_gemfile = bundled_app(custom_gemfile_name).read
+ expect(generated_gemfile).to eq(used_template)
+ end
+ end
end
diff --git a/spec/bundler/commands/inject_spec.rb b/spec/bundler/commands/inject_spec.rb
deleted file mode 100644
index 822644f39a..0000000000
--- a/spec/bundler/commands/inject_spec.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle inject", :bundler => "< 3" do
- before :each do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- end
-
- context "without a lockfile" do
- it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock")).not_to exist
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
- end
- end
-
- context "with a lockfile" do
- before do
- bundle "install"
- end
-
- it "adds the injected gems to the Gemfile" do
- expect(bundled_app("Gemfile").read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile").read).to match(/rack-obama/)
- end
-
- it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
- end
- end
-
- context "with injected gems already in the Gemfile" do
- it "doesn't add existing gems" do
- bundle "inject 'rack' '> 0'"
- expect(out).to match(/cannot specify the same gem twice/i)
- end
- end
-
- context "incorrect arguments" do
- it "fails when more than 2 arguments are passed" do
- bundle "inject gem_name 1 v"
- expect(out).to eq(<<-E.strip)
-ERROR: "bundle inject" was called with arguments ["gem_name", "1", "v"]
-Usage: "bundle inject GEM VERSION"
- E
- end
- end
-
- context "with source option" do
- it "add gem with source option in gemfile" do
- bundle "inject 'foo' '>0' --source file://#{gem_repo1}"
- gemfile = bundled_app("Gemfile").read
- str = "gem \"foo\", \"> 0\", :source => \"file://#{gem_repo1}\""
- expect(gemfile).to include str
- end
- end
-
- context "with group option" do
- it "add gem with group option in gemfile" do
- bundle "inject 'rack-obama' '>0' --group=development"
- gemfile = bundled_app("Gemfile").read
- str = "gem \"rack-obama\", \"> 0\", :group => :development"
- expect(gemfile).to include str
- end
-
- it "add gem with multiple groups in gemfile" do
- bundle "inject 'rack-obama' '>0' --group=development,test"
- gemfile = bundled_app("Gemfile").read
- str = "gem \"rack-obama\", \"> 0\", :groups => [:development, :test]"
- expect(gemfile).to include str
- end
- end
-
- context "when frozen" do
- before do
- bundle "install"
- if Bundler.feature_flag.bundler_2_mode?
- bundle! "config --local deployment true"
- else
- bundle! "config --local frozen true"
- end
- end
-
- it "injects anyway" do
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile").read).to match(/rack-obama/)
- end
-
- it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
- end
-
- it "restores frozen afterwards" do
- bundle "inject 'rack-obama' '> 0'"
- config = YAML.load(bundled_app(".bundle/config").read)
- expect(config["BUNDLE_DEPLOYMENT"] || config["BUNDLE_FROZEN"]).to eq("true")
- end
-
- it "doesn't allow Gemfile changes" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack-obama"
- G
- bundle "inject 'rack' '> 0'"
- expect(out).to match(/trying to install in deployment mode after changing/)
-
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
- end
- end
-end
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index 326f98161e..3b24434dc7 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -4,55 +4,109 @@ RSpec.describe "bundle install with gem sources" do
describe "the simple case" do
it "prints output and returns if no dependencies are specified" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
bundle :install
- expect(out).to match(/no dependencies/)
+ expect(err).to match(/no dependencies/)
end
it "does not make a lockfile if the install fails" do
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
raise StandardError, "FAIL"
G
- expect(last_command.bundler_err).to include('StandardError, "FAIL"')
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(err).to include('StandardError, "FAIL"')
+ expect(bundled_app_lock).not_to exist
end
it "creates a Gemfile.lock" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
- it "does not create ./.bundle by default", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ it "creates lockfile based on the lockfile method in Gemfile" do
+ install_gemfile <<-G
+ lockfile "OmgFile.lock"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install"
+
+ expect(bundled_app("OmgFile.lock")).to exist
+ end
+
+ it "creates lockfile using BUNDLE_LOCKFILE instead of lockfile method" do
+ ENV["BUNDLE_LOCKFILE"] = "ReallyOmgFile.lock"
+ install_gemfile <<-G
+ lockfile "OmgFile.lock"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ expect(bundled_app("ReallyOmgFile.lock")).to exist
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ ensure
+ ENV.delete("BUNDLE_LOCKFILE")
+ end
+
+ it "creates lockfile based on --lockfile option is given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --lockfile ReallyOmgFile.lock"
+
+ expect(bundled_app("ReallyOmgFile.lock")).to exist
+ end
+
+ it "does not make a lockfile if lockfile false is used in Gemfile" do
+ install_gemfile <<-G
+ lockfile false
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ expect(bundled_app_lock).not_to exist
+ end
+
+ it "does not create ./.bundle by default" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle! :install # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
+ it "will create a ./.bundle by default", bundler: "5" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(bundled_app(".bundle")).to exist
+ end
+
it "does not create ./.bundle by default when installing to system gems" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G, env: { "BUNDLE_PATH__SYSTEM" => "true" }
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle! :install, :env => { "BUNDLE_PATH__SYSTEM" => true } # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
- it "creates lock files based on the Gemfile name" do
+ it "creates lockfiles based on the Gemfile name" do
gemfile bundled_app("OmgFile"), <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
G
bundle "install --gemfile OmgFile"
@@ -60,71 +114,126 @@ RSpec.describe "bundle install with gem sources" do
expect(bundled_app("OmgFile.lock")).to exist
end
+ it "doesn't create a lockfile if --no-lock option is given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --no-lock"
+
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ end
+
+ it "doesn't create a lockfile if --no-lock and --lockfile options are given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --no-lock --lockfile ReallyOmgFile.lock"
+
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ expect(bundled_app("ReallyOmgFile.lock")).not_to exist
+ end
+
it "doesn't delete the lockfile if one already exists" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- lockfile = File.read(bundled_app("Gemfile.lock"))
+ lockfile = File.read(bundled_app_lock)
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
raise StandardError, "FAIL"
G
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
+ expect(File.read(bundled_app_lock)).to eq(lockfile)
end
it "does not touch the lockfile if nothing changed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect { run "1" }.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ expect { run "1" }.not_to change { File.mtime(bundled_app_lock) }
end
it "fetches gems" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(default_bundle_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(default_bundle_path("gems/myrack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "auto-heals missing gems" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ FileUtils.rm_r(default_bundle_path("gems/myrack-1.0.0"))
+
+ bundle "install --verbose"
+
+ expect(out).to include("Installing myrack 1.0.0")
+ expect(default_bundle_path("gems/myrack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "does not state that it's constantly reinstalling empty gems" do
+ build_repo4 do
+ build_gem "empty", "1.0.0", no_default: true
+ end
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "empty"
+ G
+ gem_dir = default_bundle_path("gems/empty-1.0.0")
+ expect(gem_dir).to be_empty
+
+ bundle "install --verbose"
+ expect(out).not_to include("Installing empty")
end
it "fetches gems when multiple versions are specified" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack', "> 0.9", "< 1.0"
+ source "https://gem.repo1"
+ gem 'myrack', "> 0.9", "< 1.0"
G
- expect(default_bundle_path("gems/rack-0.9.1")).to exist
- expect(the_bundle).to include_gems("rack 0.9.1")
+ expect(default_bundle_path("gems/myrack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
it "fetches gems when multiple versions are specified take 2" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack', "< 1.0", "> 0.9"
+ source "https://gem.repo1"
+ gem 'myrack', "< 1.0", "> 0.9"
G
- expect(default_bundle_path("gems/rack-0.9.1")).to exist
- expect(the_bundle).to include_gems("rack 0.9.1")
+ expect(default_bundle_path("gems/myrack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
it "raises an appropriate error when gems are specified using symbols" do
- install_gemfile(<<-G)
- source "file://#{gem_repo1}"
- gem :rack
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem :myrack
G
- expect(exitstatus).to eq(4) if exitstatus
+ expect(exitstatus).to eq(4)
end
it "pulls in dependencies" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -133,16 +242,22 @@ RSpec.describe "bundle install with gem sources" do
it "does the right version" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
end
it "does not install the development dependency" do
+ build_repo2 do
+ build_gem "with_development_dependency" do |s|
+ s.add_development_dependency "activesupport", "= 2.3.5"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "with_development_dependency"
G
@@ -152,7 +267,7 @@ RSpec.describe "bundle install with gem sources" do
it "resolves correctly" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activemerchant"
gem "rails"
G
@@ -162,12 +277,12 @@ RSpec.describe "bundle install with gem sources" do
it "activates gem correctly according to the resolved gems" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activemerchant"
gem "rails"
G
@@ -176,7 +291,7 @@ RSpec.describe "bundle install with gem sources" do
end
it "does not reinstall any gem that is already available locally" do
- system_gems "activesupport-2.3.2", :path => :bundle_path
+ system_gems "activesupport-2.3.2", path: default_bundle_path
build_repo2 do
build_gem "activesupport", "2.3.2" do |s|
@@ -185,7 +300,7 @@ RSpec.describe "bundle install with gem sources" do
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activerecord", "2.3.2"
G
@@ -193,219 +308,474 @@ RSpec.describe "bundle install with gem sources" do
end
it "works when the gemfile specifies gems that only exist in the system" do
- build_gem "foo", :to_bundle => true
+ build_gem "foo", to_bundle: true
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "foo"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "foo 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "foo 1.0.0"
end
it "prioritizes local gems over remote gems" do
- build_gem "rack", "1.0.0", :to_bundle => true do |s|
- s.add_dependency "activesupport", "2.3.5"
- end
+ build_gem "myrack", "9.0.0", to_bundle: true
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 9.0.0"
+ end
+
+ it "loads env plugins" do
+ plugin_msg = "hello from an env plugin!"
+ create_file "plugins/rubygems_plugin.rb", "puts '#{plugin_msg}'"
+ install_gemfile <<-G, env: { "RUBYLIB" => rubylib.unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) }
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(stdboth).to include(plugin_msg)
end
describe "with a gem that installs multiple platforms" do
it "installs gems for the local platform as first choice" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 #{Bundler.local_platform}")
+ expect(the_bundle).to include_gems("platform_specific 1.0 x86-darwin-100")
+ end
end
it "falls back on plain ruby" do
- simulate_platform "foo-bar-baz"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
+ simulate_platform "foo-bar-baz" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 RUBY")
+ expect(the_bundle).to include_gems("platform_specific 1.0 ruby")
+ end
end
it "installs gems for java" do
- simulate_platform "java"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 JAVA")
+ expect(the_bundle).to include_gems("platform_specific 1.0 java")
+ end
end
it "installs gems for windows" do
- simulate_platform mswin
+ simulate_platform "x86-mswin32" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
+ expect(the_bundle).to include_gems("platform_specific 1.0 x86-mswin32")
+ end
+ end
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 MSWIN")
+ it "installs gems for aarch64-mingw-ucrt" do
+ simulate_platform "aarch64-mingw-ucrt" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+ end
+
+ expect(out).to include("Installing platform_specific 1.0 (aarch64-mingw-ucrt)")
end
end
- describe "doing bundle install foo" do
- before do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
+ it "gives useful errors if no global sources are set, and gems not installed locally, with and without a lockfile" do
+ install_gemfile <<-G, raise_on_error: false
+ gem "myrack"
+ G
+
+ expect(err).to eq("Could not find gem 'myrack' in locally installed gems.")
+
+ lockfile <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", raise_on_error: false
+
+ expect(err).to include(
+ "Because your Gemfile specifies no global remote source, your bundle is locked to " \
+ "myrack (1.0.0) from locally installed gems. However, myrack (1.0.0) is not installed. " \
+ "You'll need to either add a global remote source to your Gemfile or make sure myrack (1.0.0) " \
+ "is available locally before rerunning Bundler."
+ )
+ end
+
+ it "creates a Gemfile.lock on a blank Gemfile" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ expect(File.exist?(bundled_app_lock)).to eq(true)
+ end
+
+ it "throws a warning if a gem is added twice in Gemfile without version requirements" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ gem "myrack"
+ G
+
+ expect(err).to include("Your Gemfile lists the gem myrack (>= 0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
+
+ it "throws a warning if a gem is added twice in Gemfile with same versions" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
+ gem "myrack", "1.0"
+ G
+
+ expect(err).to include("Your Gemfile lists the gem myrack (= 1.0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
+
+ it "throws a warning if a gem is added twice under different platforms and does not crash when using the generated lockfile" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack", :platform => :jruby
+ gem "myrack"
+ G
+
+ bundle "install"
+
+ expect(err).to include("Your Gemfile lists the gem myrack (>= 0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
+
+ it "does not throw a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_development_dependency "my-private-gem"
end
- it "works" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
- expect(the_bundle).to include_gems "rack 1.0"
+ build_repo2 do
+ build_gem "my-private-gem"
end
- it "allows running bundle install --system without deleting foo", :bundler => "< 3" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
- bundle "install", forgotten_command_line_options(:system => true)
- FileUtils.rm_rf(bundled_app("vendor"))
- expect(the_bundle).to include_gems "rack 1.0"
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gemspec
+
+ gem "my-private-gem", :group => :development
+ G
+
+ bundle :install
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("my-private-gem 1.0")
+ end
+
+ it "does not warn if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with compatible requirements" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
end
- it "allows running bundle install --system after deleting foo", :bundler => "< 3" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
- FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install", forgotten_command_line_options(:system => true)
- expect(the_bundle).to include_gems "rack 1.0"
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ build_gem "rubocop", "1.37.1"
end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "rubocop", group: :development
+ G
+
+ bundle :install
+
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
end
- it "finds gems in multiple sources", :bundler => "< 3" do
- build_repo2
- update_repo2
+ it "raises an error if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with incompatible requirements" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- source "file://#{gem_repo2}"
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ build_gem "rubocop", "1.37.1"
+ end
- gem "activesupport", "1.2.3"
- gem "rack", "1.2"
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "rubocop", "~> 1.37.0", group: :development
G
- expect(the_bundle).to include_gems "rack 1.2", "activesupport 1.2.3"
+ bundle :install, raise_on_error: false
+
+ expect(err).to include("The rubocop dependency has conflicting requirements in Gemfile (~> 1.37.0) and gemspec (~> 1.36.0)")
end
- it "gives a useful error if no sources are set" do
- install_gemfile <<-G
- gem "rack"
+ it "includes the gem without warning if two gemspecs add it with the same requirement" do
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
+
+ build_lib "my-gem", path: gem1 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_lib "my-gem-2", path: gem2 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec path: "#{gem1}"
+ gemspec path: "#{gem2}"
G
bundle :install
- expect(out).to include("Your Gemfile has no gem server sources")
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
end
- it "creates a Gemfile.lock on a blank Gemfile" do
- install_gemfile <<-G
+ it "includes the gem without warning if two gemspecs add it with compatible requirements" do
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
+
+ build_lib "my-gem", path: gem1 do |s|
+ s.add_development_dependency "rubocop", "~> 1.0"
+ end
+
+ build_lib "my-gem-2", path: gem2 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec path: "#{gem1}"
+ gemspec path: "#{gem2}"
G
- expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true)
+ bundle :install
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
end
- context "throws a warning if a gem is added twice in Gemfile" do
- it "without version requirements" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
- gem "rack"
- G
+ it "errors out if two gemspecs add it with incompatible requirements" do
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
- expect(out).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
- expect(out).to include("Remove any duplicate entries and specify the gem only once (per group).")
- expect(out).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ build_lib "my-gem", path: gem1 do |s|
+ s.add_development_dependency "rubocop", "~> 2.0"
end
- it "with same versions" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", "1.0"
- gem "rack", "1.0"
- G
+ build_lib "my-gem-2", path: gem2 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
- expect(out).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
- expect(out).to include("Remove any duplicate entries and specify the gem only once (per group).")
- expect(out).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec path: "#{gem1}"
+ gemspec path: "#{gem2}"
+ G
+
+ bundle :install, raise_on_error: false
+
+ expect(err).to include("Two gemspec development dependencies have conflicting requirements on the same gem: rubocop (~> 1.36.0) and rubocop (~> 2.0). Bundler cannot continue.")
end
- context "throws an error if a gem is added twice in Gemfile" do
- it "when version of one dependency is not specified" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
- gem "rack", "1.0"
- G
+ it "errors out if a gem is specified in a gemspec and in the Gemfile" do
+ gem = tmp("my-gem-1")
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ build_lib "rubocop", path: gem do |s|
+ s.add_development_dependency "rubocop", "~> 1.0"
end
- it "when different versions of both dependencies are specified" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", "1.0"
- gem "rack", "1.1"
- G
+ build_repo4 do
+ build_gem "rubocop"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rubocop", :path => "#{gem}"
+ gemspec path: "#{gem}"
+ G
+
+ bundle :install, raise_on_error: false
- expect(out).to include("You cannot specify the same gem twice with different version requirements")
- expect(out).to include("You specified: rack (= 1.0) and rack (= 1.1).")
+ expect(err).to include("There was an error parsing `Gemfile`: You cannot specify the same gem twice coming from different sources.")
+ expect(err).to include("You specified that rubocop (>= 0) should come from source at `#{gem}` and gemspec at `#{gem}`")
+ end
+
+ it "does not warn if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with same requirements, and different sources" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_development_dependency "activesupport"
+ end
+
+ build_repo4 do
+ build_gem "activesupport"
end
+
+ build_git "activesupport", "1.0", path: lib_path("activesupport")
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "activesupport", :git => "#{lib_path("activesupport")}"
+ G
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems "activesupport 1.0", source: "git@#{lib_path("activesupport")}"
+
+ # if the Gemfile dependency is specified first
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "activesupport", :git => "#{lib_path("activesupport")}"
+
+ gemspec
+ G
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems "activesupport 1.0", source: "git@#{lib_path("activesupport")}"
+ end
+
+ it "considers both dependencies for resolution if a gem is added once in Gemfile and also inside a local gemspec as a runtime dependency, with different requirements" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ build_gem "rubocop", "1.37.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "rubocop"
+ G
+
+ bundle :install
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when version of one dependency is not specified" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack"
+ gem "myrack", "1.0"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: myrack (>= 0) and myrack (= 1.0).")
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when different versions of both dependencies are specified" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
+ gem "myrack", "1.1"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: myrack (= 1.0) and myrack (= 1.1).")
end
it "gracefully handles error when rubygems server is unavailable" do
- install_gemfile <<-G, :artifice => nil
- source "file://#{gem_repo1}"
- source "http://localhost:9384" do
+ install_gemfile <<-G, artifice: nil, raise_on_error: false
+ source "https://gem.repo1"
+ source "http://0.0.0.0:9384" do
gem 'foo'
end
G
- bundle :install, :artifice => nil
- expect(out).to include("Could not fetch specs from http://localhost:9384/")
- expect(out).not_to include("file://")
+ expect(err).to eq("Could not reach host 0.0.0.0:9384. Check your network connection and try again.")
+ expect(err).not_to include("file://")
end
- it "fails gracefully when downloading an invalid specification from the full index", :rubygems => "2.5" do
- build_repo2 do
- build_gem "ajp-rails", "0.0.0", :gemspec => false, :skip_validation => true do |s|
- bad_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]]
+ it "fails gracefully when downloading an invalid specification from the full index" do
+ build_repo2(build_compact_index: false) do
+ build_gem "ajp-rails", "0.0.0", gemspec: false, skip_validation: true do |s|
+ invalid_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]]
s.
instance_variable_get(:@spec).
- instance_variable_set(:@dependencies, bad_deps)
-
- raise "failed to set bad deps" unless s.dependencies == bad_deps
+ instance_variable_set(:@dependencies, invalid_deps)
end
+
build_gem "ruby-ajp", "1.0.0"
end
- install_gemfile <<-G, :full_index => true
- source "file:\/\/localhost#{gem_repo2}"
+ install_gemfile <<-G, full_index: true, raise_on_error: false
+ source "https://gem.repo2"
gem "ajp-rails", "0.0.0"
G
- expect(last_command.stdboth).not_to match(/Error Report/i)
- expect(last_command.bundler_err).to include("An error occurred while installing ajp-rails (0.0.0), and Bundler cannot continue.").
- and include(normalize_uri_file("Make sure that `gem install ajp-rails -v '0.0.0' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling."))
+ expect(stdboth).not_to match(/Error Report/i)
+ expect(err).to include("An error occurred while installing ajp-rails (0.0.0), and Bundler cannot continue.").
+ and include("Bundler::APIResponseInvalidDependenciesError")
end
it "doesn't blow up when the local .bundle/config is empty" do
@@ -413,11 +783,10 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.touch(bundled_app(".bundle/config"))
install_gemfile(<<-G)
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo'
G
- expect(exitstatus).to eq(0) if exitstatus
end
it "doesn't blow up when the global .bundle/config is empty" do
@@ -425,147 +794,713 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.touch("#{Bundler.rubygems.user_home}/.bundle/config")
install_gemfile(<<-G)
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo'
G
- expect(exitstatus).to eq(0) if exitstatus
end
end
describe "Ruby version in Gemfile.lock" do
- include Bundler::GemHelpers
-
context "and using an unsupported Ruby version" do
it "prints an error" do
- install_gemfile <<-G
- ::RUBY_VERSION = '2.0.1'
- ruby '~> 2.2'
+ install_gemfile <<-G, raise_on_error: false
+ ruby '~> 1.2'
+ source "https://gem.repo1"
G
- expect(out).to include("Your Ruby version is 2.0.1, but your Gemfile specified ~> 2.2")
+ expect(err).to include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified ~> 1.2")
end
end
context "and using a supported Ruby version" do
before do
install_gemfile <<-G
- ::RUBY_VERSION = '2.1.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.1.0'
+ ruby '~> #{Gem.ruby_version}'
+ source "https://gem.repo1"
G
end
it "writes current Ruby version to Gemfile.lock" do
- lockfile_should_be <<-L
+ checksums = checksums_section_when_enabled
+ expect(lockfile).to eq <<~L
GEM
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums}
RUBY VERSION
- ruby 2.1.3p100
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
- it "updates Gemfile.lock with updated incompatible ruby version" do
+ it "updates Gemfile.lock with updated yet still compatible ruby version" do
install_gemfile <<-G
- ::RUBY_VERSION = '2.2.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.2.0'
+ ruby '~> #{current_ruby_minor}'
+ source "https://gem.repo1"
G
- lockfile_should_be <<-L
+ checksums = checksums_section_when_enabled
+
+ expect(lockfile).to eq <<~L
GEM
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums}
RUBY VERSION
- ruby 2.2.3p100
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
+
+ it "does not crash when unlocking" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby '>= 2.1.0'
+ G
+
+ bundle "update"
+
+ expect(err).not_to include("Could not find gem 'Ruby")
+ end
end
end
describe "when Bundler root contains regex chars" do
- before do
+ it "doesn't blow up when using the `gem` DSL" do
root_dir = tmp("foo[]bar")
FileUtils.mkdir_p(root_dir)
- in_app_root_custom(root_dir)
- end
- it "doesn't blow up" do
build_lib "foo"
gemfile = <<-G
+ source "https://gem.repo1"
gem 'foo', :path => "#{lib_path("foo-1.0")}"
G
- File.open("Gemfile", "w") do |file|
+ File.open("#{root_dir}/Gemfile", "w") do |file|
file.puts gemfile
end
- bundle :install
+ bundle :install, dir: root_dir
+ end
+
+ it "doesn't blow up when using the `gemspec` DSL" do
+ root_dir = tmp("foo[]bar")
+
+ FileUtils.mkdir_p(root_dir)
+
+ build_lib "foo", path: root_dir
+ gemfile = <<-G
+ source "https://gem.repo1"
+ gemspec
+ G
+ File.open("#{root_dir}/Gemfile", "w") do |file|
+ file.puts gemfile
+ end
- expect(exitstatus).to eq(0) if exitstatus
+ bundle :install, dir: root_dir
end
end
describe "when requesting a quiet install via --quiet" do
- it "should be quiet" do
+ it "should be quiet if there are no warnings" do
+ bundle_config "force_ruby_platform true"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle :install, quiet: true
+ expect(out).to be_empty
+ expect(err).to be_empty
+ end
+
+ it "should still display warnings and errors" do
+ bundle_config "force_ruby_platform true"
+
+ create_file("install_with_warning.rb", <<~RUBY)
+ require "#{lib_dir}/bundler"
+ require "#{lib_dir}/bundler/cli"
+ require "#{lib_dir}/bundler/cli/install"
+
+ module RunWithWarning
+ def run
+ super
+ rescue
+ Bundler.ui.warn "BOOOOO"
+ raise
+ end
+ end
+
+ Bundler::CLI::Install.prepend(RunWithWarning)
+ RUBY
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'non-existing-gem'
+ G
+
+ bundle :install, quiet: true, raise_on_error: false, env: { "RUBYOPT" => "-r#{bundled_app("install_with_warning.rb")}" }
+ expect(out).to be_empty
+ expect(err).to include("Could not find gem 'non-existing-gem'")
+ expect(err).to include("BOOOOO")
+ end
+ end
+
+ describe "when bundle path does not have cd permission", :permissions do
+ let(:bundle_path) { bundled_app("vendor") }
+
+ before do
+ FileUtils.mkdir_p(bundle_path)
gemfile <<-G
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod(0o500, bundle_path)
- bundle :install, :quiet => true
- expect(out).to include("Could not find gem 'rack'")
- expect(out).to_not include("Your Gemfile has no gem server sources")
+ bundle_config "path vendor"
+ bundle :install, raise_on_error: false
+ expect(err).to include(bundle_path.to_s)
+ expect(err).to include("grant executable permissions")
end
end
- describe "when bundle path does not have write access" do
+ describe "when bundle gems path does not have cd permission", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+
before do
- FileUtils.mkdir_p(bundled_app("vendor"))
+ FileUtils.mkdir_p(gems_path)
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
it "should display a proper message to explain the problem" do
- FileUtils.chmod(0o500, bundled_app("vendor"))
+ FileUtils.chmod("-x", gems_path)
+ bundle_config "path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", gems_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
- bundle :install, forgotten_command_line_options(:path => "vendor")
- expect(out).to include(bundled_app("vendor").to_s)
- expect(out).to include("grant write permissions")
+ expect(err).to include(
+ "There was an error while trying to create `#{gems_path.join("myrack-1.0.0")}`. " \
+ "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{gems_path}`."
+ )
+ end
+ end
+
+ describe "when there's an empty install folder (like with default gems) without cd permissions", :permissions do
+ let(:full_gem_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems/myrack-1.0.0") }
+
+ before do
+ FileUtils.mkdir_p(full_gem_path)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", full_gem_path)
+ bundle_config "path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", full_gem_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{full_gem_path}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
+ describe "when bundle bin dir does not have cd permission", :permissions do
+ let(:bin_dir) { bundled_app("vendor/#{Bundler.ruby_scope}/bin") }
+
+ before do
+ FileUtils.mkdir_p(bin_dir)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", bin_dir)
+ bundle_config "path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", bin_dir)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{bin_dir}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
+ describe "when bundle bin dir does not have write access", :permissions do
+ let(:bin_dir) { bundled_app("vendor/#{Bundler.ruby_scope}/bin") }
+
+ before do
+ FileUtils.mkdir_p(bin_dir)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-w", bin_dir)
+ bundle_config "path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+w", bin_dir)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{bin_dir}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
+ describe "when bundle extensions path does not have write access", :permissions do
+ let(:extensions_path) { bundled_app("vendor/#{Bundler.ruby_scope}/extensions/#{Gem::Platform.local}/#{Gem.extension_api_version}") }
+
+ before do
+ FileUtils.mkdir_p(extensions_path)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'simple_binary'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", extensions_path)
+ bundle_config "path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", extensions_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to create `#{extensions_path.join("simple_binary-1.0")}`. " \
+ "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{extensions_path}`."
+ )
+ end
+ end
+
+ describe "when the path of a specific gem does not have cd permission", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+ let(:foo_path) { gems_path.join("foo-1.0.0") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ bundle_config "path vendor"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+
+ FileUtils.chmod("-x", foo_path)
+
+ begin
+ bundle "install --force", raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", foo_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ expect(err).to include("Could not delete previous installation of `#{foo_path}`.")
+ expect(err).to include("The underlying error was Errno::EACCES")
+ end
+ end
+
+ describe "when gem home does not have the writable bit set, yet it's still writable", :permissions do
+ let(:gem_home) { bundled_app("vendor/#{Bundler.ruby_scope}") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ G
+ end
+
+ it "should still work" do
+ bundle_config "path vendor"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+
+ FileUtils.chmod("-w", gem_home)
+
+ begin
+ bundle "install --force"
+ ensure
+ FileUtils.chmod("+w", gem_home)
+ end
+
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+ end
+ end
+
+ describe "when gems path is world writable (no sticky bit set)", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ bundle_config "path vendor"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+
+ FileUtils.chmod(0o777, gems_path)
+
+ bundle "install --force", raise_on_error: false
+
+ expect(err).to include("Bundler cannot reinstall foo-1.0.0 because there's a previous installation of it at #{gems_path}/foo-1.0.0 that is unsafe to remove")
+ end
+ end
+
+ describe "when gems path is world writable (no sticky bit set), but previous install is just an empty dir (like it happens with default gems)", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+ let(:full_path) { gems_path.join("foo-1.0.0") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ G
+ end
+
+ it "does not try to remove the directory and thus don't abort with an error about unsafe directory removal" do
+ bundle_config "path vendor"
+
+ FileUtils.mkdir_p(gems_path)
+ FileUtils.chmod(0o777, gems_path)
+ Dir.mkdir(full_path)
+
+ bundle "install"
+ end
+ end
+
+ describe "when bundle cache path does not have write access", :permissions do
+ let(:cache_path) { bundled_app("vendor/#{Bundler.ruby_scope}/cache") }
+
+ before do
+ FileUtils.mkdir_p(cache_path)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod(0o500, cache_path)
+
+ bundle_config "path vendor"
+ bundle :install, raise_on_error: false
+ expect(err).to include(cache_path.to_s)
+ expect(err).to include("grant write permissions")
+ end
+ end
+
+ describe "when gemspecs are unreadable", :permissions do
+ let(:gemspec_path) { vendored_gems("specifications/myrack-1.0.0.gemspec") }
+
+ before do
+ gemfile <<~G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ bundle_config "path vendor/bundle"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+
+ FileUtils.chmod("-r", gemspec_path)
+ end
+
+ it "shows a good error" do
+ bundle :install, raise_on_error: false
+ expect(err).to include(gemspec_path.to_s)
+ expect(err).to include("grant read permissions")
+ end
+ end
+
+ describe "when using umask 002 and setgid bit", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+ let(:foo_path) { gems_path.join("foo-1.0.0") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ G
+
+ FileUtils.mkdir_p(gems_path)
+ FileUtils.chmod("g+s", gems_path)
+ end
+
+ it "should create the gem directory with proper permissions" do
+ with_umask(0o002) do
+ bundle_config "path vendor"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+ # Linux's SysV-derived mkdir(2) propagates the set-group-ID bit
+ # from the parent directory to newly created subdirectories. BSD
+ # (including macOS) inherits the parent's group via mkdir(2) but
+ # does not copy the set-group-ID bit itself, so the expected
+ # mode differs by platform.
+ expected = RUBY_PLATFORM.include?("darwin") ? 0o0775 : 0o2775
+ expect(File.stat(foo_path).mode & 0o7777).to eq(expected)
+ end
+ end
+ end
+
+ describe "parallel make" do
+ before do
+ unless Gem::Installer.private_method_defined?(:build_jobs)
+ skip "This example is runnable when RubyGems::Installer implements `build_jobs`"
+ end
+
+ @old_makeflags = ENV["MAKEFLAGS"]
+ @gemspec = nil
+
+ extconf_code = <<~CODE
+ require "mkmf"
+ create_makefile("foo")
+ CODE
+
+ build_repo4 do
+ build_gem "mypsych", "4.0.6" do |s|
+ @gemspec = s
+ extension = "ext/mypsych/extconf.rb"
+ s.extensions = extension
+
+ s.write(extension, extconf_code)
+ end
+ end
+ end
+
+ after do
+ if @old_makeflags
+ ENV["MAKEFLAGS"] = @old_makeflags
+ else
+ ENV.delete("MAKEFLAGS")
+ end
+ end
+
+ it "doesn't pass down -j to make when MAKEFLAGS is set" do
+ ENV["MAKEFLAGS"] = "-j1"
+
+ install_gemfile(<<~G, env: { "BUNDLE_JOBS" => "8" })
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).not_to include("make -j8")
+ end
+
+ it "pass down the BUNDLE_JOBS to RubyGems when running the compilation of an extension" do
+ ENV.delete("MAKEFLAGS")
+
+ install_gemfile(<<~G, env: { "BUNDLE_JOBS" => "8" })
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).to include("make -j8")
+ end
+
+ it "uses nprocessors by default" do
+ ENV.delete("MAKEFLAGS")
+
+ install_gemfile(<<~G)
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).to include("make -j#{Etc.nprocessors + 1}")
+ end
+ end
+
+ describe "when a native extension requires a transitive dependency at build time" do
+ before do
+ build_repo4 do
+ build_gem "alpha", "1.0.0" do |s|
+ extension = "ext/alpha/extconf.rb"
+ s.extensions = extension
+ s.write(extension, <<~CODE)
+ require "mkmf"
+ sleep 1
+ create_makefile("alpha")
+ CODE
+ s.write "lib/alpha.rb", "ALPHA = '1.0.0'"
+ end
+
+ build_gem "beta", "1.0.0" do |s|
+ s.add_dependency "alpha"
+ s.write "lib/beta.rb", "require 'alpha'\nBETA = '1.0.0'"
+ end
+
+ build_gem "gamma", "1.0.0" do |s|
+ s.add_dependency "beta"
+ extension = "ext/gamma/extconf.rb"
+ s.extensions = extension
+ s.write(extension, <<~EXTCONF)
+ require "beta"
+ require "mkmf"
+ create_makefile("gamma")
+ EXTCONF
+ end
+ end
+ end
+
+ it "installs successfully" do
+ install_gemfile <<~G
+ source "https://gem.repo4"
+ gem "gamma"
+ G
+
+ expect(the_bundle).to include_gems "alpha 1.0.0", "beta 1.0.0", "gamma 1.0.0"
+ end
+ end
+
+ describe "when configured path is UTF-8 and a file inside a gem package too" do
+ let(:app_path) do
+ path = tmp("♥")
+ FileUtils.mkdir_p(path)
+ path
+ end
+
+ let(:path) do
+ root.join("vendor/bundle")
+ end
+
+ before do
+ build_repo4 do
+ build_gem "mygem" do |s|
+ s.write "spec/fixtures/_posts/2016-04-01-错误.html"
+ end
+ end
+ end
+
+ it "works" do
+ bundle "config set path #{app_path}/vendor/bundle", dir: app_path
+
+ install_gemfile app_path.join("Gemfile"),<<~G, dir: app_path
+ source "https://gem.repo4"
+ gem "mygem", "1.0"
+ G
end
end
context "after installing with --standalone" do
before do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- forgotten_command_line_options(:path => "bundle")
- bundle! "install", :standalone => true
+ bundle_config "path bundle"
+ bundle "install", standalone: true
end
it "includes the standalone path" do
- bundle! "binstubs rack", :standalone => true
- standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
- expect(standalone_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath)
+ bundle "binstubs myrack", standalone: true
+ standalone_line = File.read(bundled_app("bin/myrackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
+ expect(standalone_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
end
end
@@ -577,11 +1512,604 @@ RSpec.describe "bundle install with gem sources" do
G
end
- it "should display a helpful messag explaining how to fix it" do
- bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }
- expect(exitstatus).to eq(17) if exitstatus
- expect(out).to eq("Please CGI escape your usernames and passwords before " \
+ it "should display a helpful message explaining how to fix it" do
+ bundle :install, env: { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }, raise_on_error: false
+ expect(exitstatus).to eq(17)
+ expect(err).to eq("Please CGI escape your usernames and passwords before " \
"setting them for authentication.")
end
end
+
+ context "when current platform not included in the lockfile" do
+ around do |example|
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "libv8"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform("x86_64-linux", &example)
+ end
+
+ it "adds the current platform to the lockfile" do
+ bundle "install --verbose"
+
+ expect(out).to include("re-resolving dependencies because your lockfile is missing the current platform")
+ expect(out).not_to include("you are adding a new platform to your lockfile")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-darwin-19
+ x86_64-linux
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "fails loudly if frozen mode set" do
+ bundle_config "deployment true"
+ bundle "install", raise_on_error: false
+
+ expect(err).to eq(
+ "Your bundle only supports platforms [\"x86_64-darwin-19\"] but your local platform is x86_64-linux. " \
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform x86_64-linux` and try again."
+ )
+ end
+ end
+
+ context "with missing platform specific gems in lockfile" do
+ before do
+ build_repo4 do
+ build_gem "racca", "1.5.2"
+
+ build_gem "nokogiri", "1.12.4" do |s|
+ s.platform = "x86_64-darwin"
+ s.add_dependency "racca", "~> 1.4"
+ end
+
+ build_gem "nokogiri", "1.12.4" do |s|
+ s.platform = "x86_64-linux"
+ s.add_dependency "racca", "~> 1.4"
+ end
+
+ build_gem "crass", "1.0.6"
+
+ build_gem "loofah", "2.12.0" do |s|
+ s.add_dependency "crass", "~> 1.0.2"
+ s.add_dependency "nokogiri", ">= 1.5.9"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ ruby "#{Gem.ruby_version}"
+
+ gem "loofah", "~> 2.12.0"
+ G
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "crass", "1.0.6"
+ c.checksum gem_repo4, "loofah", "2.12.0"
+ c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-darwin"
+ c.checksum gem_repo4, "racca", "1.5.2"
+ end
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ crass (1.0.6)
+ loofah (2.12.0)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ nokogiri (1.12.4-x86_64-darwin)
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ PLATFORMS
+ x86_64-darwin-20
+ x86_64-linux
+
+ DEPENDENCIES
+ loofah (~> 2.12.0)
+ #{checksums}
+ RUBY VERSION
+ #{Bundler::RubyVersion.system}
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile" do
+ bundle_config "path vendor/bundle"
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", artifice: "compact_index"
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "crass", "1.0.6"
+ c.checksum gem_repo4, "loofah", "2.12.0"
+ c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-darwin"
+ c.checksum gem_repo4, "racca", "1.5.2"
+ c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ crass (1.0.6)
+ loofah (2.12.0)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ nokogiri (1.12.4-x86_64-darwin)
+ racca (~> 1.4)
+ nokogiri (1.12.4-x86_64-linux)
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ PLATFORMS
+ x86_64-darwin-20
+ x86_64-linux
+
+ DEPENDENCIES
+ loofah (~> 2.12.0)
+ #{checksums}
+ RUBY VERSION
+ #{Bundler::RubyVersion.system}
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when lockfile has incorrect dependencies" do
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ system_gems "myrack_middleware-1.0", path: default_bundle_path
+
+ # we want to raise when the 1.0 line should be followed by " myrack (= 0.9.1)" but isn't
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a clear error message when frozen" do
+ bundle_config "frozen true"
+ bundle "install", raise_on_error: false
+
+ expect(exitstatus).to eq(41)
+ expect(err).to include("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0")
+ expect(err).to include("myrack: gemspec specifies = 0.9.1, not in lockfile")
+ end
+
+ it "updates the lockfile when not frozen" do
+ missing_dep = "myrack (0.9.1)"
+ expect(lockfile).not_to include(missing_dep)
+
+ bundle_config "frozen false"
+ bundle :install
+
+ expect(lockfile).to include(missing_dep)
+ expect(out).to include("now installed")
+ end
+ end
+
+ context "with --local flag" do
+ before do
+ system_gems "myrack-1.0.0", path: default_bundle_path
+ end
+
+ it "respects installed gems without fetching any remote sources" do
+ install_gemfile <<-G, local: true
+ source "https://gem.repo1"
+
+ source "https://not-existing-source" do
+ gem "myrack"
+ end
+ G
+
+ expect(last_command).to be_success
+ end
+ end
+
+ context "with only option" do
+ before do
+ bundle_config "only a:b"
+ end
+
+ it "installs only gems of the specified groups" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ gem "myrack", group: :a
+ gem "rake", group: :b
+ gem "yard", group: :c
+ G
+
+ expect(out).to include("Installing myrack")
+ expect(out).to include("Installing rake")
+ expect(out).not_to include("Installing yard")
+ end
+ end
+
+ context "with --prefer-local flag" do
+ context "and gems available locally" do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.1"
+ build_gem "foo", "1.0.0"
+ build_gem "bar", "1.0.0"
+
+ build_gem "a", "1.0.0" do |s|
+ s.add_dependency "foo", "~> 1.0.0"
+ end
+
+ build_gem "b", "1.0.0" do |s|
+ s.add_dependency "foo", "~> 1.0.1"
+ end
+ end
+
+ system_gems "foo-1.0.0", path: default_bundle_path, gem_repo: gem_repo4
+ end
+
+ it "fetches remote sources when not available locally" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ expect(out).to include("Using foo 1.0.0").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
+ expect(last_command).to be_success
+ end
+
+ it "fetches remote sources when local version does not match requirements" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "foo", "1.0.1"
+ gem "bar"
+ G
+
+ expect(out).to include("Fetching foo 1.0.1").and include("Installing foo 1.0.1").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
+ expect(last_command).to be_success
+ end
+
+ it "uses the locally available version for sub-dependencies when possible" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "a"
+ G
+
+ expect(out).to include("Using foo 1.0.0").and include("Fetching a 1.0.0").and include("Installing a 1.0.0")
+ expect(last_command).to be_success
+ end
+
+ it "fetches remote sources for sub-dependencies when the locally available version does not satisfy the requirement" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "b"
+ G
+
+ expect(out).to include("Fetching foo 1.0.1").and include("Installing foo 1.0.1").and include("Fetching b 1.0.0").and include("Installing b 1.0.0")
+ expect(last_command).to be_success
+ end
+ end
+
+ context "and no gems available locally" do
+ before do
+ build_repo4 do
+ build_gem "myreline", "0.3.8"
+ build_gem "debug", "0.2.1"
+
+ build_gem "debug", "1.10.0" do |s|
+ s.add_dependency "myreline"
+ end
+ end
+ end
+
+ it "resolves to the latest version if no gems are available locally" do
+ install_gemfile <<~G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "debug"
+ G
+
+ expect(out).to include("Fetching debug 1.10.0").and include("Installing debug 1.10.0").and include("Fetching myreline 0.3.8").and include("Installing myreline 0.3.8")
+ expect(last_command).to be_success
+ end
+ end
+ end
+
+ context "with a symlinked configured as bundle path and a gem with symlinks" do
+ before do
+ symlinked_bundled_app = tmp("bundled_app-symlink")
+ File.symlink(bundled_app, symlinked_bundled_app)
+ bundle_config "path #{File.join(symlinked_bundled_app, ".vendor")}"
+
+ binman_path = tmp("binman")
+ FileUtils.mkdir_p binman_path
+
+ readme_path = File.join(binman_path, "README.markdown")
+ FileUtils.touch(readme_path)
+
+ man_path = File.join(binman_path, "man", "man0")
+ FileUtils.mkdir_p man_path
+
+ File.symlink("../../README.markdown", File.join(man_path, "README.markdown"))
+
+ build_repo4 do
+ build_gem "binman", path: gem_repo4("gems"), lib_path: binman_path, no_default: true do |s|
+ s.files = ["README.markdown", "man/man0/README.markdown"]
+ end
+ end
+ end
+
+ it "installs fine" do
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "binman"
+ G
+ end
+ end
+
+ context "when a gem has equivalent versions with inconsistent dependencies" do
+ before do
+ build_repo4 do
+ build_gem "autobuild", "1.10.rc2" do |s|
+ s.add_dependency "utilrb", ">= 1.6.0"
+ end
+
+ build_gem "autobuild", "1.10.0.rc2" do |s|
+ s.add_dependency "utilrb", ">= 2.0"
+ end
+ end
+ end
+
+ it "does not crash unexpectedly" do
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "autobuild", "1.10.rc2"
+ G
+
+ bundle "install --jobs 1", raise_on_error: false
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ expect(err).to include("Could not find compatible versions")
+ end
+ end
+
+ context "when a lockfile has unmet dependencies, and the Gemfile has no resolution" do
+ before do
+ build_repo4 do
+ build_gem "aaa", "0.2.0" do |s|
+ s.add_dependency "zzz", "< 0.2.0"
+ end
+
+ build_gem "zzz", "0.2.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "aaa"
+ gem "zzz"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ aaa (0.2.0)
+ zzz (< 0.2.0)
+ zzz (0.2.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ aaa!
+ zzz!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not install, but raises a resolution error" do
+ bundle "install", raise_on_error: false
+ expect(err).to include("Could not find compatible versions")
+ end
+ end
+
+ context "when --jobs option given" do
+ before do
+ install_gemfile "source 'https://gem.repo1'", jobs: 1
+ end
+
+ it "does not save the flag to config" do
+ expect(bundled_app(".bundle/config")).not_to exist
+ end
+ end
+
+ context "when bundler installation is corrupt" do
+ before do
+ system_gems "bundler-9.99.8"
+
+ replace_version_file("9.99.9", dir: system_gem_path("gems/bundler-9.99.8"))
+ end
+
+ it "shows a proper error" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ 9.99.8
+ L
+
+ install_gemfile "source \"https://gem.repo1\"", env: { "BUNDLER_VERSION" => "9.99.8" }, raise_on_error: false
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ expect(err).to include("The running version of Bundler (9.99.9) does not match the version of the specification installed for it (9.99.8)")
+ end
+ end
+
+ it "only installs executable files in bin" do
+ bundle_config "path vendor/bundle"
+
+ install_gemfile <<~G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expected_executables = [vendored_gems("bin/myrackup").to_s]
+ expected_executables << vendored_gems("bin/myrackup.bat").to_s if Gem.win_platform?
+ expect(Dir.glob(vendored_gems("bin/*"))).to eq(expected_executables)
+ end
+
+ it "prevents removing binstubs when BUNDLE_CLEAN is set" do
+ build_repo4 do
+ build_gem "kamal", "4.0.6" do |s|
+ s.executables = ["kamal"]
+ end
+ end
+
+ gemfile = <<~G
+ source "https://gem.repo4"
+ gem "kamal"
+ G
+
+ install_gemfile(gemfile, env: { "BUNDLE_CLEAN" => "true", "BUNDLE_PATH" => "vendor/bundle" })
+
+ expected_executables = [vendored_gems("bin/kamal").to_s]
+ expected_executables << vendored_gems("bin/kamal.bat").to_s if Gem.win_platform?
+ expect(Dir.glob(vendored_gems("bin/*"))).to eq(expected_executables)
+ end
+
+ it "preserves lockfile versions conservatively" do
+ build_repo4 do
+ build_gem "mypsych", "4.0.6" do |s|
+ s.add_dependency "mystringio"
+ end
+
+ build_gem "mypsych", "5.1.2" do |s|
+ s.add_dependency "mystringio"
+ end
+
+ build_gem "mystringio", "3.1.0"
+ build_gem "mystringio", "3.1.1"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mypsych (4.0.6)
+ mystringio
+ mystringio (3.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mypsych (~> 4.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+ gem "mypsych", "~> 5.0"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mypsych (5.1.2)
+ mystringio
+ mystringio (3.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mypsych (~> 5.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
end
diff --git a/spec/bundler/commands/issue_spec.rb b/spec/bundler/commands/issue_spec.rb
index 04c575130e..346cdedc42 100644
--- a/spec/bundler/commands/issue_spec.rb
+++ b/spec/bundler/commands/issue_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle issue" do
it "exits with a message" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
diff --git a/spec/bundler/commands/licenses_spec.rb b/spec/bundler/commands/licenses_spec.rb
index d61d3492f3..ebfad5ed4a 100644
--- a/spec/bundler/commands/licenses_spec.rb
+++ b/spec/bundler/commands/licenses_spec.rb
@@ -2,8 +2,14 @@
RSpec.describe "bundle licenses" do
before :each do
+ build_repo2 do
+ build_gem "with_license" do |s|
+ s.license = "MIT"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "rails"
gem "with_license"
G
@@ -12,26 +18,19 @@ RSpec.describe "bundle licenses" do
it "prints license information for all gems in the bundle" do
bundle "licenses"
- loaded_bundler_spec = Bundler.load.specs["bundler"]
- expected = if !loaded_bundler_spec.empty?
- loaded_bundler_spec[0].license
- else
- "Unknown"
- end
-
- expect(out).to include("bundler: #{expected}")
+ expect(out).to include("bundler: MIT")
expect(out).to include("with_license: MIT")
end
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "rails"
gem "with_license"
gem "foo"
G
- bundle "config auto_install 1"
+ bundle_config "auto_install 1"
bundle :licenses
expect(out).to include("Installing foo 1.0")
end
diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb
index ba4bb9b040..c890646a81 100644
--- a/spec/bundler/commands/list_spec.rb
+++ b/spec/bundler/commands/list_spec.rb
@@ -1,115 +1,265 @@
# frozen_string_literal: true
-RSpec.describe "bundle list", :bundler => "3" do
- before do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
-
- gem "rack"
- gem "rspec", :group => [:test]
- G
+require "json"
+
+RSpec.describe "bundle list" do
+ def find_gem_name(json:, name:)
+ parse_json(json)["gems"].detect {|h| h["name"] == name }
+ end
+
+ def parse_json(json)
+ JSON.parse(json)
+ end
+
+ context "in verbose mode" do
+ it "logs the actual flags passed to the command" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ bundle "list --verbose"
+
+ expect(out).to include("Running `bundle list --verbose`")
+ end
end
context "with name-only and paths option" do
it "raises an error" do
- bundle "list --name-only --paths"
+ bundle "list --name-only --paths", raise_on_error: false
- expect(out).to eq "The `--name-only` and `--paths` options cannot be used together"
+ expect(err).to eq "The `--name-only` and `--paths` options cannot be used together"
end
end
context "with without-group and only-group option" do
it "raises an error" do
- bundle "list --without-group dev --only-group test"
+ bundle "list --without-group dev --only-group test", raise_on_error: false
- expect(out).to eq "The `--only-group` and `--without-group` options cannot be used together"
+ expect(err).to eq "The `--only-group` and `--without-group` options cannot be used together"
+ end
+ end
+
+ context "with invalid format option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+ end
+
+ it "raises an error" do
+ bundle "list --format=nope", raise_on_error: false
+
+ expect(err).to eq "Unknown option`--format=nope`. Supported formats: `json`"
end
end
describe "with without-group option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ gem "rspec", :group => [:test]
+ gem "rails", :group => [:production]
+ G
+ end
+
context "when group is present" do
it "prints the gems not in the specified group" do
- bundle! "list --without-group test"
+ bundle "list --without-group test"
- expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * myrack (1.0.0)")
+ expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems not in the specified group with json" do
+ bundle "list --without-group test --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
it "raises an error" do
- bundle "list --without-group random"
+ bundle "list --without-group random", raise_on_error: false
- expect(out).to eq "`random` group could not be found."
+ expect(err).to eq "`random` group could not be found."
+ end
+ end
+
+ context "when multiple groups" do
+ it "prints the gems not in the specified groups" do
+ bundle "list --without-group test production"
+
+ expect(out).to include(" * myrack (1.0.0)")
+ expect(out).not_to include(" * rails (2.3.2)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+
+ it "prints the gems not in the specified groups with json" do
+ bundle "list --without-group test production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem).to be_nil
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
end
end
end
describe "with only-group option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ gem "rspec", :group => [:test]
+ gem "rails", :group => [:production]
+ G
+ end
+
context "when group is present" do
it "prints the gems in the specified group" do
- bundle! "list --only-group default"
+ bundle "list --only-group default"
- expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * myrack (1.0.0)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems in the specified group with json" do
+ bundle "list --only-group default --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
it "raises an error" do
- bundle "list --only-group random"
+ bundle "list --only-group random", raise_on_error: false
- expect(out).to eq "`random` group could not be found."
+ expect(err).to eq "`random` group could not be found."
+ end
+ end
+
+ context "when multiple groups" do
+ it "prints the gems in the specified groups" do
+ bundle "list --only-group default production"
+
+ expect(out).to include(" * myrack (1.0.0)")
+ expect(out).to include(" * rails (2.3.2)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+
+ it "prints the gems in the specified groups with json" do
+ bundle "list --only-group default production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
end
end
end
context "with name-only option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ gem "rspec", :group => [:test]
+ G
+ end
+
it "prints only the name of the gems in the bundle" do
bundle "list --name-only"
- expect(out).to include("rack")
+ expect(out).to include("myrack")
expect(out).to include("rspec")
end
+
+ it "prints only the name of the gems in the bundle with json" do
+ bundle "list --name-only --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem.keys).to eq(["name"])
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem.keys).to eq(["name"])
+ end
end
context "with paths option" do
before do
build_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "bar"
end
- build_git "git_test", "1.0.0", :path => lib_path("git_test")
+ build_git "git_test", "1.0.0", path: lib_path("git_test")
- build_lib("gemspec_test", :path => tmp.join("gemspec_test")) do |s|
- s.write("Gemfile", "source :rubygems\ngemspec")
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
s.add_dependency "bar", "=1.0.0"
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
gem "rails"
gem "git_test", :git => "#{lib_path("git_test")}"
- gemspec :path => "#{tmp.join("gemspec_test")}"
+ gemspec :path => "#{tmp("gemspec_test")}"
G
-
- bundle! "install"
end
it "prints the path of each gem in the bundle" do
bundle "list --paths"
expect(out).to match(%r{.*\/rails\-2\.3\.2})
- expect(out).to match(%r{.*\/rack\-1\.2})
+ expect(out).to match(%r{.*\/myrack\-1\.2})
expect(out).to match(%r{.*\/git_test\-\w})
expect(out).to match(%r{.*\/gemspec_test})
end
+
+ it "prints the path of each gem in the bundle with json" do
+ bundle "list --paths --format=json"
+
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["path"]).to match(%r{.*\/rails\-2\.3\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["path"]).to match(%r{.*\/myrack\-1\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "git_test")
+ expect(gem["path"]).to match(%r{.*\/git_test\-\w})
+ expect(gem["git_version"]).to be_truthy
+ expect(gem["git_version"].strip).to eq(gem["git_version"])
+
+ gem = find_gem_name(json: out, name: "gemspec_test")
+ expect(gem["path"]).to match(%r{.*\/gemspec_test})
+ expect(gem["git_version"]).to be_nil
+ end
end
context "when no gems are in the gemfile" do
before do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
end
@@ -117,15 +267,49 @@ RSpec.describe "bundle list", :bundler => "3" do
bundle "list"
expect(out).to include("No gems in the Gemfile")
end
+
+ it "prints empty json" do
+ bundle "list --format=json"
+ expect(parse_json(out)["gems"]).to eq([])
+ end
end
- it "lists gems installed in the bundle" do
- bundle "list"
- expect(out).to include(" * rack (1.0.0)")
+ context "without options" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ gem "rspec", :group => [:test]
+ G
+ end
+
+ it "lists gems installed in the bundle" do
+ bundle "list"
+ expect(out).to include(" * myrack (1.0.0)")
+ end
+
+ it "lists gems installed in the bundle with json" do
+ bundle "list --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ end
end
- it "aliases the ls command to list" do
- bundle "ls"
- expect(out).to include("Gems included by the bundle")
+ context "when using the ls alias" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ gem "rspec", :group => [:test]
+ G
+ end
+
+ it "runs the list command" do
+ bundle "ls"
+ expect(out).to include("Gems included by the bundle")
+ end
end
end
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 0b77605f01..8ab3cc7e8d 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -1,27 +1,22 @@
# frozen_string_literal: true
RSpec.describe "bundle lock" do
- def strip_lockfile(lockfile)
- strip_whitespace(lockfile).sub(/\n\Z/, "")
- end
-
- def read_lockfile(file = "Gemfile.lock")
- strip_lockfile bundled_app(file).read
- end
-
- let(:repo) { gem_repo1 }
-
- before :each do
- gemfile <<-G
- source "file://localhost#{repo}"
- gem "rails"
- gem "with_license"
- gem "foo"
- G
+ let(:expected_lockfile) do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
- @lockfile = strip_lockfile(normalize_uri_file(<<-L))
+ <<~L
GEM
- remote: file://localhost#{repo}/
+ remote: https://gem.repo4/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -38,9 +33,9 @@ RSpec.describe "bundle lock" do
actionpack (= 2.3.2)
activerecord (= 2.3.2)
activeresource (= 2.3.2)
- rake (= 10.0.2)
- rake (10.0.2)
- with_license (1.0)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
PLATFORMS
#{lockfile_platforms}
@@ -48,78 +43,644 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
foo
rails
- with_license
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ let(:outdated_lockfile) do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.1"
+ c.checksum gem_repo4, "actionpack", "2.3.1"
+ c.checksum gem_repo4, "activerecord", "2.3.1"
+ c.checksum gem_repo4, "activeresource", "2.3.1"
+ c.checksum gem_repo4, "activesupport", "2.3.1"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.1"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.1)
+ activesupport (= 2.3.1)
+ actionpack (2.3.1)
+ activesupport (= 2.3.1)
+ activerecord (2.3.1)
+ activesupport (= 2.3.1)
+ activeresource (2.3.1)
+ activesupport (= 2.3.1)
+ activesupport (2.3.1)
+ foo (1.0)
+ rails (2.3.1)
+ actionmailer (= 2.3.1)
+ actionpack (= 2.3.1)
+ activerecord (= 2.3.1)
+ activeresource (= 2.3.1)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
+ let(:gemfile_with_rails_weakling_and_foo_from_repo4) do
+ build_repo4 do
+ build_gem "rake", "10.0.1"
+ build_gem "rake", rake_version
+
+ %w[2.3.1 2.3.2].each do |version|
+ build_gem "rails", version do |s|
+ s.executables = "rails"
+ s.add_dependency "rake", version == "2.3.1" ? "10.0.1" : rake_version
+ s.add_dependency "actionpack", version
+ s.add_dependency "activerecord", version
+ s.add_dependency "actionmailer", version
+ s.add_dependency "activeresource", version
+ end
+ build_gem "actionpack", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activerecord", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "actionmailer", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activeresource", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activesupport", version
+ end
+
+ build_gem "weakling", "0.0.3"
+
+ build_gem "foo"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "rails"
+ gem "weakling"
+ gem "foo"
+ G
+ end
+
it "prints a lockfile when there is no existing lockfile with --print" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --print"
- expect(out).to eq(@lockfile)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "prints a lockfile when there is an existing lockfile with --print" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --print"
- expect(out).to eq(@lockfile)
+ expect(out).to eq(expected_lockfile.chomp)
+ end
+
+ it "prints a lockfile when there is an existing checksums lockfile with --print" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
+
+ bundle "lock --print"
+
+ expect(out).to eq(expected_lockfile.chomp)
end
it "writes a lockfile when there is no existing lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock"
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
+ end
+
+ it "prints a lockfile without fetching new checksums if the existing lockfile had no checksums" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
+
+ bundle "lock --print"
+
+ expect(out).to eq(expected_lockfile.chomp)
+ end
+
+ it "touches the lockfile when there is an existing lockfile that does not need changes" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
+
+ expect do
+ bundle "lock"
+ end.to change { bundled_app_lock.mtime }
+ end
+
+ it "does not touch lockfile with --print" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
+
+ expect do
+ bundle "lock --print"
+ end.not_to change { bundled_app_lock.mtime }
end
it "writes a lockfile when there is an outdated lockfile using --update" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
+
+ bundle "lock --update"
+
+ expect(read_lockfile).to eq(expected_lockfile)
+ end
+
+ it "prints an updated lockfile when there is an outdated lockfile using --print --update" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
- bundle! "lock --update"
+ lockfile outdated_lockfile
- expect(read_lockfile).to eq(@lockfile)
+ bundle "lock --print --update"
+
+ expect(out).to eq(expected_lockfile.rstrip)
+ end
+
+ it "emits info messages to stderr when updating an outdated lockfile using --print --update" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
+
+ bundle "lock --print --update"
+
+ expect(err).to eq(<<~STDERR.rstrip)
+ Fetching gem metadata from https://gem.repo4/...
+ Resolving dependencies...
+ STDERR
+ end
+
+ it "writes a lockfile when there is an outdated lockfile and bundle is frozen" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
+
+ bundle "lock --update", env: { "BUNDLE_FROZEN" => "true" }
+
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "does not fetch remote specs when using the --local option" do
- bundle "lock --update --local"
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --update --local", raise_on_error: false
+
+ expect(err).to match(/locally installed gems/)
+ end
- expect(out).to match(/sources listed in your Gemfile|installed locally/)
+ it "does not fetch remote checksums with --local" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
+
+ bundle "lock --print --local"
+
+ expect(out).to eq(expected_lockfile.chomp)
+ end
+
+ it "works with --gemfile flag" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+ bundle "lock --gemfile CustomGemfile"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0"
+ end
+
+ lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ expect(out).to match(/Writing lockfile to.+CustomGemfile\.lock/)
+ expect(read_lockfile("CustomGemfile.lock")).to eq(lockfile)
+ expect { read_lockfile }.to raise_error(Errno::ENOENT)
end
it "writes to a custom location using --lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --lockfile=lock"
expect(out).to match(/Writing lockfile to.+lock/)
- expect(read_lockfile "lock").to eq(@lockfile)
+ expect(read_lockfile("lock")).to eq(expected_lockfile)
expect { read_lockfile }.to raise_error(Errno::ENOENT)
end
+ it "updates a specific gem and write to a custom location" do
+ build_repo4 do
+ build_gem "foo", %w[1.0.2 1.0.3]
+ build_gem "warning", %w[1.4.0 1.5.0]
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "warning"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ foo (1.0.2)
+ warning (1.4.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ uri
+ warning
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update foo --lockfile=lock"
+
+ lockfile_content = read_lockfile("lock")
+ expect(lockfile_content).to include("foo (1.0.3)")
+ expect(lockfile_content).to include("warning (1.4.0)")
+ end
+
it "writes to custom location using --lockfile when a default lockfile is present" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "install"
bundle "lock --lockfile=lock"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.2)
+ activesupport (= 2.3.2)
+ actionpack (2.3.2)
+ activesupport (= 2.3.2)
+ activerecord (2.3.2)
+ activesupport (= 2.3.2)
+ activeresource (2.3.2)
+ activesupport (= 2.3.2)
+ activesupport (2.3.2)
+ foo (1.0)
+ rails (2.3.2)
+ actionmailer (= 2.3.2)
+ actionpack (= 2.3.2)
+ activerecord (= 2.3.2)
+ activeresource (= 2.3.2)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
expect(out).to match(/Writing lockfile to.+lock/)
- expect(read_lockfile("lock")).to eq(@lockfile)
+ expect(read_lockfile("lock")).to eq(lockfile)
end
it "update specific gems using --update" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("10.0.2", "10.0.1")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.1"
+ c.checksum gem_repo4, "actionpack", "2.3.1"
+ c.checksum gem_repo4, "activerecord", "2.3.1"
+ c.checksum gem_repo4, "activeresource", "2.3.1"
+ c.checksum gem_repo4, "activesupport", "2.3.1"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.1"
+ c.checksum gem_repo4, "rake", "10.0.1"
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ lockfile_with_outdated_rails_and_rake = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.1)
+ activesupport (= 2.3.1)
+ actionpack (2.3.1)
+ activesupport (= 2.3.1)
+ activerecord (2.3.1)
+ activesupport (= 2.3.1)
+ activeresource (2.3.1)
+ activesupport (= 2.3.1)
+ activesupport (2.3.1)
+ foo (1.0)
+ rails (2.3.1)
+ actionmailer (= 2.3.1)
+ actionpack (= 2.3.1)
+ activerecord (= 2.3.1)
+ activeresource (= 2.3.1)
+ rake (= 10.0.1)
+ rake (10.0.1)
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_with_outdated_rails_and_rake
bundle "lock --update rails rake"
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
+ end
+
+ it "updates specific gems using --update, even if that requires unlocking other top level gems" do
+ build_repo4 do
+ build_gem "prism", "0.15.1"
+ build_gem "prism", "0.24.0"
+
+ build_gem "ruby-lsp", "0.12.0" do |s|
+ s.add_dependency "prism", "< 0.24.0"
+ end
+
+ build_gem "ruby-lsp", "0.16.1" do |s|
+ s.add_dependency "prism", ">= 0.24.0"
+ end
+
+ build_gem "tapioca", "0.11.10" do |s|
+ s.add_dependency "prism", "< 0.24.0"
+ end
+
+ build_gem "tapioca", "0.13.1" do |s|
+ s.add_dependency "prism", ">= 0.24.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "tapioca"
+ gem "ruby-lsp"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ prism (0.15.1)
+ ruby-lsp (0.12.0)
+ prism (< 0.24.0)
+ tapioca (0.11.10)
+ prism (< 0.24.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruby-lsp
+ tapioca
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update tapioca --verbose"
+
+ expect(lockfile).to include("tapioca (0.13.1)")
+ end
+
+ it "updates specific gems using --update, even if that requires unlocking other top level gems, but only as few as possible" do
+ build_repo4 do
+ build_gem "prism", "0.15.1"
+ build_gem "prism", "0.24.0"
+
+ build_gem "ruby-lsp", "0.12.0" do |s|
+ s.add_dependency "prism", "< 0.24.0"
+ end
+
+ build_gem "ruby-lsp", "0.16.1" do |s|
+ s.add_dependency "prism", ">= 0.24.0"
+ end
+
+ build_gem "tapioca", "0.11.10" do |s|
+ s.add_dependency "prism", "< 0.24.0"
+ end
+
+ build_gem "tapioca", "0.13.1" do |s|
+ s.add_dependency "prism", ">= 0.24.0"
+ end
+
+ build_gem "other-prism-dependent", "1.0.0" do |s|
+ s.add_dependency "prism", ">= 0.15.1"
+ end
+
+ build_gem "other-prism-dependent", "1.1.0" do |s|
+ s.add_dependency "prism", ">= 0.15.1"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "tapioca"
+ gem "ruby-lsp"
+ gem "other-prism-dependent"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ other-prism-dependent (1.0.0)
+ prism (>= 0.15.1)
+ prism (0.15.1)
+ ruby-lsp (0.12.0)
+ prism (< 0.24.0)
+ tapioca (0.11.10)
+ prism (< 0.24.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruby-lsp
+ tapioca
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update tapioca"
+
+ expect(lockfile).to include("tapioca (0.13.1)")
+ expect(lockfile).to include("other-prism-dependent (1.0.0)")
+ end
+
+ it "preserves unknown checksum algorithms" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile.gsub(/(sha256=[a-f0-9]+)$/, "constant=true,\\1,xyz=123")
+
+ previous_lockfile = read_lockfile
+
+ bundle "lock"
+
+ expect(read_lockfile).to eq(previous_lockfile)
+ end
+
+ it "does not unlock git sources when only uri shape changes" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ build_git("foo")
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+
+ # Change uri format to end with "/" and reinstall
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}/"
+ G
+
+ expect(out).to include("using resolution from the lockfile")
+ expect(out).not_to include("re-resolving dependencies because the list of sources changed")
+ end
+
+ it "updates specific gems using --update using the locked revision of unrelated git gems for resolving" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ ref = build_git("foo").ref_for("HEAD")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rake"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "deadbeef"
+ G
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{ref}
+ branch: deadbeef
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ rake (10.0.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update rake --verbose"
+ expect(out).to match(/Writing lockfile to.+lock/)
+ expect(lockfile).to include("rake (#{rake_version})")
end
it "errors when updating a missing specific gems using --update" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
- bundle "lock --update blahblah"
- expect(out).to eq("Could not find gem 'blahblah'.")
+ bundle "lock --update blahblah", raise_on_error: false
+ expect(err).to eq("Could not find gem 'blahblah'.")
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
+ end
+
+ it "can lock without downloading gems" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "thin"
+ gem "myrack_middleware", :group => "test"
+ G
+ bundle_config "without test"
+ bundle_config "path vendor/bundle"
+ bundle "lock", verbose: true
+ expect(bundled_app("vendor/bundle")).not_to exist
end
# see update_spec for more coverage on same options. logic is shared so it's not necessary
@@ -136,13 +697,16 @@ RSpec.describe "bundle lock" do
build_gem "foo", %w[1.5.1] do |s|
s.add_dependency "bar", "~> 3.0"
end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "foo", %w[2.0.0.pre] do |s|
+ s.add_dependency "bar"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 2.1.2.pre 3.0.0 3.1.0.pre 4.0.0.pre]
build_gem "qux", %w[1.0.0 1.0.1 1.1.0 2.0.0]
end
# establish a lockfile set to 1.4.3
install_gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'foo', '1.4.3'
gem 'bar', '2.0.3'
gem 'qux', '1.0.0'
@@ -151,66 +715,340 @@ RSpec.describe "bundle lock" do
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'foo'
gem 'qux'
G
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "single gem updates dependent gem to minor" do
bundle "lock --update foo --patch"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.4.5 bar-2.1.1 qux-1.0.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.4.5 bar-2.1.1 qux-1.0.0].sort)
end
it "minor preferred with strict" do
bundle "lock --update --minor --strict"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.5.0 bar-2.1.1 qux-1.1.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.5.0 bar-2.1.1 qux-1.1.0].sort)
+ end
+
+ it "shows proper error when Gemfile changes forbid patch upgrades, and --patch --strict is given" do
+ # force next minor via Gemfile
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo', '1.5.0'
+ gem 'qux'
+ G
+
+ bundle "lock --update foo --patch --strict", raise_on_error: false
+
+ expect(err).to include(
+ "foo is locked to 1.4.3, while Gemfile is requesting foo (= 1.5.0). " \
+ "--strict --patch was specified, but there are no patch level upgrades from 1.4.3 satisfying foo (= 1.5.0), so version solving has failed"
+ )
+ end
+
+ context "pre" do
+ it "defaults to major" do
+ bundle "lock --update --pre"
+
+ expect(the_bundle.locked_specs).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ end
+
+ it "patch preferred" do
+ bundle "lock --update --patch --pre"
+
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.4.5 bar-2.1.2.pre qux-1.0.1].sort)
+ end
+
+ it "minor preferred" do
+ bundle "lock --update --minor --pre"
+
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.5.1 bar-3.1.0.pre qux-1.1.0].sort)
+ end
+
+ it "major preferred" do
+ bundle "lock --update --major --pre"
+
+ expect(the_bundle.locked_specs).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ end
+ end
+ end
+
+ context "conservative updates when minor update adds a new dependency" do
+ before do
+ build_repo4 do
+ build_gem "sequel", "5.71.0"
+ build_gem "sequel", "5.72.0" do |s|
+ s.add_dependency "bigdecimal", ">= 0"
+ end
+ build_gem "bigdecimal", %w[1.4.4 99.1.4]
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem 'sequel'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sequel (5.71.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sequel
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
+
+ it "adds the latest version of the new dependency" do
+ bundle "lock --minor --update sequel"
+
+ expect(the_bundle.locked_specs).to eq(%w[sequel-5.72.0 bigdecimal-99.1.4].sort)
+ end
+ end
+
+ it "updates the bundler version in the lockfile to the latest bundler version" do
+ build_repo4 do
+ build_gem "bundler", "55"
+ end
+
+ system_gems "bundler-55", gem_repo: gem_repo4
+
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "https://gem.repo4"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
+
+ bundle "lock --update --bundler --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(lockfile).to end_with("BUNDLED WITH\n 55\n")
+
+ build_repo4 do
+ build_gem "bundler", "99"
+ end
+
+ bundle "lock --update --bundler --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(lockfile).to end_with("BUNDLED WITH\n 99\n")
+ end
+
+ it "supports adding new platforms when there's no previous lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform java x86-mingw32 --verbose"
+ expect(out).to include("Resolving dependencies because there's no lockfile")
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
+ end
+
+ it "supports adding new platforms when a previous lockfile exists" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock"
+ bundle "lock --add-platform java x86-mingw32 --verbose"
+ expect(out).to include("Found changes from the lockfile, re-resolving dependencies because you are adding a new platform to your lockfile")
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
+ end
+
+ it "supports adding new platforms, when most specific locked platform is not the current platform, and current resolve is not compatible with the target platform" do
+ simulate_platform "arm64-darwin-23" do
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.platform = "arm64-darwin"
+ end
+
+ build_gem "foo" do |s|
+ s.platform = "java"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform java"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0-arm64-darwin)
+ foo (1.0-java)
+
+ PLATFORMS
+ arm64-darwin
+ java
+
+ DEPENDENCIES
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
end
- it "supports adding new platforms" do
- bundle! "lock --add-platform java x86-mingw32"
+ it "supports adding new platforms with force_ruby_platform = true" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-x86-64_linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ platform_specific
+ L
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq)
+ bundle_config "force_ruby_platform true"
+ bundle "lock --add-platform java x86-mingw32"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to contain_exactly(Gem::Platform::RUBY, "x86_64-linux", "java", "x86-mingw32")
end
it "supports adding the `ruby` platform" do
- bundle! "lock --add-platform ruby"
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(local_platforms.unshift("ruby").uniq)
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform ruby"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("ruby"))
end
- it "warns when adding an unknown platform" do
- bundle "lock --add-platform foobarbaz"
- expect(out).to include("The platform `foobarbaz` is unknown to RubyGems and adding it will likely lead to resolution errors")
+ it "fails when adding an unknown platform" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform foobarbaz", raise_on_error: false
+ expect(err).to include("The platform `foobarbaz` is unknown to RubyGems and can't be added to the lockfile")
+ expect(last_command).to be_failure
end
it "allows removing platforms" do
- bundle! "lock --add-platform java x86-mingw32"
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform java x86-mingw32"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
+
+ bundle "lock --remove-platform java"
+
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("x86-mingw32"))
+ end
+
+ it "also cleans up redundant platform gems when removing platforms" do
+ build_repo4 do
+ build_gem "nokogiri", "1.12.0"
+ build_gem "nokogiri", "1.12.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.12.0"
+ c.checksum gem_repo4, "nokogiri", "1.12.0", "x86_64-darwin"
+ end
+
+ simulate_platform "x86_64-darwin-22" do
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.12.0)
+ nokogiri (1.12.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq)
+ checksums.delete("nokogiri", Gem::Platform::RUBY)
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "lock --remove-platform ruby"
+ end
- bundle! "lock --remove-platform java"
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.12.0-x86_64-darwin)
+
+ PLATFORMS
+ x86_64-darwin
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(local_platforms.unshift(mingw).uniq)
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "errors when removing all platforms" do
- bundle "lock --remove-platform #{local_platforms.join(" ")}"
- expect(last_command.bundler_err).to include("Removing all platforms from the bundle is not allowed")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --remove-platform #{local_platform}", raise_on_error: false
+ expect(err).to include("Removing all platforms from the bundle is not allowed")
end
- # from https://github.com/bundler/bundler/issues/4896
+ # from https://github.com/rubygems/bundler/issues/4896
it "properly adds platforms when platform requirements come from different dependencies" do
build_repo4 do
build_gem "ffi", "1.9.14"
build_gem "ffi", "1.9.14" do |s|
- s.platform = mingw
+ s.platform = "x86-mingw32"
end
build_gem "gssapi", "0.1"
@@ -236,17 +1074,24 @@ RSpec.describe "bundle lock" do
end
gemfile <<-G
- source "file://localhost#{gem_repo4}"
+ source "https://gem.repo4"
gem "mixlib-shellout"
gem "gssapi"
G
- simulate_platform(mingw) { bundle! :lock }
+ simulate_platform("x86-mingw32") { bundle :lock }
- expect(the_bundle.lockfile).to read_as(normalize_uri_file(strip_whitespace(<<-G)))
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "ffi", "1.9.14", "x86-mingw32"
+ c.checksum gem_repo4, "gssapi", "1.2.0"
+ c.checksum gem_repo4, "mixlib-shellout", "2.2.6", "universal-mingw32"
+ c.checksum gem_repo4, "win32-process", "0.8.3"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo4}/
+ remote: https://gem.repo4/
specs:
ffi (1.9.14-x86-mingw32)
gssapi (1.2.0)
@@ -262,16 +1107,20 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
gssapi
mixlib-shellout
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
- simulate_platform(rb) { bundle! :lock }
+ bundle_config "force_ruby_platform true"
+ bundle :lock
- expect(the_bundle.lockfile).to read_as(normalize_uri_file(strip_whitespace(<<-G)))
+ checksums.checksum gem_repo4, "ffi", "1.9.14"
+ checksums.checksum gem_repo4, "mixlib-shellout", "2.2.6"
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo4}/
+ remote: https://gem.repo4/
specs:
ffi (1.9.14)
ffi (1.9.14-x86-mingw32)
@@ -290,33 +1139,1739 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
gssapi
mixlib-shellout
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "doesn't crash when an update candidate doesn't have any matching platform" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0"
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "15.0.71.48.1beta2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "libv8"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0)
+ libv8 (8.4.255.0-x86_64-darwin-19)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ libv8
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
+
+ simulate_platform("x86_64-darwin-19") { bundle "lock --update" }
+
+ expect(out).to match(/Writing lockfile to.+Gemfile\.lock/)
end
- context "when an update is available" do
- let(:repo) { gem_repo2 }
+ it "adds all more specific candidates when they all have the same dependencies" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-20"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "libv8"
+ G
+
+ simulate_platform("x86_64-darwin-19") { bundle "lock" }
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-19"
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-20"
+ end
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin-19
+ x86_64-darwin-20
+
+ DEPENDENCIES
+ libv8
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "respects the previous lockfile if it had a matching less specific platform already locked, and installs the best variant for each platform" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-20"
+ end
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-19"
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-20"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "libv8"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ libv8
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ previous_lockfile = lockfile
+
+ %w[x86_64-darwin-19 x86_64-darwin-20].each do |platform|
+ simulate_platform(platform) do
+ bundle "lock"
+ expect(lockfile).to eq(previous_lockfile)
+
+ bundle "install"
+ expect(the_bundle).to include_gem("libv8 8.4.255.0 #{platform}")
+ end
+ end
+ end
+
+ it "does not conflict on ruby requirements when adding new platforms" do
+ build_repo4 do
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "universal-darwin"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x64-mingw-ucrt"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "raygun-apm"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ raygun-apm (1.0.78-universal-darwin)
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ raygun-apm
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform x86_64-linux"
+ end
+
+ it "adds platform specific gems as necessary, even when adding the current platform" do
+ build_repo4 do
+ build_gem "nokogiri", "1.16.0"
+
+ build_gem "nokogiri", "1.16.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-platform x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.0)
+ nokogiri (1.16.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "refuses to add platforms incompatible with the lockfile" do
+ build_repo4 do
+ build_gem "sorbet-static", "0.5.11989" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (0.5.11989-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-platform ruby", raise_on_error: false
+ end
+
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static' valid for all resolution platforms (x86_64-linux, ruby) in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static':
+ * sorbet-static-0.5.11989-x86_64-linux
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "respects lower bound ruby requirements" do
+ build_repo4 do
+ build_gem "our_private_gem", "0.1.0" do |s|
+ s.required_ruby_version = ">= #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+
+ gem "our_private_gem"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ our_private_gem (0.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+ DEPENDENCIES
+ our_private_gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end
+
+ context "when an update is available" do
before do
- lockfile(@lockfile)
- build_repo2 do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ build_repo4 do
build_gem "foo", "2.0"
end
+
+ lockfile(expected_lockfile)
end
it "does not implicitly update" do
- bundle! "lock"
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
- expect(read_lockfile).to eq(@lockfile)
+ expected_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.2)
+ activesupport (= 2.3.2)
+ actionpack (2.3.2)
+ activesupport (= 2.3.2)
+ activerecord (2.3.2)
+ activesupport (= 2.3.2)
+ activeresource (2.3.2)
+ activesupport (= 2.3.2)
+ activesupport (2.3.2)
+ foo (1.0)
+ rails (2.3.2)
+ actionmailer (= 2.3.2)
+ actionpack (= 2.3.2)
+ activerecord (= 2.3.2)
+ activeresource (= 2.3.2)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "accounts for changes in the gemfile" do
gemfile gemfile.gsub('"foo"', '"foo", "2.0"')
- bundle! "lock"
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "2.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ expected_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.2)
+ activesupport (= 2.3.2)
+ actionpack (2.3.2)
+ activesupport (= 2.3.2)
+ activerecord (2.3.2)
+ activesupport (= 2.3.2)
+ activeresource (2.3.2)
+ activesupport (= 2.3.2)
+ activesupport (2.3.2)
+ foo (2.0)
+ rails (2.3.2)
+ actionmailer (= 2.3.2)
+ actionpack (= 2.3.2)
+ activerecord (= 2.3.2)
+ activeresource (= 2.3.2)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo (= 2.0)
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(read_lockfile).to eq(expected_lockfile)
+ end
+ end
+
+ context "when a system gem has incorrect dependencies, different from the lockfile" do
+ before do
+ build_repo4 do
+ build_gem "debug", "1.6.3" do |s|
+ s.add_dependency "irb", ">= 1.3.6"
+ end
+
+ build_gem "irb", "1.5.0"
+ end
+
+ system_gems "irb-1.5.0", gem_repo: gem_repo4
+ system_gems "debug-1.6.3", gem_repo: gem_repo4
+
+ # simulate gemspec with wrong empty dependencies
+ debug_gemspec_path = system_gem_path("specifications/debug-1.6.3.gemspec")
+ debug_gemspec = Gem::Specification.load(debug_gemspec_path.to_s)
+ debug_gemspec.dependencies.clear
+ File.write(debug_gemspec_path, debug_gemspec.to_ruby)
+ end
+
+ it "respects the existing lockfile, even when reresolving" do
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "debug"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "debug", "1.6.3"
+ c.checksum gem_repo4, "irb", "1.5.0"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ debug (1.6.3)
+ irb (>= 1.3.6)
+ irb (1.5.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ debug
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ debug (1.6.3)
+ irb (>= 1.3.6)
+ irb (1.5.0)
+
+ PLATFORMS
+ arm64-darwin-22
+ x86_64-linux
+
+ DEPENDENCIES
+ debug
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when a system gem has incorrect dependencies, different from remote gems" do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0"
+ end
+
+ system_gems "foo-1.0.0", gem_repo: gem_repo4, path: default_bundle_path
+
+ # simulate gemspec with wrong empty dependencies
+ foo_gemspec_path = default_bundle_path("specifications/foo-1.0.0.gemspec")
+ foo_gemspec = Gem::Specification.load(foo_gemspec_path.to_s)
+ foo_gemspec.dependencies.clear
+ File.write(foo_gemspec_path, foo_gemspec.to_ruby)
+ end
+
+ it "generates a lockfile using remote dependencies, and prints a warning" do
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0.0"
+ c.checksum gem_repo4, "bar", "1.0.0"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --verbose"
+ end
+
+ expect(err).to eq("Local specification for foo-1.0.0 has different dependencies than the remote gem, ignoring it")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bar (1.0.0)
+ foo (1.0.0)
+ bar
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "properly shows resolution errors including OR requirements" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "railties", ">= 6.1", "< 7.1"
+ end
+ build_gem "actionpack", "6.1.4"
+ build_gem "actionpack", "7.0.3.1"
+ build_gem "actionpack", "7.0.4"
+ build_gem "railties", "6.1.4" do |s|
+ s.add_dependency "actionpack", "6.1.4"
+ end
+ build_gem "rails", "7.0.3.1" do |s|
+ s.add_dependency "railties", "7.0.3.1"
+ end
+ build_gem "rails", "7.0.4" do |s|
+ s.add_dependency "railties", "7.0.4"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rails", ">= 7.0.3.1"
+ gem "activeadmin", "2.13.1"
+ G
+
+ bundle "lock", raise_on_error: false
+
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
+
+ Because rails >= 7.0.4 depends on railties = 7.0.4
+ and rails < 7.0.4 depends on railties = 7.0.3.1,
+ railties = 7.0.3.1 OR = 7.0.4 is required.
+ So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository https://gem.repo4/ or installed locally,
+ version solving has failed.
+ ERR
+ end
+
+ it "is able to display some explanation on crazy irresolvable cases" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "ransack", "= 3.1.0"
+ end
+
+ # Activemodel is missing as a dependency in lockfile
+ build_gem "ransack", "3.1.0" do |s|
+ s.add_dependency "activemodel", ">= 6.0.4"
+ s.add_dependency "activesupport", ">= 6.0.4"
+ end
+
+ %w[6.0.4 7.0.2.3 7.0.3.1 7.0.4].each do |version|
+ build_gem "activesupport", version
+
+ # Activemodel is only available on 6.0.4
+ if version == "6.0.4"
+ build_gem "activemodel", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ end
+
+ build_gem "rails", version do |s|
+ # Depednencies of Rails 7.0.2.3 are in reverse order
+ if version == "7.0.2.3"
+ s.add_dependency "activesupport", version
+ s.add_dependency "activemodel", version
+ else
+ s.add_dependency "activemodel", version
+ s.add_dependency "activesupport", version
+ end
+ end
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rails", ">= 7.0.2.3"
+ gem "activeadmin", "= 2.13.1"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ activeadmin (2.13.1)
+ ransack (= 3.1.0)
+ ransack (3.1.0)
+ activemodel (>= 6.0.4)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ activeadmin (= 2.13.1)
+ ransack (= 3.1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expected_error = <<~ERR.strip
+ Could not find compatible versions
+
+ Because rails >= 7.0.4 depends on activemodel = 7.0.4
+ and rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1,
+ rails >= 7.0.3.1 requires activemodel = 7.0.3.1 OR = 7.0.4.
+ (1) So, because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
+ and every version of activemodel depends on activesupport = 6.0.4,
+ rails >= 7.0.2.3 requires activesupport = 6.0.4.
+
+ Because rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3
+ and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
+ rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
+ And because rails >= 7.0.4 depends on activesupport = 7.0.4,
+ rails >= 7.0.2.3 requires activesupport = 7.0.2.3 OR = 7.0.3.1 OR = 7.0.4.
+ And because rails >= 7.0.2.3 requires activesupport = 6.0.4 (1),
+ rails >= 7.0.2.3 cannot be used.
+ So, because Gemfile depends on rails >= 7.0.2.3,
+ version solving has failed.
+ ERR
+
+ bundle "lock", raise_on_error: false
+ expect(err).to eq(expected_error)
+
+ lockfile lockfile.gsub(/PLATFORMS\n #{local_platform}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
+
+ bundle "lock", raise_on_error: false
+ expect(err).to eq(expected_error)
+ end
+
+ it "does not accidentally resolves to prereleases" do
+ build_repo4 do
+ build_gem "autoproj", "2.0.3" do |s|
+ s.add_dependency "autobuild", ">= 1.10.0.a"
+ s.add_dependency "tty-prompt"
+ end
+
+ build_gem "tty-prompt", "0.6.0"
+ build_gem "tty-prompt", "0.7.0"
+
+ build_gem "autobuild", "1.10.0.b3"
+ build_gem "autobuild", "1.10.1" do |s|
+ s.add_dependency "tty-prompt", "~> 0.6.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "autoproj", ">= 2.0.0"
+ G
+
+ bundle "lock"
+ expect(lockfile).to_not include("autobuild (1.10.0.b3)")
+ expect(lockfile).to include("autobuild (1.10.1)")
+ end
+
+ # Newer rails depends on Bundler, while ancient Rails does not. Bundler tries
+ # a first resolution pass that does not consider pre-releases. However, when
+ # using a pre-release Bundler (like the .dev version), that results in that
+ # pre-release being ignored and resolving to a version that does not depend on
+ # Bundler at all. We should avoid that and still consider .dev Bundler.
+ #
+ it "does not ignore prereleases with there's only one candidate" do
+ build_repo4 do
+ build_gem "rails", "7.4.0.2" do |s|
+ s.add_dependency "bundler", ">= 1.15.0"
+ end
+
+ build_gem "rails", "2.3.18"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "rails"
+ G
+
+ bundle "lock"
+ expect(lockfile).to_not include("rails (2.3.18)")
+ expect(lockfile).to include("rails (7.4.0.2)")
+ end
+
+ it "deals with platform specific incompatibilities" do
+ build_repo4 do
+ build_gem "activerecord", "6.0.6"
+ build_gem "activerecord-jdbc-adapter", "60.4" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.0.0"
+ end
+ build_gem "activerecord-jdbc-adapter", "61.0" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.1.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "activerecord", "6.0.6"
+ gem "activerecord-jdbc-adapter", "61.0"
+ G
+
+ simulate_platform "universal-java-19" do
+ bundle "lock", raise_on_error: false
+ end
+
+ expect(err).to include("Could not find compatible versions")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ end
+
+ it "adds checksums to an existing lockfile, when re-resolving is necessary" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ # lockfile has a typo (nogokiri) in the dependencies section, so Bundler
+ # sees dependencies have changed, and re-resolves
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nogokiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums to an existing lockfile, when no re-resolve is necessary" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums when source is not specified" do
+ system_gems(%w[myrack-1.0.0], path: default_bundle_path)
+
+ gemfile <<-G
+ gem "myrack"
+ G
+
+ lockfile <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ # myrack is coming from gem_repo1
+ # but it's simulated to install in the system gems path
+ checksums = checksums_section do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums to an existing lockfile, when gems are already installed" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "generates checksums by default" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "disables checksums if configured to do so" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ bundle_config "lockfile_checksums false"
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "add checksums for gems installed on disk" do
+ build_repo4 do
+ build_gem "warning", "18.0.0"
+ end
+
+ bundle_config "lockfile_checksums false"
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile(<<-G, artifice: "endpoint")
+ source "https://gem.repo4"
+
+ gem "warning"
+ G
+
+ bundle "config --delete lockfile_checksums"
+ bundle("lock --add-checksums", artifice: "endpoint")
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "warning", "18.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ warning
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "doesn't add checksum for gems not installed on disk" do
+ lockfile(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ warning
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile(<<~G)
+ source "https://gem.repo4"
+
+ gem "warning"
+ G
+
+ build_repo4 do
+ build_gem "warning", "18.0.0"
+ end
+
+ FileUtils.rm_rf("#{gem_repo4}/gems")
+
+ bundle("lock --add-checksums", artifice: "endpoint")
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "warning", "18.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ warning
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ context "when re-resolving to include prereleases" do
+ before do
+ build_repo4 do
+ build_gem "tzinfo-data", "1.2022.7"
+ build_gem "rails", "7.1.0.alpha" do |s|
+ s.add_dependency "activesupport"
+ end
+ build_gem "activesupport", "7.1.0.alpha"
+ end
+ end
+
+ it "does not end up including gems scoped to other platforms in the lockfile" do
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "rails"
+ gem "tzinfo-data", platform: :windows
+ G
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).not_to include("tzinfo-data (1.2022.7)")
+ end
+ end
+
+ context "when resolving platform specific gems as indirect dependencies on truffleruby", :truffleruby_only do
+ before do
+ build_lib "foo", path: bundled_app do |s|
+ s.add_dependency "nokogiri"
+ end
+
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gemspec
+ G
+ end
+
+ it "locks both ruby and platform specific specs" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ context "and a lockfile with platform specific gems only already exists" do
+ before do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ lockfile <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "keeps platform specific gems" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+ end
+
+ context "when adding a new gem that requires unlocking other transitive deps" do
+ before do
+ build_repo4 do
+ build_gem "govuk_app_config", "0.1.0"
+
+ build_gem "govuk_app_config", "4.13.0" do |s|
+ s.add_dependency "railties", ">= 5.0"
+ end
+
+ %w[7.0.4.1 7.0.4.3].each do |v|
+ build_gem "railties", v do |s|
+ s.add_dependency "actionpack", v
+ s.add_dependency "activesupport", v
+ end
+
+ build_gem "activesupport", v
+ build_gem "actionpack", v
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "govuk_app_config"
+ gem "activesupport", "7.0.4.3"
+ G
+
+ # Simulate out of sync lockfile because top level dependency on
+ # activesuport has just been added to the Gemfile, and locked to a higher
+ # version
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionpack (7.0.4.1)
+ activesupport (7.0.4.1)
+ govuk_app_config (4.13.0)
+ railties (>= 5.0)
+ railties (7.0.4.1)
+ actionpack (= 7.0.4.1)
+ activesupport (= 7.0.4.1)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ govuk_app_config
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not downgrade top level dependencies" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "actionpack", "7.0.4.3"
+ c.no_checksum "activesupport", "7.0.4.3"
+ c.no_checksum "govuk_app_config", "4.13.0"
+ c.no_checksum "railties", "7.0.4.3"
+ end
+
+ simulate_platform "arm64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionpack (7.0.4.3)
+ activesupport (7.0.4.3)
+ govuk_app_config (4.13.0)
+ railties (>= 5.0)
+ railties (7.0.4.3)
+ actionpack (= 7.0.4.3)
+ activesupport (= 7.0.4.3)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ activesupport (= 7.0.4.3)
+ govuk_app_config
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when lockfile has incorrectly indented platforms" do
+ before do
+ build_repo4 do
+ build_gem "ffi", "1.1.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "ffi", "1.1.0" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.1.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ ffi
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not remove any gems" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.1.0-arm64-darwin)
+ ffi (1.1.0-x86_64-linux)
+
+ PLATFORMS
+ arm64-darwin
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ describe "--normalize-platforms on linux" do
+ let(:normalized_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+ irb (1.0.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "irb", "1.0.0"
+
+ build_gem "irb", "1.0.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "irb"
+ G
+ end
+
+ context "when already normalized" do
+ before do
+ lockfile normalized_lockfile
+ end
+
+ it "is a noop" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when not already normalized" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms and native gems in the lockfile" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+ end
+
+ describe "--normalize-platforms on darwin" do
+ let(:normalized_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "irb", "1.0.0"
+
+ build_gem "irb", "1.0.0" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "irb"
+ G
+ end
+
+ context "when already normalized" do
+ before do
+ lockfile normalized_lockfile
+ end
+
+ it "is a noop" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having only ruby" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms and native gems in the lockfile" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having only the current platform with version" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin-23
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms by removing version" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having other platforms with version" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms by removing version" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+ end
+
+ describe "--normalize-platforms with gems without generic variant" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (1.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "sorbet-static" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static"
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "removes invalid platforms" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
- expect(read_lockfile).to eq(@lockfile.sub("foo (1.0)", "foo (2.0)").sub(/foo$/, "foo (= 2.0)"))
+ expect(lockfile).to eq(original_lockfile.gsub(/^ ruby\n/m, ""))
end
end
end
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index e6d6e19122..65fbad05aa 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -1,179 +1,454 @@
# frozen_string_literal: true
RSpec.describe "bundle gem" do
- def reset!
- super
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ def gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to exist
+ expect(bundled_app("#{gem_name}/README.md")).to exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to exist
+ expect(bundled_app("#{gem_name}/Rakefile")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/version.rb")).to exist
+
+ expect(ignore_paths).to include("bin/")
+ expect(ignore_paths).to include("Gemfile")
end
- def remove_push_guard(gem_name)
- # Remove exception that prevents public pushes on older RubyGems versions
- if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
- path = "#{gem_name}/#{gem_name}.gemspec"
- content = File.read(path).sub(/raise "RubyGems 2\.0 or newer.*/, "")
- File.open(path, "w") {|f| f.write(content) }
- end
+ def bundle_exec_rubocop
+ prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec"))
+ bundle "config set path #{rubocop_gem_path}", dir: bundled_app(gem_name)
+ bundle "exec rubocop --debug --config .rubocop.yml", dir: bundled_app(gem_name)
end
- def execute_bundle_gem(gem_name, flag = "", to_remove_push_guard = true)
- bundle! "gem #{gem_name} #{flag}"
- remove_push_guard(gem_name) if to_remove_push_guard
- # reset gemspec cache for each test because of commit 3d4163a
- Bundler.clear_gemspec_cache
+ def bundle_exec_standardrb
+ prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec"))
+ bundle "config set path #{standard_gem_path}", dir: bundled_app(gem_name)
+ bundle "exec standardrb --debug", dir: bundled_app(gem_name)
end
- def gem_skeleton_assertions(gem_name)
- expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to exist
- expect(bundled_app("#{gem_name}/README.md")).to exist
- expect(bundled_app("#{gem_name}/Gemfile")).to exist
- expect(bundled_app("#{gem_name}/Rakefile")).to exist
- expect(bundled_app("#{gem_name}/lib/test/gem.rb")).to exist
- expect(bundled_app("#{gem_name}/lib/test/gem/version.rb")).to exist
+ def ignore_paths
+ generated = bundled_app("#{gem_name}/#{gem_name}.gemspec").read
+ matched = generated.match(/^\s+f\.start_with\?\(\*%w\[(?<ignored>.*)\]\)$/)
+ matched[:ignored]&.split(" ")
end
- before do
- git_config_content = <<-EOF
- [user]
- name = "Bundler User"
- email = user@example.com
- [github]
- user = bundleuser
- EOF
- @git_config_location = ENV["GIT_CONFIG"]
- path = "#{File.expand_path(tmp, File.dirname(__FILE__))}/test_git_config.txt"
- File.open(path, "w") {|f| f.write(git_config_content) }
- ENV["GIT_CONFIG"] = path
+ def installed_go?
+ sys_exec("go version", raise_on_error: true)
+ true
+ rescue StandardError
+ false
end
- after do
- FileUtils.rm(ENV["GIT_CONFIG"]) if File.exist?(ENV["GIT_CONFIG"])
- ENV["GIT_CONFIG"] = @git_config_location
+ let(:generated_gemspec) { Bundler.load_gemspec_uncached(bundled_app(gem_name).join("#{gem_name}.gemspec")) }
+
+ let(:gem_name) { "mygem" }
+
+ before do
+ git("config --global user.name 'Bundler User'")
+ git("config --global user.email user@example.com")
+ git("config --global github.user bundleuser")
+
+ bundle_config_global "gem.mit false"
+ bundle_config_global "gem.test false"
+ bundle_config_global "gem.coc false"
+ bundle_config_global "gem.linter false"
+ bundle_config_global "gem.ci false"
+ bundle_config_global "gem.changelog false"
+ bundle_config_global "gem.bundle false"
end
- shared_examples_for "git config is present" do
- context "git config user.{name,email} present" do
- it "sets gemspec author to git user.name if available" do
- expect(generated_gem.gemspec.authors.first).to eq("Bundler User")
- end
+ describe "git repo initialization" do
+ it "generates a gem skeleton with a .git folder" do
+ bundle "gem #{gem_name}"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).to exist
+ end
- it "sets gemspec email to git user.email if available" do
- expect(generated_gem.gemspec.email.first).to eq("user@example.com")
- end
+ it "generates a gem skeleton with a .git folder when passing --git" do
+ bundle "gem #{gem_name} --git"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).to exist
end
- end
- shared_examples_for "git config is absent" do
- it "sets gemspec author to default message if git user.name is not set or empty" do
- expect(generated_gem.gemspec.authors.first).to eq("TODO: Write your name")
+ it "generates a gem skeleton without a .git folder when passing --no-git" do
+ bundle "gem #{gem_name} --no-git"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).not_to exist
end
- it "sets gemspec email to default message if git user.email is not set or empty" do
- expect(generated_gem.gemspec.email.first).to eq("TODO: Write your email address")
+ context "on a path with spaces" do
+ before do
+ Dir.mkdir(bundled_app("path with spaces"))
+ end
+
+ it "properly initializes git repo" do
+ skip "path with spaces needs special handling on Windows" if Gem.win_platform?
+
+ bundle "gem #{gem_name}", dir: bundled_app("path with spaces")
+ expect(bundled_app("path with spaces/#{gem_name}/.git")).to exist
+ end
end
end
shared_examples_for "--mit flag" do
before do
- execute_bundle_gem(gem_name, "--mit")
+ bundle "gem #{gem_name} --mit"
end
it "generates a gem skeleton with MIT license" do
- gem_skeleton_assertions(gem_name)
- expect(bundled_app("test-gem/LICENSE.txt")).to exist
- skel = Bundler::GemHelper.new(bundled_app(gem_name).to_s)
- expect(skel.gemspec.license).to eq("MIT")
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/LICENSE.txt")).to exist
+ expect(generated_gemspec.license).to eq("MIT")
end
end
shared_examples_for "--no-mit flag" do
before do
- execute_bundle_gem(gem_name, "--no-mit")
+ bundle "gem #{gem_name} --no-mit"
end
it "generates a gem skeleton without MIT license" do
- gem_skeleton_assertions(gem_name)
- expect(bundled_app("test-gem/LICENSE.txt")).to_not exist
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/LICENSE.txt")).to_not exist
end
end
shared_examples_for "--coc flag" do
- before do
- execute_bundle_gem(gem_name, "--coc", false)
- end
it "generates a gem skeleton with MIT license" do
- gem_skeleton_assertions(gem_name)
- expect(bundled_app("test-gem/CODE_OF_CONDUCT.md")).to exist
+ bundle "gem #{gem_name} --coc"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to exist
end
- describe "README additions" do
- it "generates the README with a section for the Code of Conduct" do
- expect(bundled_app("test-gem/README.md").read).to include("## Code of Conduct")
- expect(bundled_app("test-gem/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
- end
+ it "generates the README with a section for the Code of Conduct" do
+ bundle "gem #{gem_name} --coc"
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
+ end
+
+ it "generates the README with a section for the Code of Conduct, respecting the configured git default branch", git: ">= 2.28.0" do
+ git("config --global init.defaultBranch main")
+ bundle "gem #{gem_name} --coc"
+
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/main/CODE_OF_CONDUCT.md")
end
end
shared_examples_for "--no-coc flag" do
before do
- execute_bundle_gem(gem_name, "--no-coc", false)
+ bundle "gem #{gem_name} --no-coc"
end
it "generates a gem skeleton without Code of Conduct" do
- gem_skeleton_assertions(gem_name)
- expect(bundled_app("test-gem/CODE_OF_CONDUCT.md")).to_not exist
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to_not exist
end
- describe "README additions" do
- it "generates the README without a section for the Code of Conduct" do
- expect(bundled_app("test-gem/README.md").read).not_to include("## Code of Conduct")
- expect(bundled_app("test-gem/README.md").read).not_to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
- end
+ it "generates the README without a section for the Code of Conduct" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
end
end
- context "README.md" do
- let(:gem_name) { "test_gem" }
- let(:generated_gem) { Bundler::GemHelper.new(bundled_app(gem_name).to_s) }
+ shared_examples_for "--changelog flag" do
+ before do
+ bundle "gem #{gem_name} --changelog"
+ end
+ it "generates a gem skeleton with a CHANGELOG" do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to exist
+ end
+ end
+
+ shared_examples_for "--no-changelog flag" do
+ before do
+ bundle "gem #{gem_name} --no-changelog"
+ end
+ it "generates a gem skeleton without a CHANGELOG" do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to_not exist
+ end
+ end
+
+ shared_examples_for "--bundle flag" do
+ before do
+ bundle "gem #{gem_name} --bundle"
+ end
+ it "generates a gem skeleton with bundle install" do
+ gem_skeleton_assertions
+ expect(out).to include("Running bundle install in the new gem directory.")
+ end
+ end
+
+ shared_examples_for "--no-bundle flag" do
+ before do
+ bundle "gem #{gem_name} --no-bundle"
+ end
+ it "generates a gem skeleton without bundle install" do
+ gem_skeleton_assertions
+ expect(out).to_not include("Running bundle install in the new gem directory.")
+ end
+ end
+
+ shared_examples_for "--linter=rubocop flag" do
+ before do
+ bundle "gem #{gem_name} --linter=rubocop"
+ end
+
+ it "generates a gem skeleton with rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(
+ include("# frozen_string_literal: true").
+ and(include('require "rubocop/rake_task"').
+ and(include("RuboCop::RakeTask.new").
+ and(match(/default:.+:rubocop/))))
+ )
+ end
+
+ it "includes rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).not_to be_specific
+ expect(rubocop_dep.requirement).to eq(Gem::Requirement.new([">= 0"]))
+ end
+
+ it "generates a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
+ end
+
+ shared_examples_for "--linter=standard flag" do
+ before do
+ bundle "gem #{gem_name} --linter=standard"
+ end
+
+ it "generates a gem skeleton with standard" do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(
+ include('require "standard/rake"').
+ and(match(/default:.+:standard/))
+ )
+ end
+
+ it "includes standard in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ standard_dep = builder.dependencies.find {|d| d.name == "standard" }
+ expect(standard_dep).not_to be_specific
+ expect(standard_dep.requirement).to eq(Gem::Requirement.new([">= 0"]))
+ end
+
+ it "generates a default .standard.yml" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ end
+
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ end
+ end
+
+ shared_examples_for "--no-linter flag" do
+ define_negated_matcher :exclude, :include
+
+ before do
+ bundle "gem #{gem_name} --no-linter"
+ end
+
+ it "generates a gem skeleton without rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(exclude("rubocop"))
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to read_as(exclude("rubocop"))
+ end
+
+ it "does not include rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).to be_nil
+ end
+
+ it "does not include standard in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ standard_dep = builder.dependencies.find {|d| d.name == "standard" }
+ expect(standard_dep).to be_nil
+ end
+
+ it "doesn't generate a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
+
+ it "does not add .rubocop.yml into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ end
+
+ it "doesn't generate a default .standard.yml" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+
+ it "does not add .standard.yml into ignore list" do
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
+ it "has no rubocop offenses when using --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=c and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext=c --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=c, --test=minitest, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext=c --test=minitest --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=c, --test=rspec, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext=c --test=rspec --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=c, --test=test-unit, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext=c --test=test-unit --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no standard offenses when using --linter=standard flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --linter=standard"
+ bundle_exec_standardrb
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+
+ bundle "gem #{gem_name} --ext=rust --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --test=minitest, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+
+ bundle "gem #{gem_name} --ext=rust --test=minitest --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --test=rspec, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+
+ bundle "gem #{gem_name} --ext=rust --test=rspec --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --test=test-unit, and --linter=rubocop flag" do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+
+ bundle "gem #{gem_name} --ext=rust --test=test-unit --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ shared_examples_for "CI config is absent" do
+ it "does not create any CI files" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+ end
+
+ shared_examples_for "test framework is absent" do
+ it "does not create any test framework files" do
+ expect(bundled_app("#{gem_name}/.rspec")).to_not exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/test/#{gem_name}.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to_not exist
+ end
+
+ it "does not add any test framework files into ignore list" do
+ expect(ignore_paths).not_to include("test/")
+ expect(ignore_paths).not_to include(".rspec")
+ expect(ignore_paths).not_to include("spec/")
+ end
+ end
+
+ context "README.md" do
context "git config github.user present" do
before do
- execute_bundle_gem(gem_name)
+ bundle "gem #{gem_name}"
end
it "contribute URL set to git username" do
- expect(bundled_app("test_gem/README.md").read).not_to include("[USERNAME]")
- expect(bundled_app("test_gem/README.md").read).to include("github.com/bundleuser")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/bundleuser")
end
end
context "git config github.user is absent" do
before do
- sys_exec("git config --unset github.user")
- reset!
- in_app_root
+ git("config --global --unset github.user")
bundle "gem #{gem_name}"
- remove_push_guard(gem_name)
end
it "contribute URL set to [USERNAME]" do
- expect(bundled_app("test_gem/README.md").read).to include("[USERNAME]")
- expect(bundled_app("test_gem/README.md").read).not_to include("github.com/bundleuser")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("github.com/bundleuser")
+ end
+ end
+
+ describe "test task name on readme" do
+ shared_examples_for "test task name on readme" do |framework, task_name|
+ before do
+ bundle "gem #{gem_name} --test=#{framework}"
+ end
+
+ it "renders with correct name" do
+ expect(bundled_app("#{gem_name}/README.md").read).to include("Then, run `rake #{task_name}` to run the tests.")
+ end
end
+
+ it_behaves_like "test task name on readme", "test-unit", "test"
+ it_behaves_like "test task name on readme", "minitest", "test"
+ it_behaves_like "test task name on readme", "rspec", "spec"
end
end
it "creates a new git repository" do
- in_app_root
- bundle "gem test_gem"
- expect(bundled_app("test_gem/.git")).to exist
+ bundle "gem #{gem_name}"
+ expect(bundled_app("#{gem_name}/.git")).to exist
end
context "when git is not available" do
- let(:gem_name) { "test_gem" }
-
# This spec cannot have `git` available in the test env
before do
- load_paths = [lib, spec]
- load_path_str = "-I#{load_paths.join(File::PATH_SEPARATOR)}"
-
- sys_exec "PATH=\"\" #{Gem.ruby} #{load_path_str} #{bindir.join("bundle")} gem #{gem_name}"
+ bundle "gem #{gem_name}", env: { "PATH" => "" }
end
it "creates the gem without the need for git" do
@@ -187,50 +462,32 @@ RSpec.describe "bundle gem" do
it "doesn't create a .gitignore file" do
expect(bundled_app("#{gem_name}/.gitignore")).to_not exist
end
+
+ it "does not add .gitignore into ignore list" do
+ expect(ignore_paths).not_to include(".gitignore")
+ end
end
it "generates a valid gemspec" do
- in_app_root
- bundle! "gem newgem --bin"
+ bundle "gem newgem --bin"
- process_file(bundled_app("newgem", "newgem.gemspec")) do |line|
- # Simulate replacing TODOs with real values
- case line
- when /spec\.metadata\["(?:allowed_push_host|homepage_uri|source_code_uri|changelog_uri)"\]/, /spec\.homepage/
- line.gsub(/\=.*$/, "= 'http://example.org'")
- when /spec\.summary/
- line.gsub(/\=.*$/, "= %q{A short summary of my new gem.}")
- when /spec\.description/
- line.gsub(/\=.*$/, "= %q{A longer description of my new gem.}")
- # Remove exception that prevents public pushes on older RubyGems versions
- when /raise "RubyGems 2.0 or newer/
- line.gsub(/.*/, "") if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
- else
- line
- end
- end
+ prepare_gemspec(bundled_app("newgem", "newgem.gemspec"))
- Dir.chdir(bundled_app("newgem")) do
- gems = ["rake-10.0.2", :bundler]
- # for Ruby core repository, Ruby 2.6+ has bundler as standard library.
- gems.delete(:bundler) if ruby_core?
- system_gems gems, :path => :bundle_path
- bundle! "exec rake build"
+ build_repo2 do
+ build_dummy_irb "9.9.9"
end
+ gems = ["rake-#{rake_version}", "irb-9.9.9"]
+ system_gems gems, path: system_gem_path, gem_repo: gem_repo2
+ bundle "exec rake build", dir: bundled_app("newgem")
- expect(last_command.stdboth).not_to include("ERROR")
+ expect(stdboth).not_to include("ERROR")
end
context "gem naming with relative paths" do
- before do
- reset!
- in_app_root
- end
-
it "resolves ." do
create_temporary_dir("tmp")
- bundle "gem ."
+ bundle "gem .", dir: bundled_app("tmp")
expect(bundled_app("tmp/lib/tmp.rb")).to exist
end
@@ -238,7 +495,7 @@ RSpec.describe "bundle gem" do
it "resolves .." do
create_temporary_dir("temp/empty_dir")
- bundle "gem .."
+ bundle "gem ..", dir: bundled_app("temp/empty_dir")
expect(bundled_app("temp/lib/temp.rb")).to exist
end
@@ -246,564 +503,1507 @@ RSpec.describe "bundle gem" do
it "resolves relative directory" do
create_temporary_dir("tmp/empty/tmp")
- bundle "gem ../../empty"
+ bundle "gem ../../empty", dir: bundled_app("tmp/empty/tmp")
expect(bundled_app("tmp/empty/lib/empty.rb")).to exist
end
def create_temporary_dir(dir)
- FileUtils.mkdir_p(dir)
- Dir.chdir(dir)
+ FileUtils.mkdir_p(bundled_app(dir))
end
end
- context "gem naming with underscore" do
- let(:gem_name) { "test_gem" }
+ shared_examples_for "--github-username option" do |github_username|
+ before do
+ bundle "gem #{gem_name} --github-username=#{github_username}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to given github username" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/#{github_username}")
+ end
+ end
+
+ shared_examples_for "github_username configuration" do
+ context "with github_username setting set to some value" do
+ before do
+ bundle_config_global "gem.github_username different_username"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to bundle config setting" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/different_username")
+ end
+ end
+
+ context "with github_username setting set to false" do
+ before do
+ bundle_config_global "gem.github_username false"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to [USERNAME]" do
+ expect(bundled_app("#{gem_name}/README.md").read).to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("github.com/bundleuser")
+ end
+ end
+ end
+
+ it "generates a gem skeleton" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to exist
+ expect(bundled_app("#{gem_name}/Rakefile")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/version.rb")).to exist
+ expect(bundled_app("#{gem_name}/sig/#{gem_name}.rbs")).to exist
+ expect(bundled_app("#{gem_name}/.gitignore")).to exist
+
+ expect(bundled_app("#{gem_name}/bin/setup")).to exist
+ expect(bundled_app("#{gem_name}/bin/console")).to exist
+
+ unless Gem.win_platform?
+ expect(bundled_app("#{gem_name}/bin/setup")).to be_executable
+ expect(bundled_app("#{gem_name}/bin/console")).to be_executable
+ end
+
+ expect(bundled_app("#{gem_name}/bin/setup").read).to start_with("#!")
+ expect(bundled_app("#{gem_name}/bin/console").read).to start_with("#!")
+ end
+
+ it "includes bin/ into ignore list" do
+ bundle "gem #{gem_name}"
+
+ expect(ignore_paths).to include("bin/")
+ end
+
+ it "includes Gemfile into ignore list" do
+ bundle "gem #{gem_name}"
+ expect(ignore_paths).to include("Gemfile")
+ end
+
+ it "includes .gitignore into ignore list" do
+ bundle "gem #{gem_name}"
+
+ expect(ignore_paths).to include(".gitignore")
+ end
+
+ it "starts with version 0.1.0" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/version.rb").read).to match(/VERSION = "0.1.0"/)
+ end
+
+ it "declare String type for VERSION constant" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/sig/#{gem_name}.rbs").read).to match(/VERSION: String/)
+ end
+
+ context "git config user.{name,email} is set" do
before do
- execute_bundle_gem(gem_name)
+ bundle "gem #{gem_name}"
end
- let(:generated_gem) { Bundler::GemHelper.new(bundled_app(gem_name).to_s) }
+ it "sets gemspec author to git user.name if available" do
+ expect(generated_gemspec.authors.first).to eq("Bundler User")
+ end
- it "generates a gem skeleton" do
- expect(bundled_app("test_gem/test_gem.gemspec")).to exist
- expect(bundled_app("test_gem/Gemfile")).to exist
- expect(bundled_app("test_gem/Rakefile")).to exist
- expect(bundled_app("test_gem/lib/test_gem.rb")).to exist
- expect(bundled_app("test_gem/lib/test_gem/version.rb")).to exist
- expect(bundled_app("test_gem/.gitignore")).to exist
+ it "sets gemspec email to git user.email if available" do
+ expect(generated_gemspec.email.first).to eq("user@example.com")
+ end
+ end
- expect(bundled_app("test_gem/bin/setup")).to exist
- expect(bundled_app("test_gem/bin/console")).to exist
- expect(bundled_app("test_gem/bin/setup")).to be_executable
- expect(bundled_app("test_gem/bin/console")).to be_executable
+ context "git config user.{name,email} is not set" do
+ before do
+ git("config --global --unset user.name")
+ git("config --global --unset user.email")
+ bundle "gem #{gem_name}"
end
- it "starts with version 0.1.0" do
- expect(bundled_app("test_gem/lib/test_gem/version.rb").read).to match(/VERSION = "0.1.0"/)
+ it "sets gemspec author to default message if git user.name is not set or empty" do
+ expect(generated_gemspec.authors.first).to eq("TODO: Write your name")
end
- it "does not nest constants" do
- expect(bundled_app("test_gem/lib/test_gem/version.rb").read).to match(/module TestGem/)
- expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(/module TestGem/)
+ it "sets gemspec email to default message if git user.email is not set or empty" do
+ expect(generated_gemspec.email.first).to eq("TODO: Write your email address")
end
+ end
- it_should_behave_like "git config is present"
+ it "sets gemspec metadata['allowed_push_host']" do
+ bundle "gem #{gem_name}"
- context "git config user.{name,email} is not set" do
- before do
- `git config --unset user.name`
- `git config --unset user.email`
- reset!
- in_app_root
- bundle "gem #{gem_name}"
- remove_push_guard(gem_name)
+ expect(generated_gemspec.metadata["allowed_push_host"]).
+ to match(/example\.com/)
+ end
+
+ it "includes a commented-out rubygems_mfa_required metadata hint" do
+ bundle "gem #{gem_name}"
+
+ gemspec_contents = bundled_app("#{gem_name}/#{gem_name}.gemspec").read
+
+ expect(gemspec_contents).to include('# spec.metadata["rubygems_mfa_required"] = "true"')
+ expect(gemspec_contents).to include("https://guides.rubygems.org/mfa-requirement-opt-in/")
+ end
+
+ it "sets a minimum ruby version" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=")
+ end
+
+ it "does not include the gemspec file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec")
+ end
+
+ it "does not include the Gemfile file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("Gemfile")
+ end
+
+ it "runs rake without problems" do
+ bundle "gem #{gem_name}"
+
+ system_gems ["rake-#{rake_version}"]
+
+ rakefile = <<~RAKEFILE
+ task :default do
+ puts 'SUCCESS'
+ end
+ RAKEFILE
+ File.open(bundled_app("#{gem_name}/Rakefile"), "w") do |file|
+ file.puts rakefile
+ end
+
+ sys_exec("rake", dir: bundled_app(gem_name))
+ expect(out).to include("SUCCESS")
+ end
+
+ context "--exe parameter set" do
+ before do
+ bundle "gem #{gem_name} --exe"
+ end
+
+ it "builds exe skeleton" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ unless Gem.win_platform?
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to be_executable
end
+ end
+ end
+
+ context "--bin parameter set" do
+ before do
+ bundle "gem #{gem_name} --bin"
+ end
+
+ it "builds exe skeleton" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ end
+ end
+
+ context "no --test parameter" do
+ before do
+ bundle "gem #{gem_name}"
+ end
+
+ it_behaves_like "test framework is absent"
+ end
+
+ context "--test parameter set to rspec" do
+ before do
+ bundle "gem #{gem_name} --test=rspec"
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ end
+
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
+ end
+
+ it "depends on a non-specific version of rspec in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rspec_dep = builder.dependencies.find {|d| d.name == "rspec" }
+ expect(rspec_dep).not_to be_specific
+ expect(rspec_dep.requirement).to eq(Gem::Requirement.new([">= 0"]))
+ end
+ end
- it_should_behave_like "git config is absent"
+ context "init_gems_rb setting to true" do
+ before do
+ bundle_config "init_gems_rb true"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates gems.rb instead of Gemfile" do
+ expect(bundled_app("#{gem_name}/gems.rb")).to exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to_not exist
+ end
+
+ it "includes gems.rb and gems.locked into ignore list" do
+ expect(ignore_paths).to include("gems.rb")
+ expect(ignore_paths).to include("gems.locked")
+ expect(ignore_paths).not_to include("Gemfile")
+ end
+ end
+
+ context "init_gems_rb setting to false" do
+ before do
+ bundle_config "init_gems_rb false"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates Gemfile instead of gems.rb" do
+ expect(bundled_app("#{gem_name}/gems.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to exist
+ end
+
+ it "includes Gemfile into ignore list" do
+ expect(ignore_paths).to include("Gemfile")
+ expect(ignore_paths).not_to include("gems.rb")
+ expect(ignore_paths).not_to include("gems.locked")
+ end
+ end
+
+ context "gem.test setting set to rspec" do
+ before do
+ bundle_config "gem.test rspec"
+ bundle "gem #{gem_name}"
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
end
- it "sets gemspec metadata['allowed_push_host']", :rubygems => "2.0" do
- expect(generated_gem.gemspec.metadata["allowed_push_host"]).
- to match(/mygemserver\.com/)
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
end
+ end
- it "requires the version file" do
- expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(%r{require "test_gem/version"})
+ context "gem.test setting set to rspec and --test is set to minitest" do
+ before do
+ bundle_config "gem.test rspec"
+ bundle "gem #{gem_name} --test=minitest"
end
- it "creates a base error class" do
- expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(/class Error < StandardError; end$/)
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/test_#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
end
- it "runs rake without problems" do
- system_gems ["rake-10.0.2"]
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
+ end
- rakefile = strip_whitespace <<-RAKEFILE
- task :default do
- puts 'SUCCESS'
+ context "--test parameter set to minitest" do
+ before do
+ bundle "gem #{gem_name} --test=minitest"
+ end
+
+ it "depends on a non-specific version of minitest" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ minitest_dep = builder.dependencies.find {|d| d.name == "minitest" }
+ expect(minitest_dep).not_to be_specific
+ expect(minitest_dep.requirement).to eq(Gem::Requirement.new([">= 0"]))
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/test_#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ end
+
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
+
+ it "creates a default rake task to run the test suite" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "minitest/test_task"
+
+ Minitest::TestTask.create
+
+ task default: :test
+ RAKEFILE
+
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
+ end
+ end
+
+ context "gem.test setting set to minitest" do
+ before do
+ bundle_config "gem.test minitest"
+ bundle "gem #{gem_name}"
+ end
+
+ it "creates a default rake task to run the test suite" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "minitest/test_task"
+
+ Minitest::TestTask.create
+
+ task default: :test
+ RAKEFILE
+
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
+ end
+ end
+
+ context "--test parameter set to test-unit" do
+ before do
+ bundle "gem #{gem_name} --test=test-unit"
+ end
+
+ it "depends on a non-specific version of test-unit" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ test_unit_dep = builder.dependencies.find {|d| d.name == "test-unit" }
+ expect(test_unit_dep).not_to be_specific
+ expect(test_unit_dep.requirement).to eq(Gem::Requirement.new([">= 0"]))
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/#{gem_name}_test.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ end
+
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
+
+ it "creates a default rake task to run the test suite" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "rake/testtask"
+
+ Rake::TestTask.new(:test) do |t|
+ t.libs << "test"
+ t.libs << "lib"
+ t.test_files = FileList["test/**/*_test.rb"]
end
+
+ task default: :test
RAKEFILE
- File.open(bundled_app("test_gem/Rakefile"), "w") do |file|
- file.puts rakefile
- end
- Dir.chdir(bundled_app(gem_name)) do
- sys_exec(rake)
- expect(out).to include("SUCCESS")
- end
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
+ end
- context "--exe parameter set" do
- before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --exe"
- end
+ context "--test parameter set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --test=foo", raise_on_error: false
+ end
- it "builds exe skeleton" do
- expect(bundled_app("test_gem/exe/test_gem")).to exist
- end
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--test' to be one of .*; got foo/)
+ end
+ end
- it "requires 'test-gem'" do
- expect(bundled_app("test_gem/exe/test_gem").read).to match(/require "test_gem"/)
- end
+ context "gem.test set to rspec and --test with no arguments" do
+ before do
+ bundle_config "gem.test rspec"
+ bundle "gem #{gem_name} --test"
end
- context "--bin parameter set" do
- before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --bin"
- end
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ end
- it "builds exe skeleton" do
- expect(bundled_app("test_gem/exe/test_gem")).to exist
- end
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
+ end
- it "requires 'test-gem'" do
- expect(bundled_app("test_gem/exe/test_gem").read).to match(/require "test_gem"/)
- end
+ it "hints that --test is already configured" do
+ expect(out).to match("rspec is already configured, ignoring --test flag.")
end
+ end
- context "no --test parameter" do
- before do
- reset!
- in_app_root
- bundle "gem #{gem_name}"
+ context "gem.test setting set to false and --test with no arguments", :readline do
+ before do
+ bundle_config "gem.test false"
+ bundle "gem #{gem_name} --test" do |input, _, _|
+ input.puts
end
+ end
- it "doesn't create any spec/test file" do
- expect(bundled_app("test_gem/.rspec")).to_not exist
- expect(bundled_app("test_gem/spec/test_gem_spec.rb")).to_not exist
- expect(bundled_app("test_gem/spec/spec_helper.rb")).to_not exist
- expect(bundled_app("test_gem/test/test_test_gem.rb")).to_not exist
- expect(bundled_app("test_gem/test/minitest_helper.rb")).to_not exist
- end
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
end
- context "--test parameter set to rspec" do
- before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test=rspec"
- end
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
- it "builds spec skeleton" do
- expect(bundled_app("test_gem/.rspec")).to exist
- expect(bundled_app("test_gem/spec/test_gem_spec.rb")).to exist
- expect(bundled_app("test_gem/spec/spec_helper.rb")).to exist
- end
+ it_behaves_like "test framework is absent"
+ end
- it "depends on a specific version of rspec", :rubygems => ">= 1.8.1" do
- remove_push_guard(gem_name)
- rspec_dep = generated_gem.gemspec.development_dependencies.find {|d| d.name == "rspec" }
- expect(rspec_dep).to be_specific
+ context "gem.test setting not set and --test with no arguments", :readline do
+ before do
+ bundle_config_global "BUNDLE_GEM__TEST" => nil
+ bundle "gem #{gem_name} --test" do |input, _, _|
+ input.puts
end
+ end
- it "requires 'test-gem'" do
- expect(bundled_app("test_gem/spec/spec_helper.rb").read).to include(%(require "test_gem"))
- end
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
+ end
- it "creates a default test which fails" do
- expect(bundled_app("test_gem/spec/test_gem_spec.rb").read).to include("expect(false).to eq(true)")
- end
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.test`."
+ expect(out).to match(hint)
end
- context "gem.test setting set to rspec" do
- before do
- reset!
- in_app_root
- bundle "config gem.test rspec"
- bundle "gem #{gem_name}"
+ it_behaves_like "test framework is absent"
+ end
+
+ context "gem.test setting set to a test framework and --no-test" do
+ before do
+ bundle_config "gem.test rspec"
+ bundle "gem #{gem_name} --no-test"
+ end
+
+ it_behaves_like "test framework is absent"
+ end
+
+ context "--ci with no argument" do
+ before do
+ bundle "gem #{gem_name}"
+ end
+
+ it "does not generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+
+ it "does not add any CI config files into ignore list" do
+ expect(ignore_paths).not_to include(".github/")
+ expect(ignore_paths).not_to include(".gitlab-ci.yml")
+ expect(ignore_paths).not_to include(".circleci/")
+ end
+ end
+
+ context "--ci set to github" do
+ before do
+ bundle "gem #{gem_name} --ci=github"
+ end
+
+ it "generates a GitHub Actions config file" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+
+ it "includes .github/ into ignore list" do
+ expect(ignore_paths).to include(".github/")
+ end
+ end
+
+ context "--ci set to gitlab" do
+ before do
+ bundle "gem #{gem_name} --ci=gitlab"
+ end
+
+ it "generates a GitLab CI config file" do
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+ end
+
+ it "includes .gitlab-ci.yml into ignore list" do
+ expect(ignore_paths).to include(".gitlab-ci.yml")
+ end
+ end
+
+ context "--ci set to circle" do
+ before do
+ bundle "gem #{gem_name} --ci=circle"
+ end
+
+ it "generates a CircleCI config file" do
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
+
+ it "includes .circleci/ into ignore list" do
+ expect(ignore_paths).to include(".circleci/")
+ end
+ end
+
+ context "--ci set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --ci=foo", raise_on_error: false
+ end
+
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--ci' to be one of .*; got foo/)
+ end
+ end
+
+ context "gem.ci setting set to none" do
+ it "doesn't generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+ end
+
+ context "gem.ci setting set to github" do
+ it "generates a GitHub Actions config file" do
+ bundle_config "gem.ci github"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to gitlab" do
+ it "generates a GitLab CI config file" do
+ bundle_config "gem.ci gitlab"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to circle" do
+ it "generates a CircleCI config file" do
+ bundle_config "gem.ci circle"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
+ end
+
+ context "gem.ci set to github and --ci with no arguments" do
+ before do
+ bundle_config "gem.ci github"
+ bundle "gem #{gem_name} --ci"
+ end
+
+ it "generates a GitHub Actions config file" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+
+ it "hints that --ci is already configured" do
+ expect(out).to match("github is already configured, ignoring --ci flag.")
+ end
+ end
+
+ context "gem.ci setting set to false and --ci with no arguments", :readline do
+ before do
+ bundle_config "gem.ci false"
+ bundle "gem #{gem_name} --ci" do |input, _, _|
+ input.puts "github"
end
+ end
+
+ it "asks to setup CI" do
+ expect(out).to match("Do you want to set up continuous integration for your gem?")
+ end
+
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
+ end
- it "builds spec skeleton" do
- expect(bundled_app("test_gem/.rspec")).to exist
- expect(bundled_app("test_gem/spec/test_gem_spec.rb")).to exist
- expect(bundled_app("test_gem/spec/spec_helper.rb")).to exist
+ context "gem.ci setting not set and --ci with no arguments", :readline do
+ before do
+ bundle_config_global "BUNDLE_GEM__CI" => nil
+ bundle "gem #{gem_name} --ci" do |input, _, _|
+ input.puts "github"
end
end
- context "gem.test setting set to rspec and --test is set to minitest" do
- before do
- reset!
- in_app_root
- bundle "config gem.test rspec"
- bundle "gem #{gem_name} --test=minitest"
+ it "asks to setup CI" do
+ expect(out).to match("Do you want to set up continuous integration for your gem?")
+ end
+
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.ci`."
+ expect(out).to match(hint)
+ end
+ end
+
+ context "gem.ci setting set to a CI service and --no-ci" do
+ before do
+ bundle_config "gem.ci github"
+ bundle "gem #{gem_name} --no-ci"
+ end
+
+ it "does not generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+ end
+
+ context "--linter with no argument" do
+ before do
+ bundle "gem #{gem_name}"
+ end
+
+ it "does not generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
+
+ context "--linter set to rubocop" do
+ before do
+ bundle "gem #{gem_name} --linter=rubocop"
+ end
+
+ it "generates a RuboCop config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
+
+ context "--linter set to standard" do
+ before do
+ bundle "gem #{gem_name} --linter=standard"
+ end
+
+ it "generates a Standard config" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
+
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ end
+ end
+
+ context "--linter set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --linter=foo", raise_on_error: false
+ end
+
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--linter' to be one of .*; got foo/)
+ end
+ end
+
+ context "gem.linter setting set to none" do
+ before do
+ bundle "gem #{gem_name}"
+ end
+
+ it "doesn't generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
+
+ context "gem.linter setting set to rubocop" do
+ before do
+ bundle_config "gem.linter rubocop"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a RuboCop config file" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
+ end
+
+ context "gem.linter setting set to standard" do
+ before do
+ bundle_config "gem.linter standard"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a Standard config file" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ end
+
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ end
+ end
+
+ context "gem.linter set to rubocop and --linter with no arguments" do
+ before do
+ bundle_config "gem.linter rubocop"
+ bundle "gem #{gem_name} --linter"
+ end
+
+ it "generates a RuboCop config file" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
+
+ it "hints that --linter is already configured" do
+ expect(out).to match("rubocop is already configured, ignoring --linter flag.")
+ end
+ end
+
+ context "gem.linter setting set to false and --linter with no arguments", :readline do
+ before do
+ bundle_config "gem.linter false"
+ bundle "gem #{gem_name} --linter" do |input, _, _|
+ input.puts "rubocop"
end
+ end
- it "builds spec skeleton" do
- expect(bundled_app("test_gem/test/test_gem_test.rb")).to exist
- expect(bundled_app("test_gem/test/test_helper.rb")).to exist
+ it "asks to setup a linter" do
+ expect(out).to match("Do you want to add a code linter and formatter to your gem?")
+ end
+
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
+ end
+
+ context "gem.linter setting not set and --linter with no arguments", :readline do
+ before do
+ bundle_config_global "BUNDLE_GEM__LINTER" => nil
+ bundle "gem #{gem_name} --linter" do |input, _, _|
+ input.puts "rubocop"
end
end
- context "--test parameter set to minitest" do
+ it "asks to setup a linter" do
+ expect(out).to match("Do you want to add a code linter and formatter to your gem?")
+ end
+
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.linter`."
+ expect(out).to match(hint)
+ end
+ end
+
+ context "gem.linter setting set to a linter and --no-linter" do
+ before do
+ bundle_config "gem.linter rubocop"
+ bundle "gem #{gem_name} --no-linter"
+ end
+
+ it "does not generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
+
+ context "--edit option" do
+ it "opens the generated gemspec in the user's text editor" do
+ output = bundle "gem #{gem_name} --edit=echo"
+ gemspec_path = File.join(bundled_app, gem_name, "#{gem_name}.gemspec")
+ expect(output).to include("echo \"#{gemspec_path}\"")
+ end
+ end
+
+ shared_examples_for "paths that depend on gem name" do
+ it "generates entrypoint, version file and signatures file at the proper path, with the proper content" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require_relative "#{require_relative_path}/version"})
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/class Error < StandardError; end$/)
+
+ expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist
+ expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs")).to exist
+ end
+
+ context "--exe parameter set" do
before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test=minitest"
+ bundle "gem #{gem_name} --exe"
end
- it "depends on a specific version of minitest", :rubygems => ">= 1.8.1" do
- remove_push_guard(gem_name)
- rspec_dep = generated_gem.gemspec.development_dependencies.find {|d| d.name == "minitest" }
- expect(rspec_dep).to be_specific
+ it "builds an exe file that requires the proper entrypoint" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
end
+ end
- it "builds spec skeleton" do
- expect(bundled_app("test_gem/test/test_gem_test.rb")).to exist
- expect(bundled_app("test_gem/test/test_helper.rb")).to exist
+ context "--bin parameter set" do
+ before do
+ bundle "gem #{gem_name} --bin"
end
- it "requires 'test-gem'" do
- expect(bundled_app("test_gem/test/test_helper.rb").read).to include(%(require "test_gem"))
+ it "builds an exe file that requires the proper entrypoint" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
end
+ end
- it "requires 'minitest_helper'" do
- expect(bundled_app("test_gem/test/test_gem_test.rb").read).to include(%(require "test_helper"))
+ context "--test parameter set to rspec" do
+ before do
+ bundle "gem #{gem_name} --test=rspec"
end
- it "creates a default test which fails" do
- expect(bundled_app("test_gem/test/test_gem_test.rb").read).to include("assert false")
+ it "builds a spec helper that requires the proper entrypoint, and a default test in the proper path which fails" do
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb").read).to include(%(require "#{require_path}"))
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb").read).to include("expect(false).to eq(true)")
end
end
- context "gem.test setting set to minitest" do
+ context "--test parameter set to minitest" do
before do
- reset!
- in_app_root
- bundle "config gem.test minitest"
- bundle "gem #{gem_name}"
+ bundle "gem #{gem_name} --test=minitest"
end
- it "creates a default rake task to run the test suite" do
- rakefile = strip_whitespace <<-RAKEFILE
- require "bundler/gem_tasks"
- require "rake/testtask"
+ it "builds a test helper that requires the proper entrypoint, and default test file in the proper path that defines the proper test class name, requires helper, and fails" do
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
- Rake::TestTask.new(:test) do |t|
- t.libs << "test"
- t.libs << "lib"
- t.test_files = FileList["test/**/*_test.rb"]
- end
-
- task :default => :test
- RAKEFILE
-
- expect(bundled_app("test_gem/Rakefile").read).to eq(rakefile)
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(minitest_test_class_name)
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(%(require "test_helper"))
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include("assert false")
end
end
- context "--test with no arguments" do
+ context "--test parameter set to test-unit" do
before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test"
+ bundle "gem #{gem_name} --test=test-unit"
end
- it "defaults to rspec" do
- expect(bundled_app("test_gem/spec/spec_helper.rb")).to exist
- expect(bundled_app("test_gem/test/minitest_helper.rb")).to_not exist
+ it "builds a test helper that requires the proper entrypoint, and default test file in the proper path which requires helper and fails" do
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper"))
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include("assert_equal(\"expected\", \"actual\")")
end
+ end
+ end
- it "creates a .travis.yml file to test the library against the current Ruby version on Travis CI" do
- expect(bundled_app("test_gem/.travis.yml").read).to match(/- #{RUBY_VERSION}/)
- end
+ context "with mit option in bundle config settings set to true" do
+ before do
+ bundle_config_global "gem.mit true"
end
+ it_behaves_like "--mit flag"
+ it_behaves_like "--no-mit flag"
+ end
- context "--edit option" do
- it "opens the generated gemspec in the user's text editor" do
- reset!
- in_app_root
- output = bundle "gem #{gem_name} --edit=echo"
- gemspec_path = File.join(Dir.pwd, gem_name, "#{gem_name}.gemspec")
- expect(output).to include("echo \"#{gemspec_path}\"")
- end
+ context "with mit option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.mit false"
end
+ it_behaves_like "--mit flag"
+ it_behaves_like "--no-mit flag"
end
- context "testing --mit and --coc options against bundle config settings" do
- let(:gem_name) { "test-gem" }
+ context "with coc option in bundle config settings set to true" do
+ before do
+ bundle_config_global "gem.coc true"
+ end
+ it_behaves_like "--coc flag"
+ it_behaves_like "--no-coc flag"
+ end
- context "with mit option in bundle config settings set to true" do
- before do
- global_config "BUNDLE_GEM__MIT" => "true", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
- end
- after { reset! }
- it_behaves_like "--mit flag"
- it_behaves_like "--no-mit flag"
+ context "with coc option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.coc false"
end
+ it_behaves_like "--coc flag"
+ it_behaves_like "--no-coc flag"
+ end
- context "with mit option in bundle config settings set to false" do
- it_behaves_like "--mit flag"
- it_behaves_like "--no-mit flag"
+ context "with rubocop option in bundle config settings set to true" do
+ before do
+ bundle_config_global "gem.rubocop true"
end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--no-linter flag"
+ end
- context "with coc option in bundle config settings set to true" do
- before do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "true"
- end
- after { reset! }
- it_behaves_like "--coc flag"
- it_behaves_like "--no-coc flag"
+ context "with rubocop option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.rubocop false"
end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--no-linter flag"
+ end
- context "with coc option in bundle config settings set to false" do
- it_behaves_like "--coc flag"
- it_behaves_like "--no-coc flag"
+ context "with linter option in bundle config settings set to rubocop" do
+ before do
+ bundle_config_global "gem.linter rubocop"
end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--no-linter flag"
end
- context "gem naming with dashed" do
- let(:gem_name) { "test-gem" }
+ context "with linter option in bundle config settings set to standard" do
+ before do
+ bundle_config_global "gem.linter standard"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--no-linter flag"
+ end
+ context "with linter option in bundle config settings set to false" do
before do
- execute_bundle_gem(gem_name)
+ bundle_config_global "gem.linter false"
end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--no-linter flag"
+ end
- let(:generated_gem) { Bundler::GemHelper.new(bundled_app(gem_name).to_s) }
+ context "with changelog option in bundle config settings set to true" do
+ before do
+ bundle_config_global "gem.changelog true"
+ end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
- it "generates a gem skeleton" do
- expect(bundled_app("test-gem/test-gem.gemspec")).to exist
- expect(bundled_app("test-gem/Gemfile")).to exist
- expect(bundled_app("test-gem/Rakefile")).to exist
- expect(bundled_app("test-gem/lib/test/gem.rb")).to exist
- expect(bundled_app("test-gem/lib/test/gem/version.rb")).to exist
+ context "with changelog option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.changelog false"
end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
- it "starts with version 0.1.0" do
- expect(bundled_app("test-gem/lib/test/gem/version.rb").read).to match(/VERSION = "0.1.0"/)
+ context "with bundle option in bundle config settings set to true" do
+ before do
+ bundle_config_global "gem.bundle true"
end
+ it_behaves_like "--bundle flag"
+ it_behaves_like "--no-bundle flag"
- it "nests constants so they work" do
- expect(bundled_app("test-gem/lib/test/gem/version.rb").read).to match(/module Test\n module Gem/)
- expect(bundled_app("test-gem/lib/test/gem.rb").read).to match(/module Test\n module Gem/)
+ it "runs bundle install" do
+ bundle "gem #{gem_name}"
+ expect(out).to include("Running bundle install in the new gem directory.")
+ end
+ end
+
+ context "with bundle option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.bundle false"
end
+ it_behaves_like "--bundle flag"
+ it_behaves_like "--no-bundle flag"
- it_should_behave_like "git config is present"
+ it "does not run bundle install" do
+ bundle "gem #{gem_name}"
+ expect(out).to_not include("Running bundle install in the new gem directory.")
+ end
+ end
- context "git config user.{name,email} is not set" do
+ context "without git config github.user set" do
+ before do
+ git("config --global --unset github.user")
+ end
+ context "with github-username option in bundle config settings set to some value" do
before do
- `git config --unset user.name`
- `git config --unset user.email`
- reset!
- in_app_root
- bundle "gem #{gem_name}"
- remove_push_guard(gem_name)
+ bundle_config_global "gem.github_username different_username"
end
-
- it_should_behave_like "git config is absent"
+ it_behaves_like "--github-username option", "gh_user"
end
- it "requires the version file" do
- expect(bundled_app("test-gem/lib/test/gem.rb").read).to match(%r{require "test/gem/version"})
+ it_behaves_like "github_username configuration"
+
+ context "with github-username option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.github_username false"
+ end
+ it_behaves_like "--github-username option", "gh_user"
end
- it "runs rake without problems" do
- system_gems ["rake-10.0.2"]
+ context "when changelog is enabled" do
+ it "sets gemspec changelog_uri, homepage, homepage_uri, source_code_uri to TODOs" do
+ bundle "gem #{gem_name} --changelog"
- rakefile = strip_whitespace <<-RAKEFILE
- task :default do
- puts 'SUCCESS'
- end
- RAKEFILE
- File.open(bundled_app("test-gem/Rakefile"), "w") do |file|
- file.puts rakefile
+ expect(generated_gemspec.metadata["changelog_uri"]).
+ to eq("TODO: Put your gem's CHANGELOG.md URL here.")
+ expect(generated_gemspec.homepage).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("TODO: Put your gem's public repo URL here.")
end
+ end
- Dir.chdir(bundled_app(gem_name)) do
- sys_exec(rake)
- expect(out).to include("SUCCESS")
+ context "when changelog is not enabled" do
+ it "sets gemspec homepage, homepage_uri, source_code_uri to TODOs and changelog_uri to nil" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).to be_nil
+ expect(generated_gemspec.homepage).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("TODO: Put your gem's public repo URL here.")
end
end
+ end
- context "--bin parameter set" do
+ context "with git config github.user set" do
+ context "with github-username option in bundle config settings set to some value" do
before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --bin"
+ bundle_config_global "gem.github_username different_username"
end
+ it_behaves_like "--github-username option", "gh_user"
+ end
- it "builds bin skeleton" do
- expect(bundled_app("test-gem/exe/test-gem")).to exist
+ it_behaves_like "github_username configuration"
+
+ context "with github-username option in bundle config settings set to false" do
+ before do
+ bundle_config_global "gem.github_username false"
end
+ it_behaves_like "--github-username option", "gh_user"
+ end
- it "requires 'test/gem'" do
- expect(bundled_app("test-gem/exe/test-gem").read).to match(%r{require "test/gem"})
+ context "when changelog is enabled" do
+ it "sets gemspec changelog_uri, homepage, homepage_uri, source_code_uri based on git username" do
+ bundle "gem #{gem_name} --changelog"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).
+ to eq("https://github.com/bundleuser/#{gem_name}/blob/main/CHANGELOG.md")
+ expect(generated_gemspec.homepage).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
end
end
- context "no --test parameter" do
- before do
- reset!
- in_app_root
+ context "when changelog is not enabled" do
+ it "sets gemspec source_code_uri, homepage, homepage_uri but not changelog_uri" do
bundle "gem #{gem_name}"
- end
- it "doesn't create any spec/test file" do
- expect(bundled_app("test-gem/.rspec")).to_not exist
- expect(bundled_app("test-gem/spec/test/gem_spec.rb")).to_not exist
- expect(bundled_app("test-gem/spec/spec_helper.rb")).to_not exist
- expect(bundled_app("test-gem/test/test_test/gem.rb")).to_not exist
- expect(bundled_app("test-gem/test/minitest_helper.rb")).to_not exist
+ expect(generated_gemspec.metadata["changelog_uri"]).to be_nil
+ expect(generated_gemspec.homepage).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
end
end
+ end
+
+ context "standard gem naming" do
+ let(:require_path) { gem_name }
+
+ let(:require_relative_path) { gem_name }
+
+ let(:minitest_test_file_path) { "test/test_#{gem_name}.rb" }
+
+ let(:minitest_test_class_name) { "class TestMygem < Minitest::Test" }
+
+ include_examples "paths that depend on gem name"
+ end
+
+ context "gem naming with underscore" do
+ let(:gem_name) { "test_gem" }
+
+ let(:require_path) { "test_gem" }
+
+ let(:require_relative_path) { "test_gem" }
+
+ let(:minitest_test_file_path) { "test/test_test_gem.rb" }
+
+ let(:minitest_test_class_name) { "class TestTestGem < Minitest::Test" }
+
+ let(:flags) { nil }
+
+ it "does not nest constants" do
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module TestGem/)
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module TestGem/)
+ end
+
+ include_examples "paths that depend on gem name"
+
+ context "--ext parameter set with C" do
+ let(:flags) { "--ext=c" }
- context "--test parameter set to rspec" do
before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test=rspec"
+ bundle ["gem", gem_name, flags].compact.join(" ")
end
- it "builds spec skeleton" do
- expect(bundled_app("test-gem/.rspec")).to exist
- expect(bundled_app("test-gem/spec/test/gem_spec.rb")).to exist
- expect(bundled_app("test-gem/spec/spec_helper.rb")).to exist
+ it "builds ext skeleton" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
end
- it "requires 'test/gem'" do
- expect(bundled_app("test-gem/spec/spec_helper.rb").read).to include(%(require "test/gem"))
+ it "generates native extension loading code" do
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}.rb").read).to include(<<~RUBY)
+ require_relative "test_gem/version"
+ require "#{gem_name}/#{gem_name}"
+ RUBY
end
- it "creates a default test which fails" do
- expect(bundled_app("test-gem/spec/test/gem_spec.rb").read).to include("expect(false).to eq(true)")
+ it "includes rake-compiler, but no Rust related changes" do
+ expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
+
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.add_dependency "rb_sys"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.required_rubygems_version = ">= ')
end
- it "creates a default rake task to run the specs" do
- rakefile = strip_whitespace <<-RAKEFILE
+ it "depends on compile task for build" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
+
require "bundler/gem_tasks"
- require "rspec/core/rake_task"
+ require "rake/extensiontask"
- RSpec::Core::RakeTask.new(:spec)
+ task build: :compile
- task :default => :spec
+ GEMSPEC = Gem::Specification.load("#{gem_name}.gemspec")
+
+ Rake::ExtensionTask.new("#{gem_name}", GEMSPEC) do |ext|
+ ext.lib_dir = "lib/#{gem_name}"
+ end
+
+ task default: %i[clobber compile]
RAKEFILE
- expect(bundled_app("test-gem/Rakefile").read).to eq(rakefile)
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
end
- context "--test parameter set to minitest" do
+ context "--ext parameter set with rust" do
+ let(:flags) { "--ext=rust" }
+
before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test=minitest"
+ bundle ["gem", gem_name, flags].compact.join(" ")
end
- it "builds spec skeleton" do
- expect(bundled_app("test-gem/test/test/gem_test.rb")).to exist
- expect(bundled_app("test-gem/test/test_helper.rb")).to exist
+ it "is not deprecated" do
+ expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
end
- it "requires 'test/gem'" do
- expect(bundled_app("test-gem/test/test_helper.rb").read).to match(%r{require "test/gem"})
+ it "builds ext skeleton" do
+ expect(bundled_app("#{gem_name}/Cargo.toml")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/Cargo.toml")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/src/lib.rs")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/build.rs")).to exist
end
- it "requires 'test_helper'" do
- expect(bundled_app("test-gem/test/test/gem_test.rb").read).to match(/require "test_helper"/)
+ it "includes rake-compiler and rb_sys gems constraint" do
+ expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "rb_sys"')
end
- it "creates a default test which fails" do
- expect(bundled_app("test-gem/test/test/gem_test.rb").read).to match(/assert false/)
- end
+ it "depends on compile task for build" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
- it "creates a default rake task to run the test suite" do
- rakefile = strip_whitespace <<-RAKEFILE
require "bundler/gem_tasks"
- require "rake/testtask"
+ require "rb_sys/extensiontask"
- Rake::TestTask.new(:test) do |t|
- t.libs << "test"
- t.libs << "lib"
- t.test_files = FileList["test/**/*_test.rb"]
+ task build: :compile
+
+ GEMSPEC = Gem::Specification.load("#{gem_name}.gemspec")
+
+ RbSys::ExtensionTask.new("#{gem_name}", GEMSPEC) do |ext|
+ ext.lib_dir = "lib/#{gem_name}"
end
- task :default => :test
+ task default: :compile
RAKEFILE
- expect(bundled_app("test-gem/Rakefile").read).to eq(rakefile)
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
- end
- context "--test with no arguments" do
- before do
- reset!
- in_app_root
- bundle "gem #{gem_name} --test"
+ it "configures the crate such that `cargo test` works", :ruby_repo, :mri_only do
+ env = setup_rust_env
+ gem_path = bundled_app(gem_name)
+ result = sys_exec("cargo test", env: env, dir: gem_path, timeout: 300)
+
+ expect(result).to include("1 passed")
end
- it "defaults to rspec" do
- expect(bundled_app("test-gem/spec/spec_helper.rb")).to exist
- expect(bundled_app("test-gem/test/minitest_helper.rb")).to_not exist
+ def setup_rust_env
+ skip "rust toolchain of mingw is broken" if RUBY_PLATFORM.match?("mingw")
+
+ env = {
+ "CARGO_HOME" => ENV.fetch("CARGO_HOME", File.join(ENV["HOME"], ".cargo")),
+ "RUSTUP_HOME" => ENV.fetch("RUSTUP_HOME", File.join(ENV["HOME"], ".rustup")),
+ "RUSTUP_TOOLCHAIN" => ENV.fetch("RUSTUP_TOOLCHAIN", "stable"),
+ }
+
+ system(env, "cargo", "-V", out: IO::NULL, err: [:child, :out])
+ skip "cargo not present" unless $?.success?
+ # Hermetic Cargo setup
+ RbConfig::CONFIG.each {|k, v| env["RBCONFIG_#{k}"] = v }
+ env
end
end
- context "--ext parameter set" do
+ context "--ext parameter set with go" do
+ let(:flags) { "--ext=go" }
+
before do
- reset!
- in_app_root
- bundle "gem test_gem --ext"
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
+ after do
+ sys_exec("go clean -modcache", raise_on_error: true) if installed_go?
+ end
+
+ it "is not deprecated" do
+ expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
end
it "builds ext skeleton" do
- expect(bundled_app("test_gem/ext/test_gem/extconf.rb")).to exist
- expect(bundled_app("test_gem/ext/test_gem/test_gem.h")).to exist
- expect(bundled_app("test_gem/ext/test_gem/test_gem.c")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod")).to exist
end
- it "includes rake-compiler" do
- expect(bundled_app("test_gem/test_gem.gemspec").read).to include('spec.add_development_dependency "rake-compiler"')
+ it "includes extconf.rb in gem_name.gemspec" do
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include(%(spec.extensions = ["ext/#{gem_name}/extconf.rb"]))
end
- it "depends on compile task for build" do
- rakefile = strip_whitespace <<-RAKEFILE
- require "bundler/gem_tasks"
- require "rake/extensiontask"
+ it "includes go_gem in gem_name.gemspec" do
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "go_gem", ">= 0.2"')
+ end
- task :build => :compile
+ it "includes go_gem extension in extconf.rb" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).to include(<<~RUBY)
+ require "mkmf"
+ require "go_gem/mkmf"
+ RUBY
- Rake::ExtensionTask.new("test_gem") do |ext|
- ext.lib_dir = "lib/test_gem"
- end
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).to include(%(create_go_makefile("#{gem_name}/#{gem_name}")))
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).not_to include("create_makefile")
+ end
- task :default => [:clobber, :compile, :spec]
- RAKEFILE
+ it "includes go_gem extension in gem_name.c" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c").read).to eq(<<~C)
+ #include "#{gem_name}.h"
+ #include "_cgo_export.h"
+ C
+ end
+
+ it "includes skeleton code in gem_name.go" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ /*
+ #include "#{gem_name}.h"
- expect(bundled_app("test_gem/Rakefile").read).to eq(rakefile)
+ VALUE rb_#{gem_name}_sum(VALUE self, VALUE a, VALUE b);
+ */
+ import "C"
+ GO
+
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ //export rb_#{gem_name}_sum
+ func rb_#{gem_name}_sum(_ C.VALUE, a C.VALUE, b C.VALUE) C.VALUE {
+ GO
+
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ //export Init_#{gem_name}
+ func Init_#{gem_name}() {
+ GO
+ end
+
+ it "includes valid module name in go.mod" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod").read).to include("module github.com/bundleuser/#{gem_name}")
+ end
+
+ it "includes go_gem extension in Rakefile" do
+ expect(bundled_app("#{gem_name}/Rakefile").read).to include(<<~RUBY)
+ require "go_gem/rake_task"
+
+ GoGem::RakeTask.new("#{gem_name}")
+ RUBY
+ end
+
+ context "with --no-ci" do
+ let(:flags) { "--ext=go --no-ci" }
+
+ it_behaves_like "CI config is absent"
+ end
+
+ context "--ci set to github" do
+ let(:flags) { "--ext=go --ci=github" }
+
+ it "generates .github/workflows/main.yml" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml").read).to include("go-version-file: ext/#{gem_name}/go.mod")
+ end
+ end
+
+ context "--ci set to circle" do
+ let(:flags) { "--ext=go --ci=circle" }
+
+ it "generates a .circleci/config.yml" do
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml").read).to include(<<-YAML.strip)
+ environment:
+ GO_VERSION:
+ YAML
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml").read).to include(<<-YAML)
+ - run:
+ name: Install Go
+ command: |
+ wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ tar -C /usr/local -xzf /tmp/go.tar.gz
+ echo 'export PATH=/usr/local/go/bin:"$PATH"' >> "$BASH_ENV"
+ YAML
+ end
end
+
+ context "--ci set to gitlab" do
+ let(:flags) { "--ext=go --ci=gitlab" }
+
+ it "generates a .gitlab-ci.yml" do
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml").read).to include(<<-YAML)
+ - wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ - tar -C /usr/local -xzf /tmp/go.tar.gz
+ - export PATH=/usr/local/go/bin:$PATH
+ YAML
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml").read).to include(<<-YAML.strip)
+ variables:
+ GO_VERSION:
+ YAML
+ end
+ end
+
+ context "without github.user" do
+ before do
+ # FIXME: GitHub Actions Windows Runner hang up here for some reason...
+ skip "Workaround for hung up" if Gem.win_platform?
+
+ git("config --global --unset github.user")
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
+ it "includes valid module name in go.mod" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod").read).to include("module github.com/username/#{gem_name}")
+ end
+ end
+ end
+ end
+
+ context "gem naming with dashed" do
+ let(:gem_name) { "test-gem" }
+
+ let(:require_path) { "test/gem" }
+
+ let(:require_relative_path) { "gem" }
+
+ let(:minitest_test_file_path) { "test/test/test_gem.rb" }
+
+ let(:minitest_test_class_name) { "class Test::TestGem < Minitest::Test" }
+
+ it "nests constants so they work" do
+ bundle "gem #{gem_name}"
+ expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module Test\n module Gem/)
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module Test\n module Gem/)
end
+
+ include_examples "paths that depend on gem name"
end
describe "uncommon gem names" do
it "can deal with two dashes" do
bundle "gem a--a"
- Bundler.clear_gemspec_cache
expect(bundled_app("a--a/a--a.gemspec")).to exist
end
it "fails gracefully with a ." do
- bundle "gem foo.gemspec"
- expect(last_command.bundler_err).to end_with("Invalid gem name foo.gemspec -- `Foo.gemspec` is an invalid constant name")
+ bundle "gem foo.gemspec", raise_on_error: false
+ expect(err).to end_with("Invalid gem name foo.gemspec -- `Foo.gemspec` is an invalid constant name")
end
it "fails gracefully with a ^" do
- bundle "gem ^"
- expect(last_command.bundler_err).to end_with("Invalid gem name ^ -- `^` is an invalid constant name")
+ bundle "gem ^", raise_on_error: false
+ expect(err).to end_with("Invalid gem name ^ -- `^` is an invalid constant name")
end
it "fails gracefully with a space" do
- bundle "gem 'foo bar'"
- expect(last_command.bundler_err).to end_with("Invalid gem name foo bar -- `Foo bar` is an invalid constant name")
+ bundle "gem 'foo bar'", raise_on_error: false
+ expect(err).to end_with("Invalid gem name foo bar -- `Foo bar` is an invalid constant name")
end
it "fails gracefully when multiple names are passed" do
- bundle "gem foo bar baz"
- expect(last_command.bundler_err).to eq(<<-E.strip)
+ bundle "gem foo bar baz", raise_on_error: false
+ expect(err).to eq(<<-E.strip)
ERROR: "bundle gem" was called with arguments ["foo", "bar", "baz"]
Usage: "bundle gem NAME [OPTIONS]"
E
@@ -812,100 +2012,127 @@ Usage: "bundle gem NAME [OPTIONS]"
describe "#ensure_safe_gem_name" do
before do
- bundle "gem #{subject}"
- end
- after do
- Bundler.clear_gemspec_cache
+ bundle "gem #{subject}", raise_on_error: false
end
context "with an existing const name" do
subject { "gem" }
- it { expect(out).to include("Invalid gem name #{subject}") }
+ it { expect(err).to include("Invalid gem name #{subject}") }
end
context "with an existing hyphenated const name" do
subject { "gem-specification" }
- it { expect(out).to include("Invalid gem name #{subject}") }
+ it { expect(err).to include("Invalid gem name #{subject}") }
+ end
+
+ context "starting with a number" do
+ subject { "1gem" }
+ it { expect(err).to include("Invalid gem name #{subject}") }
+ end
+
+ context "including capital letter" do
+ subject { "CAPITAL" }
+ it "should warn but not error" do
+ expect(err).to include("Gem names with capital letters are not recommended")
+ expect(bundled_app("#{subject}/#{subject}.gemspec")).to exist
+ end
end
context "starting with an existing const name" do
subject { "gem-somenewconstantname" }
- it { expect(out).not_to include("Invalid gem name #{subject}") }
+ it { expect(err).not_to include("Invalid gem name #{subject}") }
end
context "ending with an existing const name" do
subject { "somenewconstantname-gem" }
- it { expect(out).not_to include("Invalid gem name #{subject}") }
+ it { expect(err).not_to include("Invalid gem name #{subject}") }
end
end
- context "on first run" do
- before do
- in_app_root
- end
-
+ context "on first run", :readline do
it "asks about test framework" do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false"
+ bundle_config_global "BUNDLE_GEM__TEST" => nil
bundle "gem foobar" do |input, _, _|
input.puts "rspec"
end
expect(bundled_app("foobar/spec/spec_helper.rb")).to exist
- rakefile = strip_whitespace <<-RAKEFILE
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
+
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
- task :default => :spec
+ task default: :spec
RAKEFILE
expect(bundled_app("foobar/Rakefile").read).to eq(rakefile)
- expect(bundled_app("foobar/foobar.gemspec").read).to include('spec.add_development_dependency "rspec"')
+ expect(bundled_app("foobar/Gemfile").read).to include('gem "rspec"')
+ end
+
+ it "asks about CI service" do
+ bundle_config_global "BUNDLE_GEM__CI" => nil
+
+ bundle "gem foobar" do |input, _, _|
+ input.puts "github"
+ end
+
+ expect(bundled_app("foobar/.github/workflows/main.yml")).to exist
end
- it "asks about MIT license" do
- global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ it "asks about MIT license just once" do
+ bundle_config_global "BUNDLE_GEM__MIT" => nil
- bundle :config
+ bundle "config list"
bundle "gem foobar" do |input, _, _|
input.puts "yes"
end
expect(bundled_app("foobar/LICENSE.txt")).to exist
+ expect(out).to include("Using a MIT license means").once
end
- it "asks about CoC" do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false"
+ it "asks about CoC just once" do
+ bundle_config_global "BUNDLE_GEM__COC" => nil
bundle "gem foobar" do |input, _, _|
input.puts "yes"
end
expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist
+ expect(out).to include("Codes of conduct can increase contributions to your project").once
+ end
+
+ it "asks about CHANGELOG just once" do
+ bundle_config_global "BUNDLE_GEM__CHANGELOG" => nil
+
+ bundle "gem foobar" do |input, _, _|
+ input.puts "yes"
+ end
+
+ expect(bundled_app("foobar/CHANGELOG.md")).to exist
+ expect(out).to include("A changelog is a file which contains").once
end
end
context "on conflicts with a previously created file" do
it "should fail gracefully" do
- in_app_root do
- FileUtils.touch("conflict-foobar")
- end
- bundle "gem conflict-foobar"
- expect(last_command.bundler_err).to include("Errno::ENOTDIR")
- expect(exitstatus).to eql(32) if exitstatus
+ FileUtils.touch(bundled_app("conflict-foobar"))
+ bundle "gem conflict-foobar", raise_on_error: false
+ expect(err).to eq("Couldn't create a new gem named `conflict-foobar` because there's an existing file named `conflict-foobar`.")
+ expect(exitstatus).to eql(32)
end
end
context "on conflicts with a previously created directory" do
it "should succeed" do
- in_app_root do
- FileUtils.mkdir_p("conflict-foobar/Gemfile")
- end
- bundle! "gem conflict-foobar"
- expect(last_command.stdout).to include("file_clash conflict-foobar/Gemfile").
+ FileUtils.mkdir_p(bundled_app("conflict-foobar/Gemfile"))
+ bundle "gem conflict-foobar"
+ expect(out).to include("file_clash conflict-foobar/Gemfile").
and include "Initializing git repo in #{bundled_app("conflict-foobar")}"
end
end
diff --git a/spec/bundler/commands/open_spec.rb b/spec/bundler/commands/open_spec.rb
index 5cab846fb5..664dc58919 100644
--- a/spec/bundler/commands/open_spec.rb
+++ b/spec/bundler/commands/open_spec.rb
@@ -1,92 +1,175 @@
# frozen_string_literal: true
RSpec.describe "bundle open" do
- before :each do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
- G
- end
+ context "when opening a regular gem" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ G
+ end
- it "opens the gem with BUNDLER_EDITOR as highest priority" do
- bundle "open rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
- expect(out).to include("bundler_editor #{default_bundle_path("gems", "rails-2.3.2")}")
- end
+ it "opens the gem with BUNDLER_EDITOR as highest priority" do
+ bundle "open rails", env: { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ expect(out).to include("bundler_editor #{default_bundle_path("gems", "rails-2.3.2")}")
+ end
- it "opens the gem with VISUAL as 2nd highest priority" do
- bundle "open rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "" }
- expect(out).to include("visual #{default_bundle_path("gems", "rails-2.3.2")}")
- end
+ it "opens the gem with VISUAL as 2nd highest priority" do
+ bundle "open rails", env: { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("visual #{default_bundle_path("gems", "rails-2.3.2")}")
+ end
- it "opens the gem with EDITOR as 3rd highest priority" do
- bundle "open rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to include("editor #{default_bundle_path("gems", "rails-2.3.2")}")
- end
+ it "opens the gem with EDITOR as 3rd highest priority" do
+ bundle "open rails", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "rails-2.3.2")}")
+ end
- it "complains if no EDITOR is set" do
- bundle "open rails", :env => { "EDITOR" => "", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to eq("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR")
- end
+ it "complains if no EDITOR is set" do
+ bundle "open rails", env: { "EDITOR" => "", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to eq("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR")
+ end
- it "complains if gem not in bundle" do
- bundle "open missing", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to match(/could not find gem 'missing'/i)
- end
+ it "complains if gem not in bundle" do
+ bundle "open missing", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(err).to match(/could not find gem 'missing'/i)
+ end
- it "does not blow up if the gem to open does not have a Gemfile" do
- git = build_git "foo"
- ref = git.ref_for("master", 11)
+ it "does not blow up if the gem to open does not have a Gemfile" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'foo', :git => "#{lib_path("foo-1.0")}"
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
+ G
- bundle "open foo", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to match("editor #{default_bundle_path.join("bundler/gems/foo-1.0-#{ref}")}")
- end
+ bundle "open foo", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("bundler", "gems", "foo-1.0-#{ref}")}")
+ end
- it "suggests alternatives for similar-sounding gems" do
- bundle "open Rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to match(/did you mean rails\?/i)
- end
+ it "suggests alternatives for similar-sounding gems" do
+ bundle "open Rails", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(err).to match(/did you mean 'rails'\?/i)
+ end
- it "opens the gem with short words" do
- bundle "open rec", :env => { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ it "opens the gem with short words" do
+ bundle "open rec", env: { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
- expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}")
- end
+ expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}")
+ end
- it "select the gem from many match gems" do
- env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
- bundle "open active", :env => env do |input, _, _|
- input.puts "2"
+ it "opens subpath of the gem" do
+ bundle "open activerecord --path lib/activerecord", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/activerecord")
end
- expect(out).to match(/bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}\z/)
- end
+ it "opens subpath file of the gem" do
+ bundle "open activerecord --path lib/version.rb", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/version.rb")
+ end
- it "allows selecting exit from many match gems" do
- env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
- bundle! "open active", :env => env do |input, _, _|
- input.puts "0"
+ it "opens deep subpath of the gem" do
+ bundle "open activerecord --path lib/active_record", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/active_record")
+ end
+
+ it "requires value for --path arg" do
+ bundle "open activerecord --path", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(err).to eq "Cannot specify `--path` option without a value"
end
- end
- it "performs an automatic bundle install" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
- gem "foo"
- G
+ it "suggests alternatives for similar-sounding gems when using subpath" do
+ bundle "open Rails --path README.md", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(err).to match(/did you mean 'rails'\?/i)
+ end
+
+ it "suggests alternatives for similar-sounding gems when using deep subpath" do
+ bundle "open Rails --path some/path/here", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(err).to match(/did you mean 'rails'\?/i)
+ end
- bundle "config auto_install 1"
- bundle "open rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to include("Installing foo 1.0")
+ it "opens subpath of the short worded gem" do
+ bundle "open rec --path CHANGELOG.md", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/CHANGELOG.md")
+ end
+
+ it "opens deep subpath of the short worded gem" do
+ bundle "open rec --path lib/activerecord", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/activerecord")
+ end
+
+ it "opens subpath of the selected matching gem", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active --path CHANGELOG.md", env: env do |input, _, _|
+ input.puts "2"
+ end
+
+ expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2").join("CHANGELOG.md")}")
+ end
+
+ it "opens deep subpath of the selected matching gem", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active --path lib/activerecord/version.rb", env: env do |input, _, _|
+ input.puts "2"
+ end
+
+ expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2").join("lib", "activerecord", "version.rb")}")
+ end
+
+ it "select the gem from many match gems", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active", env: env do |input, _, _|
+ input.puts "2"
+ end
+
+ expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}")
+ end
+
+ it "allows selecting exit from many match gems", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active", env: env do |input, _, _|
+ input.puts "0"
+ end
+ end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ gem "foo"
+ G
+
+ bundle_config "auto_install 1"
+ bundle "open rails", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("Installing foo 1.0")
+ end
+
+ it "opens the editor with a clean env" do
+ bundle "open", env: { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
+ expect(out).not_to include("BUNDLE_GEMFILE=")
+ end
end
- it "opens the editor with a clean env" do
- bundle "open", :env => { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).not_to include("BUNDLE_GEMFILE=")
+ context "when opening a default gem" do
+ let(:default_gems) do
+ ruby(<<-RUBY).split("\n")
+ if Gem::Specification.is_a?(Enumerable)
+ puts Gem::Specification.select(&:default_gem?).map(&:name)
+ end
+ RUBY
+ end
+
+ before do
+ skip "No default gems available on this test run" if default_gems.empty?
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+ end
+
+ it "throws proper error when trying to open default gem" do
+ bundle "open json", env: { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ expect(out).to include("Unable to open json because it's a default gem, so the directory it would normally be installed to does not exist.")
+ end
end
end
diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb
index c9d3ac1de4..28ed51d61e 100644
--- a/spec/bundler/commands/outdated_spec.rb
+++ b/spec/bundler/commands/outdated_spec.rb
@@ -1,63 +1,85 @@
# frozen_string_literal: true
RSpec.describe "bundle outdated" do
- before :each do
- build_repo2 do
- build_git "foo", :path => lib_path("foo")
- build_git "zebra", :path => lib_path("zebra")
- end
-
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "zebra", :git => "#{lib_path("zebra")}"
- gem "foo", :git => "#{lib_path("foo")}"
- gem "activesupport", "2.3.5"
- gem "weakling", "~> 0.0.1"
- gem "duradura", '7.0'
- gem "terranova", '8'
- G
- end
-
describe "with no arguments" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "returns a sorted list of outdated gems" do
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "weakling", "0.2"
- update_git "foo", :path => lib_path("foo")
- update_git "zebra", :path => lib_path("zebra")
+ update_git "foo", path: lib_path("foo")
+ update_git "zebra", path: lib_path("zebra")
end
- bundle "outdated"
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ weakling 0.0.3 0.2 ~> 0.0.1 default
+ zebra 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ end
+
+ it "excludes header row from the sorting" do
+ update_repo2 do
+ build_gem "AAA", %w[1.0.0 2.0.0]
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "AAA", "1.0.0"
+ G
+
+ bundle "outdated", raise_on_error: false
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)")
- expect(out).to include("foo (newest 1.0")
+ expected_output = <<~TABLE
+ Gem Current Latest Requested Groups Release Date
+ AAA 1.0.0 2.0.0 = 1.0.0 default
+ TABLE
- # Gem names are one per-line, between "*" and their parenthesized version.
- gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact
- expect(gem_list).to eq(gem_list.sort)
+ expect(out).to include(expected_output.strip)
end
it "returns non zero exit status if outdated gems present" do
update_repo2 do
build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
+ update_git "foo", path: lib_path("foo")
end
- bundle "outdated"
+ bundle "outdated", raise_on_error: false
- expect(exitstatus).to_not be_zero if exitstatus
+ expect(exitstatus).to_not be_zero
end
it "returns success exit status if no outdated gems present" do
bundle "outdated"
-
- expect(exitstatus).to be_zero if exitstatus
end
it "adds gem group to dependency output when repo is updated" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
+
+ gem "terranova", '8'
group :development, :test do
gem 'activesupport', '2.3.5'
@@ -65,16 +87,79 @@ RSpec.describe "bundle outdated" do
G
update_repo2 { build_gem "activesupport", "3.0" }
+ update_repo2 { build_gem "terranova", "9" }
+
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ terranova 8 9 = 8 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with --verbose option" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
+ it "shows the location of the latest version's gemspec if installed" do
+ bundle_config "clean false"
+
+ update_repo2 { build_gem "activesupport", "3.0" }
+ update_repo2 { build_gem "terranova", "9" }
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "terranova", '9'
+ gem 'activesupport', '2.3.5'
+ G
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "terranova", '8'
+ gem 'activesupport', '2.3.5'
+ G
+
+ bundle "outdated --verbose", raise_on_error: false
- bundle "outdated --verbose"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5) in groups \"development, test\"")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date Path
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ terranova 8 9 = 8 default #{default_bundle_path("specifications/terranova-9.gemspec")}
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
describe "with --group option" do
- def test_group_option(group = nil, gems_list_size = 1)
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
@@ -83,80 +168,112 @@ RSpec.describe "bundle outdated" do
gem 'activesupport', '2.3.5'
end
G
+ end
+ def test_group_option(group)
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "terranova", "9"
build_gem "duradura", "8.0"
end
- bundle "outdated --group #{group}"
-
- # Gem names are one per-line, between "*" and their parenthesized version.
- gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact
- expect(gem_list).to eq(gem_list.sort)
- expect(gem_list.size).to eq gems_list_size
+ bundle "outdated --group #{group}", raise_on_error: false
end
- it "not outdated gems" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
-
- gem "weakling", "~> 0.0.1"
- gem "terranova", '8'
- group :development, :test do
- gem 'activesupport', '2.3.5'
- gem "duradura", '7.0'
- end
- G
-
+ it "works when the bundle is up to date" do
bundle "outdated --group"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
+ end
+
+ it "works when only out of date gems are not in given group" do
+ update_repo2 do
+ build_gem "terranova", "9"
+ end
+ bundle "outdated --group development"
+ expect(out).to end_with("Bundle up to date!")
end
it "returns a sorted list of outdated gems from one group => 'default'" do
test_group_option("default")
- expect(out).to include("===== Group default =====")
- expect(out).to include("terranova (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ terranova 8 9 = 8 default
+ TABLE
- expect(out).not_to include("===== Group development, test =====")
- expect(out).not_to include("activesupport")
- expect(out).not_to include("duradura")
+ expect(out).to end_with(expected_output)
end
it "returns a sorted list of outdated gems from one group => 'development'" do
- test_group_option("development", 2)
+ test_group_option("development")
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+
+ it "returns a sorted list of outdated gems from one group => 'test'" do
+ test_group_option("test")
- expect(out).not_to include("===== Group default =====")
- expect(out).not_to include("terranova (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ TABLE
- expect(out).to include("===== Group development, test =====")
- expect(out).to include("activesupport")
- expect(out).to include("duradura")
+ expect(out).to end_with(expected_output)
end
end
- describe "with --groups option" do
- it "not outdated gems" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ describe "with --groups option and outdated transitive dependencies" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
- gem "weakling", "~> 0.0.1"
- gem "terranova", '8'
- group :development, :test do
- gem 'activesupport', '2.3.5'
- gem "duradura", '7.0'
+ build_gem "bar", %w[2.0.0]
+
+ build_gem "bar_dependant", "7.0" do |s|
+ s.add_dependency "bar", "~> 2.0"
end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "bar_dependant", '7.0'
G
- bundle "outdated --groups"
- expect(out).to include("Bundle up to date!")
+ update_repo2 do
+ build_gem "bar", %w[3.0.0]
+ end
end
- it "returns a sorted list of outdated gems by groups" do
+ it "returns a sorted list of outdated gems" do
+ bundle "outdated --groups", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ bar 2.0.0 3.0.0
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with --groups option" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
@@ -165,46 +282,76 @@ RSpec.describe "bundle outdated" do
gem "duradura", '7.0'
end
G
+ end
+
+ it "not outdated gems" do
+ bundle "outdated --groups"
+ expect(out).to end_with("Bundle up to date!")
+ end
+ it "returns a sorted list of outdated gems by groups" do
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "terranova", "9"
build_gem "duradura", "8.0"
end
- bundle "outdated --groups"
- expect(out).to include("===== Group default =====")
- expect(out).to include("terranova (newest 9, installed 8, requested = 8)")
- expect(out).to include("===== Group development, test =====")
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("duradura (newest 8.0, installed 7.0, requested = 7.0)")
+ bundle "outdated --groups", raise_on_error: false
- expect(out).not_to include("weakling (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ terranova 8 9 = 8 default
+ TABLE
- # TODO: check gems order inside the group
+ expect(out).to end_with(expected_output)
end
end
describe "with --local option" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "weakling", "~> 0.0.1"
+ gem "terranova", '8'
+ group :development, :test do
+ gem 'activesupport', '2.3.5'
+ gem "duradura", '7.0'
+ end
+ G
+ end
+
it "uses local cache to return a list of outdated gems" do
update_repo2 do
build_gem "activesupport", "2.3.4"
end
- bundle! "config clean false"
+ bundle_config "clean false"
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.4"
G
- bundle "outdated --local"
+ bundle "outdated --local", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.4 2.3.5 = 2.3.4 default
+ TABLE
- expect(out).to include("activesupport (newest 2.3.5, installed 2.3.4, requested = 2.3.4)")
+ expect(out).to end_with(expected_output)
end
it "doesn't hit repo2" do
- FileUtils.rm_rf(gem_repo2)
+ FileUtils.rm_r(gem_repo2)
bundle "outdated --local"
expect(out).not_to match(/Fetching (gem|version|dependency) metadata from/)
@@ -214,54 +361,163 @@ RSpec.describe "bundle outdated" do
shared_examples_for "a minimal output is desired" do
context "and gems are outdated" do
before do
- update_repo2 do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+
build_gem "activesupport", "3.0"
build_gem "weakling", "0.2"
end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
end
- it "outputs a sorted list of outdated gems with a more minimal format" do
+ it "outputs a sorted list of outdated gems with a more minimal format to stdout" do
minimal_output = "activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)\n" \
"weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)"
subject
expect(out).to eq(minimal_output)
end
+
+ it "outputs progress to stderr" do
+ subject
+ expect(err).to include("Fetching gem metadata")
+ end
end
context "and no gems are outdated" do
- it "has empty output" do
+ before do
+ build_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "3.0"
+ G
+ end
+
+ it "does not output to stdout" do
subject
- expect(out).to eq("")
+ expect(out).to be_empty
+ end
+
+ it "outputs progress to stderr" do
+ subject
+ expect(err).to include("Fetching gem metadata")
end
end
end
describe "with --parseable option" do
- subject { bundle "outdated --parseable" }
+ subject { bundle "outdated --parseable", raise_on_error: false }
it_behaves_like "a minimal output is desired"
end
describe "with aliased --porcelain option" do
- subject { bundle "outdated --porcelain" }
+ subject { bundle "outdated --porcelain", raise_on_error: false }
it_behaves_like "a minimal output is desired"
end
describe "with specified gems" do
it "returns list of outdated gems" do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
+ update_git "foo", path: lib_path("foo")
end
- bundle "outdated foo"
- expect(out).not_to include("activesupport (newest")
- expect(out).to include("foo (newest 1.0")
+ bundle "outdated foo", raise_on_error: false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups Release Date
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ end
+
+ it "does not require gems to be installed" do
+ build_repo4 do
+ build_gem "zeitwerk", "1.0.0"
+ build_gem "zeitwerk", "2.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "zeitwerk"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ zeitwerk (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ zeitwerk
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "outdated zeitwerk", raise_on_error: false
+
+ expected_output = <<~TABLE.tr(".", "\.").strip
+ Gem Current Latest Requested Groups Release Date
+ zeitwerk 1.0.0 2.0.0 >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ expect(err).to be_empty
end
end
describe "pre-release gems" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
context "without the --pre option" do
it "ignores pre-release versions" do
update_repo2 do
@@ -269,7 +525,8 @@ RSpec.describe "bundle outdated" do
end
bundle "outdated"
- expect(out).not_to include("activesupport (3.0.0.beta > 2.3.5)")
+
+ expect(out).to end_with("Bundle up to date!")
end
end
@@ -279,8 +536,14 @@ RSpec.describe "bundle outdated" do
build_gem "activesupport", "3.0.0.beta"
end
- bundle "outdated --pre"
- expect(out).to include("activesupport (newest 3.0.0.beta, installed 2.3.5, requested = 2.3.5)")
+ bundle "outdated --pre", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0.0.beta = 2.3.5 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
@@ -292,44 +555,98 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", "3.0.0.beta.1"
G
- bundle "outdated"
- expect(out).to include("(newest 3.0.0.beta.2, installed 3.0.0.beta.1, requested = 3.0.0.beta.1)")
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 3.0.0.beta.1 3.0.0.beta.2 = 3.0.0.beta.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
end
- describe "with --strict option" do
+ describe "with --filter-strict option" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "only reports gems that have a newer version that matches the specified dependency version requirements" do
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "weakling", "0.0.5"
end
- bundle "outdated --strict"
+ bundle :outdated, "filter-strict": true, raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.0.3 0.0.5 ~> 0.0.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+
+ it "only reports gems that have a newer version that matches the specified dependency version requirements, using --strict alias" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ build_gem "weakling", "0.0.5"
+ end
+
+ bundle :outdated, strict: true, raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.0.3 0.0.5 ~> 0.0.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+
+ it "doesn't crash when some deps unused on the current platform" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", platforms: [:ruby_22]
+ G
+
+ bundle :outdated, "filter-strict": true
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.0.5, installed 0.0.3, requested ~> 0.0.1)")
+ expect(out).to end_with("Bundle up to date!")
end
it "only reports gem dependencies when they can actually be updated" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack_middleware", "1.0"
+ source "https://gem.repo2"
+ gem "myrack_middleware", "1.0"
G
- bundle "outdated --strict"
+ bundle :outdated, "filter-strict": true
- expect(out).to_not include("rack (1.2")
+ expect(out).to end_with("Bundle up to date!")
end
describe "and filter options" do
it "only reports gems that match requirement and patch filter level" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -339,15 +656,19 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.0.5"
end
- bundle "outdated --strict --filter-patch"
+ bundle :outdated, :"filter-strict" => true, "filter-patch" => true, :raise_on_error => false
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.0.5, installed 0.0.3")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.0.3 0.0.5 >= 0.0.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
it "only reports gems that match requirement and minor filter level" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -357,15 +678,19 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.1.5"
end
- bundle "outdated --strict --filter-minor"
+ bundle :outdated, :"filter-strict" => true, "filter-minor" => true, :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.0.3 0.1.5 >= 0.0.1 default
+ TABLE
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.1.5, installed 0.0.3")
+ expect(out).to end_with(expected_output)
end
it "only reports gems that match requirement and major filter level" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -375,135 +700,188 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "1.1.5"
end
- bundle "outdated --strict --filter-major"
+ bundle :outdated, :"filter-strict" => true, "filter-major" => true, :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.0.3 1.1.5 >= 0.0.1 default
+ TABLE
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 1.1.5, installed 0.0.3")
+ expect(out).to end_with(expected_output)
end
end
end
describe "with invalid gem name" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "returns could not find gem name" do
- bundle "outdated invalid_gem_name"
- expect(out).to include("Could not find gem 'invalid_gem_name'.")
+ bundle "outdated invalid_gem_name", raise_on_error: false
+ expect(err).to include("Could not find gem 'invalid_gem_name'.")
end
it "returns non-zero exit code" do
- bundle "outdated invalid_gem_name"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "outdated invalid_gem_name", raise_on_error: false
+ expect(exitstatus).to_not be_zero
end
end
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo"
G
- bundle "config auto_install 1"
- bundle :outdated
+ bundle_config "auto_install 1"
+ bundle :outdated, raise_on_error: false
expect(out).to include("Installing foo 1.0")
end
- context "after bundle install --deployment", :bundler => "< 3" do
+ context "in deployment mode" do
before do
- install_gemfile <<-G, forgotten_command_line_options(:deployment => true)
- source "file://#{gem_repo2}"
+ build_repo2
- gem "rack"
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "myrack"
gem "foo"
G
+ bundle :lock
+ bundle_config "deployment true"
end
it "outputs a helpful message about being in deployment mode" do
update_repo2 { build_gem "activesupport", "3.0" }
- bundle "outdated"
+ bundle "outdated", raise_on_error: false
expect(last_command).to be_failure
- expect(out).to include("You are trying to check outdated gems in deployment mode.")
- expect(out).to include("Run `bundle outdated` elsewhere.")
- expect(out).to include("If this is a development machine, remove the ")
- expect(out).to include("Gemfile freeze\nby running `bundle install --no-deployment`.")
+ expect(err).to include("You are trying to check outdated gems in deployment mode.")
+ expect(err).to include("Run `bundle outdated` elsewhere.")
+ expect(err).to include("If this is a development machine, remove the ")
+ expect(err).to include("Gemfile freeze\nby running `bundle config unset deployment`.")
end
end
- context "after bundle config deployment true" do
+ context "after bundle config set --local deployment true" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
gem "foo"
G
- bundle! "config deployment true"
+ bundle_config "deployment true"
end
it "outputs a helpful message about being in deployment mode" do
update_repo2 { build_gem "activesupport", "3.0" }
- bundle "outdated"
+ bundle "outdated", raise_on_error: false
expect(last_command).to be_failure
- expect(out).to include("You are trying to check outdated gems in deployment mode.")
- expect(out).to include("Run `bundle outdated` elsewhere.")
- expect(out).to include("If this is a development machine, remove the ")
- expect(out).to include("Gemfile freeze\nby running `bundle config --delete deployment`.")
+ expect(err).to include("You are trying to check outdated gems in deployment mode.")
+ expect(err).to include("Run `bundle outdated` elsewhere.")
+ expect(err).to include("If this is a development machine, remove the ")
+ expect(err).to include("Gemfile freeze\nby running `bundle config unset deployment`.")
end
end
context "update available for a gem on a different platform" do
before do
+ build_repo2
+
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "laduradura", '= 5.15.2'
G
end
it "reports that no updates are available" do
bundle "outdated"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
end
context "update available for a gem on the same platform while multiple platforms used for gem" do
+ before do
+ build_repo2
+ end
+
it "reports that updates are available if the Ruby platform is used" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
G
bundle "outdated"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
- it "reports that updates are available if the JRuby platform is used" do
- simulate_ruby_engine "jruby", "1.6.7" do
- simulate_platform "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
- G
+ it "reports that updates are available if the JRuby platform is used", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
+ G
+
+ bundle "outdated", raise_on_error: false
- bundle "outdated"
- expect(out).to include("Outdated gems included in the bundle:")
- expect(out).to include("laduradura (newest 5.15.3, installed 5.15.2, requested = 5.15.2)")
- end
- end
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ laduradura 5.15.2 5.15.3 = 5.15.2 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
shared_examples_for "version update is detected" do
it "reports that a gem has a newer version" do
subject
- expect(out).to include("Outdated gems included in the bundle:")
- expect(out).to include("activesupport (newest")
- expect(out).to_not include("ERROR REPORT TEMPLATE")
+
+ outdated_gems = out.split("\n").drop_while {|l| !l.start_with?("Gem") }[1..-1]
+
+ expect(outdated_gems.size).to be > 0
end
end
shared_examples_for "major version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.3.5"
build_gem "weakling", "0.8.0"
@@ -515,21 +893,51 @@ RSpec.describe "bundle outdated" do
context "when on a new machine" do
before do
- simulate_new_machine
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
+ pristine_system_gems
- update_git "foo", :path => lib_path("foo")
+ update_git "foo", path: lib_path("foo")
update_repo2 do
build_gem "activesupport", "3.3.5"
build_gem "weakling", "0.8.0"
end
end
- subject { bundle "outdated" }
+ subject { bundle "outdated", raise_on_error: false }
it_behaves_like "version update is detected"
end
shared_examples_for "minor version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.7.5"
build_gem "weakling", "2.0.1"
@@ -541,6 +949,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.3.7"
build_gem "weakling", "0.3.1"
@@ -553,15 +976,27 @@ RSpec.describe "bundle outdated" do
shared_examples_for "no version updates are detected" do
it "does not detect any version updates" do
subject
- expect(out).to include("updates to display.")
- expect(out).to_not include("ERROR REPORT TEMPLATE")
- expect(out).to_not include("activesupport (newest")
- expect(out).to_not include("weakling (newest")
+ expect(out).to end_with("updates to display.")
end
end
shared_examples_for "major version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.3.5"
build_gem "weakling", "1.0.1"
@@ -573,6 +1008,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "minor version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.4.5"
build_gem "weakling", "0.3.1"
@@ -584,6 +1034,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ build_git "zebra", path: lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.3.6"
build_gem "weakling", "0.0.4"
@@ -594,7 +1059,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major option" do
- subject { bundle "outdated --filter-major" }
+ subject { bundle "outdated --filter-major", raise_on_error: false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version is ignored"
@@ -602,7 +1067,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-minor option" do
- subject { bundle "outdated --filter-minor" }
+ subject { bundle "outdated --filter-minor", raise_on_error: false }
it_behaves_like "minor version updates are detected"
it_behaves_like "major version is ignored"
@@ -610,7 +1075,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-patch option" do
- subject { bundle "outdated --filter-patch" }
+ subject { bundle "outdated --filter-patch", raise_on_error: false }
it_behaves_like "patch version updates are detected"
it_behaves_like "major version is ignored"
@@ -618,7 +1083,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-minor --filter-patch options" do
- subject { bundle "outdated --filter-minor --filter-patch" }
+ subject { bundle "outdated --filter-minor --filter-patch", raise_on_error: false }
it_behaves_like "minor version updates are detected"
it_behaves_like "patch version updates are detected"
@@ -626,7 +1091,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-minor options" do
- subject { bundle "outdated --filter-major --filter-minor" }
+ subject { bundle "outdated --filter-major --filter-minor", raise_on_error: false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version updates are detected"
@@ -634,7 +1099,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-patch options" do
- subject { bundle "outdated --filter-major --filter-patch" }
+ subject { bundle "outdated --filter-major --filter-patch", raise_on_error: false }
it_behaves_like "major version updates are detected"
it_behaves_like "patch version updates are detected"
@@ -642,7 +1107,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-minor --filter-patch options" do
- subject { bundle "outdated --filter-major --filter-minor --filter-patch" }
+ subject { bundle "outdated --filter-major --filter-minor --filter-patch", raise_on_error: false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version updates are detected"
@@ -650,106 +1115,125 @@ RSpec.describe "bundle outdated" do
end
context "conservative updates" do
- context "without update-strict" do
- before do
- build_repo4 do
- build_gem "patch", %w[1.0.0 1.0.1]
- build_gem "minor", %w[1.0.0 1.0.1 1.1.0]
- build_gem "major", %w[1.0.0 1.0.1 1.1.0 2.0.0]
- end
+ before do
+ build_repo4 do
+ build_gem "patch", %w[1.0.0 1.0.1]
+ build_gem "minor", %w[1.0.0 1.0.1 1.1.0]
+ build_gem "major", %w[1.0.0 1.0.1 1.1.0 2.0.0]
+ end
- # establish a lockfile set to 1.0.0
- install_gemfile <<-G
- source "file://#{gem_repo4}"
+ # establish a lockfile set to 1.0.0
+ install_gemfile <<-G
+ source "https://gem.repo4"
gem 'patch', '1.0.0'
gem 'minor', '1.0.0'
gem 'major', '1.0.0'
- G
+ G
- # remove 1.4.3 requirement and bar altogether
- # to setup update specs below
- gemfile <<-G
- source "file://#{gem_repo4}"
+ # remove all version requirements
+ gemfile <<-G
+ source "https://gem.repo4"
gem 'patch'
gem 'minor'
gem 'major'
- G
- end
+ G
+ end
- it "shows nothing when patching and filtering to minor" do
- bundle "outdated --patch --filter-minor"
+ it "shows nothing when patching and filtering to minor" do
+ bundle "outdated --patch --filter-minor"
- expect(out).to include("No minor updates to display.")
- expect(out).not_to include("patch (newest")
- expect(out).not_to include("minor (newest")
- expect(out).not_to include("major (newest")
- end
+ expect(out).to end_with("No minor updates to display.")
+ end
- it "shows all gems when patching and filtering to patch" do
- bundle "outdated --patch --filter-patch"
+ it "shows all gems when patching and filtering to patch" do
+ bundle "outdated --patch --filter-patch", raise_on_error: false
- expect(out).to include("patch (newest 1.0.1")
- expect(out).to include("minor (newest 1.0.1")
- expect(out).to include("major (newest 1.0.1")
- end
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ major 1.0.0 1.0.1 >= 0 default
+ minor 1.0.0 1.0.1 >= 0 default
+ patch 1.0.0 1.0.1 >= 0 default
+ TABLE
- it "shows minor and major when updating to minor and filtering to patch and minor" do
- bundle "outdated --minor --filter-minor"
+ expect(out).to end_with(expected_output)
+ end
- expect(out).not_to include("patch (newest")
- expect(out).to include("minor (newest 1.1.0")
- expect(out).to include("major (newest 1.1.0")
- end
+ it "shows minor and major when updating to minor and filtering to patch and minor" do
+ bundle "outdated --minor --filter-minor", raise_on_error: false
- it "shows minor when updating to major and filtering to minor with parseable" do
- bundle "outdated --major --filter-minor --parseable"
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ major 1.0.0 1.1.0 >= 0 default
+ minor 1.0.0 1.1.0 >= 0 default
+ TABLE
- expect(out).not_to include("patch (newest")
- expect(out).to include("minor (newest")
- expect(out).not_to include("major (newest")
- end
+ expect(out).to end_with(expected_output)
end
- context "with update-strict" do
- before do
- build_repo4 do
- build_gem "foo", %w[1.4.3 1.4.4] do |s|
- s.add_dependency "bar", "~> 2.0"
- end
- build_gem "foo", %w[1.4.5 1.5.0] do |s|
- s.add_dependency "bar", "~> 2.1"
- end
- build_gem "foo", %w[1.5.1] do |s|
- s.add_dependency "bar", "~> 3.0"
- end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
- build_gem "qux", %w[1.0.0 1.1.0 2.0.0]
- end
+ it "shows minor when updating to major and filtering to minor with parseable" do
+ bundle "outdated --major --filter-minor --parseable", raise_on_error: false
- # establish a lockfile set to 1.4.3
- install_gemfile <<-G
- source "file://#{gem_repo4}"
- gem 'foo', '1.4.3'
- gem 'bar', '2.0.3'
- gem 'qux', '1.0.0'
- G
+ expect(out).not_to include("patch (newest")
+ expect(out).to include("minor (newest")
+ expect(out).not_to include("major (newest")
+ end
+ end
- # remove 1.4.3 requirement and bar altogether
- # to setup update specs below
- gemfile <<-G
- source "file://#{gem_repo4}"
- gem 'foo'
- gem 'qux'
- G
+ context "tricky conservative updates" do
+ before do
+ build_repo4 do
+ build_gem "foo", %w[1.4.3 1.4.4] do |s|
+ s.add_dependency "bar", "~> 2.0"
+ end
+ build_gem "foo", %w[1.4.5 1.5.0] do |s|
+ s.add_dependency "bar", "~> 2.1"
+ end
+ build_gem "foo", %w[1.5.1] do |s|
+ s.add_dependency "bar", "~> 3.0"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "qux", %w[1.0.0 1.1.0 2.0.0]
end
- it "shows gems with update-strict updating to patch and filtering to patch" do
- bundle "outdated --patch --update-strict --filter-patch"
+ # establish a lockfile set to 1.4.3
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo', '1.4.3'
+ gem 'bar', '2.0.3'
+ gem 'qux', '1.0.0'
+ G
- expect(out).to include("foo (newest 1.4.4")
- expect(out).to include("bar (newest 2.0.5")
- expect(out).not_to include("qux (newest")
- end
+ # remove 1.4.3 requirement and bar altogether
+ # to setup update specs below
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem 'foo'
+ gem 'qux'
+ G
+ end
+
+ it "shows gems updating to patch and filtering to patch" do
+ bundle "outdated --patch --filter-patch", raise_on_error: false, env: { "DEBUG_RESOLVER" => "1" }
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ bar 2.0.3 2.0.5
+ foo 1.4.3 1.4.4 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+
+ it "shows gems updating to patch and filtering to patch, in debug mode" do
+ bundle "outdated --patch --filter-patch", raise_on_error: false, env: { "DEBUG" => "1" }
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date Path
+ bar 2.0.3 2.0.5
+ foo 1.4.3 1.4.4 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
@@ -763,20 +1247,123 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'weakling', '0.2'
gem 'bar', '2.1'
G
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'weakling'
G
- bundle "outdated --only-explicit"
+ bundle "outdated --only-explicit", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ weakling 0.2 0.3 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with a multiplatform lockfile" do
+ before do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1"
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ end
+
+ build_gem "nokogiri", "1.11.2"
+ build_gem "nokogiri", "1.11.2" do |s|
+ s.platform = Bundler.local_platform
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.11.1)
+ nokogiri (1.11.1-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "nokogiri"
+ G
+ end
+
+ it "reports a single entry per gem" do
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ nokogiri 1.11.1 1.11.2 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ context "when a gem is no longer a dependency after a full update" do
+ before do
+ build_repo4 do
+ build_gem "mini_portile2", "2.5.2" do |s|
+ s.add_dependency "net-ftp", "~> 0.1"
+ end
+
+ build_gem "mini_portile2", "2.5.3"
+
+ build_gem "net-ftp", "0.1.2"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "mini_portile2"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mini_portile2 (2.5.2)
+ net-ftp (~> 0.1)
+ net-ftp (0.1.2)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mini_portile2
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Release Date
+ mini_portile2 2.5.2 2.5.3 >= 0 default
+ TABLE
- expect(out).to include("weakling (newest 0.3")
- expect(out).not_to include("bar (newest 2.2")
+ expect(out).to end_with(expected_output)
end
end
end
diff --git a/spec/bundler/commands/package_spec.rb b/spec/bundler/commands/package_spec.rb
deleted file mode 100644
index a8426e6322..0000000000
--- a/spec/bundler/commands/package_spec.rb
+++ /dev/null
@@ -1,306 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle package" do
- context "with --gemfile" do
- it "finds the gemfile" do
- gemfile bundled_app("NotGemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
- G
-
- bundle "package --gemfile=NotGemfile"
-
- ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-
- context "with --all" do
- context "without a gemspec" do
- it "caches all dependencies except bundler itself" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- gem 'bundler'
- D
-
- bundle :package, forgotten_command_line_options([:all, :cache_all] => true)
-
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
- end
- end
-
- context "with a gemspec" do
- context "that has the same name as the gem" do
- before do
- File.open(bundled_app("mygem.gemspec"), "w") do |f|
- f.write <<-G
- Gem::Specification.new do |s|
- s.name = "mygem"
- s.version = "0.1.1"
- s.summary = ""
- s.authors = ["gem author"]
- s.add_development_dependency "nokogiri", "=1.4.2"
- end
- G
- end
- end
-
- it "caches all dependencies except bundler and the gemspec specified gem" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- gemspec
- D
-
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
-
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
- expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
- expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
- end
- end
-
- context "that has a different name as the gem" do
- before do
- File.open(bundled_app("mygem_diffname.gemspec"), "w") do |f|
- f.write <<-G
- Gem::Specification.new do |s|
- s.name = "mygem"
- s.version = "0.1.1"
- s.summary = ""
- s.authors = ["gem author"]
- s.add_development_dependency "nokogiri", "=1.4.2"
- end
- G
- end
- end
-
- it "caches all dependencies except bundler and the gemspec specified gem" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- gemspec
- D
-
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
-
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
- expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
- expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
- end
- end
- end
-
- context "with multiple gemspecs" do
- before do
- File.open(bundled_app("mygem.gemspec"), "w") do |f|
- f.write <<-G
- Gem::Specification.new do |s|
- s.name = "mygem"
- s.version = "0.1.1"
- s.summary = ""
- s.authors = ["gem author"]
- s.add_development_dependency "nokogiri", "=1.4.2"
- end
- G
- end
- File.open(bundled_app("mygem_client.gemspec"), "w") do |f|
- f.write <<-G
- Gem::Specification.new do |s|
- s.name = "mygem_test"
- s.version = "0.1.1"
- s.summary = ""
- s.authors = ["gem author"]
- s.add_development_dependency "weakling", "=0.0.3"
- end
- G
- end
- end
-
- it "caches all dependencies except bundler and the gemspec specified gems" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- gemspec :name => 'mygem'
- gemspec :name => 'mygem_test'
- D
-
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
-
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
- expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
- expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
- expect(bundled_app("vendor/cache/mygem_test-0.1.1.gem")).to_not exist
- expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
- end
- end
- end
-
- context "with --path", :bundler => "< 3" do
- it "sets root directory for gems" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- D
-
- bundle! :package, forgotten_command_line_options(:path => bundled_app("test"))
-
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(bundled_app("test/vendor/cache/")).to exist
- end
- end
-
- context "with --no-install" do
- it "puts the gems in vendor/cache but does not install them" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- D
-
- bundle! "package --no-install"
-
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
-
- it "does not prevent installing gems with bundle install" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack'
- D
-
- bundle! "package --no-install"
- bundle! "install"
-
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-
- context "with --all-platforms" do
- it "puts the gems in vendor/cache even for other rubies", :ruby => "2.1" do
- gemfile <<-D
- source "file://#{gem_repo1}"
- gem 'rack', :platforms => :ruby_19
- D
-
- bundle "package --all-platforms"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
- end
-
- context "with --frozen" do
- before do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- bundle "install"
- end
-
- subject { bundle :package, forgotten_command_line_options(:frozen => true) }
-
- it "tries to install with frozen" do
- bundle! "config deployment true"
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
- G
- subject
- expect(exitstatus).to eq(16) if exitstatus
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile")
- expect(out).to include("* rack-obama")
- bundle "env"
- expect(out).to include("frozen").or include("deployment")
- end
- end
-end
-
-RSpec.describe "bundle install with gem sources" do
- describe "when cached and locked" do
- it "does not hit the remote at all" do
- build_repo2
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
- G
-
- bundle :pack
- simulate_new_machine
- FileUtils.rm_rf gem_repo2
-
- bundle "install --local"
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "does not hit the remote at all" do
- build_repo2
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
- gem "rack"
- G
-
- bundle! :pack
- simulate_new_machine
- FileUtils.rm_rf gem_repo2
-
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "does not reinstall already-installed gems" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- bundle :pack
-
- build_gem "rack", "1.0.0", :path => bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "raise 'omg'"
- end
-
- bundle :install
- expect(err).to lack_errors
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "ignores cached gems for the wrong platform" do
- simulate_platform "java" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
- bundle :pack
- end
-
- simulate_new_machine
-
- simulate_platform "ruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "platform_specific"
- G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 RUBY")
- end
- end
-
- it "does not update the cache if --no-cache is passed" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- bundled_app("vendor/cache").mkpath
- expect(bundled_app("vendor/cache").children).to be_empty
-
- bundle "install --no-cache"
- expect(bundled_app("vendor/cache").children).to be_empty
- end
- end
-end
diff --git a/spec/bundler/commands/platform_spec.rb b/spec/bundler/commands/platform_spec.rb
new file mode 100644
index 0000000000..9d7354c54f
--- /dev/null
+++ b/spec/bundler/commands/platform_spec.rb
@@ -0,0 +1,1260 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle platform" do
+ context "without flags" do
+ it "returns all the output" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ #{ruby_version_correct}
+
+ gem "foo"
+ G
+
+ bundle "platform"
+ expect(out).to eq(<<-G.chomp)
+Your platform is: #{Gem::Platform.local}
+
+Your app has gems that work on these platforms:
+* #{local_platform}
+
+Your Gemfile specifies a Ruby version requirement:
+* ruby #{Gem.ruby_version}
+
+Your current platform satisfies the Ruby version requirement.
+G
+ end
+
+ it "returns all the output including the patchlevel" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ #{ruby_version_correct_patchlevel}
+
+ gem "foo"
+ G
+
+ bundle "platform"
+ expect(out).to eq(<<-G.chomp)
+Your platform is: #{Gem::Platform.local}
+
+Your app has gems that work on these platforms:
+* #{local_platform}
+
+Your Gemfile specifies a Ruby version requirement:
+* #{Bundler::RubyVersion.system.single_version_string}
+
+Your current platform satisfies the Ruby version requirement.
+G
+ end
+
+ it "doesn't print ruby version requirement if it isn't specified" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "foo"
+ G
+
+ bundle "platform"
+ expect(out).to eq(<<-G.chomp)
+Your platform is: #{Gem::Platform.local}
+
+Your app has gems that work on these platforms:
+* #{local_platform}
+
+Your Gemfile does not specify a Ruby version requirement.
+G
+ end
+
+ it "doesn't match the ruby version requirement" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ #{ruby_version_incorrect}
+
+ gem "foo"
+ G
+
+ bundle "platform"
+ expect(out).to eq(<<-G.chomp)
+Your platform is: #{Gem::Platform.local}
+
+Your app has gems that work on these platforms:
+* #{local_platform}
+
+Your Gemfile specifies a Ruby version requirement:
+* ruby #{not_local_ruby_version}
+
+Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified #{not_local_ruby_version}
+G
+ end
+ end
+
+ context "--ruby" do
+ it "returns ruby version when explicit" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("ruby 1.9.3")
+ end
+
+ it "defaults to MRI" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.9.3"
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("ruby 1.9.3")
+ end
+
+ it "handles jruby" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5'
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("ruby 1.8.7 (jruby 1.6.5)")
+ end
+
+ it "handles rbx" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("ruby 1.8.7 (rbx 1.2.4)")
+ end
+
+ it "handles truffleruby" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "2.5.1", :engine => 'truffleruby', :engine_version => '1.0.0-rc6'
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("ruby 2.5.1 (truffleruby 1.0.0-rc6)")
+ end
+
+ it "raises an error if engine is used but engine version is not" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.8.7", :engine => 'rbx'
+
+ gem "foo"
+ G
+
+ bundle "platform", raise_on_error: false
+
+ expect(exitstatus).not_to eq(0)
+ end
+
+ it "raises an error if engine_version is used but engine is not" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.8.7", :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle "platform", raise_on_error: false
+
+ expect(exitstatus).not_to eq(0)
+ end
+
+ it "raises an error if engine version doesn't match ruby version for MRI" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle "platform", raise_on_error: false
+
+ expect(exitstatus).not_to eq(0)
+ end
+
+ it "should print if no ruby version is specified" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "foo"
+ G
+
+ bundle "platform --ruby"
+
+ expect(out).to eq("No ruby version specified")
+ end
+
+ it "handles when there is a locked requirement" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby "< 1.8.7"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ RUBY VERSION
+ ruby 1.0.0p127
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "platform --ruby"
+ expect(out).to eq("ruby 1.0.0")
+ end
+
+ it "handles when there is a lockfile with no requirement" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "platform --ruby"
+ expect(out).to eq("No ruby version specified")
+ end
+
+ it "handles when there is a requirement in the gemfile" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby ">= 1.8.7"
+ G
+
+ bundle "platform --ruby"
+ expect(out).to eq("ruby 1.8.7")
+ end
+
+ it "handles when there are multiple requirements in the gemfile" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby ">= 1.8.7", "< 2.0.0"
+ G
+
+ bundle "platform --ruby"
+ expect(out).to eq("ruby 1.8.7")
+ end
+ end
+
+ let(:ruby_version_correct) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{local_engine_version}\"" }
+ let(:ruby_version_correct_engineless) { "ruby \"#{Gem.ruby_version}\"" }
+ let(:ruby_version_correct_patchlevel) { "#{ruby_version_correct}, :patchlevel => '#{RUBY_PATCHLEVEL}'" }
+ let(:ruby_version_incorrect) { "ruby \"#{not_local_ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_ruby_version}\"" }
+ let(:engine_incorrect) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{not_local_tag}\", :engine_version => \"#{Gem.ruby_version}\"" }
+ let(:engine_version_incorrect) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_engine_version}\"" }
+ let(:patchlevel_incorrect) { "#{ruby_version_correct}, :patchlevel => '#{not_local_patchlevel}'" }
+ let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" }
+
+ def should_be_ruby_version_incorrect
+ expect(exitstatus).to eq(18)
+ expect(err).to be_include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified #{not_local_ruby_version}")
+ end
+
+ def should_be_engine_incorrect
+ expect(exitstatus).to eq(18)
+ expect(err).to be_include("Your Ruby engine is #{local_ruby_engine}, but your Gemfile specified #{not_local_tag}")
+ end
+
+ def should_be_engine_version_incorrect
+ expect(exitstatus).to eq(18)
+ expect(err).to be_include("Your #{local_ruby_engine} version is #{local_engine_version}, but your Gemfile specified #{local_ruby_engine} #{not_local_engine_version}")
+ end
+
+ def should_ignore_patchlevel
+ expect(exitstatus).to eq(0)
+ expect(err).to eq("")
+ end
+
+ def should_be_patchlevel_fixnum
+ expect(exitstatus).to eq(18)
+ expect(err).to be_include("The Ruby patchlevel in your Gemfile must be a string")
+ end
+
+ context "bundle install" do
+ it "installs fine when the ruby version matches" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_correct}
+ G
+
+ expect(bundled_app_lock).to exist
+ end
+
+ it "installs fine with any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ expect(bundled_app_lock).to exist
+ end
+
+ it "installs fine when the patchlevel matches" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_correct_patchlevel}
+ G
+
+ expect(bundled_app_lock).to exist
+ end
+
+ it "doesn't install when the ruby version doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_incorrect}
+ G
+
+ expect(bundled_app_lock).not_to exist
+ should_be_ruby_version_incorrect
+ end
+
+ it "doesn't install when engine doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{engine_incorrect}
+ G
+
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_incorrect
+ end
+
+ it "doesn't install when engine version doesn't match", :jruby_only do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{engine_version_incorrect}
+ G
+
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_version_incorrect
+ end
+
+ it "does install even when patchlevel doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ expect(bundled_app_lock).to exist
+ should_ignore_patchlevel
+ end
+ end
+
+ context "bundle check" do
+ it "checks fine when the ruby version matches" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_correct}
+ G
+
+ bundle :check
+ expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/)
+ end
+
+ it "checks fine with any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle :check
+ expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/)
+ end
+
+ it "fails when ruby version doesn't match" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle :check, raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when engine doesn't match" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{engine_incorrect}
+ G
+
+ bundle :check, raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails when engine version doesn't match", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{engine_version_incorrect}
+ G
+
+ bundle :check, raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "checks fine even when patchlevel doesn't match" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle :check
+ should_ignore_patchlevel
+ end
+ end
+
+ context "bundle update" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ G
+ end
+
+ it "updates successfully when the ruby version matches" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+
+ #{ruby_version_correct}
+ G
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle "update", all: true
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
+ end
+
+ it "updates fine with any engine", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+
+ #{ruby_version_correct_engineless}
+ G
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle "update", all: true
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
+ end
+
+ it "fails when ruby version doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+
+ #{ruby_version_incorrect}
+ G
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle :update, all: true, raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when ruby engine doesn't match", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+
+ #{engine_incorrect}
+ G
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle :update, all: true, raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails when ruby engine version doesn't match", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+
+ #{engine_version_incorrect}
+ G
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle :update, all: true, raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "updates fine even when patchlevel doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+
+ #{patchlevel_incorrect}
+ G
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle :update, all: true
+ should_ignore_patchlevel
+ expect(the_bundle).to include_gems "activesupport 3.0"
+ end
+ end
+
+ context "bundle info" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ G
+ end
+
+ it "prints path if ruby version is correct" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{ruby_version_correct}
+ G
+
+ bundle "info rails --path"
+ expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
+ end
+
+ it "prints path if ruby version is correct for any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle "info rails --path"
+ expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
+ end
+
+ it "fails if ruby version doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle "show rails", raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails if engine doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{engine_incorrect}
+ G
+
+ bundle "show rails", raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails if engine version doesn't match", jruby_only: true do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{engine_version_incorrect}
+ G
+
+ bundle "show rails", raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "prints path even when patchlevel doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle "show rails"
+ should_ignore_patchlevel
+ expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
+ end
+ end
+
+ context "bundle cache" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "copies the .gem file to vendor/cache when ruby version matches" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_correct}
+ G
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "copies the .gem file to vendor/cache when ruby version matches for any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "fails if the ruby version doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails if the engine doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{engine_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails if the engine version doesn't match", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{engine_version_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "copies the .gem file to vendor/cache even when patchlevel doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle :cache
+ should_ignore_patchlevel
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+ end
+
+ context "bundle pack" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "copies the .gem file to vendor/cache when ruby version matches" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_correct}
+ G
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "copies the .gem file to vendor/cache when ruby version matches any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+
+ it "fails if the ruby version doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails if the engine doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{engine_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails if the engine version doesn't match", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+
+ #{engine_version_incorrect}
+ G
+
+ bundle :cache, raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "copies the .gem file to vendor/cache even when patchlevel doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle :cache
+ should_ignore_patchlevel
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ end
+ end
+
+ context "bundle exec" do
+ before do
+ ENV["BUNDLER_FORCE_TTY"] = "true"
+ system_gems "myrack-1.0.0", "myrack-0.9.1", path: default_bundle_path
+ end
+
+ it "activates the correct gem when ruby version matches" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+
+ #{ruby_version_correct}
+ G
+
+ bundle "exec myrackup"
+ expect(out).to include("0.9.1")
+ end
+
+ it "activates the correct gem when ruby version matches any engine", :jruby_only do
+ system_gems "myrack-1.0.0", "myrack-0.9.1", path: default_bundle_path
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle "exec myrackup"
+ expect(out).to include("0.9.1")
+ end
+
+ it "fails when the ruby version doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle "exec myrackup", raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when the engine doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+
+ #{engine_incorrect}
+ G
+
+ bundle "exec myrackup", raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails when the engine version doesn't match", :jruby_only do
+ gemfile <<-G
+ gem "myrack", "0.9.1"
+
+ #{engine_version_incorrect}
+ G
+
+ bundle "exec myrackup", raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "activates the correct gem even when patchlevel doesn't match" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle "exec myrackup"
+ should_ignore_patchlevel
+ expect(out).to include("1.0.0")
+ end
+ end
+
+ context "bundle console" do
+ before do
+ build_repo2 do
+ build_dummy_irb
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
+ gem "activesupport", :group => :test
+ gem "myrack_middleware", :group => :development
+ G
+ end
+
+ it "starts IRB with the default group loaded when ruby version matches", :readline do
+ gemfile gemfile + "\n\n#{ruby_version_correct}\n"
+
+ bundle "console" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ expect(out).to include("0.9.1")
+ end
+
+ it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby_only do
+ gemfile gemfile + "\n\n#{ruby_version_correct_engineless}\n"
+
+ bundle "console" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ expect(out).to include("0.9.1")
+ end
+
+ it "fails when ruby version doesn't match" do
+ gemfile gemfile + "\n\n#{ruby_version_incorrect}\n"
+
+ bundle "console", raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when engine doesn't match" do
+ gemfile gemfile + "\n\n#{engine_incorrect}\n"
+
+ bundle "console", raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails when engine version doesn't match", :jruby_only do
+ gemfile gemfile + "\n\n#{engine_version_incorrect}\n"
+
+ bundle "console", raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "starts IRB with the default group loaded even when patchlevel doesn't match", :readline do
+ gemfile gemfile + "\n\n#{patchlevel_incorrect}\n"
+
+ bundle "console" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ should_ignore_patchlevel
+ expect(out).to include("0.9.1")
+ end
+ end
+
+ context "Bundler.setup" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack", :group => :test
+ G
+
+ ENV["BUNDLER_FORCE_TTY"] = "true"
+ end
+
+ it "makes a Gemfile.lock if setup succeeds" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{ruby_version_correct}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ run "1"
+ expect(bundled_app_lock).to exist
+ end
+
+ it "makes a Gemfile.lock if setup succeeds for any engine", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ run "1"
+ expect(bundled_app_lock).to exist
+ end
+
+ it "fails when ruby version doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{ruby_version_incorrect}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ ruby "require 'bundler/setup'", env: { "BUNDLER_VERSION" => Bundler::VERSION }, raise_on_error: false
+
+ expect(bundled_app_lock).not_to exist
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when engine doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{engine_incorrect}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ ruby "require 'bundler/setup'", env: { "BUNDLER_VERSION" => Bundler::VERSION }, raise_on_error: false
+
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_incorrect
+ end
+
+ it "fails when engine version doesn't match", :jruby_only do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{engine_version_incorrect}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ ruby "require 'bundler/setup'", env: { "BUNDLER_VERSION" => Bundler::VERSION }, raise_on_error: false
+
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_version_incorrect
+ end
+
+ it "makes a Gemfile.lock even when patchlevel doesn't match" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack"
+
+ #{patchlevel_incorrect}
+ G
+
+ FileUtils.rm(bundled_app_lock)
+
+ ruby "require 'bundler/setup'", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+
+ should_ignore_patchlevel
+ expect(bundled_app_lock).to exist
+ end
+ end
+
+ context "bundle outdated" do
+ before do
+ build_repo2 do
+ build_git "foo", path: lib_path("foo")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+ end
+
+ it "returns list of outdated gems when the ruby version matches" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{ruby_version_correct}
+ G
+
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ end
+
+ it "returns list of outdated gems when the ruby version matches for any engine", :jruby_only do
+ bundle :install
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{ruby_version_correct_engineless}
+ G
+
+ bundle "outdated", raise_on_error: false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups Release Date
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ end
+
+ it "fails when the ruby version doesn't match" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{ruby_version_incorrect}
+ G
+
+ bundle "outdated", raise_on_error: false
+ should_be_ruby_version_incorrect
+ end
+
+ it "fails when the engine doesn't match" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{engine_incorrect}
+ G
+
+ bundle "outdated", raise_on_error: false
+ should_be_engine_incorrect
+ end
+
+ it "fails when the engine version doesn't match", :jruby_only do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{engine_version_incorrect}
+ G
+
+ bundle "outdated", raise_on_error: false
+ should_be_engine_version_incorrect
+ end
+
+ it "reports outdated gems even when patchlevel doesn't match" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", path: lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{patchlevel_incorrect}
+ G
+
+ bundle "outdated", raise_on_error: false
+ expect(err).not_to include("patchlevel")
+ expect(out).to include("activesupport")
+ expect(out).to include("foo")
+ end
+ end
+end
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
new file mode 100644
index 0000000000..088fc29fe1
--- /dev/null
+++ b/spec/bundler/commands/post_bundle_message_spec.rb
@@ -0,0 +1,183 @@
+# frozen_string_literal: true
+
+RSpec.describe "post bundle message" do
+ before :each do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "activesupport", "2.3.5", :group => [:emo, :test]
+ group :test do
+ gem "rspec"
+ end
+ gem "myrack-obama", :group => :obama
+ G
+ end
+
+ let(:bundle_path) { "./.bundle" }
+ let(:bundle_show_system_message) { "Use `bundle info [gemname]` to see where a bundled gem is installed." }
+ let(:bundle_show_path_message) { "Bundled gems are installed into `#{bundle_path}`" }
+ let(:bundle_complete_message) { "Bundle complete!" }
+ let(:bundle_updated_message) { "Bundle updated!" }
+ let(:installed_gems_stats) { "4 Gemfile dependencies, 4 gems now installed." }
+
+ describe "when installing to system gems" do
+ before do
+ bundle_config "path.system true"
+ end
+
+ it "shows proper messages according to the configured groups" do
+ bundle :install
+ expect(out).to include(bundle_show_system_message)
+ expect(out).not_to include("Gems in the group")
+ expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
+
+ bundle_config "without emo"
+ bundle :install
+ expect(out).to include(bundle_show_system_message)
+ expect(out).to include("Gems in the group 'emo' were not installed")
+ expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
+
+ bundle_config "without emo test"
+ bundle :install
+ expect(out).to include(bundle_show_system_message)
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not installed")
+ expect(out).to include(bundle_complete_message)
+ expect(out).to include("4 Gemfile dependencies, 2 gems now installed.")
+
+ bundle_config "without emo obama test"
+ bundle :install
+ expect(out).to include(bundle_show_system_message)
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed")
+ expect(out).to include(bundle_complete_message)
+ expect(out).to include("4 Gemfile dependencies, 1 gem now installed.")
+ end
+
+ describe "for second bundle install run" do
+ it "without any options" do
+ 2.times { bundle :install }
+ expect(out).to include(bundle_show_system_message)
+ expect(out).to_not include("Gems in the groups")
+ expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
+ end
+ end
+ end
+
+ describe "with `path` configured" do
+ let(:bundle_path) { "./vendor" }
+
+ it "shows proper messages according to the configured groups" do
+ bundle_config "path vendor"
+ bundle :install
+ expect(out).to include(bundle_show_path_message)
+ expect(out).to_not include("Gems in the group")
+ expect(out).to include(bundle_complete_message)
+
+ bundle_config "path vendor"
+ bundle_config "without emo"
+ bundle :install
+ expect(out).to include(bundle_show_path_message)
+ expect(out).to include("Gems in the group 'emo' were not installed")
+ expect(out).to include(bundle_complete_message)
+
+ bundle_config "path vendor"
+ bundle_config "without emo test"
+ bundle :install
+ expect(out).to include(bundle_show_path_message)
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not installed")
+ expect(out).to include(bundle_complete_message)
+
+ bundle_config "path vendor"
+ bundle_config "without emo obama test"
+ bundle :install
+ expect(out).to include(bundle_show_path_message)
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed")
+ expect(out).to include(bundle_complete_message)
+ end
+ end
+
+ describe "with an absolute `path` inside the cwd configured" do
+ let(:bundle_path) { bundled_app("cache") }
+
+ it "shows proper messages according to the configured groups" do
+ bundle_config "path #{bundle_path}"
+ bundle :install
+ expect(out).to include("Bundled gems are installed into `./cache`")
+ expect(out).to_not include("Gems in the group")
+ expect(out).to include(bundle_complete_message)
+ end
+ end
+
+ describe "with `path` configured to an absolute path outside the cwd" do
+ let(:bundle_path) { tmp("not_bundled_app") }
+
+ it "shows proper messages according to the configured groups" do
+ bundle_config "path #{bundle_path}"
+ bundle :install
+ expect(out).to include("Bundled gems are installed into `#{tmp("not_bundled_app")}`")
+ expect(out).to_not include("Gems in the group")
+ expect(out).to include(bundle_complete_message)
+ end
+ end
+
+ describe "with misspelled or non-existent gem name" do
+ before do
+ bundle_config "force_ruby_platform true"
+ end
+
+ it "should report a helpful error message" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "not-a-gem", :group => :development
+ G
+ expect(err).to include <<~EOS.strip
+ Could not find gem 'not-a-gem' in rubygems repository https://gem.repo1/ or installed locally.
+ EOS
+ end
+
+ it "should report a helpful error message with reference to cache if available" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "not-a-gem", :group => :development
+ G
+ expect(err).to include("Could not find gem 'not-a-gem' in").
+ and include("or in gems cached in vendor/cache.")
+ end
+ end
+
+ describe "for bundle update" do
+ it "shows proper messages according to the configured groups" do
+ bundle :update, all: true
+ expect(out).not_to include("Gems in the groups")
+ expect(out).to include(bundle_updated_message)
+
+ bundle_config "without emo"
+ bundle :install
+ bundle :update, all: true
+ expect(out).to include("Gems in the group 'emo' were not updated")
+ expect(out).to include(bundle_updated_message)
+
+ bundle_config "without emo test"
+ bundle :install
+ bundle :update, all: true
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not updated")
+ expect(out).to include(bundle_updated_message)
+
+ bundle_config "without emo obama test"
+ bundle :install
+ bundle :update, all: true
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not updated")
+ expect(out).to include(bundle_updated_message)
+ end
+ end
+end
diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb
index d8761bba26..5f80b9e534 100644
--- a/spec/bundler/commands/pristine_spec.rb
+++ b/spec/bundler/commands/pristine_spec.rb
@@ -2,9 +2,9 @@
require "bundler/vendored_fileutils"
-RSpec.describe "bundle pristine", :ruby_repo do
+RSpec.describe "bundle pristine" do
before :each do
- build_lib "baz", :path => bundled_app do |s|
+ build_lib "baz", path: bundled_app do |s|
s.version = "1.0.0"
s.add_development_dependency "baz-dev", "=1.0.0"
end
@@ -13,26 +13,28 @@ RSpec.describe "bundle pristine", :ruby_repo do
build_gem "weakling"
build_gem "baz-dev", "1.0.0"
build_gem "very_simple_binary", &:add_c_extension
- build_git "foo", :path => lib_path("foo")
- build_git "git_with_ext", :path => lib_path("git_with_ext"), &:add_c_extension
- build_lib "bar", :path => lib_path("bar")
+ build_git "foo", path: lib_path("foo")
+ build_git "git_with_ext", path: lib_path("git_with_ext"), &:add_c_extension
+ build_lib "bar", path: lib_path("bar")
end
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "weakling"
gem "very_simple_binary"
- gem "foo", :git => "#{lib_path("foo")}"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
gem "git_with_ext", :git => "#{lib_path("git_with_ext")}"
gem "bar", :path => "#{lib_path("bar")}"
gemspec
G
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
context "when sourced from RubyGems" do
it "reverts using cached .gem file" do
- spec = Bundler.definition.specs["weakling"].first
+ spec = find_spec("weakling")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
@@ -43,50 +45,115 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
it "does not delete the bundler gem" do
- ENV["BUNDLER_SPEC_KEEP_DEFAULT_BUNDLER_GEM"] = "true"
- system_gems :bundler
- bundle! "install"
- bundle! "pristine", :system_bundler => true
- bundle! "-v", :system_bundler => true
-
- expected = if Bundler::VERSION < "3.0"
- "Bundler version"
- else
- Bundler::VERSION
- end
+ bundle "install"
+ bundle "pristine"
+ bundle "-v"
- expect(out).to start_with(expected)
+ expect(out).to end_with(Bundler::VERSION)
end
end
context "when sourced from git repo" do
it "reverts by resetting to current revision`" do
- spec = Bundler.definition.specs["foo"].first
+ spec = find_spec("foo")
changed_file = Pathname.new(spec.full_gem_path).join("lib/foo.rb")
diff = "#Pristine spec changes"
File.open(changed_file, "a") {|f| f.puts diff }
expect(File.read(changed_file)).to include(diff)
- bundle! "pristine"
+ bundle "pristine"
expect(File.read(changed_file)).to_not include(diff)
end
it "removes added files" do
- spec = Bundler.definition.specs["foo"].first
+ spec = find_spec("foo")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
expect(changes_txt).to be_file
- bundle! "pristine"
+ bundle "pristine"
expect(changes_txt).not_to be_file
end
+
+ it "displays warning and ignores changes when a local config exists" do
+ spec = find_spec("foo")
+ bundle_config "local.#{spec.name} #{lib_path(spec.name)}"
+
+ changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
+ FileUtils.touch(changes_txt)
+ expect(changes_txt).to be_file
+
+ bundle "pristine"
+ expect(changes_txt).to be_file
+ expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is locally overridden.")
+ end
+
+ it "doesn't run multiple git processes for the same repository" do
+ nested_gems = [
+ "actioncable",
+ "actionmailer",
+ "actionpack",
+ "actionview",
+ "activejob",
+ "activemodel",
+ "activerecord",
+ "activestorage",
+ "activesupport",
+ "railties",
+ ]
+
+ build_repo2 do
+ nested_gems.each do |gem|
+ build_lib gem, path: lib_path("rails/#{gem}")
+ end
+
+ build_git "rails", path: lib_path("rails") do |s|
+ nested_gems.each do |gem|
+ s.add_dependency gem
+ end
+ end
+ end
+
+ install_gemfile <<-G
+ source 'https://rubygems.org'
+
+ git "#{lib_path("rails")}" do
+ gem "rails"
+ gem "actioncable"
+ gem "actionmailer"
+ gem "actionpack"
+ gem "actionview"
+ gem "activejob"
+ gem "activemodel"
+ gem "activerecord"
+ gem "activestorage"
+ gem "activesupport"
+ gem "railties"
+ end
+ G
+
+ changed_files = []
+ diff = "#Pristine spec changes"
+
+ nested_gems.each do |gem|
+ spec = find_spec(gem)
+ changed_files << Pathname.new(spec.full_gem_path).join("lib/#{gem}.rb")
+ File.open(changed_files.last, "a") {|f| f.puts diff }
+ end
+
+ bundle "pristine"
+
+ changed_files.each do |changed_file|
+ expect(File.read(changed_file)).to_not include(diff)
+ end
+ end
end
context "when sourced from gemspec" do
it "displays warning and ignores changes when sourced from gemspec" do
- spec = Bundler.definition.specs["baz"].first
+ spec = find_spec("baz")
changed_file = Pathname.new(spec.full_gem_path).join("lib/baz.rb")
diff = "#Pristine spec changes"
@@ -95,12 +162,12 @@ RSpec.describe "bundle pristine", :ruby_repo do
bundle "pristine"
expect(File.read(changed_file)).to include(diff)
- expect(out).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is sourced from local path.")
+ expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is sourced from local path.")
end
it "reinstall gemspec dependency" do
- spec = Bundler.definition.specs["baz-dev"].first
- changed_file = Pathname.new(spec.full_gem_path).join("lib/baz-dev.rb")
+ spec = find_spec("baz-dev")
+ changed_file = Pathname.new(spec.full_gem_path).join("lib/baz/dev.rb")
diff = "#Pristine spec changes"
File.open(changed_file, "a") {|f| f.puts "#Pristine spec changes" }
@@ -113,37 +180,37 @@ RSpec.describe "bundle pristine", :ruby_repo do
context "when sourced from path" do
it "displays warning and ignores changes when sourced from local path" do
- spec = Bundler.definition.specs["bar"].first
+ spec = find_spec("bar")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
expect(changes_txt).to be_file
bundle "pristine"
- expect(out).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is sourced from local path.")
+ expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is sourced from local path.")
expect(changes_txt).to be_file
end
end
context "when passing a list of gems to pristine" do
it "resets them" do
- foo = Bundler.definition.specs["foo"].first
+ foo = find_spec("foo")
foo_changes_txt = Pathname.new(foo.full_gem_path).join("lib/changes.txt")
FileUtils.touch(foo_changes_txt)
expect(foo_changes_txt).to be_file
- bar = Bundler.definition.specs["bar"].first
+ bar = find_spec("bar")
bar_changes_txt = Pathname.new(bar.full_gem_path).join("lib/changes.txt")
FileUtils.touch(bar_changes_txt)
expect(bar_changes_txt).to be_file
- weakling = Bundler.definition.specs["weakling"].first
+ weakling = find_spec("weakling")
weakling_changes_txt = Pathname.new(weakling.full_gem_path).join("lib/changes.txt")
FileUtils.touch(weakling_changes_txt)
expect(weakling_changes_txt).to be_file
- bundle! "pristine foo bar weakling"
+ bundle "pristine foo bar weakling"
- expect(out).to include("Cannot pristine bar (1.0). Gem is sourced from local path.").
- and include("Installing weakling 1.0")
+ expect(err).to include("Cannot pristine bar (1.0). Gem is sourced from local path.")
+ expect(out).to include("Installing weakling 1.0")
expect(weakling_changes_txt).not_to be_file
expect(foo_changes_txt).not_to be_file
@@ -151,42 +218,58 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
it "raises when one of them is not in the lockfile" do
- bundle "pristine abcabcabc"
- expect(out).to include("Could not find gem 'abcabcabc'.")
+ bundle "pristine abcabcabc", raise_on_error: false
+ expect(err).to include("Could not find gem 'abcabcabc'.")
end
end
context "when a build config exists for one of the gems" do
- let(:very_simple_binary) { Bundler.definition.specs["very_simple_binary"].first }
+ let(:very_simple_binary) { find_spec("very_simple_binary") }
let(:c_ext_dir) { Pathname.new(very_simple_binary.full_gem_path).join("ext") }
let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" }
- before { bundle "config build.very_simple_binary -- #{build_opt}" }
+ before { bundle_config "build.very_simple_binary -- #{build_opt}" }
# This just verifies that the generated Makefile from the c_ext gem makes
# use of the build_args from the bundle config
it "applies the config when installing the gem" do
- bundle! "pristine"
+ bundle "pristine"
makefile_contents = File.read(c_ext_dir.join("Makefile").to_s)
- expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/)
- expect(makefile_contents).to match(/LIBPATH =.*-L#{c_ext_dir}/)
+ expect(makefile_contents).to match(/libpath =.*#{Regexp.escape(c_ext_dir.to_s)}/)
+ expect(makefile_contents).to match(/LIBPATH =.*-L#{Regexp.escape(c_ext_dir.to_s)}/)
end
end
context "when a build config exists for a git sourced gem" do
- let(:git_with_ext) { Bundler.definition.specs["git_with_ext"].first }
+ let(:git_with_ext) { find_spec("git_with_ext") }
let(:c_ext_dir) { Pathname.new(git_with_ext.full_gem_path).join("ext") }
let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" }
- before { bundle "config build.git_with_ext -- #{build_opt}" }
+ before { bundle_config "build.git_with_ext -- #{build_opt}" }
# This just verifies that the generated Makefile from the c_ext gem makes
# use of the build_args from the bundle config
it "applies the config when installing the gem" do
- bundle! "pristine"
+ bundle "pristine"
makefile_contents = File.read(c_ext_dir.join("Makefile").to_s)
- expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/)
- expect(makefile_contents).to match(/LIBPATH =.*-L#{c_ext_dir}/)
+ expect(makefile_contents).to match(/libpath =.*#{Regexp.escape(c_ext_dir.to_s)}/)
+ expect(makefile_contents).to match(/LIBPATH =.*-L#{Regexp.escape(c_ext_dir.to_s)}/)
+ end
+ end
+
+ context "when BUNDLE_GEMFILE doesn't exist" do
+ before do
+ bundle "pristine", env: { "BUNDLE_GEMFILE" => "does/not/exist" }, raise_on_error: false
+ end
+
+ it "shows a meaningful error" do
+ expect(err).to eq("#{bundled_app("does/not/exist")} not found")
+ end
+ end
+
+ def find_spec(name)
+ without_env_side_effects do
+ Bundler.definition.specs[name].first
end
end
end
diff --git a/spec/bundler/commands/remove_spec.rb b/spec/bundler/commands/remove_spec.rb
index faeb654b14..8a2e6778ea 100644
--- a/spec/bundler/commands/remove_spec.rb
+++ b/spec/bundler/commands/remove_spec.rb
@@ -4,27 +4,42 @@ RSpec.describe "bundle remove" do
context "when no gems are specified" do
it "throws error" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
- bundle "remove"
+ bundle "remove", raise_on_error: false
- expect(out).to include("Please specify gems to remove.")
+ expect(err).to include("Please specify gems to remove.")
end
end
- context "when --install flag is specified" do
- it "removes gems from .bundle" do
- gemfile <<-G
- source "file://#{gem_repo1}"
+ context "after 'bundle install' is run" do
+ describe "running 'bundle remove GEM_NAME'" do
+ it "removes it from the lockfile" do
+ myrack_dep = <<~L
- gem "rack"
- G
+ DEPENDENCIES
+ myrack
+
+ L
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include(myrack_dep)
- bundle! "remove rack --install"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- expect(the_bundle).to_not include_gems "rack"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ G
+ expect(lockfile).to_not include(myrack_dep)
+ end
end
end
@@ -32,49 +47,76 @@ RSpec.describe "bundle remove" do
context "when gem is present in gemfile" do
it "shows success for removed gem" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(the_bundle).to_not include_gems "myrack"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
+
+ context "when gem is specified in multiple lines" do
+ it "shows success for removed gem" do
+ build_git "myrack"
+
+ gemfile <<-G
+ source 'https://gem.repo1'
+
+ gem 'git'
+ gem 'myrack',
+ git: "#{lib_path("myrack-1.0")}",
+ branch: 'main'
+ gem 'nokogiri'
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source 'https://gem.repo1'
+
+ gem 'git'
+ gem 'nokogiri'
+ G
+ end
+ end
end
context "when gem is not present in gemfile" do
it "shows warning for gem that could not be removed" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
- bundle "remove rack"
+ bundle "remove myrack", raise_on_error: false
- expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
end
- describe "remove mutiple gems from gemfile" do
+ describe "remove multiple gems from gemfile" do
context "when all gems are present in gemfile" do
it "shows success fir all removed gems" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rails"
G
- bundle! "remove rack rails"
+ bundle "remove myrack rails"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(out).to include("rails was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
@@ -82,18 +124,18 @@ RSpec.describe "bundle remove" do
context "when some gems are not present in the gemfile" do
it "shows warning for those not present and success for those that can be removed" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
gem "minitest"
gem "rspec"
G
- bundle "remove rails rack minitest"
+ bundle "remove rails myrack minitest", raise_on_error: false
- expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
gem "rails"
gem "minitest"
@@ -106,16 +148,16 @@ RSpec.describe "bundle remove" do
context "with inline groups" do
it "removes the specified gem" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", :group => [:dev]
+ gem "myrack", :group => [:dev]
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
@@ -124,18 +166,42 @@ RSpec.describe "bundle remove" do
context "when single group block with gem to be removed is present" do
it "removes the group block" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test do
gem "rspec"
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ G
+ end
+ end
+
+ context "when gem to be removed is outside block" do
+ it "does not modify group" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ group :test do
+ gem "coffee-script-source"
+ end
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+
+ group :test do
+ gem "coffee-script-source"
+ end
G
end
end
@@ -143,7 +209,7 @@ RSpec.describe "bundle remove" do
context "when an empty block is also present" do
it "removes all empty blocks" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test do
gem "rspec"
@@ -153,38 +219,38 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
- context "when the gem belongs to mutiple groups" do
+ context "when the gem belongs to multiple groups" do
it "removes the groups" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test, :serioustest do
gem "rspec"
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
- context "when the gem is present in mutiple groups" do
+ context "when the gem is present in multiple groups" do
it "removes all empty blocks" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :one do
gem "rspec"
@@ -195,11 +261,11 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
@@ -209,7 +275,7 @@ RSpec.describe "bundle remove" do
context "when all the groups will be empty after removal" do
it "removes the empty nested blocks" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test do
group :serioustest do
@@ -218,11 +284,11 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
@@ -230,10 +296,10 @@ RSpec.describe "bundle remove" do
context "when outer group will not be empty after removal" do
it "removes only empty blocks" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test do
- gem "rack-test"
+ gem "myrack-test"
group :serioustest do
gem "rspec"
@@ -241,14 +307,14 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
group :test do
- gem "rack-test"
+ gem "myrack-test"
end
G
@@ -258,25 +324,25 @@ RSpec.describe "bundle remove" do
context "when inner group will not be empty after removal" do
it "removes only empty blocks" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
group :test do
group :serioustest do
gem "rspec"
- gem "rack-test"
+ gem "myrack-test"
end
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
group :test do
group :serioustest do
- gem "rack-test"
+ gem "myrack-test"
end
end
G
@@ -285,45 +351,41 @@ RSpec.describe "bundle remove" do
end
describe "arbitrary gemfile" do
- context "when mutiple gems are present in same line" do
+ context "when multiple gems are present in same line" do
it "shows warning for gems not removed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"; gem "rails"
+ source "https://gem.repo1"
+ gem "myrack"; gem "rails"
G
- bundle "remove rails"
+ bundle "remove rails", raise_on_error: false
- if Gem::VERSION >= "1.6.0"
- expect(out).to include("Gems could not be removed. rack (>= 0) would also have been removed.")
- else
- expect(out).to include("Gems could not be removed. rack (>= 0, runtime) would also have been removed.")
- end
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
- gem "rack"; gem "rails"
+ expect(err).to include("Gems could not be removed. myrack (>= 0) would also have been removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ gem "myrack"; gem "rails"
G
end
end
context "when some gems could not be removed" do
it "shows warning for gems not removed and success for those removed" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem"rack"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem"myrack"
gem"rspec"
gem "rails"
gem "minitest"
G
- bundle! "remove rails rack rspec minitest"
+ bundle "remove rails myrack rspec minitest"
expect(out).to include("rails was removed.")
expect(out).to include("minitest was removed.")
- expect(out).to include("rack, rspec could not be removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
- gem"rack"
+ expect(out).to include("myrack, rspec could not be removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ gem"myrack"
gem"rspec"
G
end
@@ -332,31 +394,31 @@ RSpec.describe "bundle remove" do
context "with sources" do
before do
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "rspec"
end
end
it "removes gems and empty source blocks" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
- source "file://#{gem_repo3}" do
+ source "https://gem.repo3" do
gem "rspec"
end
G
- bundle! "install"
+ bundle "install"
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
end
end
@@ -364,40 +426,40 @@ RSpec.describe "bundle remove" do
describe "with eval_gemfile" do
context "when gems are present in both gemfiles" do
it "removes the gems" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
end
end
context "when gems are present in other gemfile" do
it "removes the gems" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
- expect(out).to include("rack was removed.")
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
+ expect(out).to include("myrack was removed.")
end
end
@@ -409,65 +471,61 @@ RSpec.describe "bundle remove" do
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
- bundle "remove rack"
+ bundle "remove myrack", raise_on_error: false
- expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ expect(err).to include("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
context "when the gem is present in parent file but not in gemfile specified by eval_gemfile" do
it "removes the gem" do
- create_file "Gemfile-other", <<-G
+ gemfile "Gemfile-other", <<-G
gem "rails"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack", raise_on_error: false
- expect(out).to include("rack was removed.")
- expect(out).to include("`rack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(err).to include("`myrack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
end
end
- context "when gems can not be removed from other gemfile" do
+ context "when gems cannot be removed from other gemfile" do
it "shows error" do
- create_file "Gemfile-other", <<-G
- gem "rails"; gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "rails"; gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack", raise_on_error: false
- expect(out).to include("rack was removed.")
- if Gem::VERSION >= "1.6.0"
- expect(out).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
- else
- expect(out).to include("Gems could not be removed. rails (>= 0, runtime) would also have been removed.")
- end
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
@@ -476,51 +534,47 @@ RSpec.describe "bundle remove" do
context "when gems could not be removed from parent gemfile" do
it "shows error" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rails"; gem "rack"
+ gem "rails"; gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack", raise_on_error: false
- if Gem::VERSION >= "1.6.0"
- expect(out).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
- else
- expect(out).to include("Gems could not be removed. rails (>= 0, runtime) would also have been removed.")
- end
- expect(bundled_app("Gemfile-other").read).to include("gem \"rack\"")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
+ expect(bundled_app("Gemfile-other").read).to include("gem \"myrack\"")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rails"; gem "rack"
+ gem "rails"; gem "myrack"
G
end
end
context "when gem present in gemfiles but could not be removed from one from one of them" do
- it "removes gem which can be removed and shows warning for file from which it can not be removed" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ it "removes gem which can be removed and shows warning for file from which it cannot be removed" do
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem"rack"
+ gem"myrack"
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
+ expect(out).to include("myrack was removed.")
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
end
end
end
@@ -528,18 +582,18 @@ RSpec.describe "bundle remove" do
context "with install_if" do
it "removes gems inside blocks and empty blocks" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
install_if(lambda { false }) do
- gem "rack"
+ gem "myrack"
end
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
@@ -547,37 +601,136 @@ RSpec.describe "bundle remove" do
context "with env" do
it "removes gems inside blocks and empty blocks" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" do
- gem "rack"
+ gem "myrack"
end
G
- bundle! "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
- source "file://#{gem_repo1}"
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
G
end
end
context "with gemspec" do
it "should not remove the gem" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo.gemspec", "")
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
install_gemfile(<<-G)
- source "file://#{gem_repo1}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
- bundle! "remove foo"
+ bundle "remove foo"
expect(out).to include("foo could not be removed.")
end
end
+
+ describe "with comments that mention gems" do
+ context "when comment is a separate line comment" do
+ it "does not remove the line comment" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ # gem "myrack" might be used in the future
+ gem "myrack"
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+
+ # gem "myrack" might be used in the future
+ G
+ end
+ end
+
+ context "when gem specified for removal has an inline comment" do
+ it "removes the inline comment" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack" # this can be removed
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ G
+ end
+ end
+
+ context "when gem specified for removal is mentioned in other gem's comment" do
+ it "does not remove other gem" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
+
+ gem "myrack"
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to_not include("puma was removed.")
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
+ G
+ end
+ end
+
+ context "when gem specified for removal has a comment that mentions other gem" do
+ it "does not remove other gem" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
+
+ gem "myrack"
+ G
+
+ bundle "remove puma"
+
+ expect(out).to include("puma was removed.")
+ expect(out).to_not include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ G
+ end
+ end
+ end
+
+ context "when gem definition has parentheses" do
+ it "removes the gem" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem("myrack")
+ gem("myrack", ">= 0")
+ gem("myrack", require: false)
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ G
+ end
+ end
end
diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb
index a5c6beec1a..d0d55ffbb9 100644
--- a/spec/bundler/commands/show_spec.rb
+++ b/spec/bundler/commands/show_spec.rb
@@ -1,28 +1,30 @@
# frozen_string_literal: true
-RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
+RSpec.describe "bundle show" do
context "with a standard Gemfile" do
before :each do
+ build_repo2
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "rails"
G
end
it "creates a Gemfile.lock if one did not exist" do
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "show"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "creates a Gemfile.lock when invoked with a gem name" do
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "show rails"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "prints path if gem exists in bundle" do
@@ -30,60 +32,18 @@ RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- context "when show command deprecation is enabled" do
- before { bundle "config major_deprecations yes" }
-
- it "prints path if gem exists in bundle" do
- bundle "show rails"
- expect(out).to eq(
- "[DEPRECATED FOR 3.0] use `bundle info rails` instead of `bundle show rails`\n" +
- default_bundle_path("gems", "rails-2.3.2").to_s
- )
- end
-
- it "prints the path to the running bundler" do
- bundle "show bundler"
- expect(out).to eq(
- "[DEPRECATED FOR 3.0] use `bundle info bundler` instead of `bundle show bundler`\n" +
- root.to_s
- )
- end
-
- it "prints path if gem exists in bundle (with --paths option)" do
- bundle "show rails --paths"
- expect(out).to eq(
- "[DEPRECATED FOR 3.0] use `bundle info rails --path` instead of `bundle show rails --paths`\n" +
- default_bundle_path("gems", "rails-2.3.2").to_s
- )
- end
-
- it "prints path of all gems in bundle sorted by name" do
- bundle "show --paths"
-
- expect(out).to include(default_bundle_path("gems", "rake-10.0.2").to_s)
- expect(out).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
-
- out_lines = out.split("\n")
- expect(out_lines[0]).to eq("[DEPRECATED FOR 3.0] use `bundle list` instead of `bundle show --paths`")
-
- # Gem names are the last component of their path.
- gem_list = out_lines[1..-1].map {|p| p.split("/").last }
- expect(gem_list).to eq(gem_list.sort)
- end
- end
-
it "prints path if gem exists in bundle (with --paths option)" do
bundle "show rails --paths"
expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- it "warns if path no longer exists on disk" do
- FileUtils.rm_rf(default_bundle_path("gems", "rails-2.3.2"))
+ it "warns if specification is installed, but path does not exist on disk" do
+ FileUtils.rm_r(default_bundle_path("gems", "rails-2.3.2"))
bundle "show rails"
- expect(out).to match(/has been deleted/i).
- and include(default_bundle_path("gems", "rails-2.3.2").to_s)
+ expect(err).to match(/is missing/i)
+ expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s)
end
it "prints the path to the running bundler" do
@@ -92,14 +52,14 @@ RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
end
it "complains if gem not in bundle" do
- bundle "show missing"
- expect(out).to match(/could not find gem 'missing'/i)
+ bundle "show missing", raise_on_error: false
+ expect(err).to match(/could not find gem 'missing'/i)
end
it "prints path of all gems in bundle sorted by name" do
bundle "show --paths"
- expect(out).to include(default_bundle_path("gems", "rake-10.0.2").to_s)
+ expect(out).to include(default_bundle_path("gems", "rake-#{rake_version}").to_s)
expect(out).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
# Gem names are the last component of their path.
@@ -110,17 +70,41 @@ RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
it "prints summary of gems" do
bundle "show --verbose"
- loaded_bundler_spec = Bundler.load.specs["bundler"]
- expected = if !loaded_bundler_spec.empty?
- loaded_bundler_spec[0].homepage
- else
- "No website available."
+ expect(out).to include <<~MSG
+ * actionmailer (2.3.2)
+ \tSummary: This is just a fake gem for testing
+ \tHomepage: http://example.com
+ \tStatus: Up to date
+ MSG
+ end
+
+ it "includes bundler in the summary of gems" do
+ bundle "show --verbose"
+
+ expect(out).to include <<~MSG
+ * bundler (#{Bundler::VERSION})
+ \tSummary: The best way to manage your application's dependencies
+ \tHomepage: https://bundler.io
+ \tStatus: Up to date
+ MSG
+ end
+
+ it "includes up to date status in summary of gems" do
+ update_repo2 do
+ build_gem "rails", "3.0.0"
end
- expect(out).to include("* actionmailer (2.3.2)")
- expect(out).to include("\tSummary: This is just a fake gem for testing")
- expect(out).to include("\tHomepage: #{expected}")
- expect(out).to include("\tStatus: Up to date")
+ bundle "show --verbose"
+
+ expect(out).to include <<~MSG
+ * rails (2.3.2)
+ \tSummary: This is just a fake gem for testing
+ \tHomepage: http://example.com
+ \tStatus: Outdated - 2.3.2 < 3.0.0
+ MSG
+
+ # check lockfile is not accidentally updated
+ expect(lockfile).to include("actionmailer (2.3.2)")
end
end
@@ -136,11 +120,11 @@ RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
expect(the_bundle).to include_gems "foo 1.0"
bundle :show
- expect(out).to include("foo (1.0 #{@git.ref_for("master", 6)}")
+ expect(out).to include("foo (1.0 #{@git.ref_for("main", 6)}")
end
- it "prints out branch names other than master" do
- update_git "foo", :branch => "omg" do |s|
+ it "prints out branch names other than main" do
+ update_git "foo", branch: "omg" do |s|
s.write "lib/foo.rb", "FOO = '1.0.omg'"
end
@revision = revision_for(lib_path("foo-1.0"))[0...6]
@@ -164,81 +148,70 @@ RSpec.describe "bundle show", :bundler => "< 3", :ruby => ">= 2.0" do
expect(out).to include("foo (1.0 #{sha[0..6]})")
end
- it "handles when a version is a '-' prerelease", :rubygems => "2.1" do
- @git = build_git("foo", "1.0.0-beta.1", :path => lib_path("foo"))
+ it "handles when a version is a '-' prerelease" do
+ @git = build_git("foo", "1.0.0-beta.1", path: lib_path("foo"))
install_gemfile <<-G
gem "foo", "1.0.0-beta.1", :git => "#{lib_path("foo")}"
G
expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1"
- bundle! :show
+ bundle :show
expect(out).to include("foo (1.0.0.pre.beta.1")
end
end
context "in a fresh gem in a blank git repo" do
before :each do
- build_git "foo", :path => lib_path("foo")
- in_app_root_custom lib_path("foo")
- File.open("Gemfile", "w") {|f| f.puts "gemspec" }
- sys_exec "rm -rf .git && git init"
+ build_git "foo", path: lib_path("foo")
+ File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts "gemspec" }
+ sys_exec "rm -rf .git && git init", dir: lib_path("foo")
end
it "does not output git errors" do
- bundle :show
- expect(err).to lack_errors
+ bundle :show, dir: lib_path("foo")
+ expect(err_without_deprecations).to be_empty
end
end
it "performs an automatic bundle install" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo"
G
- bundle "config auto_install 1"
+ bundle_config "auto_install 1"
bundle :show
expect(out).to include("Installing foo 1.0")
end
- context "with an invalid regexp for gem name" do
- it "does not find the gem" do
+ context "with a valid regexp for gem name" do
+ it "presents alternatives", :readline do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
- invalid_regexp = "[]"
-
- bundle "show #{invalid_regexp}"
- expect(out).to include("Could not find gem '#{invalid_regexp}'.")
+ bundle "show rac"
+ expect(out).to match(/\A1 : myrack\n2 : myrack-obama\n0 : - exit -(\n>|\z)/)
end
end
- context "--outdated option" do
- # Regression test for https://github.com/bundler/bundler/issues/5375
- before do
- build_repo2
- end
-
- it "doesn't update gems to newer versions" do
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
+ context "with an invalid regexp for gem name" do
+ it "does not find the gem" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "rails"
G
- expect(the_bundle).to include_gem("rails 2.3.2")
-
- update_repo2 do
- build_gem "rails", "3.0.0" do |s|
- s.executables = "rails"
- end
- end
-
- bundle! "show --outdated"
+ invalid_regexp = "[]"
- bundle! "install"
- expect(the_bundle).to include_gem("rails 2.3.2")
+ bundle "show #{invalid_regexp}", raise_on_error: false
+ expect(err).to include("Could not find gem '#{invalid_regexp}'.")
end
end
end
+
+RSpec.describe "bundle show", bundler: "5" do
+ pending "shows a friendly error about the command removal"
+end
diff --git a/spec/bundler/commands/ssl_spec.rb b/spec/bundler/commands/ssl_spec.rb
new file mode 100644
index 0000000000..4220731b69
--- /dev/null
+++ b/spec/bundler/commands/ssl_spec.rb
@@ -0,0 +1,373 @@
+# frozen_string_literal: true
+
+require "bundler/cli"
+require "bundler/cli/doctor"
+require "bundler/cli/doctor/ssl"
+require_relative "../support/artifice/helpers/artifice"
+require "bundler/vendored_persistent.rb"
+
+RSpec.describe "bundle doctor ssl" do
+ before(:each) do
+ require_rack_test
+ require_relative "../support/artifice/helpers/endpoint"
+
+ @dummy_endpoint = Class.new(Endpoint) do
+ get "/" do
+ end
+ end
+
+ @previous_ui = Bundler.ui
+ Bundler.ui = Bundler::UI::Shell.new
+ Bundler.ui.level = "info"
+
+ @previous_client = Gem::Request::ConnectionPools.client
+ Artifice.activate_with(@dummy_endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+ end
+
+ after(:each) do
+ Bundler.ui = @previous_ui
+ Artifice.deactivate
+ Gem::Request::ConnectionPools.client = @previous_client
+ end
+
+ context "when a diagnostic fails" do
+ it "prints the diagnostic when openssl can't be loaded" do
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ allow(subject).to receive(:require).with("openssl").and_raise(LoadError)
+
+ expected_err = <<~MSG
+ Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to rubygems.org.
+ You'll need to recompile or reinstall Ruby with OpenSSL support and try again.
+ MSG
+
+ expect { subject.run }.to output("").to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to certificate verification", :ruby_repo do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "certificate verify failed"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (certificate verification)
+ RubyGems: failed (certificate verification)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Below affect only Ruby net/http connections:
+ SSL_CERT_FILE: exists #{OpenSSL::X509::DEFAULT_CERT_FILE}
+ SSL_CERT_DIR: exists #{OpenSSL::X509::DEFAULT_CERT_DIR}
+
+ Your Ruby can't connect to rubygems.org because you are missing the certificate files OpenSSL needs to verify you are connecting to the genuine rubygems.org servers.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a too old tls version" do
+ subject = Bundler::CLI::Doctor::SSL.new({})
+
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Your Ruby can't connect to rubygems.org because your version of OpenSSL is too old.
+ You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL.
+
+ MSG
+
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to unsupported tls 1.3 version" do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Your Ruby can't connect to rubygems.org because TLS1_3 isn't supported yet.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new("tls-version": "1.3")
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a bundler and rubygems connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Ruby net/http: success
+
+ For some reason, your Ruby installation can connect to rubygems.org, but neither RubyGems nor Bundler can.
+ The most likely fix is to manually upgrade RubyGems by following the instructions at http://ruby.to/ssl-check-failed.
+ After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣
+
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a bundler connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ if request.user_agent.include?("bundler")
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ RubyGems: success
+ Ruby net/http: success
+
+ Although your Ruby installation and RubyGems can both connect to rubygems.org, Bundler is having trouble.
+ The most likely way to fix this is to upgrade Bundler by running `gem install bundler`.
+ Run this script again after doing that to make sure everything is all set.
+ If you're still having trouble, check out the troubleshooting guide at http://ruby.to/ssl-check-failed.
+
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a RubyGems connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ if request.user_agent.include?("Ruby, RubyGems")
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ Ruby net/http: success
+
+ It looks like Ruby and Bundler can connect to rubygems.org, but RubyGems itself cannot.
+ You can likely solve this by manually downloading and installing a RubyGems update.
+ Visit http://ruby.to/ssl-check-failed for instructions on how to manually upgrade RubyGems.
+
+ MSG
+
+ expected_err = <<~MSG
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+ end
+
+ context "when no diagnostic fails" do
+ it "prints the SSL environment" do
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to rubygems.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output("").to_stderr
+ end
+
+ it "uses the tls_version verify mode and host when given as option" do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ class << self
+ attr_accessor :verify_mode, :min_version, :max_version
+ end
+
+ def connect
+ self.class.verify_mode = verify_mode
+ self.class.min_version = min_version
+ self.class.max_version = max_version
+
+ super
+ end
+ end
+
+ net_http.endpoint = @dummy_endpoint
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://example.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to example.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new("tls-version": "1.3", "verify-mode": :none, host: "example.org")
+ expect { subject.run }.to output(expected_out).to_stdout.and output("").to_stderr
+ expect(net_http.verify_mode).to eq(0)
+ expect(net_http.min_version.to_s).to eq("TLS1_3")
+ expect(net_http.max_version.to_s).to eq("TLS1_3")
+ end
+
+ it "warns when TLS1.2 is not supported" do
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to rubygems.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ expected_err = <<~MSG
+
+ WARNING: Although your Ruby can connect to rubygems.org today, your OpenSSL is very old!
+ WARNING: You will need to upgrade OpenSSL to use rubygems.org.
+
+ MSG
+
+ previous_version = OpenSSL::SSL::TLS1_2_VERSION
+ OpenSSL::SSL.send(:remove_const, :TLS1_2_VERSION)
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ ensure
+ OpenSSL::SSL.const_set(:TLS1_2_VERSION, previous_version)
+ end
+ end
+end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 1effba6526..03a3786d80 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -1,98 +1,148 @@
# frozen_string_literal: true
RSpec.describe "bundle update" do
- before :each do
- build_repo2
+ describe "with no arguments" do
+ before do
+ build_repo2
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
- G
- end
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
- describe "with no arguments", :bundler => "< 3" do
it "updates the entire bundle" do
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "activesupport", "3.0"
end
bundle "update"
expect(out).to include("Bundle updated!")
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
end
it "doesn't delete the Gemfile.lock file if something goes wrong" do
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
exit!
G
- bundle "update"
- expect(bundled_app("Gemfile.lock")).to exist
+ bundle "update", raise_on_error: false
+ expect(bundled_app_lock).to exist
end
end
- describe "with --all", :bundler => "3" do
+ describe "with --verbose" do
+ before do
+ build_repo2
+
+ install_gemfile <<~G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+ end
+
+ it "logs the reason for re-resolving" do
+ bundle "update --verbose"
+ expect(out).not_to include("Found changes from the lockfile")
+ expect(out).to include("Re-resolving dependencies because bundler is unlocking")
+ end
+ end
+
+ describe "with --all" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "updates the entire bundle" do
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "activesupport", "3.0"
end
- bundle! "update", :all => true
+ bundle "update", all: true
expect(out).to include("Bundle updated!")
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
end
it "doesn't delete the Gemfile.lock file if something goes wrong" do
+ install_gemfile "source 'https://gem.repo1'"
+
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
exit!
G
- bundle "update", :all => true
- expect(bundled_app("Gemfile.lock")).to exist
+ bundle "update", all: true, raise_on_error: false
+ expect(bundled_app_lock).to exist
end
end
describe "with --gemfile" do
- it "creates lock files based on the Gemfile name" do
+ it "creates lockfiles based on the Gemfile name" do
gemfile bundled_app("OmgFile"), <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
G
- bundle! "update --gemfile OmgFile", :all => bundle_update_requires_all?
+ bundle "update --gemfile OmgFile", all: true
expect(bundled_app("OmgFile.lock")).to exist
end
end
context "when update_requires_all_flag is set" do
- before { bundle! "config update_requires_all_flag true" }
+ before { bundle_config "update_requires_all_flag true" }
it "errors when passed nothing" do
- install_gemfile! ""
- bundle :update
- expect(out).to eq("To update everything, pass the `--all` flag.")
+ install_gemfile "source 'https://gem.repo1'"
+ bundle :update, raise_on_error: false
+ expect(err).to eq("To update everything, pass the `--all` flag.")
end
it "errors when passed --all and another option" do
- install_gemfile! ""
- bundle "update --all foo"
- expect(out).to eq("Cannot specify --all along with specific options.")
+ install_gemfile "source 'https://gem.repo1'"
+ bundle "update --all foo", raise_on_error: false
+ expect(err).to eq("Cannot specify --all along with specific options.")
end
it "updates everything when passed --all" do
- install_gemfile! ""
+ install_gemfile "source 'https://gem.repo1'"
bundle "update --all"
expect(out).to include("Bundle updated!")
end
end
describe "--quiet argument" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "hides UI messages" do
bundle "update --quiet"
expect(out).not_to include("Bundle updated!")
@@ -100,133 +150,604 @@ RSpec.describe "bundle update" do
end
describe "with a top level dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "unlocks all child dependencies that are unrelated to other locked dependencies" do
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "activesupport", "3.0"
end
- bundle "update rack-obama"
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 2.3.5"
+ bundle "update myrack-obama"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 2.3.5"
end
end
describe "with an unknown dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "should inform the user" do
- bundle "update halting-problem-solver"
- expect(out).to include "Could not find gem 'halting-problem-solver'"
+ bundle "update halting-problem-solver", raise_on_error: false
+ expect(err).to include "Could not find gem 'halting-problem-solver'"
end
it "should suggest alternatives" do
- bundle "update active-support"
- expect(out).to include "Did you mean activesupport?"
+ bundle "update platformspecific", raise_on_error: false
+ expect(err).to include "Did you mean 'platform_specific'?"
end
end
describe "with a child dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "should update the child dependency" do
- update_repo2
- bundle "update rack"
- expect(the_bundle).to include_gems "rack 1.2"
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+ end
+
+ bundle "update myrack"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
describe "when a possible resolve requires an older version of a locked gem" do
- context "and only_update_to_newer_versions is set" do
- before do
- bundle! "config only_update_to_newer_versions true"
+ it "does not go to an older version" do
+ build_repo4 do
+ build_gem "tilt", "2.0.8"
+ build_gem "slim", "3.0.9" do |s|
+ s.add_dependency "tilt", [">= 1.3.3", "< 2.1"]
+ end
+ build_gem "slim_lint", "0.16.1" do |s|
+ s.add_dependency "slim", [">= 3.0", "< 5.0"]
+ end
+ build_gem "slim-rails", "0.2.1" do |s|
+ s.add_dependency "slim", ">= 0.9.2"
+ end
+ build_gem "slim-rails", "3.1.3" do |s|
+ s.add_dependency "slim", "~> 3.0"
+ end
end
- it "does not go to an older version" do
- build_repo4 do
- build_gem "tilt", "2.0.8"
- build_gem "slim", "3.0.9" do |s|
- s.add_dependency "tilt", [">= 1.3.3", "< 2.1"]
- end
- build_gem "slim_lint", "0.16.1" do |s|
- s.add_dependency "slim", [">= 3.0", "< 5.0"]
- end
- build_gem "slim-rails", "0.2.1" do |s|
- s.add_dependency "slim", ">= 0.9.2"
- end
- build_gem "slim-rails", "3.1.3" do |s|
- s.add_dependency "slim", "~> 3.0"
- end
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "slim-rails"
+ gem "slim_lint"
+ G
+
+ expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+
+ build_repo4 do
+ build_gem "slim", "4.0.0" do |s|
+ s.add_dependency "tilt", [">= 2.0.6", "< 2.1"]
end
+ end
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- gem "slim-rails"
- gem "slim_lint"
- G
+ bundle "update", all: true
- expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ end
- update_repo4 do
- build_gem "slim", "4.0.0" do |s|
- s.add_dependency "tilt", [">= 2.0.6", "< 2.1"]
- end
+ it "does not go to an older version, even if the version upgrade that could cause another gem to downgrade is activated first" do
+ build_repo4 do
+ # countries is processed before country_select by the resolver due to having less spec groups (groups of versions with the same dependencies) (2 vs 3)
+
+ build_gem "countries", "2.1.4"
+ build_gem "countries", "3.1.0"
+
+ build_gem "countries", "4.0.0" do |s|
+ s.add_dependency "sixarm_ruby_unaccent", "~> 1.1"
end
- bundle! "update", :all => bundle_update_requires_all?
+ build_gem "country_select", "1.2.0"
- expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ build_gem "country_select", "2.1.4" do |s|
+ s.add_dependency "countries", "~> 2.0"
+ end
+ build_gem "country_select", "3.1.1" do |s|
+ s.add_dependency "countries", "~> 2.0"
+ end
+
+ build_gem "country_select", "5.1.0" do |s|
+ s.add_dependency "countries", "~> 3.0"
+ end
+
+ build_gem "sixarm_ruby_unaccent", "1.1.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "country_select"
+ gem "countries"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "countries", "3.1.0")
+ c.checksum(gem_repo4, "country_select", "5.1.0")
end
- it "should still downgrade if forced by the Gemfile" do
- build_repo4 do
- build_gem "a"
- build_gem "b", "1.0"
- build_gem "b", "2.0"
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ countries (3.1.0)
+ country_select (5.1.0)
+ countries (~> 3.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ countries
+ country_select
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ previous_lockfile = lockfile
+
+ bundle "lock --update", env: { "DEBUG" => "1" }, verbose: true
+
+ expect(lockfile).to eq(previous_lockfile)
+ end
+
+ it "does not downgrade direct dependencies when run with --conservative" do
+ build_repo4 do
+ build_gem "oauth2", "2.0.6" do |s|
+ s.add_dependency "faraday", ">= 0.17.3", "< 3.0"
end
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- gem "a"
- gem "b"
- G
+ build_gem "oauth2", "1.4.10" do |s|
+ s.add_dependency "faraday", ">= 0.17.3", "< 3.0"
+ s.add_dependency "multi_json", "~> 1.3"
+ end
- expect(the_bundle).to include_gems("a 1.0", "b 2.0")
+ build_gem "faraday", "2.5.2"
- gemfile <<-G
- source "file://#{gem_repo4}"
- gem "a"
- gem "b", "1.0"
- G
+ build_gem "multi_json", "1.15.0"
+
+ build_gem "quickbooks-ruby", "1.0.19" do |s|
+ s.add_dependency "oauth2", "~> 1.4"
+ end
+
+ build_gem "quickbooks-ruby", "0.1.9" do |s|
+ s.add_dependency "oauth2"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "oauth2"
+ gem "quickbooks-ruby"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ faraday (2.5.2)
+ multi_json (1.15.0)
+ oauth2 (1.4.10)
+ faraday (>= 0.17.3, < 3.0)
+ multi_json (~> 1.3)
+ quickbooks-ruby (1.0.19)
+ oauth2 (~> 1.4)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ oauth2
+ quickbooks-ruby
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update --conservative --verbose"
+
+ expect(out).not_to include("Installing quickbooks-ruby 0.1.9")
+ expect(out).to include("Installing quickbooks-ruby 1.0.19").and include("Installing oauth2 1.4.10")
+ end
+
+ it "does not downgrade direct dependencies when using gemspec sources" do
+ create_file("rails.gemspec", <<-G)
+ Gem::Specification.new do |gem|
+ gem.name = "rails"
+ gem.version = "7.1.0.alpha"
+ gem.author = "DHH"
+ gem.summary = "Full-stack web application framework."
+ end
+ G
+
+ build_repo4 do
+ build_gem "rake", "12.3.3"
+ build_gem "rake", "13.0.6"
+
+ build_gem "sneakers", "2.11.0" do |s|
+ s.add_dependency "rake"
+ end
+
+ build_gem "sneakers", "2.12.0" do |s|
+ s.add_dependency "rake", "~> 12.3"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "rake"
+ gem "sneakers"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: .
+ specs:
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rake (13.0.6)
+ sneakers (2.11.0)
+ rake
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rake
+ sneakers
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update --verbose"
+
+ expect(out).not_to include("Installing sneakers 2.12.0")
+ expect(out).not_to include("Installing rake 12.3.3")
+ expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6")
+ end
+
+ it "downgrades indirect dependencies if required to fulfill an explicit upgrade request" do
+ build_repo4 do
+ build_gem "rbs", "3.6.1"
+ build_gem "rbs", "3.9.4"
+
+ build_gem "solargraph", "0.56.0" do |s|
+ s.add_dependency "rbs", "~> 3.3"
+ end
+
+ build_gem "solargraph", "0.56.2" do |s|
+ s.add_dependency "rbs", "~> 3.6.1"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem 'solargraph', '~> 0.56.0'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rbs (3.9.4)
+ solargraph (0.56.0)
+ rbs (~> 3.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ solargraph (~> 0.56.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update solargraph"
+
+ expect(lockfile).to include("solargraph (0.56.2)")
+ end
+
+ it "does not downgrade direct dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "redis", "4.8.1"
+ build_gem "redis", "5.3.0"
+
+ build_gem "sidekiq", "6.5.5" do |s|
+ s.add_dependency "redis", ">= 4.5.0"
+ end
- bundle! "update b"
+ build_gem "sidekiq", "6.5.12" do |s|
+ s.add_dependency "redis", ">= 4.5.0", "< 5"
+ end
+
+ # one version of sidekiq above Gemfile's range is needed to make the
+ # resolver choose `redis` first and trying to upgrade it, reproducing
+ # the accidental sidekiq downgrade as a result
+ build_gem "sidekiq", "7.0.0 " do |s|
+ s.add_dependency "redis", ">= 4.2.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.0" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.4" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "redis"
+ gem "sidekiq", "~> 6.5"
+ gem "sentry-sidekiq"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ redis (4.8.1)
+ sentry-sidekiq (5.22.0)
+ sidekiq (>= 3.0)
+ sidekiq (6.5.12)
+ redis (>= 4.5.0, < 5)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ redis
+ sentry-sidekiq
+ sidekiq (~> 6.5)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update sentry-sidekiq"
+
+ expect(lockfile).to eq(original_lockfile.sub("sentry-sidekiq (5.22.0)", "sentry-sidekiq (5.22.4)"))
+ end
- expect(the_bundle).to include_gems("a 1.0", "b 1.0")
+ it "does not downgrade indirect dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "a" do |s|
+ s.add_dependency "b"
+ s.add_dependency "c"
+ end
+ build_gem "b"
+ build_gem "c"
+ build_gem "c", "2.0"
end
+
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo4"
+ gem "a"
+ G
+
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+
+ build_repo4 do
+ build_gem "b", "2.0" do |s|
+ s.add_dependency "c", "< 2"
+ end
+ end
+
+ bundle "update", all: true, verbose: true
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+ end
+
+ it "should still downgrade if forced by the Gemfile" do
+ build_repo4 do
+ build_gem "a"
+ build_gem "b", "1.0"
+ build_gem "b", "2.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "a"
+ gem "b"
+ G
+
+ expect(the_bundle).to include_gems("a 1.0", "b 2.0")
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "a"
+ gem "b", "1.0"
+ G
+
+ bundle "update b"
+
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0")
+ end
+
+ it "should still downgrade if forced by the Gemfile, when transitive dependencies also need downgrade" do
+ build_repo4 do
+ build_gem "activesupport", "6.1.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 2.0"
+ end
+
+ build_gem "activesupport", "6.0.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 1.1"
+ end
+
+ build_gem "tzinfo", "2.0.4"
+ build_gem "tzinfo", "1.2.9"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "activesupport", "~> 6.1.0"
+ G
+
+ expect(the_bundle).to include_gems("activesupport 6.1.4.1", "tzinfo 2.0.4")
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "activesupport", "~> 6.0.0"
+ G
+
+ original_lockfile = lockfile
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "activesupport", "6.0.4.1"
+ c.checksum gem_repo4, "tzinfo", "1.2.9"
+ end
+
+ expected_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ activesupport (6.0.4.1)
+ tzinfo (~> 1.1)
+ tzinfo (1.2.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport (~> 6.0.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update activesupport"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "lock --update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
end
end
describe "with --local option" do
- it "doesn't hit repo2" do
- FileUtils.rm_rf(gem_repo2)
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
- bundle "update --local --all"
- expect(out).not_to include("Fetching source index")
+ it "doesn't hit repo2" do
+ simulate_platform "x86-darwin-100" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ activesupport (2.3.5)
+ platform_specific (1.0-x86-darwin-100)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ x86-darwin-100
+
+ DEPENDENCIES
+ activesupport
+ platform_specific
+ myrack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ FileUtils.rm_r(gem_repo2)
+
+ bundle "update --local --all"
+ expect(out).not_to include("Fetching source index")
+ end
end
end
describe "with --group option" do
+ before do
+ build_repo2
+ end
+
it "should update only specified group gems" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", :group => :development
- gem "rack"
+ gem "myrack"
G
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "activesupport", "3.0"
end
bundle "update --group development"
expect(the_bundle).to include_gems "activesupport 3.0"
- expect(the_bundle).not_to include_gems "rack 1.2"
+ expect(the_bundle).not_to include_gems "myrack 1.2"
end
context "when conservatively updating a group with non-group sub-deps" do
it "should update only specified group gems" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activemerchant", :group => :development
gem "activesupport"
G
@@ -241,10 +762,10 @@ RSpec.describe "bundle update" do
end
context "when there is a source with the same name as a gem in a group" do
- before :each do
- build_git "foo", :path => lib_path("activesupport")
+ before do
+ build_git "foo", path: lib_path("activesupport")
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "activesupport", :group => :development
gem "foo", :git => "#{lib_path("activesupport")}"
G
@@ -252,7 +773,7 @@ RSpec.describe "bundle update" do
it "should not update the gems from that source" do
update_repo2 { build_gem "activesupport", "3.0" }
- update_git "foo", "2.0", :path => lib_path("activesupport")
+ update_git "foo", "2.0", path: lib_path("activesupport")
bundle "update --group development"
expect(the_bundle).to include_gems "activesupport 3.0"
@@ -263,82 +784,100 @@ RSpec.describe "bundle update" do
context "when bundler itself is a transitive dependency" do
it "executes without error" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport", :group => :development
- gem "rack"
+ gem "myrack"
G
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "activesupport", "3.0"
end
bundle "update --group development"
expect(the_bundle).to include_gems "activesupport 2.3.5"
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
- expect(the_bundle).not_to include_gems "rack 1.2"
+ expect(the_bundle).not_to include_gems "myrack 1.2"
end
end
end
describe "in a frozen bundle" do
- it "should fail loudly", :bundler => "< 3" do
- bundle! "install --deployment"
- bundle "update", :all => bundle_update_requires_all?
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ gem "myrack-obama"
+ gem "platform_specific"
+ G
+ end
+
+ it "should fail loudly" do
+ bundle_config "deployment true"
+ bundle "update", all: true, raise_on_error: false
expect(last_command).to be_failure
- expect(out).to match(/You are trying to install in deployment mode after changing.your Gemfile/m)
- expect(out).to match(/freeze \nby running `bundle install --no-deployment`./m)
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
end
- it "should suggest different command when frozen is set globally", :bundler => "< 3" do
- bundle! "config --global frozen 1"
- bundle "update", :all => bundle_update_requires_all?
- expect(out).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
- and match(/freeze \nby running `bundle config --delete frozen`./m)
+ it "should fail loudly when frozen is set globally" do
+ bundle_config_global "frozen 1"
+ bundle "update", all: true, raise_on_error: false
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
end
- it "should suggest different command when frozen is set globally", :bundler => "3" do
- bundle! "config --global deployment true"
- bundle "update", :all => bundle_update_requires_all?
- expect(out).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
- and match(/freeze \nby running `bundle config --delete deployment`./m)
+ it "should fail loudly when deployment is set globally" do
+ bundle_config_global "deployment true"
+ bundle "update", all: true, raise_on_error: false
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
+ end
+
+ it "should not suggest any command to unfreeze bundler if frozen is set through ENV" do
+ bundle "update", all: true, raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
+ expect(err).to eq("Bundler is unlocking, but the lockfile can't be updated because frozen mode is set")
end
end
describe "with --source option" do
- it "should not update gems not included in the source that happen to have the same name", :bundler => "< 3" do
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- G
- update_repo2 { build_gem "activesupport", "3.0" }
-
- bundle! "update --source activesupport"
- expect(the_bundle).to include_gem "activesupport 3.0"
+ before do
+ build_repo2
end
- it "should not update gems not included in the source that happen to have the same name", :bundler => "3" do
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
+ it "should not update gems not included in the source that happen to have the same name" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
- bundle! "update --source activesupport"
+ bundle "update --source activesupport"
expect(the_bundle).not_to include_gem "activesupport 3.0"
end
- context "with unlock_source_unlocks_spec set to false" do
- before { bundle! "config unlock_source_unlocks_spec false" }
-
- it "should not update gems not included in the source that happen to have the same name" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- G
- update_repo2 { build_gem "activesupport", "3.0" }
+ it "should not update gems not included in the source that happen to have the same name" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ G
+ update_repo2 { build_gem "activesupport", "3.0" }
- bundle "update --source activesupport"
- expect(the_bundle).not_to include_gems "activesupport 3.0"
- end
+ bundle "update --source activesupport"
+ expect(the_bundle).not_to include_gems "activesupport 3.0"
end
end
@@ -352,26 +891,13 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "harry"
gem "fred"
G
end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do
- update_repo2 do
- build_gem "fred", "2.0"
- build_gem "harry", "2.0" do |s|
- s.add_dependency "fred"
- end
- end
-
- bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 2.0"
- expect(the_bundle).to include_gems "fred 1.0"
- end
-
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
+ it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "fred", "2.0"
build_gem "harry", "2.0" do |s|
@@ -397,13 +923,13 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "harry"
gem "fred"
G
end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do
+ it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "george", "2.0"
build_gem "harry", "2.0" do |s|
@@ -412,71 +938,233 @@ RSpec.describe "bundle update" do
end
bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 2.0"
- expect(the_bundle).to include_gems "fred 1.0"
- expect(the_bundle).to include_gems "george 1.0"
+ expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0"
+ end
+ end
+
+ it "shows the previous version of the gem when updated from rubygems source" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ G
+
+ bundle "update", all: true, verbose: true
+ expect(out).to include("Using activesupport 2.3.5")
+
+ update_repo2 do
+ build_gem "activesupport", "3.0"
end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
+ bundle "update", all: true
+ expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
+ end
+
+ it "only prints `Using` for versions that have changed" do
+ build_repo4 do
+ build_gem "bar"
+ build_gem "foo"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "bar"
+ gem "foo"
+ G
+
+ bundle "update", all: true
+ expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
+
+ build_repo4 do
+ build_gem "foo", "2.0"
+ end
+
+ bundle "update", all: true
+ expect(out.sub("Removing foo (1.0)\n", "")).to match(/Resolving dependencies\.\.\.\.*\nFetching foo 2\.0 \(was 1\.0\)\nInstalling foo 2\.0 \(was 1\.0\)\nBundle updated/)
+ end
+
+ it "shows error message when Gemfile.lock is not preset and gem is specified" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ G
+
+ bundle "update nonexisting", raise_on_error: false
+ expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
+ expect(exitstatus).to eq(22)
+ end
+
+ context "with multiple sources and caching enabled" do
+ before do
+ build_repo2 do
+ build_gem "myrack", "1.0.0"
+
+ build_gem "request_store", "1.0.0" do |s|
+ s.add_dependency "myrack", "1.0.0"
+ end
+ end
+
+ build_repo4 do
+ # set up repo with no gems
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "request_store"
+
+ source "https://gem.repo4" do
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+ request_store (1.0.0)
+ myrack (= 1.0.0)
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ request_store
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle :install
+ bundle :cache
+
update_repo2 do
- build_gem "george", "2.0"
- build_gem "harry", "2.0" do |s|
- s.add_dependency "george"
+ build_gem "request_store", "1.1.0" do |s|
+ s.add_dependency "myrack", "1.0.0"
end
end
- bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0"
+ bundle "update request_store"
+
+ expect(out).to include("Bundle updated!")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+ request_store (1.1.0)
+ myrack (= 1.0.0)
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ request_store
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
end
end
RSpec.describe "bundle update in more complicated situations" do
- before :each do
+ before do
build_repo2
end
it "will eagerly unlock dependencies of a specified gem" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "thin"
- gem "rack-obama"
+ gem "myrack-obama"
G
update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
build_gem "thin", "2.0" do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
end
bundle "update thin"
- expect(the_bundle).to include_gems "thin 2.0", "rack 1.2", "rack-obama 1.0"
+ expect(the_bundle).to include_gems "thin 2.0", "myrack 1.2", "myrack-obama 1.0"
end
it "will warn when some explicitly updated gems are not updated" do
- install_gemfile! <<-G
- source "file:#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "thin"
- gem "rack-obama"
+ gem "myrack-obama"
G
update_repo2 do
- build_gem("thin", "2.0") {|s| s.add_dependency "rack" }
- build_gem "rack", "10.0"
+ build_gem("thin", "2.0") {|s| s.add_dependency "myrack" }
+ build_gem "myrack", "10.0"
end
- bundle! "update thin rack-obama"
- expect(last_command.stdboth).to include "Bundler attempted to update rack-obama but its version stayed the same"
- expect(the_bundle).to include_gems "thin 2.0", "rack 10.0", "rack-obama 1.0"
+ bundle "update thin myrack-obama"
+ expect(stdboth).to include "Bundler attempted to update myrack-obama but its version stayed the same"
+ expect(the_bundle).to include_gems "thin 2.0", "myrack 10.0", "myrack-obama 1.0"
+ end
+
+ it "will not warn when an explicitly updated git gem changes sha but not version" do
+ build_git "foo"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ update_git "foo" do |s|
+ s.write "lib/foo2.rb", "puts :foo2"
+ end
+
+ bundle "update foo"
+
+ expect(stdboth).not_to include "attempted to update"
+ end
+
+ it "will not warn when changing gem sources but not versions" do
+ build_git "myrack"
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack", :git => '#{lib_path("myrack-1.0")}'
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "update myrack"
+
+ expect(stdboth).not_to include "attempted to update"
end
it "will update only from pinned source" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
- source "file://#{gem_repo1}" do
+ source "https://gem.repo1" do
gem "thin"
end
G
@@ -485,12 +1173,12 @@ RSpec.describe "bundle update in more complicated situations" do
build_gem "thin", "2.0"
end
- bundle "update"
+ bundle "update", artifice: "compact_index"
expect(the_bundle).to include_gems "thin 1.0"
end
context "when the lockfile is for a different platform" do
- before do
+ around do |example|
build_repo4 do
build_gem("a", "0.9")
build_gem("a", "0.9") {|s| s.platform = "java" }
@@ -499,13 +1187,13 @@ RSpec.describe "bundle update in more complicated situations" do
end
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem "a"
G
lockfile <<-L
GEM
- remote: file://#{gem_repo4}
+ remote: https://gem.repo4
specs:
a (0.9-java)
@@ -516,19 +1204,54 @@ RSpec.describe "bundle update in more complicated situations" do
a
L
- simulate_platform linux
+ simulate_platform "x86_64-linux", &example
end
it "allows updating" do
- bundle! :update, :all => true
+ bundle :update, all: true
expect(the_bundle).to include_gem "a 1.1"
end
it "allows updating a specific gem" do
- bundle! "update a"
+ bundle "update a"
expect(the_bundle).to include_gem "a 1.1"
end
end
+
+ context "when the dependency is for a different platform" do
+ before do
+ build_repo4 do
+ build_gem("a", "0.9") {|s| s.platform = "java" }
+ build_gem("a", "1.1") {|s| s.platform = "java" }
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "a", platform: :jruby
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ a (0.9-java)
+
+ PLATFORMS
+ java
+
+ DEPENDENCIES
+ a
+ L
+ end
+
+ it "is not updated because it is not actually included in the bundle" do
+ simulate_platform "x86_64-linux" do
+ bundle "update a"
+ expect(stdboth).to include "Bundler attempted to update a but it was not considered because it is for a different platform from the current one"
+ expect(the_bundle).to_not include_gem "a"
+ end
+ end
+ end
end
RSpec.describe "bundle update without a Gemfile.lock" do
@@ -536,144 +1259,69 @@ RSpec.describe "bundle update without a Gemfile.lock" do
build_repo2
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
- gem "rack", "1.0"
+ gem "myrack", "1.0"
G
- bundle "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
RSpec.describe "bundle update when a gem depends on a newer version of bundler" do
- before(:each) do
+ before do
build_repo2 do
build_gem "rails", "3.0.1" do |s|
- s.add_dependency "bundler", Bundler::VERSION.succ
+ s.add_dependency "bundler", "9.9.9"
end
+
+ build_gem "bundler", "9.9.9"
end
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails", "3.0.1"
G
end
- it "should explain that bundler conflicted", :bundler => "< 3" do
- bundle "update", :all => bundle_update_requires_all?
- expect(last_command.stdboth).not_to match(/in snapshot/i)
- expect(last_command.bundler_err).to match(/current Bundler version/i).
- and match(/perhaps you need to update bundler/i)
- end
-
- it "should warn that the newer version of Bundler would conflict", :bundler => "3" do
- bundle! "update", :all => true
- expect(last_command.bundler_err).to include("rails (3.0.1) has dependency bundler").
- and include("so the dependency is being ignored")
- expect(the_bundle).to include_gem "rails 3.0.1"
- end
-end
-
-RSpec.describe "bundle update" do
- it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
- build_repo2
-
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- G
-
- bundle "update", :all => bundle_update_requires_all?
- expect(out).to include("Using activesupport 2.3.5")
-
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle "update", :all => bundle_update_requires_all?
- expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
- end
-
- context "with suppress_install_using_messages set" do
- before { bundle! "config suppress_install_using_messages true" }
-
- it "only prints `Using` for versions that have changed" do
- build_repo4 do
- build_gem "bar"
- build_gem "foo"
- end
-
- install_gemfile! <<-G
- source "file://#{gem_repo4}"
- gem "bar"
- gem "foo"
- G
-
- bundle! "update", :all => bundle_update_requires_all?
- out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "")
- expect(out).to include "Resolving dependencies...\nBundle updated!"
-
- update_repo4 do
- build_gem "foo", "2.0"
- end
-
- bundle! "update", :all => bundle_update_requires_all?
- out.sub!("Removing foo (1.0)\n", "")
- out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "")
- expect(out).to include strip_whitespace(<<-EOS).strip
- Resolving dependencies...
- Fetching foo 2.0 (was 1.0)
- Installing foo 2.0 (was 1.0)
- Bundle updated
- EOS
- end
- end
-
- it "shows error message when Gemfile.lock is not preset and gem is specified" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- G
-
- bundle "update nonexisting"
- expect(out).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
- expect(exitstatus).to eq(22) if exitstatus
+ it "should explain that bundler conflicted and how to resolve the conflict" do
+ bundle "update", all: true, raise_on_error: false
+ expect(stdboth).not_to match(/in snapshot/i)
+ expect(err).to match(/current Bundler version/i).
+ and match(/Install the necessary version with `gem install bundler:9\.9\.9`/i)
end
end
RSpec.describe "bundle update --ruby" do
- before do
- install_gemfile <<-G
- ::RUBY_VERSION = '2.1.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.1.0'
- G
- bundle "update --ruby"
- end
-
context "when the Gemfile removes the ruby" do
before do
install_gemfile <<-G
- ::RUBY_VERSION = '2.1.4'
- ::RUBY_PATCHLEVEL = 222
+ ruby '~> #{Gem.ruby_version}'
+ source "https://gem.repo1"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
G
end
+
it "removes the Ruby from the Gemfile.lock" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums_section_when_enabled}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -681,27 +1329,33 @@ RSpec.describe "bundle update --ruby" do
context "when the Gemfile specified an updated Ruby version" do
before do
install_gemfile <<-G
- ::RUBY_VERSION = '2.1.4'
- ::RUBY_PATCHLEVEL = 222
- ruby '~> 2.1.0'
+ ruby '~> #{Gem.ruby_version}'
+ source "https://gem.repo1"
+ G
+
+ gemfile <<-G
+ ruby '~> #{current_ruby_minor}'
+ source "https://gem.repo1"
G
end
+
it "updates the Gemfile.lock with the latest version" do
bundle "update --ruby"
- lockfile_should_be <<-L
- GEM
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
- DEPENDENCIES
+ PLATFORMS
+ #{lockfile_platforms}
- RUBY VERSION
- ruby 2.1.4p222
+ DEPENDENCIES
+ #{checksums_section_when_enabled}
+ RUBY VERSION
+ #{Bundler::RubyVersion.system}
- BUNDLED WITH
+ BUNDLED WITH
#{Bundler::VERSION}
L
end
@@ -710,66 +1364,435 @@ RSpec.describe "bundle update --ruby" do
context "when a different Ruby is being used than has been versioned" do
before do
install_gemfile <<-G
- ::RUBY_VERSION = '2.2.2'
- ::RUBY_PATCHLEVEL = 505
+ ruby '~> #{Gem.ruby_version}'
+ source "https://gem.repo1"
+ G
+
+ gemfile <<-G
ruby '~> 2.1.0'
+ source "https://gem.repo1"
G
end
it "shows a helpful error message" do
- bundle "update --ruby"
+ bundle "update --ruby", raise_on_error: false
- expect(out).to include("Your Ruby version is 2.2.2, but your Gemfile specified ~> 2.1.0")
+ expect(err).to include("Your Ruby version is #{Bundler::RubyVersion.system.gem_version}, but your Gemfile specified ~> 2.1.0")
end
end
context "when updating Ruby version and Gemfile `ruby`" do
before do
- install_gemfile <<-G
- ::RUBY_VERSION = '1.8.3'
- ::RUBY_PATCHLEVEL = 55
- ruby '~> 1.8.0'
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+
+ CHECKSUMS
+
+ RUBY VERSION
+ ruby 2.1.4p222
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ ruby '~> #{Gem.ruby_version}'
+ source "https://gem.repo1"
G
end
+
it "updates the Gemfile.lock with the latest version" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums_section_when_enabled}
RUBY VERSION
- ruby 1.8.3p55
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
end
RSpec.describe "bundle update --bundler" do
- it "updates the bundler version in the lockfile without re-resolving" do
+ it "updates the bundler version in the lockfile" do
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "bundler", "2.5.9"
+ build_gem "myrack", "1.0"
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
end
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
G
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
- FileUtils.rm_r gem_repo4
+ bundle :update, bundler: true, verbose: true
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(the_bundle).to include_gem "myrack 1.0"
+ end
+
+ it "updates the bundler version in the lockfile without re-resolving if the highest version is already installed" do
+ build_repo4 do
+ build_gem "bundler", "2.3.9"
+ build_gem "myrack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ end
+
+ bundle :update, bundler: true, verbose: true
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
- bundle! :update, :bundler => true, :verbose => true
- expect(the_bundle).to include_gem "rack 1.0"
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
- expect(the_bundle.locked_gems.bundler_version).to eq v(Bundler::VERSION)
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(the_bundle).to include_gem "myrack 1.0"
+ end
+
+ it "updates the bundler version in the lockfile even if the latest version is not installed", :ruby_repo do
+ bundle_config "path.system true"
+
+ pristine_system_gems "bundler-9.0.0"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+
+ build_bundler "999.0.0"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ c.checksum(gem_repo4, "bundler", "999.0.0")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ bundle :update, bundler: true, verbose: true
+
+ expect(out).to include("Updating bundler to 999.0.0")
+ expect(out).to include("Running `bundle update --bundler \"> 0.a\" --verbose` with bundler 999.0.0")
+ expect(out).not_to include("Installing Bundler 2.99.9 and restarting using that version.")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ 999.0.0
+ L
+
+ expect(the_bundle).to include_gems "bundler 999.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
+ end
+
+ it "does not claim to update to Bundler version to a wrong version when cached gems are present" do
+ pristine_system_gems "bundler-4.99.0"
+
+ build_repo4 do
+ build_gem "myrack", "3.0.9.1"
+
+ build_bundler "4.99.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (3.0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ 2.99.0
+ L
+
+ bundle :cache, verbose: true
+
+ bundle :update, bundler: true, verbose: true
+
+ expect(out).not_to include("Updating bundler to")
+ end
+
+ it "does not update the bundler version in the lockfile if the latest version is not compatible with current ruby", :ruby_repo do
+ pristine_system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+
+ build_bundler "9.9.9"
+ build_bundler "999.0.0" do |s|
+ s.required_ruby_version = "> #{Gem.ruby_version}"
+ end
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ c.checksum(gem_repo4, "bundler", "9.9.9")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ bundle :update, bundler: true, verbose: true
+
+ expect(out).to include("Using bundler 9.9.9")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ 9.9.9
+ L
+
+ expect(the_bundle).to include_gems "bundler 9.9.9"
+ expect(the_bundle).to include_gems "myrack 1.0"
+ end
+
+ it "errors if the explicit target version does not exist" do
+ pristine_system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ bundle :update, bundler: "999.999.999", raise_on_error: false
+
+ expect(last_command).to be_failure
+ expect(err).to eq("The `bundle update --bundler` target version (999.999.999) does not exist")
+ end
+
+ it "errors if the explicit target version does not exist, even if auto switching is disabled" do
+ pristine_system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ bundle :update, bundler: "999.999.999", raise_on_error: false, env: { "BUNDLER_VERSION" => "9.9.9" }
+
+ expect(last_command).to be_failure
+ expect(err).to eq("The `bundle update --bundler` target version (999.999.999) does not exist")
+ end
+
+ it "allows updating to development versions if already installed locally" do
+ system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ system_gems "bundler-9.0.0.dev", path: local_gem_path
+ bundle :update, bundler: "9.0.0.dev", verbose: "true"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ end
+ checksums.delete("bundler")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ 9.0.0.dev
+ L
+
+ expect(out).to include("Using bundler 9.0.0.dev")
+ end
+
+ it "does not touch the network if not necessary" do
+ system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+ system_gems "bundler-9.0.0", path: local_gem_path
+ bundle :update, bundler: "9.0.0", verbose: true
+
+ expect(out).not_to include("Fetching gem metadata from https://rubygems.org/")
+
+ # Only updates properly on modern RubyGems.
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ c.checksum(local_gem_path, "bundler", "9.0.0", Gem::Platform::RUBY, "cache")
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ 9.0.0
+ L
+
+ expect(out).to include("Using bundler 9.0.0")
+ end
+
+ it "prints an error when trying to update bundler in frozen mode" do
+ system_gems "bundler-9.0.0"
+
+ gemfile <<~G
+ source "https://gem.repo2"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ 9.0.0
+ L
+
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ bundle "update --bundler=9.9.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ expect(err).to include("An update to the version of Bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
end
end
@@ -787,13 +1810,16 @@ RSpec.describe "bundle update conservative" do
build_gem "foo", %w[1.5.1] do |s|
s.add_dependency "bar", "~> 3.0"
end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "foo", %w[2.0.0.pre] do |s|
+ s.add_dependency "bar"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 2.1.2.pre 3.0.0 3.1.0.pre 4.0.0.pre]
build_gem "qux", %w[1.0.0 1.0.1 1.1.0 2.0.0]
end
# establish a lockfile set to 1.4.3
install_gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'foo', '1.4.3'
gem 'bar', '2.0.3'
gem 'qux', '1.0.0'
@@ -802,21 +1828,30 @@ RSpec.describe "bundle update conservative" do
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'foo'
gem 'qux'
G
end
+ context "with patch set as default update level in config" do
+ it "should do a patch level update" do
+ bundle_config "prefer_patch true"
+ bundle "update foo"
+
+ expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0"
+ end
+ end
+
context "patch preferred" do
it "single gem updates dependent gem to minor" do
- bundle! "update --patch foo"
+ bundle "update --patch foo"
expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0"
end
it "update all" do
- bundle! "update --patch", :all => bundle_update_requires_all?
+ bundle "update --patch", all: true
expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.1"
end
@@ -824,7 +1859,7 @@ RSpec.describe "bundle update conservative" do
context "minor preferred" do
it "single gem updates dependent gem to major" do
- bundle! "update --minor foo"
+ bundle "update --minor foo"
expect(the_bundle).to include_gems "foo 1.5.1", "bar 3.0.0", "qux 1.0.0"
end
@@ -832,17 +1867,43 @@ RSpec.describe "bundle update conservative" do
context "strict" do
it "patch preferred" do
- bundle! "update --patch foo bar --strict"
+ bundle "update --patch foo bar --strict"
expect(the_bundle).to include_gems "foo 1.4.4", "bar 2.0.5", "qux 1.0.0"
end
it "minor preferred" do
- bundle! "update --minor --strict", :all => bundle_update_requires_all?
+ bundle "update --minor --strict", all: true
expect(the_bundle).to include_gems "foo 1.5.0", "bar 2.1.1", "qux 1.1.0"
end
end
+
+ context "pre" do
+ it "defaults to major" do
+ bundle "update --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 2.0.0.pre", "bar 4.0.0.pre", "qux 1.0.0"
+ end
+
+ it "patch preferred" do
+ bundle "update --patch --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.2.pre", "qux 1.0.0"
+ end
+
+ it "minor preferred" do
+ bundle "update --minor --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 1.5.1", "bar 3.1.0.pre", "qux 1.0.0"
+ end
+
+ it "major preferred" do
+ bundle "update --major --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 2.0.0.pre", "bar 4.0.0.pre", "qux 1.0.0"
+ end
+ end
end
context "eager unlocking" do
@@ -863,16 +1924,16 @@ RSpec.describe "bundle update conservative" do
end
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'isolated_owner'
gem 'shared_owner_a'
gem 'shared_owner_b'
G
- lockfile <<-L
+ lockfile <<~L
GEM
- remote: file://#{gem_repo4}
+ remote: https://gem.repo4/
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.1)
@@ -884,15 +1945,17 @@ RSpec.describe "bundle update conservative" do
shared_dep (~> 5.0)
PLATFORMS
- ruby
+ #{local_platform}
DEPENDENCIES
+ isolated_owner
shared_owner_a
shared_owner_b
- isolated_owner
+
+ CHECKSUMS
BUNDLED WITH
- 1.13.0
+ #{Bundler::VERSION}
L
end
@@ -911,12 +1974,55 @@ RSpec.describe "bundle update conservative" do
it "should not eagerly unlock with --conservative" do
bundle "update --conservative shared_owner_a isolated_owner"
- expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ end
+
+ it "should only update direct dependencies when fully updating with --conservative" do
+ bundle "update --conservative"
+
+ expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.2"
+ end
+
+ it "should only change direct dependencies when updating the lockfile with --conservative" do
+ bundle "lock --update --conservative"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "isolated_dep", "2.0.1"
+ c.checksum gem_repo4, "isolated_owner", "1.0.2"
+ c.checksum gem_repo4, "shared_dep", "5.0.1"
+ c.checksum gem_repo4, "shared_owner_a", "3.0.2"
+ c.checksum gem_repo4, "shared_owner_b", "4.0.2"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ isolated_dep (2.0.1)
+ isolated_owner (1.0.2)
+ isolated_dep (~> 2.0)
+ shared_dep (5.0.1)
+ shared_owner_a (3.0.2)
+ shared_dep (~> 5.0)
+ shared_owner_b (4.0.2)
+ shared_dep (~> 5.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ isolated_owner
+ shared_owner_a
+ shared_owner_b
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "should match bundle install conservative update behavior when not eagerly unlocking" do
gemfile <<-G
- source "file://#{gem_repo4}"
+ source "https://gem.repo4"
gem 'isolated_owner', '1.0.2'
gem 'shared_owner_a', '3.0.2'
@@ -925,19 +2031,65 @@ RSpec.describe "bundle update conservative" do
bundle "install"
- expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ end
+ end
+
+ context "when Gemfile dependencies have changed" do
+ before do
+ build_repo4 do
+ build_gem "nokogiri", "1.16.4" do |s|
+ s.platform = "arm64-darwin"
+ end
+
+ build_gem "nokogiri", "1.16.4" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "prism", "0.25.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "nokogiri", ">=1.16.4"
+ gem "prism", ">=0.25.0"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.4-arm64-darwin)
+ nokogiri (1.16.4-x86_64-linux)
+
+ PLATFORMS
+ arm64-darwin
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (>= 1.16.4)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "still works" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "update"
+ end
end
end
context "error handling" do
before do
- gemfile ""
+ gemfile "source 'https://gem.repo1'"
end
it "raises if too many flags are provided" do
- bundle "update --patch --minor", :all => bundle_update_requires_all?
+ bundle "update --patch --minor", all: true, raise_on_error: false
- expect(last_command.bundler_err).to eq "Provide only one of the following options: minor, patch"
+ expect(err).to eq "Provide only one of the following options: minor, patch"
end
end
end
diff --git a/spec/bundler/commands/version_spec.rb b/spec/bundler/commands/version_spec.rb
index 66c7930397..4320ad0611 100644
--- a/spec/bundler/commands/version_spec.rb
+++ b/spec/bundler/commands/version_spec.rb
@@ -1,39 +1,65 @@
# frozen_string_literal: true
+require_relative "../support/path"
+
RSpec.describe "bundle version" do
+ if Spec::Path.ruby_core?
+ COMMIT_HASH = /unknown|[a-fA-F0-9]{7,}/
+ else
+ COMMIT_HASH = /[a-fA-F0-9]{7,}/
+ end
+
context "with -v" do
- it "outputs the version", :bundler => "< 3" do
- bundle! "-v"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ it "outputs the version and virtual version if set" do
+ bundle "-v"
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "outputs the version", :bundler => "3" do
- bundle! "-v"
- expect(out).to eq(Bundler::VERSION)
+ bundle_config "simulate_version 5"
+ bundle "-v"
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
end
end
context "with --version" do
- it "outputs the version", :bundler => "< 3" do
- bundle! "--version"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ it "outputs the version and virtual version if set" do
+ bundle "--version"
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "outputs the version", :bundler => "3" do
- bundle! "--version"
- expect(out).to eq(Bundler::VERSION)
+ bundle_config "simulate_version 5"
+ bundle "--version"
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
end
end
context "with version" do
- it "outputs the version with build metadata", :bundler => "< 3" do
- bundle! "version"
- expect(out).to match(/\ABundler version #{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit [a-fA-F0-9]{7,}\)\z/)
+ context "when released", :ruby_repo do
+ before do
+ system_gems "bundler-4.9.9", released: true
+ end
+
+ it "outputs the version, virtual version if set, and build metadata" do
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(2100-01-01 commit #{COMMIT_HASH}\)\z/)
+
+ bundle_config "simulate_version 5"
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(simulating Bundler 5\) \(2100-01-01 commit #{COMMIT_HASH}\)\z/)
+ end
end
- it "outputs the version with build metadata", :bundler => "3" do
- bundle! "version"
- expect(out).to match(/\A#{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit [a-fA-F0-9]{7,}\)\z/)
+ context "when not released" do
+ before do
+ system_gems "bundler-4.9.9", released: false
+ end
+
+ it "outputs the version, virtual version if set, and build metadata" do
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(20\d{2}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+
+ bundle_config "simulate_version 5"
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(simulating Bundler 5\) \(20\d{2}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+ end
end
end
end
diff --git a/spec/bundler/commands/viz_spec.rb b/spec/bundler/commands/viz_spec.rb
deleted file mode 100644
index 61414956a9..0000000000
--- a/spec/bundler/commands/viz_spec.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle viz", :ruby => "1.9.3", :bundler => "< 3", :if => Bundler.which("dot") do
- let(:ruby_graphviz) do
- graphviz_glob = base_system_gems.join("cache/ruby-graphviz*")
- Pathname.glob(graphviz_glob).first
- end
-
- before do
- system_gems ruby_graphviz
- end
-
- it "graphs gems from the Gemfile" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
- G
-
- bundle! "viz"
- expect(out).to include("gem_graph.png")
-
- bundle! "viz", :format => "debug"
- expect(out).to eq(strip_whitespace(<<-DOT).strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- DOT
- end
-
- it "graphs gems that are prereleases" do
- build_repo2 do
- build_gem "rack", "1.3.pre"
- end
-
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack", "= 1.3.pre"
- gem "rack-obama"
- G
-
- bundle! "viz"
- expect(out).to include("gem_graph.png")
-
- bundle! "viz", :format => :debug, :version => true
- expect(out).to eq(strip_whitespace(<<-EOS).strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack\\n1.3.pre"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama\\n1.0"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- EOS
- end
-
- context "with another gem that has a graphviz file" do
- before do
- build_repo4 do
- build_gem "graphviz", "999" do |s|
- s.write("lib/graphviz.rb", "abort 'wrong graphviz gem loaded'")
- end
- end
-
- system_gems ruby_graphviz, "graphviz-999", :gem_repo => gem_repo4
- end
-
- it "loads the correct ruby-graphviz gem" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
- G
-
- bundle! "viz", :format => "debug"
- expect(out).to eq(strip_whitespace(<<-DOT).strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- DOT
- end
- end
-
- context "--without option" do
- it "one group" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
-
- group :rails do
- gem "rails"
- end
- G
-
- bundle! "viz --without=rails"
- expect(out).to include("gem_graph.png")
- end
-
- it "two groups" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
-
- group :rack do
- gem "rack"
- end
-
- group :rails do
- gem "rails"
- end
- G
-
- bundle! "viz --without=rails:rack"
- expect(out).to include("gem_graph.png")
- end
- end
-end
diff --git a/spec/bundler/install/allow_offline_install_spec.rb b/spec/bundler/install/allow_offline_install_spec.rb
index d4bb595771..c7ab7c3d7e 100644
--- a/spec/bundler/install/allow_offline_install_spec.rb
+++ b/spec/bundler/install/allow_offline_install_spec.rb
@@ -1,59 +1,58 @@
# frozen_string_literal: true
-RSpec.describe "bundle install with :allow_offline_install" do
- before do
- bundle "config allow_offline_install true"
- end
-
+RSpec.describe "bundle install allows offline install" do
context "with no cached data locally" do
it "still installs" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
- expect(the_bundle).to include_gem("rack 1.0")
+ expect(the_bundle).to include_gem("myrack 1.0")
end
it "still fails when the network is down" do
- install_gemfile <<-G, :artifice => "fail"
+ install_gemfile <<-G, artifice: "fail", raise_on_error: false
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
- expect(out).to include("Could not reach host testgemserver.local.")
+ expect(err).to include("Could not reach host testgemserver.local.")
expect(the_bundle).to_not be_locked
end
end
context "with cached data locally" do
it "will install from the compact index" do
- system_gems ["rack-1.0.0"], :path => :bundle_path
+ system_gems ["myrack-1.0.0"], path: default_bundle_path
- bundle! "config clean false"
- install_gemfile! <<-G, :artifice => "compact_index"
+ bundle_config "clean false"
+ install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
- gem "rack-obama"
- gem "rack", "< 1.0"
+ gem "myrack-obama"
+ gem "myrack", "< 1.0"
G
- expect(the_bundle).to include_gems("rack-obama 1.0", "rack 0.9.1")
+ expect(the_bundle).to include_gems("myrack-obama 1.0", "myrack 0.9.1")
gemfile <<-G
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
- bundle! :update, :artifice => "fail", :all => true
- expect(last_command.stdboth).to include "Using the cached data for the new index because of a network error"
+ bundle :update, artifice: "fail", all: true
+ expect(stdboth).to include "Using the cached data for the new index because of a network error"
- expect(the_bundle).to include_gems("rack-obama 1.0", "rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack-obama 1.0", "myrack 1.0.0")
end
def break_git_remote_ops!
FileUtils.mkdir_p(tmp("broken_path"))
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
- f.puts strip_whitespace(<<-RUBY)
+ f.puts <<~RUBY
#!/usr/bin/env ruby
- if %w(fetch --force --quiet --tags refs/heads/*:refs/heads/*).-(ARGV).empty? || %w(clone --bare --no-hardlinks --quiet).-(ARGV).empty?
+ fetch_args = %w(fetch --force --quiet --no-tags)
+ clone_args = %w(clone --bare --no-hardlinks --quiet)
+
+ if (fetch_args.-(ARGV).empty? || clone_args.-(ARGV).empty?) && File.exist?(ARGV[ARGV.index("--") + 1])
warn "git remote ops have been disabled"
exit 1
end
@@ -70,22 +69,26 @@ RSpec.describe "bundle install with :allow_offline_install" do
end
it "will install from a cached git repo" do
- git = build_git "a", "1.0.0", :path => lib_path("a")
- update_git("a", :path => git.path, :branch => "new_branch")
- install_gemfile! <<-G
+ skip "doesn't print errors" if Gem.win_platform?
+
+ git = build_git "a", "1.0.0", path: lib_path("a")
+ update_git("a", path: git.path, branch: "new_branch")
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "a", :git => #{git.path.to_s.dump}
G
- break_git_remote_ops! { bundle! :update, :all => true }
- expect(out).to include("Using cached git data because of network errors")
+ break_git_remote_ops! { bundle :update, all: true }
+ expect(err).to include("Using cached git data because of network errors")
expect(the_bundle).to be_locked
break_git_remote_ops! do
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "a", :git => #{git.path.to_s.dump}, :branch => "new_branch"
G
end
- expect(out).to include("Using cached git data because of network errors")
+ expect(err).to include("Using cached git data because of network errors")
expect(the_bundle).to be_locked
end
end
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index f04d3fe654..c2eccb3ef2 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -1,43 +1,49 @@
# frozen_string_literal: true
-RSpec.describe "bundle install", :bundler => "< 3" do
+RSpec.describe "bundle install" do
describe "when system_bindir is set" do
- # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if
- # you want to avoid sudo installs for system gems with OS X's default ruby
it "overrides Gem.bindir" do
- expect(Pathname.new("/usr/bin")).not_to be_writable unless Process.euid == 0
+ expect(Pathname.new("/usr/bin")).not_to be_writable
gemfile <<-G
- require 'rubygems'
def Gem.bindir; "/usr/bin"; end
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- config "BUNDLE_SYSTEM_BINDIR" => system_gem_path("altbin").to_s
+ bundle_config "BUNDLE_SYSTEM_BINDIR" => system_gem_path("altbin").to_s
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(system_gem_path("altbin/rackup")).to exist
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(system_gem_path("altbin/myrackup")).to exist
end
end
- describe "when multiple gems contain the same exe", :bundler => "< 3" do
+ describe "when multiple gems contain the same exe" do
before do
build_repo2 do
build_gem "fake", "14" do |s|
- s.executables = "rackup"
+ s.executables = "myrackup"
end
end
- install_gemfile <<-G, :binstubs => true
- source "file://#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "fake"
- gem "rack"
+ gem "myrack"
G
end
- it "loads the correct spec's executable" do
- gembin("rackup")
- expect(out).to eq("1.2")
+ it "warns about the situation" do
+ bundle "exec myrackup"
+
+ expect(last_command.stderr).to include(
+ "The `myrackup` executable in the `fake` gem is being loaded, but it's also present in other gems (myrack).\n" \
+ "If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \
+ "If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names."
+ ).or include(
+ "The `myrackup` executable in the `myrack` gem is being loaded, but it's also present in other gems (fake).\n" \
+ "If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \
+ "If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names."
+ )
end
end
end
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index 42863ed89b..86c22dad55 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe "bundle install" do
before(:each) do
build_repo2 do
build_gem "rails", "3.0" do |s|
- s.add_dependency "bundler", ">= 0.9.0.pre"
+ s.add_dependency "bundler", ">= 0.9.0"
end
build_gem "bundler", "0.9.1"
build_gem "bundler", Bundler::VERSION
@@ -14,55 +14,101 @@ RSpec.describe "bundle install" do
it "are forced to the current bundler version" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "are not added if not already present" do
+ it "are forced to the current bundler version even if not already present" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).not_to include_gems "bundler #{Bundler::VERSION}"
+ expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "causes a conflict if explicitly requesting a different version" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ it "causes a conflict if explicitly requesting a different version of bundler" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem "rails", "3.0"
+ gem "bundler", "0.9.1"
+ G
+
+ nice_error = <<~E.strip
+ Could not find compatible versions
+
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.1
+ and Gemfile depends on bundler = 0.9.1,
+ version solving has failed.
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a non matching requirement on bundler" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem "rails", "3.0"
+ gem "bundler", "~> 0.8"
+ G
+
+ nice_error = <<~E.strip
+ Could not find compatible versions
+
+ Because rails >= 3.0 depends on bundler >= 0.9.0
+ and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0, < 1.A,
+ rails >= 3.0 requires bundler >= 1.A.
+ So, because Gemfile depends on rails = 3.0
+ and Gemfile depends on bundler ~> 0.8,
+ version solving has failed.
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem "rails", "3.0"
gem "bundler", "0.9.2"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "bundler":
- In Gemfile:
- bundler (= 0.9.2)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
- This Gemfile requires a different version of Bundler.
- Perhaps you need to update Bundler by running `gem install bundler`?
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.2
+ and Gemfile depends on bundler = 0.9.2,
+ version solving has failed.
- Could not find gem 'bundler (= 0.9.2)' in any
+ Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.
E
- expect(last_command.bundler_err).to include(nice_error)
+ expect(err).to include(nice_error)
end
it "works for gems with multiple versions in its dependencies" do
+ build_repo2 do
+ build_gem "multiple_versioned_deps" do |s|
+ s.add_dependency "weakling", ">= 0.0.1", "< 0.1"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "multiple_versioned_deps"
G
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "multiple_versioned_deps"
- gem "rack"
+ gem "myrack"
G
expect(the_bundle).to include_gems "multiple_versioned_deps 1.0.0"
@@ -70,7 +116,7 @@ RSpec.describe "bundle install" do
it "includes bundler in the bundle when it's a child dependency" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
@@ -80,8 +126,8 @@ RSpec.describe "bundle install" do
it "allows gem 'bundler' when Bundler is not in the Gemfile or its dependencies" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
run "begin; gem 'bundler'; puts 'WIN'; rescue Gem::LoadError => e; puts e.backtrace; end"
@@ -89,89 +135,134 @@ RSpec.describe "bundle install" do
end
it "causes a conflict if child dependencies conflict" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ bundle_config "force_ruby_platform true"
+
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem "activemerchant"
- gem "rails_fail"
+ gem "rails_pinned_to_old_activesupport"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activemerchant was resolved to 1.0, which depends on
- activesupport (>= 2.0.0)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- rails_fail was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and every version of activemerchant depends on activesupport >= 2.0.0,
+ every version of rails_pinned_to_old_activesupport is incompatible with activemerchant >= 0.
+ So, because Gemfile depends on activemerchant >= 0
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ version solving has failed.
E
- expect(last_command.bundler_err).to include(nice_error)
+ expect(err).to include(nice_error)
end
it "causes a conflict if a child dependency conflicts with the Gemfile" do
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rails_fail"
+ bundle_config "force_ruby_platform true"
+
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem "rails_pinned_to_old_activesupport"
gem "activesupport", "2.3.5"
G
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activesupport (= 2.3.5)
+ nice_error = <<~E.strip
+ Could not find compatible versions
- rails_fail was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ activesupport = 1.2.3 is required.
+ So, because Gemfile depends on activesupport = 2.3.5,
+ version solving has failed.
E
- expect(last_command.bundler_err).to include(nice_error)
+ expect(err).to include(nice_error)
end
- it "can install dependencies with newer bundler version with system gems", :ruby => "> 2" do
- bundle! "config path.system true"
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
- gem "rails", "3.0"
+ it "does not cause a conflict if new dependencies in the Gemfile require older dependencies than the lockfile" do
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'rails', "2.3.2"
G
- simulate_bundler_version "99999999.99.1"
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails_pinned_to_old_activesupport"
+ G
- bundle! "check", :env => { "BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD" => "1" }
- expect(out).to include("The Gemfile's dependencies are satisfied")
+ expect(out).to include("Installing activesupport 1.2.3 (was 2.3.2)")
+ expect(err).to be_empty
end
- it "can install dependencies with newer bundler version with a local path", :ruby => "> 2" do
- bundle! "config path .bundle"
- bundle! "config global_path_appends_ruby_scope true"
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
- gem "rails", "3.0"
+ it "prints the previous version when switching to a previously downloaded gem" do
+ build_repo4 do
+ build_gem "rails", "7.0.3"
+ build_gem "rails", "7.0.4"
+ end
+
+ bundle_config "path.system true"
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem 'rails', "7.0.4"
G
- simulate_bundler_version "99999999.99.1"
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem 'rails', "7.0.3"
+ G
- bundle! "check", :env => { "BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD" => "1" }
- expect(out).to include("The Gemfile's dependencies are satisfied")
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem 'rails', "7.0.4"
+ G
+
+ expect(out).to include("Using rails 7.0.4 (was 7.0.3)")
+ expect(err).to be_empty
end
- context "with allow_bundler_dependency_conflicts set" do
- before { bundle! "config allow_bundler_dependency_conflicts true" }
+ it "can install dependencies with newer bundler version with system gems" do
+ bundle_config "path.system true"
- it "are forced to the current bundler version with warnings when no compatible version is found" do
- build_repo4 do
- build_gem "requires_nonexistant_bundler" do |s|
- s.add_runtime_dependency "bundler", "99.99.99.99"
- end
- end
+ system_gems "bundler-99999999.99.1"
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "3.0"
+ G
+
+ bundle "check"
+ expect(out).to include("The Gemfile's dependencies are satisfied")
+ end
- install_gemfile! <<-G
- source "file://#{gem_repo4}"
- gem "requires_nonexistant_bundler"
- G
+ it "can install dependencies with newer bundler version with a local path" do
+ bundle_config "path .bundle"
- expect(out).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \
- "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored"
+ system_gems "bundler-99999999.99.1"
- expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0"
- end
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "3.0"
+ G
+
+ bundle "check"
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
end
end
diff --git a/spec/bundler/install/cooldown_spec.rb b/spec/bundler/install/cooldown_spec.rb
new file mode 100644
index 0000000000..b3f57d93cc
--- /dev/null
+++ b/spec/bundler/install/cooldown_spec.rb
@@ -0,0 +1,272 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with the cooldown setting" do
+ before do
+ build_repo2
+ end
+
+ context "Gemfile DSL" do
+ it "accepts `source ..., cooldown: N` without error" do
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo2", cooldown: 5
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "accepts `cooldown: 0` to disable cooldown for a source" do
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo2", cooldown: 0
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+ end
+
+ context "CLI flag" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+ end
+
+ it "accepts --cooldown N on install" do
+ bundle "install --cooldown 7", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "accepts --cooldown 0 as an escape hatch" do
+ bundle "install --cooldown 0", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "rejects a negative --cooldown value" do
+ bundle "install --cooldown=-7", artifice: "compact_index", raise_on_error: false
+
+ expect(err).to match(/non-negative integer/)
+ end
+ end
+
+ context "configuration" do
+ it "reads BUNDLE_COOLDOWN as an integer" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle "install", env: { "BUNDLE_COOLDOWN" => "7" }, artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "reads `bundle config set cooldown N`" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle "config set cooldown 7"
+ bundle "install", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+ end
+
+ context "end-to-end with v2 compact index" do
+ before do
+ now = Time.now.utc
+ build_repo3 do
+ build_gem "ripe_gem", "1.0.0" do |s|
+ s.date = now - (30 * 86_400)
+ end
+ build_gem "ripe_gem", "2.0.0" do |s|
+ s.date = now - (1 * 86_400)
+ end
+ end
+ end
+
+ it "excludes versions within the cooldown window" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ bundle "install --cooldown 7", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 1.0.0")
+ end
+
+ it "selects the latest version when --cooldown 0 is passed" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ bundle "install --cooldown 0", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 2.0.0")
+ end
+
+ it "applies cooldown declared per-source in the Gemfile" do
+ gemfile <<-G
+ source "https://gem.repo3", cooldown: 7
+ gem "ripe_gem"
+ G
+
+ bundle "install", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 1.0.0")
+ end
+
+ it "is overridden by CLI --cooldown when Gemfile sets a different per-source value" do
+ gemfile <<-G
+ source "https://gem.repo3", cooldown: 0
+ gem "ripe_gem"
+ G
+
+ bundle "install --cooldown 7", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 1.0.0")
+ end
+
+ it "bypasses cooldown when bundle install uses an existing lockfile" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ ripe_gem (2.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ripe_gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --cooldown 7", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 2.0.0")
+ end
+
+ it "annotates in-cooldown versions in bundle outdated table output" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem", "1.0.0"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ ripe_gem (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ripe_gem (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "outdated --cooldown 7", artifice: "compact_index_cooldown", raise_on_error: false
+
+ expect(out).to match(/ripe_gem.*\(cooldown \d+d\)/)
+ end
+
+ it "annotates in-cooldown versions in bundle outdated --parseable output" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem", "1.0.0"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ ripe_gem (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ripe_gem (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "outdated --cooldown 7 --parseable", artifice: "compact_index_cooldown", raise_on_error: false
+
+ expect(out).to match(/ripe_gem.*in cooldown for \d+ more day/)
+ end
+
+ it "excludes a locally-installed version that is still within the cooldown window" do
+ system_gems "ripe_gem-2.0.0", gem_repo: gem_repo3
+
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ bundle "install --cooldown 7", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 1.0.0")
+ end
+
+ it "selects a locally-installed in-cooldown version when --cooldown 0 bypasses the filter" do
+ system_gems "ripe_gem-2.0.0", gem_repo: gem_repo3
+
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ bundle "install --cooldown 0", artifice: "compact_index_cooldown"
+
+ expect(the_bundle).to include_gems("ripe_gem 2.0.0")
+ end
+
+ it "surfaces a cooldown hint when bundle update filters every candidate" do
+ gemfile <<-G
+ source "https://gem.repo3"
+ gem "ripe_gem"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ ripe_gem (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ripe_gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update ripe_gem --cooldown 99999", artifice: "compact_index_cooldown", raise_on_error: false
+
+ expect(err).to match(/excluded by the cooldown setting/)
+ expect(err).to match(/--cooldown 0/)
+ end
+ end
+end
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index ec72ff69fc..a3b4a87ecf 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -1,107 +1,139 @@
# frozen_string_literal: true
-RSpec.describe "install with --deployment or --frozen" do
+RSpec.describe "install in deployment or frozen mode" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- context "with CLI flags", :bundler => "< 3" do
- it "fails without a lockfile and says that --deployment requires a lock" do
- bundle "install --deployment"
- expect(out).to include("The --deployment flag requires a Gemfile.lock")
- end
-
- it "fails without a lockfile and says that --frozen requires a lock" do
- bundle "install --frozen"
- expect(out).to include("The --frozen flag requires a Gemfile.lock")
- end
-
- it "disallows --deployment --system" do
- bundle "install --deployment --system"
- expect(out).to include("You have specified both --deployment")
- expect(out).to include("Please choose only one option")
- expect(exitstatus).to eq(15) if exitstatus
- end
-
- it "disallows --deployment --path --system" do
- bundle "install --deployment --path . --system"
- expect(out).to include("You have specified both --path")
- expect(out).to include("as well as --system")
- expect(out).to include("Please choose only one option")
- expect(exitstatus).to eq(15) if exitstatus
- end
+ it "fails without a lockfile and says that deployment requires a lock" do
+ bundle_config "deployment true"
+ bundle "install", raise_on_error: false
+ expect(err).to include("The deployment setting requires a lockfile")
+ end
- it "works after you try to deploy without a lock" do
- bundle "install --deployment"
- bundle! :install
- expect(the_bundle).to include_gems "rack 1.0"
- end
+ it "fails without a lockfile and says that frozen requires a lock" do
+ bundle_config "frozen true"
+ bundle "install", raise_on_error: false
+ expect(err).to include("The frozen setting requires a lockfile")
end
it "still works if you are not in the app directory and specify --gemfile" do
bundle "install"
- Dir.chdir tmp do
- simulate_new_machine
- bundle! :install,
- forgotten_command_line_options(:gemfile => "#{tmp}/bundled_app/Gemfile",
- :deployment => true,
- :path => "vendor/bundle")
- end
- expect(the_bundle).to include_gems "rack 1.0"
+ pristine_system_gems
+ bundle_config "deployment true"
+ bundle_config "path vendor/bundle"
+ bundle "install --gemfile #{tmp}/bundled_app/Gemfile", dir: tmp
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "works if you exclude a group with a git gem" do
build_git "foo"
gemfile <<-G
+ source "https://gem.repo1"
group :test do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
G
bundle :install
- bundle! :install, forgotten_command_line_options(:deployment => true, :without => "test")
+ bundle_config "deployment true"
+ bundle_config "without test"
+ bundle :install
end
- it "works when you bundle exec bundle", :ruby_repo do
+ it "works when you bundle exec bundle" do
+ skip "doesn't find bundle" if Gem.win_platform?
+
+ bundle :install
+ bundle_config "deployment true"
bundle :install
- bundle "install --deployment"
- bundle! "exec bundle check"
+ bundle "exec bundle check", env: { "PATH" => path }
end
it "works when using path gems from the same path and the version is specified" do
- build_lib "foo", :path => lib_path("nested/foo")
- build_lib "bar", :path => lib_path("nested/bar")
+ build_lib "foo", path: lib_path("nested/foo")
+ build_lib "bar", path: lib_path("nested/bar")
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", "1.0", :path => "#{lib_path("nested")}"
gem "bar", :path => "#{lib_path("nested")}"
G
- bundle! :install
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle :install
+ bundle_config "deployment true"
+ bundle :install
+ end
+
+ it "works when path gems are specified twice" do
+ build_lib "foo", path: lib_path("nested/foo")
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ G
+
+ bundle :install
+ bundle_config "deployment true"
+ bundle :install
end
it "works when there are credentials in the source URL" do
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
+ install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
source "http://user:pass@localgemserver.test/"
- gem "rack-obama", ">= 1.0"
+ gem "myrack-obama", ">= 1.0"
G
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint_strict_basic_authentication")
+ bundle_config "deployment true"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
end
it "works with sources given by a block" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}" do
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ source "https://gem.repo1" do
+ gem "myrack"
end
G
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle_config "deployment true"
+ bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
+ end
+
+ context "when replacing a host with the same host with credentials" do
+ before do
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ gemfile <<-G
+ source "http://user_name:password@localgemserver.test/"
+ gem "myrack"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{generic_local_platform}
+
+ DEPENDENCIES
+ myrack
+ G
+
+ bundle_config "deployment true"
+ end
+
+ it "allows the replace" do
+ bundle :install
+
+ expect(out).to match(/Bundle complete!/)
+ end
end
describe "with an existing lockfile" do
@@ -109,311 +141,349 @@ RSpec.describe "install with --deployment or --frozen" do
bundle "install"
end
- it "works with the --deployment flag if you didn't change anything", :bundler => "< 3" do
- bundle! "install --deployment"
+ it "installs gems by default to vendor/bundle" do
+ bundle_config "deployment true"
+ expect do
+ bundle "install"
+ end.not_to change { bundled_app_lock.mtime }
+ expect(out).to include("vendor/bundle")
+ end
+
+ it "installs gems to custom path if specified" do
+ bundle_config "path vendor/bundle2"
+ bundle_config "deployment true"
+ bundle "install"
+ expect(out).to include("vendor/bundle2")
+ end
+
+ it "installs gems to custom path if specified, even when configured through ENV" do
+ bundle_config "deployment true"
+ bundle "install", env: { "BUNDLE_PATH" => "vendor/bundle2" }
+ expect(out).to include("vendor/bundle2")
end
- it "works with the --frozen flag if you didn't change anything", :bundler => "< 3" do
- bundle! "install --frozen"
+ it "works with the `frozen` setting" do
+ bundle_config "frozen true"
+ expect do
+ bundle "install"
+ end.not_to change { bundled_app_lock.mtime }
end
it "works with BUNDLE_FROZEN if you didn't change anything" do
- bundle! :install, :env => { "BUNDLE_FROZEN" => "true" }
+ expect do
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }
+ end.not_to change { bundled_app_lock.mtime }
end
- it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
+ it "explodes with the `deployment` setting if you make a change and don't check in the lockfile" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile")
- expect(out).to include("* rack-obama")
- expect(out).not_to include("You have deleted from the Gemfile")
- expect(out).not_to include("You have changed in the Gemfile")
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile")
+ expect(err).to include("* myrack-obama")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have changed in the Gemfile")
end
it "works if a path gem is missing but is in a without group" do
build_lib "path_gem"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
G
expect(the_bundle).to include_gems "path_gem 1.0"
FileUtils.rm_r lib_path("path_gem-1.0")
- bundle! :install, forgotten_command_line_options(:path => ".bundle", :without => "development", :deployment => true).merge(:env => { :DEBUG => "1" })
- run! "puts :WIN"
+ bundle_config "path .bundle"
+ bundle_config "without development"
+ bundle_config "deployment true"
+ bundle :install, env: { "DEBUG" => "1" }
+ run "puts :WIN"
expect(out).to eq("WIN")
end
+ it "works if a gem is missing, but it's on a different platform" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+
+ source "https://gem.repo1" do
+ gem "rake", platform: :#{not_local_tag}
+ end
+ G
+
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }
+ expect(last_command).to be_success
+ end
+
+ it "shows a good error if a gem is missing from the lockfile" do
+ build_repo4 do
+ build_gem "foo"
+ build_gem "bar"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false, artifice: "compact_index"
+ expect(err).to include("Your lockfile is missing \"bar\", but can't be updated because frozen mode is set")
+ end
+
it "explodes if a path gem is missing" do
build_lib "path_gem"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
G
expect(the_bundle).to include_gems "path_gem 1.0"
FileUtils.rm_r lib_path("path_gem-1.0")
- bundle :install, forgotten_command_line_options(:path => ".bundle", :deployment => true)
- expect(out).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.")
+ bundle_config "path .bundle"
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.")
end
- it "can have --frozen set via an environment variable", :bundler => "< 3" do
+ it "can have --frozen set via an environment variable" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_FROZEN"] = "1"
- bundle "install"
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile")
- expect(out).to include("* rack-obama")
- expect(out).not_to include("You have deleted from the Gemfile")
- expect(out).not_to include("You have changed in the Gemfile")
+ bundle "install", raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile")
+ expect(err).to include("* myrack-obama")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have changed in the Gemfile")
end
it "can have --deployment set via an environment variable" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_DEPLOYMENT"] = "true"
+ bundle "install", raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile")
+ expect(err).to include("* myrack-obama")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have changed in the Gemfile")
+ end
+
+ it "installs gems by default to vendor/bundle when deployment mode is set via an environment variable" do
+ ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install"
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile")
- expect(out).to include("* rack-obama")
- expect(out).not_to include("You have deleted from the Gemfile")
- expect(out).not_to include("You have changed in the Gemfile")
+ expect(out).to include("vendor/bundle")
+ end
+
+ it "installs gems to custom path when deployment mode is set via an environment variable " do
+ ENV["BUNDLE_DEPLOYMENT"] = "true"
+ ENV["BUNDLE_PATH"] = "vendor/bundle2"
+ bundle "install"
+ expect(out).to include("vendor/bundle2")
end
it "can have --frozen set to false via an environment variable" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_FROZEN"] = "false"
ENV["BUNDLE_DEPLOYMENT"] = "false"
bundle "install"
- expect(out).not_to include("deployment mode")
+ expect(out).not_to include("frozen mode")
expect(out).not_to include("You have added to the Gemfile")
- expect(out).not_to include("* rack-obama")
+ expect(out).not_to include("* myrack-obama")
end
- it "explodes with the --frozen flag if you make a change and don't check in the lockfile", :bundler => "< 2" do
+ it "explodes if you replace a gem and don't check in the lockfile" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama", "1.1"
+ source "https://gem.repo1"
+ gem "activesupport"
G
- bundle :install, forgotten_command_line_options(:frozen => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile")
- expect(out).to include("* rack-obama (= 1.1)")
- expect(out).not_to include("You have deleted from the Gemfile")
- expect(out).not_to include("You have changed in the Gemfile")
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile:\n* activesupport\n\n")
+ expect(err).to include("You have deleted from the Gemfile:\n* myrack")
+ expect(err).not_to include("You have changed in the Gemfile")
end
it "explodes if you remove a gem and don't check in the lockfile" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
- G
-
- bundle :install, forgotten_command_line_options(:deployment => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile:\n* activesupport\n\n")
- expect(out).to include("You have deleted from the Gemfile:\n* rack")
- expect(out).not_to include("You have changed in the Gemfile")
+ gemfile 'source "https://gem.repo1"'
+
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("Some dependencies were deleted")
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have deleted from the Gemfile:\n* myrack")
+ expect(err).not_to include("You have changed in the Gemfile")
end
it "explodes if you add a source" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "git://hubz.com"
+ source "https://gem.repo1"
+ gem "myrack", :git => "git://hubz.com"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)")
- expect(out).not_to include("You have changed in the Gemfile")
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `no specified source` to `git://hubz.com`")
end
- it "explodes if you unpin a source" do
- build_git "rack"
+ it "explodes if you change a source from git to the default" do
+ build_git "myrack"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-1.0")}"
G
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master@#{revision_for(lib_path("rack-1.0"))[0..6]}")
- expect(out).not_to include("You have added to the Gemfile")
- expect(out).not_to include("You have changed in the Gemfile")
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack-1.0")}` to `no specified source`")
end
- it "explodes if you unpin a source, leaving it pinned somewhere else" do
- build_lib "foo", :path => lib_path("rack/foo")
- build_git "rack", :path => lib_path("rack")
+ it "explodes if you change a source from git to the default, in presence of other git sources" do
+ build_lib "foo", path: lib_path("myrack/foo")
+ build_git "myrack", path: lib_path("myrack")
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack")}"
- gem "foo", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack")}"
+ gem "foo", :git => "#{lib_path("myrack")}"
G
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "foo", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "foo", :git => "#{lib_path("myrack")}"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
- expect(out).to include("deployment mode")
- expect(out).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master@#{revision_for(lib_path("rack"))[0..6]})`")
- expect(out).not_to include("You have added to the Gemfile")
- expect(out).not_to include("You have deleted from the Gemfile")
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack")}` to `no specified source`")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).not_to include("You have deleted from the Gemfile")
end
- context "when replacing a host with the same host with credentials" do
- let(:success_message) do
- if Bundler.bundler_major_version < 3
- "Could not reach host localgemserver.test"
- else
- "Bundle complete!"
- end
- end
-
- before do
- install_gemfile <<-G
- source "http://user_name:password@localgemserver.test/"
- gem "rack"
- G
+ it "explodes if you change a source from path to git" do
+ build_git "myrack", path: lib_path("myrack")
- lockfile <<-G
- GEM
- remote: http://localgemserver.test/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{local}
-
- DEPENDENCIES
- rack
- G
- end
-
- it "prevents the replace by default" do
- bundle :install, forgotten_command_line_options(:deployment => true)
-
- expect(out).to match(/The list of sources changed/)
- end
-
- context "when allow_deployment_source_credential_changes is true" do
- before { bundle! "config allow_deployment_source_credential_changes true" }
-
- it "allows the replace" do
- bundle :install, forgotten_command_line_options(:deployment => true)
-
- expect(out).to match(/#{success_message}/)
- end
- end
-
- context "when allow_deployment_source_credential_changes is false" do
- before { bundle! "config allow_deployment_source_credential_changes false" }
-
- it "prevents the replace" do
- bundle :install, forgotten_command_line_options(:deployment => true)
-
- expect(out).to match(/The list of sources changed/)
- end
- end
-
- context "when BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES env var is true" do
- before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "true" }
-
- it "allows the replace" do
- bundle :install, forgotten_command_line_options(:deployment => true)
-
- expect(out).to match(/#{success_message}/)
- end
- end
-
- context "when BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES env var is false" do
- before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "false" }
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :path => "#{lib_path("myrack")}"
+ G
- it "prevents the replace" do
- bundle :install, forgotten_command_line_options(:deployment => true)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :git => "https:/my-git-repo-for-myrack"
+ G
- expect(out).to match(/The list of sources changed/)
- end
- end
+ bundle_config "frozen true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack")}` to `https:/my-git-repo-for-myrack`")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).not_to include("You have deleted from the Gemfile")
end
it "remembers that the bundle is frozen at runtime" do
- bundle! :lock
+ bundle :lock
- bundle! "config deployment true"
+ bundle_config "deployment true"
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0.0"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ gem "myrack-obama"
G
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(err).to include strip_whitespace(<<-E).strip
-The dependencies in your gemfile changed
+ run "require 'myrack'", raise_on_error: false
+ expect(err).to include <<~E.strip
+ The dependencies in your gemfile changed, but the lockfile can't be updated because frozen mode is set (Bundler::ProductionError)
-You have added to the Gemfile:
-* rack (= 1.0.0)
-* rack-obama
+ You have added to the Gemfile:
+ * myrack (= 1.0.0)
+ * myrack-obama
-You have deleted from the Gemfile:
-* rack
+ You have deleted from the Gemfile:
+ * myrack
E
end
end
context "with path in Gemfile and packed" do
it "works fine after bundle package and bundle install --local" do
- build_lib "foo", :path => lib_path("foo")
- install_gemfile! <<-G
+ build_lib "foo", path: lib_path("foo")
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gems "foo 1.0"
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
+
+ bundle :cache
expect(bundled_app("vendor/cache/foo")).to be_directory
- bundle! "install --local"
+ bundle "install --local"
expect(out).to include("Updating files in vendor/cache")
- simulate_new_machine
- bundle! "install --verbose", forgotten_command_line_options(:deployment => true)
- expect(out).not_to include("You are trying to install in deployment mode after changing your Gemfile")
+ pristine_system_gems
+ bundle_config "deployment true"
+ bundle "install --verbose"
+ expect(out).not_to include("can't be updated because frozen mode is set")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("You have deleted from the Gemfile")
expect(out).to include("vendor/cache/foo")
diff --git a/spec/bundler/install/failure_spec.rb b/spec/bundler/install/failure_spec.rb
index b4cdf13857..32ca455439 100644
--- a/spec/bundler/install/failure_spec.rb
+++ b/spec/bundler/install/failure_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install" do
context "installing a gem fails" do
- it "prints out why that gem was being installed" do
+ it "prints out why that gem was being installed and the underlying error" do
build_repo2 do
build_gem "activesupport", "2.3.2" do |s|
s.extensions << "Rakefile"
@@ -14,13 +14,13 @@ RSpec.describe "bundle install" do
end
end
- install_gemfile <<-G
- source "file:\/\/localhost#{gem_repo2}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem "rails"
G
- expect(last_command.bundler_err).to end_with(normalize_uri_file(<<-M.strip))
+ expect(err).to start_with("Gem::Ext::BuildError: ERROR: Failed to build gem native extension.")
+ expect(err).to end_with(<<-M.strip)
An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-Make sure that `gem install activesupport -v '2.3.2' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling.
In Gemfile:
rails was resolved to 2.3.2, which depends on
@@ -29,97 +29,57 @@ In Gemfile:
M
end
- context "when installing a git gem" do
- it "does not tell the user to run 'gem install'" do
- build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
+ context "because the downloaded .gem was invalid" do
+ before do
+ build_repo4 do
+ build_gem "a"
end
- install_gemfile <<-G
- source "file:\/\/localhost#{gem_repo1}"
- gem "rails"
- gem "activesupport", :git => "#{lib_path("activesupport")}"
- G
-
- expect(last_command.bundler_err).to end_with(<<-M.strip)
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
+ gem_repo4("gems", "a-1.0.gem").open("w") {|f| f << "<html></html>" }
end
- end
-
- context "when installing a gem using a git block" do
- it "does not tell the user to run 'gem install'" do
- build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
- end
-
- install_gemfile <<-G
- source "file:\/\/localhost#{gem_repo1}"
- gem "rails"
- git "#{lib_path("activesupport")}" do
- gem "activesupport"
- end
+ it "removes the downloaded .gem" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo4"
+ gem "a"
G
- expect(last_command.bundler_err).to end_with(<<-M.strip)
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-
-
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
+ expect(default_bundle_path("cache", "a-1.0.gem")).not_to exist
end
end
+ end
- it "prints out the hint for the remote source when available" do
- build_repo2 do
- build_gem "activesupport", "2.3.2" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
+ context "when lockfile dependencies don't match the gemspec" do
+ before do
+ build_repo4 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.add_dependency "myrack-test", "~> 1.0"
end
- end
- build_repo4 do
- build_gem "a"
+ build_gem "myrack-test", "1.0.0"
end
- install_gemfile <<-G
- source "file:\/\/localhost#{gem_repo4}"
- source "file:\/\/localhost#{gem_repo2}" do
- gem "rails"
- end
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
G
- expect(last_command.bundler_err).to end_with(normalize_uri_file(<<-M.strip))
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-Make sure that `gem install activesupport -v '2.3.2' --source 'file://localhost#{gem_repo2}/'` succeeds before bundling.
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
+ # First install to generate lockfile
+ bundle :install
+
+ # Manually edit lockfile to have incorrect dependencies
+ lockfile_content = File.read(bundled_app_lock)
+ # Remove the myrack-test dependency from myrack
+ lockfile_content.gsub!(/^ myrack \(1\.0\.0\)\n myrack-test \(~> 1\.0\)\n/, " myrack (1.0.0)\n")
+ File.write(bundled_app_lock, lockfile_content)
+ end
+
+ it "reports the mismatch with detailed information" do
+ bundle :install, raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
+
+ expect(err).to include("Bundler found incorrect dependencies in the lockfile for myrack-1.0.0")
+ expect(err).to include("myrack-test: gemspec specifies ~> 1.0, not in lockfile")
+ expect(err).to include("Please run `bundle install` to regenerate the lockfile.")
end
end
end
diff --git a/spec/bundler/install/force_spec.rb b/spec/bundler/install/force_spec.rb
new file mode 100644
index 0000000000..e0f6fb6364
--- /dev/null
+++ b/spec/bundler/install/force_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install" do
+ before :each do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ shared_examples_for "an option to force reinstalling gems" do
+ it "re-installs installed gems" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+
+ bundle :install
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :install, flag => true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "works on first bundle install" do
+ bundle :install, flag => true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ context "with a git gem" do
+ let!(:ref) { build_git("foo", "1.0").ref_for("HEAD", 11) }
+
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+ end
+
+ it "re-installs installed gems" do
+ foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb")
+
+ bundle :install
+ foo_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :install, flag => true
+
+ expect(foo_lib.open(&:read)).to eq("FOO = '1.0'\n")
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
+ it "works on first bundle install" do
+ bundle :install, flag => true
+
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+ end
+ end
+
+ describe "with --force" do
+ it_behaves_like "an option to force reinstalling gems" do
+ let(:flag) { "force" }
+ end
+ end
+
+ describe "with --redownload" do
+ it_behaves_like "an option to force reinstalling gems" do
+ let(:flag) { "redownload" }
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
index 035d3692aa..3afa4f5daa 100644
--- a/spec/bundler/install/gemfile/eval_gemfile_spec.rb
+++ b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
before do
- build_lib("gunks", :path => bundled_app.join("gems/gunks")) do |s|
+ build_lib("gunks", path: bundled_app("gems/gunks")) do |s|
s.name = "gunks"
s.version = "0.0.1"
end
@@ -10,44 +10,83 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
context "eval-ed Gemfile points to an internal gemspec" do
before do
- create_file "Gemfile-other", <<-G
+ gemfile "Gemfile-other", <<-G
+ source "https://gem.repo1"
gemspec :path => 'gems/gunks'
G
end
it "installs the gemspec specified gem" do
install_gemfile <<-G
+ source "https://gem.repo1"
eval_gemfile 'Gemfile-other'
G
expect(out).to include("Resolving dependencies")
expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gem "gunks 0.0.1", :source => "path@#{bundled_app("gems", "gunks")}"
+ expect(the_bundle).to include_gem "gunks 0.0.1", source: "path@#{bundled_app("gems", "gunks")}"
+ end
+ end
+
+ context "eval-ed Gemfile points to an internal gemspec and uses a scoped source that duplicates the main Gemfile global source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "6.1.3.2"
+
+ build_gem "zip-zip", "0.3"
+ end
+
+ gemfile bundled_app("gems/Gemfile"), <<-G
+ source "https://gem.repo2"
+
+ gemspec :path => "\#{__dir__}/gunks"
+
+ source "https://gem.repo2" do
+ gem "zip-zip"
+ end
+ G
+ end
+
+ it "installs and finds gems correctly" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "rails"
+
+ eval_gemfile File.join(__dir__, "gems/Gemfile")
+ G
+ expect(out).to include("Resolving dependencies")
+ expect(out).to include("Bundle complete")
+
+ expect(the_bundle).to include_gem "rails 6.1.3.2"
end
end
context "eval-ed Gemfile has relative-path gems" do
before do
- build_lib("a", :path => "gems/a")
- create_file "nested/Gemfile-nested", <<-G
+ build_lib("a", path: bundled_app("gems/a"))
+ gemfile bundled_app("nested/Gemfile-nested"), <<-G
+ source "https://gem.repo1"
gem "a", :path => "../gems/a"
G
gemfile <<-G
+ source "https://gem.repo1"
eval_gemfile "nested/Gemfile-nested"
G
end
it "installs the path gem" do
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem("a 1.0")
end
# Make sure that we are properly comparing path based gems between the
# parsed lockfile and the evaluated gemfile.
- it "bundles with --deployment" do
- bundle! :install
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ it "bundles with deployment mode configured" do
+ bundle :install
+ bundle_config "deployment true"
+ bundle :install
end
end
@@ -56,27 +95,28 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
it "installs the gemspec specified gem" do
install_gemfile <<-G
+ source "https://gem.repo1"
eval_gemfile 'other/Gemfile-other'
gemspec :path => 'gems/gunks'
G
expect(out).to include("Resolving dependencies")
expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gem "gunks 0.0.1", :source => "path@#{bundled_app("gems", "gunks")}"
+ expect(the_bundle).to include_gem "gunks 0.0.1", source: "path@#{bundled_app("gems", "gunks")}"
end
end
context "eval-ed Gemfile references other gemfiles" do
it "works with relative paths" do
- create_file "other/Gemfile-other", "gem 'rack'"
- create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'"
- create_file "Gemfile-alt", <<-G
- source "file:#{gem_repo1}"
+ gemfile "other/Gemfile-other", "gem 'myrack'"
+ gemfile "other/Gemfile", "eval_gemfile 'Gemfile-other'"
+ gemfile "Gemfile-alt", <<-G
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
G
- install_gemfile! "eval_gemfile File.expand_path('Gemfile-alt')"
+ install_gemfile "eval_gemfile File.expand_path('Gemfile-alt')"
- expect(the_bundle).to include_gem "rack 1.0.0"
+ expect(the_bundle).to include_gem "myrack 1.0.0"
end
end
end
diff --git a/spec/bundler/install/gemfile/force_ruby_platform_spec.rb b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
new file mode 100644
index 0000000000..bcc1f36823
--- /dev/null
+++ b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
+ context "when no transitive deps" do
+ before do
+ build_repo4 do
+ # Build a gem with platform specific versions
+ build_gem("platform_specific")
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ end
+
+ # Build the exact same gem with a different name to compare using vs not using the option
+ build_gem("platform_specific_forced")
+
+ build_gem("platform_specific_forced") do |s|
+ s.platform = Bundler.local_platform
+ end
+ end
+ end
+
+ it "pulls the pure ruby variant of the given gem" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{Bundler.local_platform}"
+ end
+
+ it "still respects a global `force_ruby_platform` config" do
+ install_gemfile <<-G, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+ source "https://gem.repo4"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
+ end
+
+ context "when also a transitive dependency" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") {|s| s.add_dependency "platform_specific" }
+
+ build_gem("platform_specific")
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ end
+ end
+ end
+
+ it "still pulls the ruby variant" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "depends_on_platform_specific"
+ gem "platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
+ end
+
+ context "with transitive dependencies with platform specific versions" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_dependency "platform_specific"
+ end
+
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_dependency "platform_specific"
+ s.platform = Bundler.local_platform
+ end
+
+ build_gem("platform_specific")
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ end
+ end
+ end
+
+ it "ignores ruby variants for the transitive dependencies" do
+ install_gemfile <<-G, env: { "DEBUG_RESOLVER" => "true" }
+ source "https://gem.repo4"
+
+ gem "depends_on_platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "depends_on_platform_specific 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{Bundler.local_platform}"
+ end
+
+ it "reinstalls the ruby variant when a platform specific variant is already installed, the lockile has only ruby platform, and :force_ruby_platform is used in the Gemfile" do
+ skip "Can't simulate platform reliably on JRuby, installing a platform specific gem fails to activate io-wait because only the -java version is present, and we're simulating a different platform" if RUBY_ENGINE == "jruby"
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86-darwin-100" do
+ system_gems "platform_specific-1.0-x86-darwin-100", path: default_bundle_path
+
+ install_gemfile <<-G, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, artifice: "compact_index"
+ source "https://gem.repo4"
+
+ gem "platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index bbb56da5a4..e51fc9247d 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -9,35 +9,35 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should install runtime and development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "that is hidden should install runtime and development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
- FileUtils.mv tmp.join("foo", "foo.gemspec"), tmp.join("foo", ".gemspec")
+ FileUtils.mv tmp("foo", "foo.gemspec"), tmp("foo", ".gemspec")
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "should handle a list of requirements" do
@@ -46,174 +46,171 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "baz", "1.1"
end
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "baz", ">= 1.0", "< 1.1"
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "baz 1.0"
end
it "should raise if there are no gemspecs available" do
- build_lib("foo", :path => tmp.join("foo"), :gemspec => false)
+ build_lib("foo", path: tmp("foo"), gemspec: false)
- install_gemfile(<<-G)
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}'
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
- expect(last_command.bundler_err).to match(/There are no gemspecs at #{tmp.join('foo')}/)
+ expect(err).to match(/There are no gemspecs at #{tmp("foo")}/)
end
it "should raise if there are too many gemspecs available" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby)
end
- install_gemfile(<<-G)
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}'
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
- expect(last_command.bundler_err).to match(/There are multiple gemspecs at #{tmp.join('foo')}/)
+ expect(err).to match(/There are multiple gemspecs at #{tmp("foo")}/)
end
it "should pick a specific gemspec" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile(<<-G)
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :development
end
it "should use a specific group for development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile(<<-G)
- source "file://#{gem_repo2}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo', :development_group => :dev
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo', :development_group => :dev
G
expect(the_bundle).to include_gems "bar 1.0.0"
- expect(the_bundle).not_to include_gems "bar-dev 1.0.0", :groups => :development
- expect(the_bundle).to include_gems "bar-dev 1.0.0", :groups => :dev
+ expect(the_bundle).not_to include_gems "bar-dev 1.0.0", groups: :development
+ expect(the_bundle).to include_gems "bar-dev 1.0.0", groups: :dev
end
it "should match a lockfile even if the gemspec defines development dependencies" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.write("Gemfile", "source 'file://#{gem_repo1}'\ngemspec")
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.write("Gemfile", "source 'https://gem.repo1'\ngemspec")
s.add_dependency "actionpack", "=2.3.2"
- s.add_development_dependency "rake", "=10.0.2"
+ s.add_development_dependency "rake", rake_version
end
- Dir.chdir(tmp.join("foo")) do
- bundle "install"
- # This should really be able to rely on $stderr, but, it's not written
- # right, so we can't. In fact, this is a bug negation test, and so it'll
- # ghost pass in future, and will only catch a regression if the message
- # doesn't change. Exit codes should be used correctly (they can be more
- # than just 0 and 1).
- output = bundle("install --deployment")
- expect(output).not_to match(/You have added to the Gemfile/)
- expect(output).not_to match(/You have deleted from the Gemfile/)
- expect(output).not_to match(/install in deployment mode after changing/)
- end
+ bundle "install", dir: tmp("foo"), artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ # This should really be able to rely on $stderr, but, it's not written
+ # right, so we can't. In fact, this is a bug negation test, and so it'll
+ # ghost pass in future, and will only catch a regression if the message
+ # doesn't change. Exit codes should be used correctly (they can be more
+ # than just 0 and 1).
+ bundle_config "deployment true"
+ output = bundle("install", dir: tmp("foo"), artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s })
+ expect(output).not_to match(/You have added to the Gemfile/)
+ expect(output).not_to match(/You have deleted from the Gemfile/)
+ expect(output).not_to match(/the lockfile can't be updated because frozen mode is set/)
end
it "should match a lockfile without needing to re-resolve" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.add_dependency "rack"
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack"
end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gemspec :path => '#{tmp.join("foo")}'
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}'
G
- bundle! "install", :verbose => true
+ bundle "install", verbose: true
message = "Found no changes, using resolution from the lockfile"
expect(out.scan(message).size).to eq(1)
end
it "should match a lockfile without needing to re-resolve with development dependencies" do
- simulate_platform java
-
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.add_dependency "rack"
- s.add_development_dependency "thin"
- end
+ simulate_platform "java" do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack"
+ s.add_development_dependency "thin"
+ end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gemspec :path => '#{tmp.join("foo")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}'
+ G
- bundle! "install", :verbose => true
+ bundle "install", verbose: true
- message = "Found no changes, using resolution from the lockfile"
- expect(out.scan(message).size).to eq(1)
+ message = "Found no changes, using resolution from the lockfile"
+ expect(out.scan(message).size).to eq(1)
+ end
end
- it "should match a lockfile on non-ruby platforms with a transitive platform dependency" do
- simulate_platform java
- simulate_ruby_engine "jruby"
-
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby_only do
+ build_lib("foo", path: tmp("foo")) do |s|
s.add_dependency "platform_specific"
end
- system_gems "platform_specific-1.0-java", :path => :bundle_path, :keep_path => true
+ system_gems "platform_specific-1.0-java", path: default_bundle_path
- install_gemfile! <<-G
- gemspec :path => '#{tmp.join("foo")}'
+ install_gemfile <<-G
+ gemspec :path => '#{tmp("foo")}'
G
- bundle! "update --bundler", :verbose => true
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA"
+ bundle "update --bundler", artifice: "compact_index", verbose: true
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 java"
end
it "should evaluate the gemspec in its directory" do
- build_lib("foo", :path => tmp.join("foo"))
- File.open(tmp.join("foo/foo.gemspec"), "w") do |s|
- s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'"
+ build_lib("foo", path: tmp("foo"))
+ File.open(tmp("foo/foo.gemspec"), "w") do |s|
+ s.write "raise 'ahh' unless Dir.pwd == '#{tmp("foo")}'"
end
- install_gemfile <<-G
- gemspec :path => '#{tmp.join("foo")}'
+ install_gemfile <<-G, raise_on_error: false
+ gemspec :path => '#{tmp("foo")}'
G
- expect(last_command.stdboth).not_to include("ahh")
+ expect(stdboth).not_to include("ahh")
end
it "allows the gemspec to activate other gems" do
ENV["BUNDLE_PATH__SYSTEM"] = "true"
- # see https://github.com/bundler/bundler/issues/5409
+ # see https://github.com/rubygems/bundler/issues/5409
#
# issue was caused by rubygems having an unresolved gem during a require,
# so emulate that
- system_gems %w[rack-1.0.0 rack-0.9.1 rack-obama-1.0]
+ system_gems %w[myrack-1.0.0 myrack-0.9.1 myrack-obama-1.0]
- build_lib("foo", :path => bundled_app)
+ build_lib("foo", path: bundled_app)
gemspec = bundled_app("foo.gemspec").read
bundled_app("foo.gemspec").open("w") do |f|
- f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack-obama' }"
+ f.write "#{gemspec.strip}.tap { gem 'myrack-obama'; require 'myrack/obama' }"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gemspec
G
@@ -221,26 +218,26 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "allows conflicts" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
- build_gem "deps", :to_bundle => true do |s|
+ build_gem "deps", to_bundle: true do |s|
s.add_dependency "foo", "= 0.0.1"
end
- build_gem "foo", "0.0.1", :to_bundle => true
+ build_gem "foo", "0.0.1", to_bundle: true
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "deps"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "foo 1.0.0"
end
- it "does not break Gem.finish_resolve with conflicts", :rubygems => ">= 2" do
- build_lib("foo", :path => tmp.join("foo")) do |s|
+ it "does not break Gem.finish_resolve with conflicts" do
+ build_lib("foo", path: tmp("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
@@ -251,39 +248,74 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "foo", "0.0.1"
end
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "deps"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "foo 1.0.0"
- run! "Gem.finish_resolve; puts 'WIN'"
+ run "Gem.finish_resolve; puts 'WIN'"
expect(out).to eq("WIN")
end
+ it "does not make Gem.try_activate warn when local gem has extensions" do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.version = "1.0.0"
+ s.add_c_extension
+ end
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
+ G
+
+ expect(the_bundle).to include_gems "foo 1.0.0"
+
+ run "Gem.try_activate('irb/lc/es/error.rb'); puts 'WIN'"
+ expect(out).to eq("WIN")
+ expect(err).to be_empty
+ end
+
+ it "handles downgrades" do
+ build_lib "omg", "2.0", path: lib_path("omg")
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => "#{lib_path("omg")}"
+ G
+
+ build_lib "omg", "1.0", path: lib_path("omg")
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "omg 1.0"
+ end
+
context "in deployment mode" do
context "when the lockfile was not updated after a change to the gemspec's dependencies" do
it "reports that installation failed" do
- build_lib "cocoapods", :path => bundled_app do |s|
+ build_lib "cocoapods", path: bundled_app do |s|
s.add_dependency "activesupport", ">= 1"
end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gemspec
G
expect(the_bundle).to include_gems("cocoapods 1.0", "activesupport 2.3.5")
- build_lib "cocoapods", :path => bundled_app do |s|
+ build_lib "cocoapods", path: bundled_app do |s|
s.add_dependency "activesupport", ">= 1.0.1"
end
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle_config "deployment true"
+ bundle :install, raise_on_error: false
- expect(out).to include("changed")
+ expect(err).to include("changed")
end
end
end
@@ -291,119 +323,93 @@ RSpec.describe "bundle install from an existing gemspec" do
context "when child gemspecs conflict with a released gemspec" do
before do
# build the "parent" gem that depends on another gem in the same repo
- build_lib "source_conflict", :path => bundled_app do |s|
- s.add_dependency "rack_middleware"
+ build_lib "source_conflict", path: bundled_app do |s|
+ s.add_dependency "myrack_middleware"
end
# build the "child" gem that is the same version as a released gem, but
# has completely different and conflicting dependency requirements
- build_lib "rack_middleware", "1.0", :path => bundled_app("rack_middleware") do |s|
- s.add_dependency "rack", "1.0" # anything other than 0.9.1
+ build_lib "myrack_middleware", "1.0", path: bundled_app("myrack_middleware") do |s|
+ s.add_dependency "myrack", "1.0" # anything other than 0.9.1
end
end
it "should install the child gemspec's deps" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gemspec
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
context "with a lockfile and some missing dependencies" do
let(:source_uri) { "http://localgemserver.test" }
- context "previously bundled for Ruby" do
- let(:platform) { "ruby" }
- let(:explicit_platform) { false }
-
- before do
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.add_dependency "rack", "=1.0.0"
- end
-
- if explicit_platform
- create_file(
- tmp.join("foo", "foo-#{platform}.gemspec"),
- build_spec("foo", "1.0", platform) do
- dep "rack", "=1.0.0"
- @spec.authors = "authors"
- @spec.summary = "summary"
- end.first.to_ruby
- )
- end
-
- gemfile <<-G
- source "#{source_uri}"
- gemspec :path => "../foo"
- G
-
- lockfile <<-L
- PATH
- remote: ../foo
- specs:
- foo (1.0)
- rack (= 1.0.0)
-
- GEM
- remote: #{source_uri}
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ before do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack", "=1.0.0"
end
- context "using JRuby with explicit platform" do
- let(:platform) { "java" }
- let(:explicit_platform) { true }
+ gemfile <<-G
+ source "#{source_uri}"
+ gemspec :path => "../foo"
+ G
- it "should install" do
- simulate_ruby_engine "jruby" do
- simulate_platform "java" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
- end
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
end
- context "using JRuby" do
- let(:platform) { "java" }
+ lockfile <<-L
+ PATH
+ remote: ../foo
+ specs:
+ foo (1.0)
+ myrack (= 1.0.0)
+
+ GEM
+ remote: #{source_uri}
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- it "should install" do
- simulate_ruby_engine "jruby" do
- simulate_platform "java" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
- end
+ context "using JRuby with explicit platform", :jruby_only do
+ before do
+ create_file(
+ tmp("foo", "foo-java.gemspec"),
+ build_spec("foo", "1.0", "java") do
+ dep "myrack", "=1.0.0"
+ @spec.authors = "authors"
+ @spec.summary = "summary"
+ end.first.to_ruby
+ )
end
- context "using Windows" do
- it "should install" do
- simulate_windows do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
+ it "should install" do
+ results = bundle "install", artifice: "endpoint"
+ expect(results).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
- context "bundled for ruby and jruby" do
+ it "should install", :jruby do
+ results = bundle "install", artifice: "endpoint"
+ expect(results).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ context "bundled for multiple platforms" do
let(:platform_specific_type) { :runtime }
let(:dependency) { "platform_specific" }
before do
@@ -413,36 +419,49 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- build_lib "foo", :path => "." do |s|
- if platform_specific_type == :runtime
+ build_lib "foo", path: bundled_app do |s|
+ case platform_specific_type
+ when :runtime
s.add_runtime_dependency dependency
- elsif platform_specific_type == :development
+ when :development
s.add_development_dependency dependency
else
- raise "wrong dependency type #{platform_specific_type}, can only be :development or :runtime"
+ raise ArgumentError, "wrong dependency type #{platform_specific_type}, can only be :development or :runtime"
end
end
- %w[ruby jruby].each do |platform|
- simulate_platform(platform) do
- install_gemfile <<-G
- source "file://localhost#{gem_repo2}"
- gemspec
- G
- end
- end
+ gemfile <<-G
+ source "https://gem.repo2"
+ gemspec
+ G
+
+ bundle_config "force_ruby_platform true"
+ bundle "install"
+
+ simulate_new_machine
+ simulate_platform("jruby") { bundle "install" }
+ expect(lockfile).to include("platform_specific (1.0-java)")
+ simulate_platform("x64-mingw-ucrt") { bundle "install" }
end
- context "on ruby", :bundler => "< 3" do
+ context "on ruby" do
before do
- simulate_platform("ruby")
+ bundle_config "force_ruby_platform true"
bundle :install
end
context "as a runtime dependency" do
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
+ it "keeps all platform dependencies in the lockfile" do
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 ruby"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
@@ -450,20 +469,22 @@ RSpec.describe "bundle install from an existing gemspec" do
platform_specific
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
+ x64-mingw-ucrt
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -471,30 +492,40 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a development dependency" do
let(:platform_specific_type) { :development }
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
+ it "keeps all platform dependencies in the lockfile" do
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 ruby"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
foo (1.0)
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
+ x64-mingw-ucrt
DEPENDENCIES
foo!
platform_specific
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -503,170 +534,204 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:platform_specific_type) { :development }
let(:dependency) { "indirect_platform_specific" }
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
+ it "keeps all platform dependencies in the lockfile" do
+ expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 ruby"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo2, "indirect_platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0"
+ c.checksum gem_repo2, "platform_specific", "1.0", "java"
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
+ end
+
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
foo (1.0)
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
indirect_platform_specific (1.0)
platform_specific
platform_specific (1.0)
platform_specific (1.0-java)
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
+ x64-mingw-ucrt
DEPENDENCIES
foo!
indirect_platform_specific
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
end
+ end
+ end
- context "on ruby", :bundler => "3" do
- before do
- simulate_platform("ruby")
- bundle :install
- end
+ context "with multiple platforms" do
+ before do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.version = "1.0.0"
+ s.add_development_dependency "myrack"
+ s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "myrack", "1.0.0" }.first.to_ruby
+ end
+ end
- context "as a runtime dependency" do
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
- platform_specific (1.0)
- platform_specific (1.0-java)
+ it "installs the ruby platform gemspec" do
+ bundle_config "force_ruby_platform true"
- PATH
- remote: .
- specs:
- foo (1.0)
- platform_specific
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
+ G
- PLATFORMS
- java
- ruby
+ expect(the_bundle).to include_gems "foo 1.0.0", "myrack 1.0.0"
+ end
- DEPENDENCIES
- foo!
+ it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do
+ bundle_config "force_ruby_platform true"
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
- end
+ bundle_config "without development"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
+ G
- context "as a development dependency" do
- let(:platform_specific_type) { :development }
+ expect(the_bundle).to include_gem "foo 1.0.0"
+ expect(the_bundle).not_to include_gem "myrack"
+ end
+ end
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
- platform_specific (1.0)
- platform_specific (1.0-java)
+ context "with multiple platforms and resolving for more specific platforms" do
+ before do
+ build_lib("chef", path: tmp("chef")) do |s|
+ s.version = "17.1.17"
+ s.write "chef-universal-mingw-ucrt.gemspec", build_spec("chef", "17.1.17", "universal-mingw-ucrt") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby
+ end
+ end
- PATH
- remote: .
- specs:
- foo (1.0)
+ it "does not remove the platform specific specs from the lockfile when updating" do
+ build_repo4 do
+ build_gem "win32-api", "1.5.3" do |s|
+ s.platform = "universal-mingw-ucrt"
+ end
+ end
- PLATFORMS
- java
- ruby
+ gemfile <<-G
+ source "https://gem.repo4"
+ gemspec :path => "../chef"
+ G
- DEPENDENCIES
- foo!
- platform_specific
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "chef", "17.1.17"
+ c.no_checksum "chef", "17.1.17", "universal-mingw-ucrt"
+ c.checksum gem_repo4, "win32-api", "1.5.3", "universal-mingw-ucrt"
+ end
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
- end
+ initial_lockfile = <<~L
+ PATH
+ remote: ../chef
+ specs:
+ chef (17.1.17)
+ chef (17.1.17-universal-mingw-ucrt)
+ win32-api (~> 1.5.3)
- context "with an indirect platform-specific development dependency" do
- let(:platform_specific_type) { :development }
- let(:dependency) { "indirect_platform_specific" }
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ win32-api (1.5.3-universal-mingw-ucrt)
- it "keeps java dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY"
- expect(lockfile).to eq normalize_uri_file(strip_whitespace(<<-L))
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
- indirect_platform_specific (1.0)
- platform_specific
- platform_specific (1.0)
- platform_specific (1.0-java)
+ PLATFORMS
+ #{lockfile_platforms("ruby", "x64-mingw-ucrt", "x86-mingw32")}
- PATH
- remote: .
- specs:
- foo (1.0)
+ DEPENDENCIES
+ chef!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- PLATFORMS
- java
- ruby
+ lockfile initial_lockfile
- DEPENDENCIES
- foo!
- indirect_platform_specific
+ bundle "update"
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
- end
- end
+ expect(lockfile).to eq initial_lockfile
end
end
- context "with multiple platforms" do
+ context "with multiple locked platforms" do
before do
- build_lib("foo", :path => tmp.join("foo")) do |s|
- s.version = "1.0.0"
- s.add_development_dependency "rack"
- s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "rack", "1.0.0" }.first.to_ruby
+ build_lib("activeadmin", path: tmp("activeadmin")) do |s|
+ s.version = "2.9.0"
+ s.add_dependency "railties", ">= 5.2", "< 6.2"
end
- end
- it "installs the ruby platform gemspec" do
- simulate_platform "ruby"
+ build_repo4 do
+ build_gem "railties", "6.1.4"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ build_gem "jruby-openssl", "0.10.7" do |s|
+ s.platform = "java"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gemspec :path => "../activeadmin"
+ gem "jruby-openssl", :platform => :jruby
G
- expect(the_bundle).to include_gems "foo 1.0.0", "rack 1.0.0"
+ bundle "lock --add-platform java"
end
- it "installs the ruby platform gemspec and skips dev deps with --without development" do
- simulate_platform "ruby"
+ it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "activeadmin", "2.9.0"
+ c.checksum gem_repo4, "jruby-openssl", "0.10.7", "java"
+ c.checksum gem_repo4, "railties", "6.1.4"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: ../activeadmin
+ specs:
+ activeadmin (2.9.0)
+ railties (>= 5.2, < 6.2)
- install_gemfile! <<-G, forgotten_command_line_options(:without => "development")
- source "file://#{gem_repo1}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
- G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ jruby-openssl (0.10.7-java)
+ railties (6.1.4)
- expect(the_bundle).to include_gem "foo 1.0.0"
- expect(the_bundle).not_to include_gem "rack"
+ PLATFORMS
+ #{lockfile_platforms("java")}
+
+ DEPENDENCIES
+ activeadmin!
+ jruby-openssl
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemspec = tmp("activeadmin/activeadmin.gemspec")
+ File.write(gemspec, File.read(gemspec).sub(">= 5.2", ">= 6.0"))
+
+ previous_lockfile = lockfile
+
+ bundle "install --local"
+
+ expect(lockfile).to eq(previous_lockfile.sub(">= 5.2", ">= 6.0"))
end
end
end
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index fe396c7a0f..b2a82caf01 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -1,21 +1,26 @@
# frozen_string_literal: true
RSpec.describe "bundle install with git sources" do
- describe "when floating on master" do
- before :each do
- build_git "foo" do |s|
- s.executables = "foobar"
- end
-
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ describe "when floating on main" do
+ let(:base_gemfile) do
+ <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
end
+ let(:install_base_gemfile) do
+ build_git "foo" do |s|
+ s.executables = "foobar"
+ end
+
+ install_gemfile base_gemfile
+ end
+
it "fetches gems" do
+ install_base_gemfile
expect(the_bundle).to include_gems("foo 1.0")
run <<-RUBY
@@ -26,18 +31,69 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
- it "caches the git repo", :bundler => "< 3" do
- expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes :size => 1
+ it "does not (yet?) enforce CHECKSUMS" do
+ build_git "foo"
+ revision = revision_for(lib_path("foo-1.0"))
+
+ bundle_config "lockfile_checksums true"
+ gemfile base_gemfile
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{revision}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ CHECKSUMS
+ foo (1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle_config "frozen true"
+
+ bundle "install"
+ expect(the_bundle).to include_gems("foo 1.0")
+ end
+
+ it "caches the git repo" do
+ install_base_gemfile
+ expect(Dir["#{default_cache_path}/git/foo-1.0-*"]).to have_attributes size: 1
end
- it "caches the git repo globally" do
- simulate_new_machine
- bundle! "config global_gem_cache true"
- bundle! :install
- expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes :size => 1
+ it "does not write to cache on bundler/setup" do
+ install_base_gemfile
+ FileUtils.rm_r(default_cache_path)
+ ruby "require 'bundler/setup'"
+ expect(default_cache_path).not_to exist
+ end
+
+ it "caches the git repo globally and properly uses the cached repo on the next invocation" do
+ install_base_gemfile
+ pristine_system_gems
+ bundle_config "global_gem_cache true"
+ bundle :install
+ expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes size: 1
+
+ bundle "install --verbose"
+ expect(err).to be_empty
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")}")
end
it "caches the evaluated gemspec" do
+ install_base_gemfile
git = update_git "foo" do |s|
s.executables = ["foobar"] # we added this the first time, so keep it now
s.files = ["bin/foobar"] # updating git nukes the files list
@@ -47,35 +103,35 @@ RSpec.describe "bundle install with git sources" do
bundle "update foo"
- sha = git.ref_for("master", 11)
- spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec").to_s
- ruby_code = Gem::Specification.load(spec_file).to_ruby
+ sha = git.ref_for("main", 11)
+ spec_file = default_bundle_path("bundler/gems/foo-1.0-#{sha}/foo.gemspec")
+ expect(spec_file).to exist
+ ruby_code = Gem::Specification.load(spec_file.to_s).to_ruby
file_code = File.read(spec_file)
expect(file_code).to eq(ruby_code)
end
it "does not update the git source implicitly" do
+ install_base_gemfile
update_git "foo"
- in_app_root2 do
- install_gemfile bundled_app2("Gemfile"), <<-G
- git "#{lib_path("foo-1.0")}" do
- gem 'foo'
- end
- G
- end
+ install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
+ source "https://gem.repo1"
+ git "#{lib_path("foo-1.0")}" do
+ gem 'foo'
+ end
+ G
- in_app_root do
- run <<-RUBY
- require 'foo'
- puts "fail" if defined?(FOO_PREV_REF)
- RUBY
+ run <<-RUBY
+ require 'foo'
+ puts "fail" if defined?(FOO_PREV_REF)
+ RUBY
- expect(out).to be_empty
- end
+ expect(out).to be_empty
end
it "sets up git gem executables on the path" do
+ install_base_gemfile
bundle "exec foobar"
expect(out).to eq("1.0")
end
@@ -83,32 +139,30 @@ RSpec.describe "bundle install with git sources" do
it "complains if pinned specs don't exist in the git repo" do
build_git "foo"
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}"
G
- expect(out).to include("The source contains 'foo' at: 1.0")
+ expect(err).to include("The source contains the following gems matching 'foo':\n * foo-1.0")
end
- it "complains with version and platform if pinned specs don't exist in the git repo" do
- simulate_platform "java"
-
+ it "complains with version and platform if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java" do |s|
s.platform = "java"
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.0-java")}"
end
G
- expect(out).to include("The source contains 'only_java' at: 1.0 java")
+ expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java")
end
- it "complains with multiple versions and platforms if pinned specs don't exist in the git repo" do
- simulate_platform "java"
-
+ it "complains with multiple versions and platforms if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java", "1.0" do |s|
s.platform = "java"
end
@@ -118,42 +172,45 @@ RSpec.describe "bundle install with git sources" do
s.write "only_java1-0.gemspec", File.read("#{lib_path("only_java-1.0-java")}/only_java.gemspec")
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.1-java")}"
end
G
- expect(out).to include("The source contains 'only_java' at: 1.0 java, 1.1 java")
+ expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java\n * only_java-1.1-java")
end
it "still works after moving the application directory" do
- bundle "install --path vendor/bundle"
+ bundle_config "path vendor/bundle"
+ install_base_gemfile
+
FileUtils.mv bundled_app, tmp("bundled_app.bck")
- Dir.chdir tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", dir: tmp("bundled_app.bck")
end
it "can still install after moving the application directory" do
- bundle "install --path vendor/bundle"
+ bundle_config "path vendor/bundle"
+ install_base_gemfile
+
FileUtils.mv bundled_app, tmp("bundled_app.bck")
- update_git "foo", "1.1", :path => lib_path("foo-1.0")
+ update_git "foo", "1.1", path: lib_path("foo-1.0")
- Dir.chdir tmp("bundled_app.bck")
gemfile tmp("bundled_app.bck/Gemfile"), <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
- gem "rack", "1.0"
+ gem "myrack", "1.0"
G
- bundle "update foo"
+ bundle "update foo", dir: tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.1", "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.1", "myrack 1.0", dir: tmp("bundled_app.bck")
end
end
@@ -161,8 +218,8 @@ RSpec.describe "bundle install with git sources" do
before do
build_git "foo"
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
git "#{lib_path("foo-1.0")}" do
# this page left intentionally blank
@@ -172,7 +229,7 @@ RSpec.describe "bundle install with git sources" do
it "does not explode" do
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -185,10 +242,12 @@ RSpec.describe "bundle install with git sources" do
it "works" do
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "#{@revision}" do
gem "foo"
end
G
+ expect(err).to be_empty
run <<-RUBY
require 'foo'
@@ -200,11 +259,12 @@ RSpec.describe "bundle install with git sources" do
it "works when the revision is a symbol" do
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => #{@revision.to_sym.inspect} do
gem "foo"
end
G
- expect(err).to lack_errors
+ expect(err).to be_empty
run <<-RUBY
require 'foo'
@@ -214,29 +274,67 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
+ it "works when an abbreviated revision is added after an initial, potentially shallow clone" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ git "#{lib_path("foo-1.0")}" do
+ gem "foo"
+ end
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ git "#{lib_path("foo-1.0")}", :ref => #{@revision[0..7].inspect} do
+ gem "foo"
+ end
+ G
+ end
+
+ it "works when a tag that does not look like a commit hash is used as the value of :ref" do
+ build_git "foo"
+ @remote = build_git("bar", bare: true)
+ update_git "foo", remote: @remote.path
+ update_git "foo", push: "main"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{@remote.path}"
+ G
+
+ # Create a new tag on the remote that needs fetching
+ update_git "foo", tag: "v1.0.0"
+ update_git "foo", push: "v1.0.0"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{@remote.path}", :ref => "v1.0.0"
+ G
+
+ expect(err).to be_empty
+ end
+
it "works when the revision is a non-head ref" do
- # want to ensure we don't fallback to master
- update_git "foo", :path => lib_path("foo-1.0") do |s|
+ # want to ensure we don't fallback to main
+ update_git "foo", path: lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- Dir.chdir(lib_path("foo-1.0")) do
- `git update-ref -m 'Bundler Spec!' refs/bundler/1 master~1`
- end
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
- update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
- s.write("lib/foo.rb", "raise 'FAIL'")
+ update_git "foo", path: lib_path("foo-1.0"), branch: "rando" do |s|
+ s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
G
- expect(err).to lack_errors
+ expect(err).to be_empty
- run! <<-RUBY
+ run <<-RUBY
require 'foo'
puts "WIN" if defined?(FOO)
RUBY
@@ -245,34 +343,34 @@ RSpec.describe "bundle install with git sources" do
end
it "works when the revision is a non-head ref and it was previously downloaded" do
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
- # want to ensure we don't fallback to master
- update_git "foo", :path => lib_path("foo-1.0") do |s|
+ # want to ensure we don't fallback to main
+ update_git "foo", path: lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- Dir.chdir(lib_path("foo-1.0")) do
- `git update-ref -m 'Bundler Spec!' refs/bundler/1 master~1`
- end
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
- update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
- s.write("lib/foo.rb", "raise 'FAIL'")
+ update_git "foo", path: lib_path("foo-1.0"), branch: "rando" do |s|
+ s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
G
- expect(err).to lack_errors
+ expect(err).to be_empty
- run! <<-RUBY
+ run <<-RUBY
require 'foo'
puts "WIN" if defined?(FOO)
RUBY
@@ -281,24 +379,21 @@ RSpec.describe "bundle install with git sources" do
end
it "does not download random non-head refs" do
- Dir.chdir(lib_path("foo-1.0")) do
- sys_exec!("git update-ref -m 'Bundler Spec!' refs/bundler/1 master~1")
- end
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", lib_path("foo-1.0"))
- bundle! "config global_gem_cache true"
+ bundle_config "global_gem_cache true"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
# ensure we also git fetch after cloning
- bundle! :update, :all => bundle_update_requires_all?
+ bundle :update, all: true
- Dir.chdir(Dir[home(".bundle/cache/git/foo-*")].first) do
- sys_exec("git ls-remote .")
- end
+ git("ls-remote .", Dir[home(".bundle/cache/git/foo-*")].first)
expect(out).not_to include("refs/bundler/1")
end
@@ -307,12 +402,12 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying a branch" do
let(:branch) { "branch" }
let(:repo) { build_git("foo").path }
- before(:each) do
- update_git("foo", :path => repo, :branch => branch)
- end
it "works" do
+ update_git("foo", path: repo, branch: branch)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -324,7 +419,12 @@ RSpec.describe "bundle install with git sources" do
context "when the branch starts with a `#`" do
let(:branch) { "#149/redirect-url-fragment" }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", path: repo, branch: branch)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -337,7 +437,12 @@ RSpec.describe "bundle install with git sources" do
context "when the branch includes quotes" do
let(:branch) { %('") }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", path: repo, branch: branch)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -351,12 +456,12 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying a tag" do
let(:tag) { "tag" }
let(:repo) { build_git("foo").path }
- before(:each) do
- update_git("foo", :path => repo, :tag => tag)
- end
it "works" do
+ update_git("foo", path: repo, tag: tag)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -368,7 +473,12 @@ RSpec.describe "bundle install with git sources" do
context "when the tag starts with a `#`" do
let(:tag) { "#149/redirect-url-fragment" }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", path: repo, tag: tag)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -381,7 +491,12 @@ RSpec.describe "bundle install with git sources" do
context "when the tag includes quotes" do
let(:tag) { %('") }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", path: repo, tag: tag)
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -394,185 +509,216 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying local override" do
it "uses the local repository instead of checking a new one out" do
- # We don't generate it because we actually don't need it
- # build_git "rack", "0.8"
-
- build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle! %(config local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "chooses the local repository on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- run "require 'rack'"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "unlocks the source when the dependencies have changed while switching to the local" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
- s.write "rack.gemspec", build_spec("rack", "0.8") { runtime "rspec", "> 0" }.first.to_ruby
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "myrack.gemspec", build_spec("myrack", "0.8") { runtime "rspec", "> 0" }.first.to_ruby
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle! %(config local.rack #{lib_path("local-rack")})
- bundle! :install
- run! "require 'rack'"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "updates specs on runtime" do
system_gems "nokogiri-1.4.2"
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- lockfile0 = File.read(bundled_app("Gemfile.lock"))
+ lockfile0 = File.read(bundled_app_lock)
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
s.add_dependency "nokogiri", "1.4.2"
end
- bundle %(config local.rack #{lib_path("local-rack")})
- run "require 'rack'"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'"
- lockfile1 = File.read(bundled_app("Gemfile.lock"))
+ lockfile1 = File.read(bundled_app_lock)
expect(lockfile1).not_to eq(lockfile0)
end
it "updates ref on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- lockfile0 = File.read(bundled_app("Gemfile.lock"))
+ lockfile0 = File.read(bundled_app_lock)
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
- update_git "rack", "0.8", :path => lib_path("local-rack")
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
+ update_git "myrack", "0.8", path: lib_path("local-myrack")
- bundle %(config local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
- lockfile1 = File.read(bundled_app("Gemfile.lock"))
+ lockfile1 = File.read(bundled_app_lock)
expect(lockfile1).not_to eq(lockfile0)
end
- it "explodes if given path does not exist on install" do
- build_git "rack", "0.8"
+ it "explodes and gives correct solution if given path does not exist on install" do
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install, raise_on_error: false
+ expect(err).to match(/Cannot use local override for myrack-0.8 because #{Regexp.escape(lib_path("local-myrack").to_s)} does not exist/)
+
+ solution = "config unset local.myrack"
+ expect(err).to match(/Run `bundle #{solution}` to remove the local override/)
+
+ bundle solution
bundle :install
- expect(out).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
+
+ expect(err).to be_empty
end
- it "explodes if branch is not given on install" do
- build_git "rack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ it "explodes and gives correct solution if branch is not given on install" do
+ build_git "myrack", "0.8"
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- bundle %(config local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install, raise_on_error: false
+ expect(err).to match(/Cannot use local override for myrack-0.8 at #{Regexp.escape(lib_path("local-myrack").to_s)} because :branch is not specified in Gemfile/)
+
+ solution = "config unset local.myrack"
+ expect(err).to match(/Specify a branch or run `bundle #{solution}` to remove the local override/)
+
+ bundle solution
bundle :install
- expect(out).to match(/cannot use local override/i)
+
+ expect(err).to be_empty
end
it "does not explode if disable_local_branch_check is given" do
- build_git "rack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ build_git "myrack", "0.8"
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle %(config disable_local_branch_check true)
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle %(config set disable_local_branch_check true)
bundle :install
expect(out).to match(/Bundle complete!/)
end
it "explodes on different branches on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", :path => lib_path("local-rack"), :branch => "another" do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack"), branch: "another" do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle :install
- expect(out).to match(/is using branch another but Gemfile specifies master/)
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install, raise_on_error: false
+ expect(err).to match(/is using branch another but Gemfile specifies main/)
end
it "explodes on invalid revision on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install, raise_on_error: false
+ expect(err).to match(/The Gemfile lock is pointing to revision \w+/)
+ end
+
+ it "does not explode on invalid revision on install" do
+ build_git "myrack", "0.8"
+
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
+ G
+
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle %(config set disable_local_revision_check true)
bundle :install
- expect(out).to match(/The Gemfile lock is pointing to revision \w+/)
+ expect(out).to match(/Bundle complete!/)
end
end
@@ -594,75 +740,76 @@ RSpec.describe "bundle install with git sources" do
# end
it "installs from git even if a newer gem is available elsewhere" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- expect(the_bundle).to include_gems "rack 0.8"
+ expect(the_bundle).to include_gems "myrack 0.8"
end
it "installs dependencies from git even if a newer gem is available elsewhere" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
- s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
+ build_lib "myrack", "1.0", path: lib_path("nested/bar") do |s|
+ s.write "lib/myrack.rb", "puts 'WIN OVERRIDE'"
end
- build_git "foo", :path => lib_path("nested") do |s|
- s.add_dependency "rack", "= 1.0"
+ build_git "foo", path: lib_path("nested") do |s|
+ s.add_dependency "myrack", "= 1.0"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("nested")}"
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN OVERRIDE")
end
it "correctly unlocks when changing to a git source" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- build_git "rack", :path => lib_path("rack")
+ build_git "myrack", path: lib_path("myrack")
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0.0", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0", :git => "#{lib_path("myrack")}"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "correctly unlocks when changing to a git source without versions" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- build_git "rack", "1.2", :path => lib_path("rack")
+ build_git "myrack", "1.2", path: lib_path("myrack")
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack")}"
G
- expect(the_bundle).to include_gems "rack 1.2"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
describe "block syntax" do
it "pulls all gems from a git block" do
- build_lib "omg", :path => lib_path("hi2u/omg")
- build_lib "hi2u", :path => lib_path("hi2u")
+ build_lib "omg", path: lib_path("hi2u/omg")
+ build_lib "hi2u", path: lib_path("hi2u")
install_gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path("hi2u")}" do
gem "omg"
gem "hi2u"
@@ -679,6 +826,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{@revision}"
G
@@ -696,7 +844,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
gem "rails", "2.3.2"
G
@@ -706,10 +854,10 @@ RSpec.describe "bundle install with git sources" do
end
it "runs the gemspec in the context of its parent directory" do
- build_lib "bar", :path => lib_path("foo/bar"), :gemspec => false do |s|
+ build_lib "bar", path: lib_path("foo/bar"), gemspec: false do |s|
s.write lib_path("foo/bar/lib/version.rb"), %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
- $:.unshift Dir.pwd # For 1.9
+ $:.unshift Dir.pwd
require 'lib/version'
Gem::Specification.new do |s|
s.name = 'bar'
@@ -721,12 +869,12 @@ RSpec.describe "bundle install with git sources" do
G
end
- build_git "foo", :path => lib_path("foo") do |s|
+ build_git "foo", path: lib_path("foo") do |s|
s.write "bin/foo", ""
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("foo")}"
gem "rails", "2.3.2"
G
@@ -735,14 +883,41 @@ RSpec.describe "bundle install with git sources" do
expect(the_bundle).to include_gems "rails 2.3.2"
end
+ it "runs the gemspec in the context of its parent directory, when using local overrides" do
+ build_git "foo", path: lib_path("foo"), gemspec: false do |s|
+ s.write lib_path("foo/lib/foo/version.rb"), %(FOO_VERSION = '1.0')
+ s.write "foo.gemspec", <<-G
+ $:.unshift Dir.pwd
+ require 'lib/foo/version'
+ Gem::Specification.new do |s|
+ s.name = 'foo'
+ s.author = 'no one'
+ s.version = FOO_VERSION
+ s.summary = 'Foo'
+ s.files = Dir["lib/**/*.rb"]
+ end
+ G
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "https://github.com/gems/foo", branch: "main"
+ G
+
+ bundle %(config set local.foo #{lib_path("foo")})
+
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
it "installs from git even if a rubygems gem is present" do
- build_gem "foo", "1.0", :path => lib_path("fake_foo"), :to_system => true do |s|
+ build_gem "foo", "1.0", path: lib_path("fake_foo"), to_system: true do |s|
s.write "lib/foo.rb", "raise 'FAIL'"
end
build_git "foo", "1.0"
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}"
G
@@ -750,10 +925,10 @@ RSpec.describe "bundle install with git sources" do
end
it "fakes the gem out if there is no gemspec" do
- build_git "foo", :gemspec => false
+ build_git "foo", gemspec: false
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}"
gem "rails", "2.3.2"
G
@@ -764,20 +939,22 @@ RSpec.describe "bundle install with git sources" do
it "catches git errors and spits out useful output" do
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "omgomg"
G
- bundle :install
+ bundle :install, raise_on_error: false
- expect(out).to include("Git error:")
+ expect(err).to include("Git error:")
expect(err).to include("fatal")
expect(err).to include("omgomg")
end
it "works when the gem path has spaces in it" do
- build_git "foo", :path => lib_path("foo space-1.0")
+ build_git "foo", path: lib_path("foo space-1.0")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo space-1.0")}"
G
@@ -788,6 +965,7 @@ RSpec.describe "bundle install with git sources" do
build_git "forced", "1.0"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("forced-1.0")}" do
gem 'forced'
end
@@ -798,48 +976,50 @@ RSpec.describe "bundle install with git sources" do
s.write "lib/forced.rb", "FORCED = '1.1'"
end
- bundle "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.1"
- Dir.chdir(lib_path("forced-1.0")) do
- `git reset --hard HEAD^`
- end
+ git("reset --hard HEAD^", lib_path("forced-1.0"))
- bundle "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.0"
end
it "ignores submodules if :submodule is not passed" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
G
- expect(out).to match(/could not find gem 'submodule/i)
+ expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository https://gem.repo1/ or installed locally})
expect(the_bundle).not_to include_gems "has_submodule 1.0"
end
it "handles repos with submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -848,10 +1028,33 @@ RSpec.describe "bundle install with git sources" do
expect(the_bundle).to include_gems "has_submodule 1.0"
end
+ it "does not warn when deiniting submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
+ build_git "submodule", "1.0"
+ build_git "has_submodule", "1.0"
+
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ git "#{lib_path("has_submodule-1.0")}" do
+ gem "has_submodule"
+ end
+ G
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems "has_submodule 1.0"
+ expect(the_bundle).to_not include_gems "submodule 1.0"
+ end
+
it "handles implicit updates when modifying the source info" do
git = build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -861,6 +1064,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "#{git.ref_for("HEAD^")}" do
gem "foo"
end
@@ -874,14 +1078,15 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
- it "does not to a remote fetch if the revision is cached locally" do
+ it "does not do a remote fetch if the revision is cached locally" do
build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- FileUtils.rm_rf(lib_path("foo-1.0"))
+ FileUtils.rm_r(lib_path("foo-1.0"))
bundle "install"
expect(out).not_to match(/updating/i)
@@ -891,12 +1096,12 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
bundle "install"
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
end
it "prints a friendly error if a file blocks the git repo" do
@@ -905,49 +1110,50 @@ RSpec.describe "bundle install with git sources" do
FileUtils.mkdir_p(default_bundle_path)
FileUtils.touch(default_bundle_path("bundler"))
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- expect(exitstatus).to_not eq(0) if exitstatus
- expect(out).to include("Bundler could not install a gem because it " \
+ expect(last_command).to be_failure
+ expect(err).to include("Bundler could not install a gem because it " \
"needs to create a directory, but a file exists " \
"- #{default_bundle_path("bundler")}")
end
it "does not duplicate git gem sources" do
- build_lib "foo", :path => lib_path("nested/foo")
- build_lib "bar", :path => lib_path("nested/bar")
+ build_lib "foo", path: lib_path("nested/foo")
+ build_lib "bar", path: lib_path("nested/bar")
- build_git "foo", :path => lib_path("nested")
- build_git "bar", :path => lib_path("nested")
+ build_git "foo", path: lib_path("nested")
+ build_git "bar", path: lib_path("nested")
- gemfile <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("nested")}"
gem "bar", :git => "#{lib_path("nested")}"
G
- bundle "install"
- expect(File.read(bundled_app("Gemfile.lock")).scan("GIT").size).to eq(1)
+ expect(File.read(bundled_app_lock).scan("GIT").size).to eq(1)
end
describe "switching sources" do
it "doesn't explode when switching Path to Git sources" do
- build_gem "foo", "1.0", :to_system => true do |s|
+ build_gem "foo", "1.0", to_system: true do |s|
s.write "lib/foo.rb", "raise 'fail'"
end
- build_lib "foo", "1.0", :path => lib_path("bar/foo")
- build_git "bar", "1.0", :path => lib_path("bar") do |s|
+ build_lib "foo", "1.0", path: lib_path("bar/foo")
+ build_git "bar", "1.0", path: lib_path("bar") do |s|
s.add_dependency "foo"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "bar", :path => "#{lib_path("bar")}"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar")}"
G
@@ -956,24 +1162,67 @@ RSpec.describe "bundle install with git sources" do
it "doesn't explode when switching Gem to Git source" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack-obama"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack-obama"
+ gem "myrack", "1.0.0"
G
- build_git "rack", "1.0" do |s|
+ build_git "myrack", "1.0" do |s|
s.write "lib/new_file.rb", "puts 'USING GIT'"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack-obama"
- gem "rack", "1.0.0", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo1"
+ gem "myrack-obama"
+ gem "myrack", "1.0.0", :git => "#{lib_path("myrack-1.0")}"
G
run "require 'new_file'"
expect(out).to eq("USING GIT")
end
+
+ it "doesn't explode when removing an explicit exact version from a git gem with dependencies" do
+ build_lib "activesupport", "7.1.4", path: lib_path("rails/activesupport")
+ build_git "rails", "7.1.4", path: lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 7.1.4"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", "7.1.4", :git => "#{lib_path("rails")}"
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_path("rails")}"
+ G
+
+ expect(the_bundle).to include_gem "rails 7.1.4", "activesupport 7.1.4"
+ end
+
+ it "doesn't explode when adding an explicit ref to a git gem with dependencies" do
+ lib_root = lib_path("rails")
+
+ build_lib "activesupport", "7.1.4", path: lib_root.join("activesupport")
+ build_git "rails", "7.1.4", path: lib_root do |s|
+ s.add_dependency "activesupport", "= 7.1.4"
+ end
+
+ old_revision = revision_for(lib_root)
+ update_git "rails", "7.1.4", path: lib_root
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", "7.1.4", :git => "#{lib_root}"
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_root}", :ref => "#{old_revision}"
+ G
+
+ expect(the_bundle).to include_gem "rails 7.1.4", "activesupport 7.1.4"
+ end
end
describe "bundle install after the remote has been updated" do
@@ -981,17 +1230,16 @@ RSpec.describe "bundle install with git sources" do
build_git "valim"
install_gemfile <<-G
- gem "valim", :git => "file://#{lib_path("valim-1.0")}"
+ source "https://gem.repo1"
+ gem "valim", :git => "#{lib_path("valim-1.0")}"
G
old_revision = revision_for(lib_path("valim-1.0"))
update_git "valim"
new_revision = revision_for(lib_path("valim-1.0"))
- lockfile = File.read(bundled_app("Gemfile.lock"))
- File.open(bundled_app("Gemfile.lock"), "w") do |file|
- file.puts lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}")
- end
+ old_lockfile = File.read(bundled_app_lock)
+ lockfile(bundled_app_lock, old_lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}"))
bundle "install"
@@ -1008,31 +1256,43 @@ RSpec.describe "bundle install with git sources" do
revision = revision_for(lib_path("foo-1.0"))
install_gemfile <<-G
- gem "foo", :git => "file://#{lib_path("foo-1.0")}", :ref => "#{revision}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{revision}"
G
- bundle "install"
expect(out).to_not match(/Revision.*does not exist/)
- install_gemfile <<-G
- gem "foo", :git => "file://#{lib_path("foo-1.0")}", :ref => "deadbeef"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "deadbeef"
G
- bundle "install"
- expect(out).to include("Revision deadbeef does not exist in the repository")
+ expect(err).to include("Revision deadbeef does not exist in the repository")
+ end
+
+ it "gives a helpful error message when the remote branch no longer exists" do
+ build_git "foo"
+
+ install_gemfile <<-G, env: { "LANG" => "en" }, raise_on_error: false
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "deadbeef"
+ G
+
+ expect(err).to include("Revision deadbeef does not exist in the repository")
end
end
- describe "bundle install --deployment with git sources" do
+ describe "bundle install with deployment mode configured and git sources" do
it "works" do
- build_git "valim", :path => lib_path("valim")
+ build_git "valim", path: lib_path("valim")
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "valim", "= 1.0", :git => "#{lib_path("valim")}"
G
- simulate_new_machine
+ pristine_system_gems
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle_config "deployment true"
+ bundle :install
end
end
@@ -1040,12 +1300,12 @@ RSpec.describe "bundle install with git sources" do
it "runs pre-install hooks" do
build_git "foo"
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.pre_install_hooks << lambda do |inst|
STDERR.puts "Ran pre-install hook: \#{inst.spec.full_name}"
end
@@ -1053,19 +1313,19 @@ RSpec.describe "bundle install with git sources" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(err).to eq_err("Ran pre-install hook: foo-1.0")
+ requires: [lib_path("install_hooks.rb")]
+ expect(err_without_deprecations).to eq("Ran pre-install hook: foo-1.0")
end
it "runs post-install hooks" do
build_git "foo"
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.post_install_hooks << lambda do |inst|
STDERR.puts "Ran post-install hook: \#{inst.spec.full_name}"
end
@@ -1073,39 +1333,38 @@ RSpec.describe "bundle install with git sources" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(err).to eq_err("Ran post-install hook: foo-1.0")
+ requires: [lib_path("install_hooks.rb")]
+ expect(err_without_deprecations).to eq("Ran post-install hook: foo-1.0")
end
it "complains if the install hook fails" do
build_git "foo"
gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.pre_install_hooks << lambda do |inst|
false
end
H
end
- bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(out).to include("failed for foo-1.0")
+ bundle :install, requires: [lib_path("install_hooks.rb")], raise_on_error: false
+ expect(err).to include("failed for foo-1.0")
end
end
context "with an extension" do
- it "installs the extension", :ruby_repo do
+ it "installs the extension" do
build_git "foo" do |s|
s.add_dependency "rake"
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/foo.rb", "w") do |f|
f.puts "FOO = 'YES'"
@@ -1115,7 +1374,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1125,14 +1384,14 @@ RSpec.describe "bundle install with git sources" do
R
expect(out).to eq("YES")
- run! <<-R
+ run <<-R
puts $:.grep(/ext/)
R
- expect(out).to eq(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
+ expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
end
- it "does not use old extension after ref changes", :ruby_repo do
- git_reader = build_git "foo", :no_default => true do |s|
+ it "does not use old extension after ref changes" do
+ git_reader = build_git "foo", no_default: true do |s|
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-RUBY
require "mkmf"
@@ -1142,20 +1401,19 @@ RSpec.describe "bundle install with git sources" do
end
2.times do |i|
- Dir.chdir(git_reader.path) do
- File.open("ext/foo.c", "w") do |file|
- file.write <<-C
- #include "ruby.h"
- VALUE foo() { return INT2FIX(#{i}); }
- void Init_foo() { rb_define_global_function("foo", &foo, 0); }
- C
- end
- `git commit -m 'commit for iteration #{i}' ext/foo.c`
+ File.open(git_reader.path.join("ext/foo.c"), "w") do |file|
+ file.write <<-C
+ #include "ruby.h"
+ VALUE foo(VALUE self) { return INT2FIX(#{i}); }
+ void Init_foo() { rb_define_global_function("foo", &foo, 0); }
+ C
end
+ git("commit -m \"commit for iteration #{i}\" ext/foo.c", git_reader.path)
+
git_commit_sha = git_reader.ref_for("HEAD")
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{git_commit_sha}"
G
@@ -1179,12 +1437,12 @@ RSpec.describe "bundle install with git sources" do
RUBY
end
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- expect(last_command.bundler_err).to end_with(<<-M.strip)
+ expect(err).to end_with(<<-M.strip)
An error occurred while installing foo (1.0), and Bundler cannot continue.
In Gemfile:
@@ -1193,13 +1451,13 @@ In Gemfile:
expect(out).not_to include("gem install foo")
end
- it "does not reinstall the extension", :ruby_repo, :rubygems => ">= 2.3.0" do
+ it "does not reinstall the extension" do
build_git "foo" do |s|
s.add_dependency "rake"
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
cur_time = Time.now.to_f.to_s
File.open("\#{path}/foo.rb", "w") do |f|
@@ -1210,11 +1468,11 @@ In Gemfile:
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1223,16 +1481,114 @@ In Gemfile:
expect(installed_time).to match(/\A\d+\.\d+\z/)
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
expect(out).to eq(installed_time)
end
+
+ it "does not reinstall the extension when changing another gem" do
+ build_git "foo" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ cur_time = Time.now.to_f.to_s
+ File.open("\#{path}/foo.rb", "w") do |f|
+ f.puts "FOO = \#{cur_time}"
+ end
+ end
+ RUBY
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+
+ run <<-R
+ require 'foo'
+ puts FOO
+ R
+
+ installed_time = out
+ expect(installed_time).to match(/\A\d+\.\d+\z/)
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+
+ run <<-R
+ require 'foo'
+ puts FOO
+ R
+ expect(out).to eq(installed_time)
+ end
+
+ it "does reinstall the extension when changing refs" do
+ build_git "foo" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ cur_time = Time.now.to_f.to_s
+ File.open("\#{path}/foo.rb", "w") do |f|
+ f.puts "FOO = \#{cur_time}"
+ end
+ end
+ RUBY
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+
+ run <<-R
+ require 'foo'
+ puts FOO
+ R
+
+ installed_time = out
+
+ update_git("foo", branch: "branch2")
+
+ expect(installed_time).to match(/\A\d+\.\d+\z/)
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "branch2"
+ G
+
+ run <<-R
+ require 'foo'
+ puts FOO
+ R
+ expect(out).not_to eq(installed_time)
+
+ installed_time = out
+
+ update_git("foo")
+ bundle "update foo"
+
+ run <<-R
+ require 'foo'
+ puts FOO
+ R
+ expect(out).not_to eq(installed_time)
+ end
end
it "ignores git environment variables" do
@@ -1245,54 +1601,91 @@ In Gemfile:
ENV["GIT_WORK_TREE"] = "bar"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
git "#{lib_path("xxxxxx-1.0")}" do
gem 'xxxxxx'
end
G
- expect(exitstatus).to eq(0) if exitstatus
expect(ENV["GIT_DIR"]).to eq("bar")
expect(ENV["GIT_WORK_TREE"]).to eq("bar")
end
end
describe "without git installed" do
- it "prints a better error message" do
+ it "prints a better error message when installing" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "rake", git: "https://github.com/ruby/rake"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: https://github.com/ruby/rake
+ revision: 5c60da8644a9e4f655e819252e3b6ca77f42b7af
+ specs:
+ rake (13.0.6)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rake!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ with_path_as("") do
+ bundle "install", raise_on_error: false
+ end
+ expect(err).
+ to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
+ end
+
+ it "prints a better error message when updating" do
build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
with_path_as("") do
- bundle "update", :all => bundle_update_requires_all?
+ bundle "update", all: true, raise_on_error: false
end
- expect(last_command.bundler_err).
+ expect(err).
to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
end
- it "installs a packaged git gem successfully" do
+ it "doesn't need git in the new machine if an installed git gem is copied to another machine" do
build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
- bundle :package, forgotten_command_line_options([:all, :cache_all] => true)
- simulate_new_machine
+ bundle_config_global "path vendor/bundle"
+ bundle :install
+ pristine_system_gems
- bundle! "install", :env => { "PATH" => "" }
+ bundle "install", env: { "PATH" => "" }
expect(out).to_not include("You need to install git to be able to use gems from git repositories.")
end
end
describe "when the git source is overridden with a local git repo" do
before do
- bundle! "config --global local.foo #{lib_path("foo")}"
+ bundle_config_global "local.foo #{lib_path("foo")}"
end
describe "and git output is colorized" do
@@ -1303,10 +1696,11 @@ In Gemfile:
end
it "installs successfully" do
- build_git "foo", "1.0", :path => lib_path("foo")
+ build_git "foo", "1.0", path: lib_path("foo")
gemfile <<-G
- gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
G
bundle :install
@@ -1320,15 +1714,15 @@ In Gemfile:
let(:credentials) { "user1:password1" }
it "does not display the password" do
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
git "https://#{credentials}@github.com/company/private-repo" do
gem "foo"
end
G
- bundle :install
- expect(last_command.stdboth).to_not include("password1")
- expect(last_command.stdout).to include("Fetching https://user1@github.com/company/private-repo")
+ expect(stdboth).to_not include("password1")
+ expect(out).to include("Fetching https://user1@github.com/company/private-repo")
end
end
@@ -1336,15 +1730,15 @@ In Gemfile:
let(:credentials) { "oauth_token" }
it "displays the oauth scheme but not the oauth token" do
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
git "https://#{credentials}:x-oauth-basic@github.com/company/private-repo" do
gem "foo"
end
G
- bundle :install
- expect(last_command.stdboth).to_not include("oauth_token")
- expect(last_command.stdout).to include("Fetching https://x-oauth-basic@github.com/company/private-repo")
+ expect(stdboth).to_not include("oauth_token")
+ expect(out).to include("Fetching https://x-oauth-basic@github.com/company/private-repo")
end
end
end
diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb
index 45395e606f..4013b112ec 100644
--- a/spec/bundler/install/gemfile/groups_spec.rb
+++ b/spec/bundler/install/gemfile/groups_spec.rb
@@ -4,8 +4,8 @@ RSpec.describe "bundle install with groups" do
describe "installing with no options" do
before :each do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
end
@@ -14,7 +14,7 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs gems in a group block into that group" do
@@ -25,7 +25,7 @@ RSpec.describe "bundle install with groups" do
puts ACTIVESUPPORT
R
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- activesupport/)
end
it "installs gems with inline :groups into those groups" do
@@ -36,11 +36,11 @@ RSpec.describe "bundle install with groups" do
puts THIN
R
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- thin/)
end
it "sets up everything if Bundler.setup is used with no groups" do
- output = run("require 'rack'; puts RACK")
+ output = run("require 'myrack'; puts MYRACK")
expect(output).to eq("1.0.0")
output = run("require 'activesupport'; puts ACTIVESUPPORT")
@@ -57,7 +57,7 @@ RSpec.describe "bundle install with groups" do
puts THIN
RUBY
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- thin/)
end
it "sets up old groups when they have previously been removed" do
@@ -70,12 +70,12 @@ RSpec.describe "bundle install with groups" do
end
end
- describe "installing --without" do
+ describe "without option" do
describe "with gems assigned to a single group" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
end
@@ -86,54 +86,58 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ bundle_config "without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: [:default]
end
- it "does not install gems from the excluded group" do
- bundle :install, :without => "emo"
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
+ it "respects global `without` configuration, but does not save it locally" do
+ bundle_config_global "without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: [:default]
+ bundle "config list"
+ expect(out).not_to include("Set for your local app (#{bundled_app(".bundle/config")}): [:emo]")
+ expect(out).to include("Set for the current user (#{home(".bundle/config")}): [:emo]")
+ end
+
+ it "allows running application where groups where configured by a different user" do
+ bundle_config "without emo"
+ bundle :install
+ bundle "exec ruby -e 'puts 42'", env: { "BUNDLE_USER_HOME" => tmp("new_home").to_s }
+ expect(out).to include("42")
end
- it "does not install gems from the previously excluded group" do
- bundle :install, forgotten_command_line_options(:without => "emo")
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
+ it "does not install gems from the excluded group" do
+ bundle_config "without emo"
bundle :install
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
end
it "does not say it installed gems from the excluded group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle_config "without emo"
+ bundle :install
expect(out).not_to include("activesupport")
end
it "allows Bundler.setup for specific groups" do
- bundle :install, forgotten_command_line_options(:without => "emo")
- run!("require 'rack'; puts RACK", :default)
+ bundle_config "without emo"
+ bundle :install
+ run("require 'myrack'; puts MYRACK", :default)
expect(out).to eq("1.0.0")
end
it "does not effect the resolve" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport"
group :emo do
gem "rails", "2.3.2"
end
G
- bundle :install, forgotten_command_line_options(:without => "emo")
- expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => [:default]
- end
-
- it "still works on a different machine and excludes gems" do
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- simulate_new_machine
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
+ bundle_config "without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "activesupport 2.3.2", groups: [:default]
end
it "still works when BUNDLE_WITHOUT is set" do
@@ -142,100 +146,52 @@ RSpec.describe "bundle install with groups" do
bundle :install
expect(out).not_to include("activesupport")
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: [:default]
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
ENV["BUNDLE_WITHOUT"] = nil
end
- it "clears without when passed an empty list" do
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- bundle :install, forgotten_command_line_options(:without => "")
- expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
-
- it "doesn't clear without when nothing is passed" do
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- bundle :install
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- end
-
it "does not install gems from the optional group" do
bundle :install
expect(the_bundle).not_to include_gems "thin 1.0"
end
- it "does install gems from the optional group when requested" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- expect(the_bundle).to include_gems "thin 1.0"
- end
-
- it "does install gems from the previously requested group" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- expect(the_bundle).to include_gems "thin 1.0"
+ it "installs gems from the optional group when requested" do
+ bundle_config "with debugging"
bundle :install
expect(the_bundle).to include_gems "thin 1.0"
end
- it "does install gems from the optional groups requested with BUNDLE_WITH" do
+ it "installs gems from the optional groups requested with BUNDLE_WITH" do
ENV["BUNDLE_WITH"] = "debugging"
bundle :install
expect(the_bundle).to include_gems "thin 1.0"
ENV["BUNDLE_WITH"] = nil
end
- it "clears with when passed an empty list" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- bundle :install, forgotten_command_line_options(:with => "")
- expect(the_bundle).not_to include_gems "thin 1.0"
- end
-
- it "does remove groups from without when passed at --with", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:without => "emo")
- bundle :install, forgotten_command_line_options(:with => "emo")
- expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
-
- it "does remove groups from with when passed at --without", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- bundle :install, forgotten_command_line_options(:without => "debugging")
- expect(the_bundle).not_to include_gem "thin 1.0"
- end
-
- it "errors out when passing a group to with and without via CLI flags", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:with => "emo debugging", :without => "emo")
- expect(last_command).to be_failure
- expect(out).to include("The offending groups are: emo")
- end
-
it "allows the BUNDLE_WITH setting to override BUNDLE_WITHOUT" do
ENV["BUNDLE_WITH"] = "debugging"
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem "thin 1.0"
ENV["BUNDLE_WITHOUT"] = "debugging"
expect(the_bundle).to include_gem "thin 1.0"
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem "thin 1.0"
end
- it "can add and remove a group at the same time" do
- bundle :install, forgotten_command_line_options(:with => "debugging", :without => "emo")
- expect(the_bundle).to include_gems "thin 1.0"
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- end
-
- it "does have no effect when listing a not optional group in with" do
- bundle :install, forgotten_command_line_options(:with => "emo")
+ it "has no effect when listing a not optional group in with" do
+ bundle_config "with emo"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "does have no effect when listing an optional group in without" do
- bundle :install, forgotten_command_line_options(:without => "debugging")
+ it "has no effect when listing an optional group in without" do
+ bundle_config "without debugging"
+ bundle :install
expect(the_bundle).not_to include_gems "thin 1.0"
end
end
@@ -243,8 +199,8 @@ RSpec.describe "bundle install with groups" do
describe "with gems assigned to multiple groups" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo, :lolercoaster do
gem "activesupport", "2.3.5"
end
@@ -252,20 +208,22 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle_config "without emo lolercoaster"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ bundle_config "without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
describe "with a gem defined multiple times in different groups" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
@@ -277,23 +235,21 @@ RSpec.describe "bundle install with groups" do
G
end
- it "installs the gem w/ option --without emo" do
- bundle :install, forgotten_command_line_options(:without => "emo")
+ it "installs the gem unless all groups are excluded" do
+ bundle_config "without emo"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
- it "installs the gem w/ option --without lolercoaster" do
- bundle :install, forgotten_command_line_options(:without => "lolercoaster")
+ bundle_config "without lolercoaster"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
- it "does not install the gem w/ option --without emo lolercoaster" do
- bundle :install, forgotten_command_line_options(:without => "emo lolercoaster")
+ bundle_config "without emo lolercoaster"
+ bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- end
- it "does not install the gem w/ option --without 'emo lolercoaster'" do
- bundle :install, forgotten_command_line_options(:without => "'emo lolercoaster'")
+ bundle "config set --local without 'emo lolercoaster'"
+ bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
end
end
@@ -302,8 +258,8 @@ RSpec.describe "bundle install with groups" do
describe "nesting groups" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
group :lolercoaster do
gem "activesupport", "2.3.5"
@@ -313,13 +269,15 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle_config "without emo lolercoaster"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ bundle_config "without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
end
end
@@ -327,8 +285,8 @@ RSpec.describe "bundle install with groups" do
describe "when loading only the default group" do
it "should not load all groups" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "activesupport", :groups => :development
G
@@ -336,7 +294,7 @@ RSpec.describe "bundle install with groups" do
require "bundler"
Bundler.setup :default
Bundler.require :default
- puts RACK
+ puts MYRACK
begin
require "activesupport"
rescue LoadError
@@ -349,36 +307,39 @@ RSpec.describe "bundle install with groups" do
end
end
- describe "when locked and installed with --without" do
+ describe "when locked and installed with `without` setting" do
before(:each) do
build_repo2
- system_gems "rack-0.9.1" do
- install_gemfile <<-G, forgotten_command_line_options(:without => "rack")
- source "file://#{gem_repo2}"
- gem "rack"
- group :rack do
- gem "rack_middleware"
- end
- G
- end
+ system_gems "myrack-0.9.1"
+
+ bundle_config "without myrack"
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+
+ group :myrack do
+ gem "myrack_middleware"
+ end
+ G
end
- it "uses the correct versions even if --without was used on the original" do
- expect(the_bundle).to include_gems "rack 0.9.1"
- expect(the_bundle).not_to include_gems "rack_middleware 1.0"
+ it "uses versions from excluded gems in a machine without the without configuration" do
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
simulate_new_machine
bundle :install
- expect(the_bundle).to include_gems "rack 0.9.1"
- expect(the_bundle).to include_gems "rack_middleware 1.0"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).to include_gems "myrack_middleware 1.0"
end
it "does not hit the remote a second time" do
- FileUtils.rm_rf gem_repo2
- bundle! :install, forgotten_command_line_options(:without => "rack").merge(:verbose => true)
- expect(last_command.stdboth).not_to match(/fetching/i)
+ FileUtils.rm_r gem_repo2
+ bundle_config "without myrack"
+ bundle :install, verbose: true
+ expect(stdboth).not_to match(/fetching/i)
end
end
end
diff --git a/spec/bundler/install/gemfile/install_if.rb b/spec/bundler/install/gemfile/install_if.rb
deleted file mode 100644
index 1319051fdb..0000000000
--- a/spec/bundler/install/gemfile/install_if.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-describe "bundle install with install_if conditionals" do
- it "follows the install_if DSL" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- install_if(lambda { true }) do
- gem "activesupport", "2.3.5"
- end
- gem "thin", :install_if => false
- install_if(lambda { false }) do
- gem "foo"
- end
- gem "rack"
- G
-
- expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5")
- expect(the_bundle).not_to include_gems("thin")
- expect(the_bundle).not_to include_gems("foo")
-
- lockfile_should_be <<-L
- GEM
- remote: file:#{gem_repo1}/
- specs:
- activesupport (2.3.5)
- foo (1.0)
- rack (1.0.0)
- thin (1.0)
- rack
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- activesupport (= 2.3.5)
- foo
- rack
- thin
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-end
diff --git a/spec/bundler/install/gemfile/install_if_spec.rb b/spec/bundler/install/gemfile/install_if_spec.rb
new file mode 100644
index 0000000000..05a6d15129
--- /dev/null
+++ b/spec/bundler/install/gemfile/install_if_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with install_if conditionals" do
+ it "follows the install_if DSL" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ install_if(lambda { true }) do
+ gem "activesupport", "2.3.5"
+ end
+ gem "thin", :install_if => false
+ install_if(lambda { false }) do
+ gem "foo"
+ end
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems("myrack 1.0", "activesupport 2.3.5")
+ expect(the_bundle).not_to include_gems("thin")
+ expect(the_bundle).not_to include_gems("foo")
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "activesupport", "2.3.5"
+ c.checksum gem_repo1, "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ c.checksum gem_repo1, "thin", "1.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ activesupport (2.3.5)
+ foo (1.0)
+ myrack (1.0.0)
+ thin (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport (= 2.3.5)
+ foo
+ myrack
+ thin
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+end
diff --git a/spec/bundler/install/gemfile/lockfile_spec.rb b/spec/bundler/install/gemfile/lockfile_spec.rb
index dc1baca6ea..19bd7074b2 100644
--- a/spec/bundler/install/gemfile/lockfile_spec.rb
+++ b/spec/bundler/install/gemfile/lockfile_spec.rb
@@ -2,13 +2,14 @@
RSpec.describe "bundle install with a lockfile present" do
let(:gf) { <<-G }
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- subject do
+ it "touches the lockfile on install even when nothing has changed" do
install_gemfile(gf)
+ expect { bundle :install }.to change { bundled_app_lock.mtime }
end
context "gemfile evaluation" do
@@ -16,32 +17,25 @@ RSpec.describe "bundle install with a lockfile present" do
context "with plugins disabled" do
before do
- bundle! "config plugins false"
- subject
+ bundle_config "plugins false"
end
- it "does not evaluate the gemfile twice" do
- bundle! :install
+ it "does not evaluate the gemfile twice when the gem is already installed" do
+ install_gemfile(gf)
+ bundle :install
- with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
+ with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "myrack 1.0.0" }
- # The first eval is from the initial install, we're testing that the
- # second install doesn't double-eval
expect(bundled_app("evals").read.lines.to_a.size).to eq(2)
end
- context "when the gem is not installed" do
- before { FileUtils.rm_rf ".bundle" }
+ it "does not evaluate the gemfile twice when the gem is not installed" do
+ gemfile(gf)
+ bundle :install
- it "does not evaluate the gemfile twice" do
- bundle! :install
+ with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "myrack 1.0.0" }
- with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
-
- # The first eval is from the initial install, we're testing that the
- # second install doesn't double-eval
- expect(bundled_app("evals").read.lines.to_a.size).to eq(2)
- end
+ expect(bundled_app("evals").read.lines.to_a.size).to eq(1)
end
end
end
diff --git a/spec/bundler/install/gemfile/override_spec.rb b/spec/bundler/install/gemfile/override_spec.rb
new file mode 100644
index 0000000000..02b0e7d772
--- /dev/null
+++ b/spec/bundler/install/gemfile/override_spec.rb
@@ -0,0 +1,401 @@
+# frozen_string_literal: true
+
+RSpec.describe "override DSL" do
+ context "with a version: string operation" do
+ it "replaces a direct dependency requirement with the override version spec" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 0.9.1"
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ end
+
+ it "replaces a transitive dependency requirement" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 1.0.0"
+ gem "myrack_middleware"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack_middleware 1.0"
+ end
+
+ it "replaces the requirement even when the Gemfile pins a different version" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 0.9.1"
+ gem "myrack", "= 1.0.0"
+ G
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ end
+
+ it "applies the override against an existing lockfile" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 0.9.1"
+ gem "myrack"
+ G
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ end
+
+ it "pins a prerelease version that the Gemfile dependency would otherwise filter out" do
+ build_repo2 do
+ build_gem "has_prerelease", "1.0"
+ build_gem "has_prerelease", "1.1.pre"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ override "has_prerelease", version: "= 1.1.pre"
+ gem "has_prerelease"
+ G
+
+ expect(the_bundle).to include_gems "has_prerelease 1.1.pre"
+ end
+ end
+
+ context "with a version: :ignore_upper operation" do
+ it "strips a < upper bound on a direct dependency" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: :ignore_upper
+ gem "myrack", "< 1.0"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "folds ~> into >= so newer versions become reachable" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: :ignore_upper
+ gem "myrack", "~> 0.9.1"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+ end
+
+ context "with a version: nil operation" do
+ it "drops a direct dependency's pin entirely" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: nil
+ gem "myrack", "= 0.9.1"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "drops a transitive dependency's pin entirely" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: nil
+ gem "myrack_middleware"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack_middleware 1.0"
+ end
+
+ it "applies a transitive-only override against an existing lockfile" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack_middleware"
+ G
+
+ expect(the_bundle).to include_gems "myrack 0.9.1", "myrack_middleware 1.0"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 1.0.0"
+ gem "myrack_middleware"
+ G
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack_middleware 1.0"
+ end
+ end
+
+ context "lockfile contents" do
+ it "does not record the override directive in Gemfile.lock" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ override "myrack", version: "= 0.9.1"
+ gem "myrack"
+ G
+
+ expect(lockfile).not_to match(/override/i)
+ end
+ end
+
+ context "with a required_ruby_version: operation" do
+ it "lets the resolver pick a gem whose required_ruby_version excludes the current Ruby with :ignore_upper" do
+ build_repo2 do
+ build_gem "needs_old_ruby", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_ruby", required_ruby_version: :ignore_upper
+ gem "needs_old_ruby"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("needs_old_ruby (1.0)")
+ end
+
+ it "lets the resolver pick the gem with required_ruby_version: nil" do
+ build_repo2 do
+ build_gem "needs_old_ruby", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_ruby", required_ruby_version: nil
+ gem "needs_old_ruby"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("needs_old_ruby (1.0)")
+ end
+
+ it "applies to a transitive dependency's required_ruby_version" do
+ build_repo2 do
+ build_gem "needs_old_ruby", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ build_gem "wraps_old", "1.0" do |s|
+ s.add_dependency "needs_old_ruby"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_ruby", required_ruby_version: :ignore_upper
+ gem "wraps_old"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("needs_old_ruby (1.0)")
+ expect(lockfile).to include("wraps_old (1.0)")
+ end
+
+ it "re-resolves a direct dep when a metadata override is added against an existing lockfile" do
+ build_repo2 do
+ build_gem "selectable", "1.0"
+ build_gem "selectable", "2.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "selectable"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("selectable (1.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "selectable", required_ruby_version: :ignore_upper
+ gem "selectable"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("selectable (2.0)")
+ end
+ end
+
+ context "with a required_rubygems_version: operation" do
+ it "lets the resolver pick a gem whose required_rubygems_version excludes the current RubyGems with :ignore_upper" do
+ build_repo2 do
+ build_gem "needs_old_rubygems", "1.0" do |s|
+ s.required_rubygems_version = "< #{Gem.rubygems_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_rubygems", required_rubygems_version: :ignore_upper
+ gem "needs_old_rubygems"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("needs_old_rubygems (1.0)")
+ end
+ end
+
+ context "with an :all target" do
+ it "applies required_ruby_version: :ignore_upper to every gem" do
+ build_repo2 do
+ build_gem "needs_old_ruby_a", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ build_gem "needs_old_ruby_b", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override :all, required_ruby_version: :ignore_upper
+ gem "needs_old_ruby_a"
+ gem "needs_old_ruby_b"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("needs_old_ruby_a (1.0)")
+ expect(lockfile).to include("needs_old_ruby_b (1.0)")
+ end
+
+ it "is overridden by a per-gem override on the same field" do
+ build_repo2 do
+ build_gem "permissive", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ build_gem "still_blocked", "1.0" do |s|
+ s.required_ruby_version = "= #{Gem.ruby_version}.999"
+ end
+ end
+
+ # :all says ignore_upper (would unblock both), but per-gem on
+ # still_blocked nails it to a hard requirement that still fails.
+ gemfile <<-G
+ source "https://gem.repo2"
+ override :all, required_ruby_version: :ignore_upper
+ override "still_blocked", required_ruby_version: "= #{Gem.ruby_version}.999"
+ gem "permissive"
+ gem "still_blocked"
+ G
+
+ bundle :lock, raise_on_error: false
+ expect(err).to include("still_blocked")
+ end
+
+ it "preserves locked versions when an :all metadata override is added without bundle update" do
+ build_repo2 do
+ build_gem "selectable", "1.0"
+ build_gem "selectable", "2.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "selectable"
+ G
+
+ bundle :lock
+ expect(lockfile).to include("selectable (1.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override :all, required_ruby_version: :ignore_upper
+ gem "selectable"
+ G
+
+ # :all override alone does not pre-unlock locked specs; narrow change
+ # should not trigger unrelated lockfile churn.
+ bundle :lock
+ expect(lockfile).to include("selectable (1.0)")
+
+ # bundle update opts the user into re-resolution under the override.
+ bundle "update selectable"
+ expect(lockfile).to include("selectable (2.0)")
+ end
+ end
+
+ context "diagnostic on resolve failure" do
+ it "lists active overrides with their Gemfile location" do
+ build_repo2 do
+ build_gem "needs_old_ruby", "1.0" do |s|
+ s.required_ruby_version = "= #{Gem.ruby_version}.999"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_ruby", required_ruby_version: "= #{Gem.ruby_version}.999"
+ gem "needs_old_ruby"
+ G
+
+ bundle :lock, raise_on_error: false
+ expect(err).to include("Bundler applied the following overrides")
+ expect(err).to include("override \"needs_old_ruby\", required_ruby_version:")
+ expect(err).to match(/declared at Gemfile:\d+/)
+ end
+ end
+
+ context "install-time compatibility" do
+ it "installs a gem whose required_ruby_version excludes the current Ruby when an override removes the constraint" do
+ build_repo2 do
+ build_gem "needs_old_ruby", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_ruby", required_ruby_version: nil
+ gem "needs_old_ruby"
+ G
+
+ expect(the_bundle).to include_gems "needs_old_ruby 1.0"
+ end
+
+ it "installs a gem whose required_rubygems_version excludes the current RubyGems when an override removes it" do
+ build_repo2 do
+ build_gem "needs_old_rubygems", "1.0" do |s|
+ s.required_rubygems_version = "< #{Gem.rubygems_version}"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ override "needs_old_rubygems", required_rubygems_version: nil
+ gem "needs_old_rubygems"
+ G
+
+ expect(the_bundle).to include_gems "needs_old_rubygems 1.0"
+ end
+
+ it "installs every gem when :all required_ruby_version override is in effect" do
+ build_repo2 do
+ build_gem "needs_old_ruby_a", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ build_gem "needs_old_ruby_b", "1.0" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ override :all, required_ruby_version: :ignore_upper
+ gem "needs_old_ruby_a"
+ gem "needs_old_ruby_b"
+ G
+
+ expect(the_bundle).to include_gems "needs_old_ruby_a 1.0", "needs_old_ruby_b 1.0"
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index a508c971ad..b069488531 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -1,17 +1,6 @@
# frozen_string_literal: true
RSpec.describe "bundle install with explicit source paths" do
- it "fetches gems with a global path source", :bundler => "< 3" do
- build_lib "foo"
-
- install_gemfile <<-G
- path "#{lib_path("foo-1.0")}"
- gem 'foo'
- G
-
- expect(the_bundle).to include_gems("foo 1.0")
- end
-
it "fetches gems" do
build_lib "foo"
@@ -37,7 +26,7 @@ RSpec.describe "bundle install with explicit source paths" do
it "supports relative paths" do
build_lib "foo"
- relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new(Dir.pwd))
+ relative_path = lib_path("foo-1.0").relative_path_from(bundled_app)
install_gemfile <<-G
gem 'foo', :path => "#{relative_path}"
@@ -59,71 +48,116 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "expands paths raise error with not existing user's home dir" do
+ skip "problems with ~ expansion" if Gem.win_platform?
+
build_lib "foo"
username = "some_unexisting_user"
relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("/home/#{username}").expand_path)
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
gem 'foo', :path => "~#{username}/#{relative_path}"
G
- expect(out).to match("There was an error while trying to use the path `~#{username}/#{relative_path}`.")
- expect(out).to match("user #{username} doesn't exist")
+ expect(err).to match("There was an error while trying to use the path `~#{username}/#{relative_path}`.")
+ expect(err).to match("user #{username} doesn't exist")
end
it "expands paths relative to Bundler.root" do
- build_lib "foo", :path => bundled_app("foo-1.0")
+ build_lib "foo", path: bundled_app("foo-1.0")
install_gemfile <<-G
gem 'foo', :path => "./foo-1.0"
G
- bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- expect(the_bundle).to include_gems("foo 1.0")
+ expect(the_bundle).to include_gems("foo 1.0", dir: bundled_app("subdir").mkpath)
+ end
+
+ it "sorts paths consistently on install and update when they start with ./" do
+ build_lib "demo", path: lib_path("demo")
+ build_lib "aaa", path: lib_path("demo/aaa")
+
+ gemfile lib_path("demo/Gemfile"), <<-G
+ source "https://gem.repo1"
+ gemspec
+ gem "aaa", :path => "./aaa"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "aaa", "1.0"
+ c.no_checksum "demo", "1.0"
end
+
+ lockfile = <<~L
+ PATH
+ remote: .
+ specs:
+ demo (1.0)
+
+ PATH
+ remote: aaa
+ specs:
+ aaa (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ aaa!
+ demo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install, dir: lib_path("demo")
+ expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
+ bundle :update, all: true, dir: lib_path("demo")
+ expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
end
it "expands paths when comparing locked paths to Gemfile paths" do
- build_lib "foo", :path => bundled_app("foo-1.0")
+ build_lib "foo", path: bundled_app("foo-1.0")
install_gemfile <<-G
- gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__)
+ gem 'foo', :path => File.expand_path("foo-1.0", __dir__)
G
- bundle! :install, forgotten_command_line_options(:frozen => true)
- expect(exitstatus).to eq(0) if exitstatus
+ bundle_config "frozen true"
+ bundle :install
end
it "installs dependencies from the path even if a newer gem is available elsewhere" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
- s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
+ build_lib "myrack", "1.0", path: lib_path("nested/bar") do |s|
+ s.write "lib/myrack.rb", "puts 'WIN OVERRIDE'"
end
- build_lib "foo", :path => lib_path("nested") do |s|
- s.add_dependency "rack", "= 1.0"
+ build_lib "foo", path: lib_path("nested") do |s|
+ s.add_dependency "myrack", "= 1.0"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
gem "foo", :path => "#{lib_path("nested")}"
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN OVERRIDE")
end
it "works" do
- build_gem "foo", "1.0.0", :to_system => true do |s|
+ build_gem "foo", "1.0.0", to_system: true do |s|
s.write "lib/foo.rb", "puts 'FAIL'"
end
- build_lib "omg", "1.0", :path => lib_path("omg") do |s|
+ build_lib "omg", "1.0", path: lib_path("omg") do |s|
s.add_dependency "foo"
end
- build_lib "foo", "1.0.0", :path => lib_path("omg/foo")
+ build_lib "foo", "1.0.0", path: lib_path("omg/foo")
install_gemfile <<-G
gem "omg", :path => "#{lib_path("omg")}"
@@ -132,8 +166,88 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "foo 1.0"
end
+ it "works when using prereleases of 0.0.0" do
+ build_lib "foo", "0.0.0.dev", path: lib_path("foo")
+
+ gemfile <<~G
+ source "https://gem.repo1"
+ gem "foo", :path => "#{lib_path("foo")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (0.0.0.dev)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "foo 0.0.0.dev"
+ end
+
+ it "works when using uppercase prereleases of 0.0.0" do
+ build_lib "foo", "0.0.0.SNAPSHOT", path: lib_path("foo")
+
+ gemfile <<~G
+ source "https://gem.repo1"
+ gem "foo", :path => "#{lib_path("foo")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (0.0.0.SNAPSHOT)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "foo 0.0.0.SNAPSHOT"
+ end
+
+ it "handles downgrades" do
+ build_lib "omg", "2.0", path: lib_path("omg")
+
+ install_gemfile <<-G
+ gem "omg", :path => "#{lib_path("omg")}"
+ G
+
+ build_lib "omg", "1.0", path: lib_path("omg")
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "omg 1.0"
+ end
+
it "prefers gemspecs closer to the path root" do
- build_lib "premailer", "1.0.0", :path => lib_path("premailer") do |s|
+ build_lib "premailer", "1.0.0", path: lib_path("premailer") do |s|
s.write "gemfiles/ruby187.gemspec", <<-G
Gem::Specification.new do |s|
s.name = 'premailer'
@@ -153,7 +267,7 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "premailer 1.0.0"
end
- it "warns on invalid specs", :rubygems => "1.7" do
+ it "warns on invalid specs" do
build_lib "foo"
gemspec = lib_path("foo-1.0").join("foo.gemspec").to_s
@@ -165,106 +279,152 @@ RSpec.describe "bundle install with explicit source paths" do
G
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- expect(out).to_not include("ERROR REPORT")
- expect(out).to_not include("Your Gemfile has no gem server sources.")
- expect(out).to match(/is not valid. Please fix this gemspec./)
- expect(out).to match(/The validation error was 'missing value for attribute version'/)
- expect(out).to match(/You have one or more invalid gemspecs that need to be fixed/)
+ expect(err).to match(/is not valid. Please fix this gemspec./)
+ expect(err).to match(/The validation error was 'missing value for attribute version'/)
+ expect(err).to match(/You have one or more invalid gemspecs that need to be fixed/)
end
it "supports gemspec syntax" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "1.0"
end
- gemfile = <<-G
- source "file://#{gem_repo1}"
+ gemfile lib_path("foo/Gemfile"), <<-G
+ source "https://gem.repo1"
gemspec
G
- File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile }
+ bundle "install", dir: lib_path("foo")
+ expect(the_bundle).to include_gems "foo 1.0", dir: lib_path("foo")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("foo")
+ end
- Dir.chdir(lib_path("foo")) do
- bundle "install"
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ it "does not unlock dependencies of path sources" do
+ build_repo4 do
+ build_gem "graphql", "2.0.15"
+ build_gem "graphql", "2.0.16"
+ end
+
+ build_lib "foo", "0.1.0", path: lib_path("foo") do |s|
+ s.add_dependency "graphql", "~> 2.0"
+ end
+
+ gemfile_path = lib_path("foo/Gemfile")
+
+ gemfile gemfile_path, <<-G
+ source "https://gem.repo4"
+ gemspec
+ G
+
+ lockfile_path = lib_path("foo/Gemfile.lock")
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "0.1.0"
+ c.checksum gem_repo4, "graphql", "2.0.15"
end
+
+ original_lockfile = <<~L
+ PATH
+ remote: .
+ specs:
+ foo (0.1.0)
+ graphql (~> 2.0)
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ graphql (2.0.15)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_path, original_lockfile
+
+ build_lib "foo", "0.1.1", path: lib_path("foo") do |s|
+ s.add_dependency "graphql", "~> 2.0"
+ end
+
+ bundle "install", dir: lib_path("foo")
+ expect(lockfile_path).to read_as(original_lockfile.gsub("foo (0.1.0)", "foo (0.1.1)"))
end
it "supports gemspec syntax with an alternative path" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "1.0"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gemspec :path => "#{lib_path("foo")}"
G
expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "doesn't automatically unlock dependencies when using the gemspec syntax" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", ">= 1.0"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", ">= 1.0"
end
- Dir.chdir lib_path("foo")
-
- install_gemfile lib_path("foo/Gemfile"), <<-G
- source "file://#{gem_repo1}"
+ install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
+ source "https://gem.repo1"
gemspec
G
- build_gem "rack", "1.0.1", :to_system => true
+ build_gem "myrack", "1.0.1", to_system: true
- bundle "install"
+ bundle "install", dir: lib_path("foo")
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", dir: lib_path("foo")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("foo")
end
it "doesn't automatically unlock dependencies when using the gemspec syntax and the gem has development dependencies" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", ">= 1.0"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", ">= 1.0"
s.add_development_dependency "activesupport"
end
- Dir.chdir lib_path("foo")
-
- install_gemfile lib_path("foo/Gemfile"), <<-G
- source "file://#{gem_repo1}"
+ install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
+ source "https://gem.repo1"
gemspec
G
- build_gem "rack", "1.0.1", :to_system => true
+ build_gem "myrack", "1.0.1", to_system: true
- bundle "install"
+ bundle "install", dir: lib_path("foo")
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", dir: lib_path("foo")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("foo")
end
it "raises if there are multiple gemspecs" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.write "bar.gemspec", build_spec("bar", "1.0").first.to_ruby
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
gemspec :path => "#{lib_path("foo")}"
G
- expect(exitstatus).to eq(15) if exitstatus
- expect(out).to match(/There are multiple gemspecs/)
+ expect(exitstatus).to eq(15)
+ expect(err).to match(/There are multiple gemspecs/)
end
it "allows :name to be specified to resolve ambiguity" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.write "bar.gemspec"
end
@@ -280,11 +440,12 @@ RSpec.describe "bundle install with explicit source paths" do
s.executables = "foobar"
end
- install_gemfile <<-G
+ install_gemfile <<-G, verbose: true
path "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
+ expect(out).to include("Using foo 1.0 from source at `#{lib_path("foo-1.0")}` and installing its executables")
expect(the_bundle).to include_gems "foo 1.0"
bundle "exec foobar"
@@ -293,13 +454,13 @@ RSpec.describe "bundle install with explicit source paths" do
it "handles directories in bin/" do
build_lib "foo"
- lib_path("foo-1.0").join("foo.gemspec").rmtree
+ FileUtils.rm_rf lib_path("foo-1.0").join("foo.gemspec")
lib_path("foo-1.0").join("bin/performance").mkpath
install_gemfile <<-G
gem 'foo', '1.0', :path => "#{lib_path("foo-1.0")}"
G
- expect(err).to lack_errors
+ expect(err).to be_empty
end
it "removes the .gem file after installing" do
@@ -329,9 +490,9 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "keeps source pinning" do
- build_lib "foo", "1.0", :path => lib_path("foo")
- build_lib "omg", "1.0", :path => lib_path("omg")
- build_lib "foo", "1.0", :path => lib_path("omg/foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo")
+ build_lib "omg", "1.0", path: lib_path("omg")
+ build_lib "foo", "1.0", path: lib_path("omg/foo") do |s|
s.write "lib/foo.rb", "puts 'FAIL'"
end
@@ -344,7 +505,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works when the path does not have a gemspec" do
- build_lib "foo", :gemspec => false
+ build_lib "foo", gemspec: false
gemfile <<-G
gem "foo", "1.0", :path => "#{lib_path("foo-1.0")}"
@@ -356,54 +517,50 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "works when the path does not have a gemspec but there is a lockfile" do
- lockfile <<-L
- PATH
- remote: vendor/bar
- specs:
-
- GEM
- remote: http://rubygems.org
+ lockfile <<~L
+ PATH
+ remote: vendor/bar
+ specs:
L
- in_app_root { FileUtils.mkdir_p("vendor/bar") }
+ FileUtils.mkdir_p(bundled_app("vendor/bar"))
install_gemfile <<-G
gem "bar", "1.0.0", path: "vendor/bar", require: "bar/nyard"
G
- expect(exitstatus).to eq(0) if exitstatus
end
context "existing lockfile" do
it "rubygems gems don't re-resolve without changes" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack-obama', '1.0'
+ source "https://gem.repo1"
+ gem 'myrack-obama', '1.0'
gem 'net-ssh', '1.0'
G
- bundle :check, :env => { "DEBUG" => 1 }
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0", "net-ssh 1.0"
end
it "source path gems w/deps don't re-resolve without changes" do
- build_lib "rack-obama", "1.0", :path => lib_path("omg") do |s|
+ build_lib "myrack-obama", "1.0", path: lib_path("omg") do |s|
s.add_dependency "yard"
end
- build_lib "net-ssh", "1.0", :path => lib_path("omg") do |s|
+ build_lib "net-ssh", "1.0", path: lib_path("omg") do |s|
s.add_dependency "yard"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack-obama', :path => "#{lib_path("omg")}"
+ source "https://gem.repo1"
+ gem 'myrack-obama', :path => "#{lib_path("omg")}"
gem 'net-ssh', :path => "#{lib_path("omg")}"
G
- bundle :check, :env => { "DEBUG" => 1 }
+ bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0", "net-ssh 1.0"
end
end
@@ -422,10 +579,10 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when the gem version in the path is updated" do
before :each do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
s.add_dependency "bar"
end
- build_lib "bar", "1.0", :path => lib_path("foo/bar")
+ build_lib "bar", "1.0", path: lib_path("foo/bar")
install_gemfile <<-G
gem "foo", :path => "#{lib_path("foo")}"
@@ -433,7 +590,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "unlocks all gems when the top level gem is updated" do
- build_lib "foo", "2.0", :path => lib_path("foo") do |s|
+ build_lib "foo", "2.0", path: lib_path("foo") do |s|
s.add_dependency "bar"
end
@@ -443,7 +600,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "unlocks all gems when a child dependency gem is updated" do
- build_lib "bar", "2.0", :path => lib_path("foo/bar")
+ build_lib "bar", "2.0", path: lib_path("foo/bar")
bundle "install"
@@ -453,42 +610,280 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when dependencies in the path are updated" do
before :each do
- build_lib "foo", "1.0", :path => lib_path("foo")
+ build_lib "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
end
it "gets dependencies that are updated in the path" do
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack"
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack"
end
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "keeps using the same version if it's compatible" do
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "0.9.1"
+ end
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ end
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ myrack (= 0.9.1)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack"
+ end
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ myrack
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ end
+
+ it "keeps using the same version even when another dependency is added" do
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "0.9.1"
+ end
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ end
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ myrack (= 0.9.1)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack"
+ s.add_dependency "rake", rake_version
+ end
+
+ bundle "install"
+
+ checksums.checksum gem_repo1, "rake", rake_version
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ myrack
+ rake (= #{rake_version})
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+ rake (#{rake_version})
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ end
+
+ it "does not remove existing ruby platform" do
+ build_lib "foo", "1.0", path: lib_path("foo") do |s|
+ s.add_dependency "myrack", "0.9.1"
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ checksums.checksum gem_repo1, "myrack", "0.9.1"
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ myrack (= 0.9.1)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+ end
+
+ context "when platform specific version locked, and having less dependencies that the generic version that's actually installed" do
+ before do
+ build_repo4 do
+ build_gem "racc", "1.8.1"
+ build_gem "mini_portile2", "2.8.2"
+ end
+
+ build_lib "nokogiri", "1.18.9", path: lib_path("nokogiri") do |s|
+ s.add_dependency "mini_portile2", "~> 2.8.2"
+ s.add_dependency "racc", "~> 1.4"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri", path: "#{lib_path("nokogiri")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("nokogiri")}
+ specs:
+ nokogiri (1.18.9)
+ mini_portile2 (~> 2.8.2)
+ racc (~> 1.4)
+ nokogiri (1.18.9-arm64-darwin)
+ racc (~> 1.4)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ racc (1.8.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ nokogiri!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle "install"
end
end
describe "switching sources" do
it "doesn't switch pinned git sources to rubygems when pinning the parent gem to a path source" do
- build_gem "foo", "1.0", :to_system => true do |s|
+ build_gem "foo", "1.0", to_system: true do |s|
s.write "lib/foo.rb", "raise 'fail'"
end
- build_lib "foo", "1.0", :path => lib_path("bar/foo")
- build_git "bar", "1.0", :path => lib_path("bar") do |s|
+ build_lib "foo", "1.0", path: lib_path("bar/foo")
+ build_git "bar", "1.0", path: lib_path("bar") do |s|
s.add_dependency "foo"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
gem "bar", :git => "#{lib_path("bar")}"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
gem "bar", :path => "#{lib_path("bar")}"
G
@@ -496,23 +891,23 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "switches the source when the gem existed in rubygems and the path was already being used for another gem" do
- build_lib "foo", "1.0", :path => lib_path("foo")
- build_gem "bar", "1.0", :to_system => true do |s|
+ build_lib "foo", "1.0", path: lib_path("foo")
+ build_gem "bar", "1.0", to_bundle: true do |s|
s.write "lib/bar.rb", "raise 'fail'"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "bar"
path "#{lib_path("foo")}" do
gem "foo"
end
G
- build_lib "bar", "1.0", :path => lib_path("foo/bar")
+ build_lib "bar", "1.0", path: lib_path("foo/bar")
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
path "#{lib_path("foo")}" do
gem "foo"
gem "bar"
@@ -525,21 +920,17 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when there are both a gemspec and remote gems" do
it "doesn't query rubygems for local gemspec name" do
- build_lib "private_lib", "2.2", :path => lib_path("private_lib")
- gemfile = <<-G
+ build_lib "private_lib", "2.2", path: lib_path("private_lib")
+ gemfile lib_path("private_lib/Gemfile"), <<-G
source "http://localgemserver.test"
gemspec
- gem 'rack'
+ gem 'myrack'
G
- File.open(lib_path("private_lib/Gemfile"), "w") {|f| f.puts gemfile }
-
- Dir.chdir(lib_path("private_lib")) do
- bundle :install, :env => { "DEBUG" => 1 }, :artifice => "endpoint"
- expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$})
- expect(out).not_to match(/^HTTP GET.*private_lib/)
- expect(the_bundle).to include_gems "private_lib 2.2"
- expect(the_bundle).to include_gems "rack 1.0"
- end
+ bundle :install, env: { "DEBUG" => "1" }, artifice: "endpoint", dir: lib_path("private_lib")
+ expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=myrack$})
+ expect(out).not_to match(/^HTTP GET.*private_lib/)
+ expect(the_bundle).to include_gems "private_lib 2.2", dir: lib_path("private_lib")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("private_lib")
end
end
@@ -552,7 +943,6 @@ RSpec.describe "bundle install with explicit source paths" do
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.pre_install_hooks << lambda do |inst|
STDERR.puts "Ran pre-install hook: \#{inst.spec.full_name}"
end
@@ -560,8 +950,8 @@ RSpec.describe "bundle install with explicit source paths" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(err).to eq_err("Ran pre-install hook: foo-1.0")
+ requires: [lib_path("install_hooks.rb")]
+ expect(err_without_deprecations).to eq("Ran pre-install hook: foo-1.0")
end
it "runs post-install hooks" do
@@ -572,7 +962,6 @@ RSpec.describe "bundle install with explicit source paths" do
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.post_install_hooks << lambda do |inst|
STDERR.puts "Ran post-install hook: \#{inst.spec.full_name}"
end
@@ -580,8 +969,8 @@ RSpec.describe "bundle install with explicit source paths" do
end
bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(err).to eq_err("Ran post-install hook: foo-1.0")
+ requires: [lib_path("install_hooks.rb")]
+ expect(err_without_deprecations).to eq("Ran post-install hook: foo-1.0")
end
it "complains if the install hook fails" do
@@ -592,16 +981,14 @@ RSpec.describe "bundle install with explicit source paths" do
File.open(lib_path("install_hooks.rb"), "w") do |h|
h.write <<-H
- require 'rubygems'
Gem.pre_install_hooks << lambda do |inst|
false
end
H
end
- bundle :install,
- :requires => [lib_path("install_hooks.rb")]
- expect(out).to include("failed for foo-1.0")
+ bundle :install, requires: [lib_path("install_hooks.rb")], raise_on_error: false
+ expect(err).to include("failed for foo-1.0")
end
it "loads plugins from the path gem" do
@@ -611,14 +998,14 @@ RSpec.describe "bundle install with explicit source paths" do
expect(bar_file).not_to be_file
build_lib "foo" do |s|
- s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{foo_file}')")
+ s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{foo_file}')")
end
build_git "bar" do |s|
- s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{bar_file}')")
+ s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{bar_file}')")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :path => "#{lib_path("bar-1.0")}"
G
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index b5dbc41a33..e12933ebcf 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -4,30 +4,30 @@ RSpec.describe "bundle install across platforms" do
it "maintains the same lockfile if all gems are compatible across platforms" do
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{not_local}
DEPENDENCIES
- rack
+ myrack
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
end
it "pulls in the correct platform specific gem" do
lockfile <<-G
GEM
- remote: file:#{gem_repo1}
+ remote: https://gem.repo1
specs:
platform_specific (1.0)
platform_specific (1.0-java)
@@ -40,37 +40,139 @@ RSpec.describe "bundle install across platforms" do
platform_specific
G
- simulate_platform "java"
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 java"
+ end
+ end
+
+ it "pulls the pure ruby version on jruby if the java platform is not present in the lockfile and bundler is run in frozen mode", :jruby_only do
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo1
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+ G
+
+ bundle_config "frozen true"
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "platform_specific"
G
- expect(the_bundle).to include_gems "platform_specific 1.0 JAVA"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ expect(err).to be_empty
+ end
+
+ context "on universal Rubies" do
+ before do
+ build_repo4 do
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "ruby"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "arm64-darwin"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+ end
+
+ it "pulls in the correct architecture gem" do
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo4
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21" do
+ simulate_ruby_platform "universal.x86_64-darwin21" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 x86_64-darwin"
+ end
+ end
+ end
+
+ it "pulls in the correct architecture gem on arm64e macOS Ruby" do
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo4
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21" do
+ simulate_ruby_platform "universal.arm64e-darwin21" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 arm64-darwin"
+ end
+ end
+ end
end
it "works with gems that have different dependencies" do
- simulate_platform "java"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
- gem "nokogiri"
- G
+ gem "nokogiri"
+ G
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 java", "weakling 0.0.3"
- simulate_new_machine
+ pristine_system_gems
+ bundle_config "force_ruby_platform true"
+ bundle "install"
- simulate_platform "ruby"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2"
+ expect(the_bundle).not_to include_gems "weakling"
- gem "nokogiri"
- G
+ simulate_new_machine
+ bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2"
- expect(the_bundle).not_to include_gems "weakling"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 java", "weakling 0.0.3"
+ end
end
it "does not keep unneeded platforms for gems that are used" do
@@ -78,205 +180,255 @@ RSpec.describe "bundle install across platforms" do
build_gem "empyrean", "0.1.0"
build_gem "coderay", "1.1.2"
build_gem "method_source", "0.9.0"
- build_gem("spoon", "0.0.6") {|s| s.add_runtime_dependency "ffi" }
+ build_gem("spoon", "0.0.6") {|s| s.add_dependency "ffi" }
build_gem "pry", "0.11.3" do |s|
s.platform = "java"
- s.add_runtime_dependency "coderay", "~> 1.1.0"
- s.add_runtime_dependency "method_source", "~> 0.9.0"
- s.add_runtime_dependency "spoon", "~> 0.0"
+ s.add_dependency "coderay", "~> 1.1.0"
+ s.add_dependency "method_source", "~> 0.9.0"
+ s.add_dependency "spoon", "~> 0.0"
end
build_gem "pry", "0.11.3" do |s|
- s.add_runtime_dependency "coderay", "~> 1.1.0"
- s.add_runtime_dependency "method_source", "~> 0.9.0"
+ s.add_dependency "coderay", "~> 1.1.0"
+ s.add_dependency "method_source", "~> 0.9.0"
end
build_gem("ffi", "1.9.23") {|s| s.platform = "java" }
build_gem("ffi", "1.9.23")
end
- simulate_platform java
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
- install_gemfile! <<-G
- source "file://localhost/#{gem_repo4}"
+ gem "empyrean", "0.1.0"
+ gem "pry"
+ G
- gem "empyrean", "0.1.0"
- gem "pry"
- G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "coderay", "1.1.2"
+ c.checksum gem_repo4, "empyrean", "0.1.0"
+ c.checksum gem_repo4, "ffi", "1.9.23", "java"
+ c.checksum gem_repo4, "method_source", "0.9.0"
+ c.checksum gem_repo4, "pry", "0.11.3", "java"
+ c.checksum gem_repo4, "spoon", "0.0.6"
+ end
- expect(the_bundle.lockfile).to read_as normalize_uri_file(strip_whitespace(<<-L))
- GEM
- remote: file://localhost/#{gem_repo4}/
- specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
+
+ PLATFORMS
+ java
+
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform ruby"
+
+ checksums.checksum gem_repo4, "pry", "0.11.3"
+
+ good_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(lockfile).to eq good_lockfile
+
+ bad_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ 1.16.1
+ L
+
+ aggregate_failures do
+ lockfile bad_lockfile
+ bundle :install, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle :update, all: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle "update ffi", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle "update empyrean", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle :lock, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+ end
+ end
+ end
- PLATFORMS
- java
+ it "works with gems with platform-specific dependency having different requirements order" do
+ simulate_platform "x86_64-darwin-15" do
+ update_repo2 do
+ build_gem "fspath", "3"
+ build_gem "image_optim_pack", "1.2.3" do |s|
+ s.add_dependency "fspath", ">= 2.1", "< 4"
+ end
+ build_gem "image_optim_pack", "1.2.3" do |s|
+ s.platform = "universal-darwin"
+ s.add_dependency "fspath", "< 4", ">= 2.1"
+ end
+ end
- DEPENDENCIES
- empyrean (= 0.1.0)
- pry
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ G
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ install_gemfile <<-G
+ source "https://gem.repo2"
- bundle! "lock --add-platform ruby"
+ gem "image_optim_pack"
+ G
- good_lockfile = strip_whitespace(<<-L)
- GEM
- remote: file://localhost/#{gem_repo4}/
- specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
+ expect(err).not_to include "Unable to use the platform-specific"
- PLATFORMS
- java
- ruby
+ expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin"
+ end
+ end
- DEPENDENCIES
- empyrean (= 0.1.0)
- pry
+ it "fetches gems again after changing the version of Ruby" do
+ gemfile <<-G
+ source "https://gem.repo1"
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ gem "myrack", "1.0.0"
+ G
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
+ bundle_config "path vendor/bundle"
+ bundle :install
- bad_lockfile = strip_whitespace <<-L
+ FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, "1.8"))
+
+ bundle :install
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
+ end
+
+ it "keeps existing platforms when installing with force_ruby_platform" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "platform_specific", "1.0"
+ c.checksum gem_repo1, "platform_specific", "1.0", "java"
+ end
+
+ lockfile <<-G
GEM
- remote: file://localhost/#{gem_repo4}/
+ remote: https://gem.repo1/
specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
+ platform_specific (1.0-java)
PLATFORMS
java
- ruby
DEPENDENCIES
- empyrean (= 0.1.0)
- pry
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- aggregate_failures do
- lockfile bad_lockfile
- bundle! :install
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
-
- lockfile bad_lockfile
- bundle! :update, :all => true
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
-
- lockfile bad_lockfile
- bundle! "update ffi"
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
-
- lockfile bad_lockfile
- bundle! "update empyrean"
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
+ platform_specific
+ #{checksums}
+ G
- lockfile bad_lockfile
- bundle! :lock
- expect(the_bundle.lockfile).to read_as normalize_uri_file(good_lockfile)
- end
- end
+ bundle_config "force_ruby_platform true"
- it "works the other way with gems that have different dependencies" do
- simulate_platform "ruby"
install_gemfile <<-G
- source "file://#{gem_repo1}"
-
- gem "nokogiri"
+ source "https://gem.repo1"
+ gem "platform_specific"
G
- simulate_platform "java"
- bundle "install"
-
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
- end
+ checksums.checksum gem_repo1, "platform_specific", "1.0"
- it "works with gems that have extra platform-specific runtime dependencies", :bundler => "< 3" do
- simulate_platform x64_mac
-
- update_repo2 do
- build_gem "facter", "2.4.6"
- build_gem "facter", "2.4.6" do |s|
- s.platform = "universal-darwin"
- s.add_runtime_dependency "CFPropertyList"
- end
- build_gem "CFPropertyList"
- end
+ expect(the_bundle).to include_gem "platform_specific 1.0 ruby"
- install_gemfile! <<-G
- source "file://#{gem_repo2}"
-
- gem "facter"
- G
-
- expect(out).to include "Unable to use the platform-specific (universal-darwin) version of facter (2.4.6) " \
- "because it has different dependencies from the ruby version. " \
- "To use the platform-specific version of the gem, run `bundle config specific_platform true` and install again."
-
- expect(the_bundle).to include_gem "facter 2.4.6"
- expect(the_bundle).not_to include_gem "CFPropertyList"
- end
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-java)
- it "fetches gems again after changing the version of Ruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
+ PLATFORMS
+ java
+ ruby
- gem "rack", "1.0.0"
+ DEPENDENCIES
+ platform_specific
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
-
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
-
- new_version = Gem::ConfigMap[:ruby_version] == "1.8" ? "1.9.1" : "1.8"
- FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, new_version))
-
- bundle! :install
- expect(vendored_gems("gems/rack-1.0.0")).to exist
end
end
RSpec.describe "bundle install with platform conditionals" do
it "installs gems tagged w/ the current platforms" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
platforms :#{local_tag} do
gem "nokogiri"
@@ -288,20 +440,63 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not install gems tagged w/ another platforms" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
platforms :#{not_local_tag} do
gem "nokogiri"
end
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
end
+ it "installs gems tagged w/ another platform but also dependent on the current one transitively" do
+ build_repo4 do
+ build_gem "activesupport", "6.1.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 2.0"
+ end
+
+ build_gem "tzinfo", "2.0.4"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "activesupport"
+
+ platforms :#{not_local_tag} do
+ gem "tzinfo", "~> 1.2"
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ activesupport (6.1.4.1)
+ tzinfo (~> 2.0)
+ tzinfo (2.0.4)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ activesupport
+ tzinfo (~> 1.2)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+
+ expect(the_bundle).to include_gems "tzinfo 2.0.4"
+ end
+
it "installs gems tagged w/ the current platforms inline" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "nokogiri", :platforms => :#{local_tag}
G
expect(the_bundle).to include_gems "nokogiri 1.4.2"
@@ -309,17 +504,17 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not install gems tagged w/ another platforms inline" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "nokogiri", :platforms => :#{not_local_tag}
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
end
it "installs gems tagged w/ the current platform inline" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "nokogiri", :platform => :#{local_tag}
G
expect(the_bundle).to include_gems "nokogiri 1.4.2"
@@ -327,7 +522,7 @@ RSpec.describe "bundle install with platform conditionals" do
it "doesn't install gems tagged w/ another platform inline" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "nokogiri", :platform => :#{not_local_tag}
G
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
@@ -337,21 +532,20 @@ RSpec.describe "bundle install with platform conditionals" do
build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
platform :#{not_local_tag} do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
G
bundle :list
- expect(exitstatus).to eq(0) if exitstatus
end
it "does not attempt to install gems from :rbx when using --local" do
- simulate_platform "ruby"
- simulate_ruby_engine "ruby"
+ bundle_config "force_ruby_platform true"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "some_gem", :platform => :rbx
G
@@ -360,67 +554,85 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "does not attempt to install gems from other rubies when using --local" do
- simulate_platform "ruby"
- simulate_ruby_engine "ruby"
- other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18
-
+ bundle_config "force_ruby_platform true"
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "some_gem", platform: :#{other_ruby_version_tag}
+ source "https://gem.repo1"
+ gem "some_gem", platform: :ruby_22
G
bundle "install --local"
expect(out).not_to match(/Could not find gem 'some_gem/)
end
- it "prints a helpful warning when a dependency is unused on any platform" do
- simulate_platform "ruby"
- simulate_ruby_engine "ruby"
+ it "does not print a warning when a dependency is unused on a platform different from the current one" do
+ bundle_config "force_ruby_platform true"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
+ gem "myrack", :platform => [:windows, :jruby]
G
- bundle! "install"
+ bundle "install"
- expect(out).to include <<-O.strip
-The dependency #{Gem::Dependency.new("rack", ">= 0")} will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
- O
- end
+ expect(err).to be_empty
- context "when disable_platform_warnings is true" do
- before { bundle! "config disable_platform_warnings true" }
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
- it "does not print the warning when a dependency is unused on any platform" do
- simulate_platform "ruby"
- simulate_ruby_engine "ruby"
+ PLATFORMS
+ ruby
- gemfile <<-G
- source "file://#{gem_repo1}"
+ DEPENDENCIES
+ myrack
+ #{checksums_section_when_enabled}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
- G
+ it "resolves fine when a dependency is unused on a platform different from the current one, but reintroduced transitively" do
+ bundle_config "force_ruby_platform true"
- bundle! "install"
+ build_repo4 do
+ build_gem "listen", "3.7.1" do |s|
+ s.add_dependency "ffi"
+ end
- expect(out).not_to match(/The dependency (.*) will be unused/)
+ build_gem "ffi", "1.15.5"
end
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "listen"
+ gem "ffi", :platform => :windows
+ G
+ expect(err).to be_empty
end
end
RSpec.describe "when a gem has no architecture" do
it "still installs correctly" do
- simulate_platform mswin
+ simulate_platform "x86-mswin32" do
+ build_repo2 do
+ # The rcov gem is platform mswin32, but has no arch
+ build_gem "rcov" do |s|
+ s.platform = Gem::Platform.new([nil, "mswin32", nil])
+ s.write "lib/rcov.rb", "RCOV = '1.0.0'"
+ end
+ end
- gemfile <<-G
- # Try to install gem with nil arch
- source "http://localgemserver.test/"
- gem "rcov"
- G
+ gemfile <<-G
+ # Try to install gem with nil arch
+ source "http://localgemserver.test/"
+ gem "rcov"
+ G
- bundle :install, :artifice => "windows"
- expect(the_bundle).to include_gems "rcov 1.0.0"
+ bundle :install, artifice: "windows", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(the_bundle).to include_gems "rcov 1.0.0"
+ end
end
end
diff --git a/spec/bundler/install/gemfile/ruby_spec.rb b/spec/bundler/install/gemfile/ruby_spec.rb
index 24fe021fa3..d937abd714 100644
--- a/spec/bundler/install/gemfile/ruby_spec.rb
+++ b/spec/bundler/install/gemfile/ruby_spec.rb
@@ -2,107 +2,156 @@
RSpec.describe "ruby requirement" do
def locked_ruby_version
- Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(lockfile).ruby_version)
+ Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(File.read(bundled_app_lock)).ruby_version)
end
- # As discovered by https://github.com/bundler/bundler/issues/4147, there is
+ # As discovered by https://github.com/rubygems/bundler/issues/4147, there is
# no test coverage to ensure that adding a gem is possible with a ruby
# requirement. This test verifies the fix, committed in bfbad5c5.
it "allows adding gems" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "#{RUBY_VERSION}"
- gem "rack"
+ source "https://gem.repo1"
+ ruby "#{Gem.ruby_version}"
+ gem "myrack"
G
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "#{RUBY_VERSION}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ ruby "#{Gem.ruby_version}"
+ gem "myrack"
+ gem "myrack-obama"
G
- expect(exitstatus).to eq(0) if exitstatus
- expect(the_bundle).to include_gems "rack-obama 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0"
end
it "allows removing the ruby version requirement" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "~> #{RUBY_VERSION}"
- gem "rack"
+ source "https://gem.repo1"
+ ruby "~> #{Gem.ruby_version}"
+ gem "myrack"
G
expect(lockfile).to include("RUBY VERSION")
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(lockfile).not_to include("RUBY VERSION")
end
it "allows changing the ruby version requirement to something compatible" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby ">= 1.0.0"
- gem "rack"
+ source "https://gem.repo1"
+ ruby ">= #{current_ruby_minor}"
+ gem "myrack"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
- simulate_ruby_version "5100"
-
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby ">= 1.0.1"
- gem "rack"
+ source "https://gem.repo1"
+ ruby ">= #{Gem.ruby_version}"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end
it "allows changing the ruby version requirement to something incompatible" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
ruby ">= 1.0.0"
- gem "rack"
+ gem "myrack"
G
- expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ RUBY VERSION
+ ruby 2.1.4
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- simulate_ruby_version "5100"
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
install_gemfile <<-G
- source "file://#{gem_repo1}"
- ruby ">= 5000.0"
- gem "rack"
+ source "https://gem.repo1"
+ ruby ">= #{current_ruby_minor}"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(locked_ruby_version.versions).to eq(["5100"])
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end
it "allows requirements with trailing whitespace" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- ruby "#{RUBY_VERSION}\\n \t\\n"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ ruby "#{Gem.ruby_version}\\n \t\\n"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "fails gracefully with malformed requirements" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
ruby ">= 0", "-.\\0"
- gem "rack"
+ gem "myrack"
G
- expect(out).to include("There was an error parsing") # i.e. DSL error, not error template
+ expect(err).to include("There was an error parsing") # i.e. DSL error, not error template
+ end
+
+ it "allows picking up ruby version from a file" do
+ create_file ".ruby-version", Gem.ruby_version.to_s
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ ruby file: ".ruby-version"
+ gem "myrack"
+ G
+
+ expect(lockfile).to include("RUBY VERSION")
+ end
+
+ it "reads the ruby version file from the right folder when nested Gemfiles are involved" do
+ create_file ".ruby-version", Gem.ruby_version.to_s
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ ruby file: ".ruby-version"
+ gem "myrack"
+ G
+
+ nested_dir = bundled_app(".ruby-lsp")
+
+ FileUtils.mkdir nested_dir
+
+ gemfile ".ruby-lsp/Gemfile", <<-G
+ eval_gemfile(File.expand_path("../Gemfile", __dir__))
+ G
+
+ bundle "install", dir: nested_dir
+
+ expect(bundled_app(".ruby-lsp/Gemfile.lock").read).to include("RUBY VERSION")
end
end
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index efe6ccce7f..654d638e1f 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -2,425 +2,514 @@
RSpec.describe "bundle install with gems on multiple sources" do
# repo1 is built automatically before all of the specs run
- # it contains rack-obama 1.0.0 and rack 0.9.1 & 1.0.0 amongst other gems
-
- context "without source affinity" do
- before do
- # Oh no! Someone evil is trying to hijack rack :(
- # need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", repo3_rack_version do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
- end
-
- context "with multiple toplevel sources" do
- let(:repo3_rack_version) { "1.0.0" }
-
- before do
- gemfile <<-G
- source "file://localhost#{gem_repo3}"
- source "file://localhost#{gem_repo1}"
- gem "rack-obama"
- gem "rack"
- G
- bundle "config major_deprecations true"
- end
-
- it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do
- bundle :install
-
- expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
- expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo1}"))
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
- end
-
- it "errors when disable_multisource is set" do
- bundle "config disable_multisource true"
- bundle :install
- expect(out).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4) if exitstatus
- end
- end
-
- context "when different versions of the same gem are in multiple sources" do
- let(:repo3_rack_version) { "1.2" }
-
- before do
- gemfile <<-G
- source "file://localhost#{gem_repo3}"
- source "file://localhost#{gem_repo1}"
- gem "rack-obama"
- gem "rack", "1.0.0" # force it to install the working version in repo1
- G
- bundle "config major_deprecations true"
- end
-
- it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do
- bundle :install
-
- expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
- expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo1}"))
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
- end
- end
- end
+ # it contains myrack-obama 1.0.0 and myrack 0.9.1 & 1.0.0 amongst other gems
context "with source affinity" do
context "with sources given by a block" do
before do
- # Oh no! Someone evil is trying to hijack rack :(
+ # Oh no! Someone evil is trying to hijack myrack :(
# need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
end
end
gemfile <<-G
- source "file://#{gem_repo3}"
- source "file://#{gem_repo1}" do
+ source "https://gem.repo3"
+ source "https://gem.repo1" do
gem "thin" # comes first to test name sorting
- gem "rack"
+ gem "myrack"
end
- gem "rack-obama" # shoud come from repo3!
+ gem "myrack-obama" # should come from repo3!
G
end
it "installs the gems without any warning" do
- bundle! :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("rack-obama 1.0.0")
- expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1")
+ bundle :install, artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", source: "remote1")
end
it "can cache and deploy" do
- bundle! :package
+ bundle :cache, artifice: "compact_index"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-obama-1.0.gem")).to exist
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle_config "deployment true"
+ bundle :install, artifice: "compact_index"
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0")
end
end
context "with sources set by an option" do
before do
- # Oh no! Someone evil is trying to hijack rack :(
+ # Oh no! Someone evil is trying to hijack myrack :(
# need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
end
end
- gemfile <<-G
- source "file://#{gem_repo3}"
- gem "rack-obama" # should come from repo3!
- gem "rack", :source => "file://#{gem_repo1}"
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo3"
+ gem "myrack-obama" # should come from repo3!
+ gem "myrack", :source => "https://gem.repo1"
G
end
it "installs the gems without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0")
end
end
- context "when a pinned gem has an indirect dependency" do
+ context "when a pinned gem has an indirect dependency in the pinned source" do
before do
- build_repo gem_repo3 do
- build_gem "depends_on_rack", "1.0.1" do |s|
- s.add_dependency "rack"
+ build_repo3 do
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
+ end
+ end
+
+ # we need a working myrack gem in repo3
+ update_repo gem_repo3 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ source "https://gem.repo3" do
+ gem "depends_on_myrack"
end
+ G
+ end
+
+ context "and not in any other sources" do
+ before do
+ build_repo(gem_repo2) {}
+ end
+
+ it "installs from the same source without any warning" do
+ bundle :install, artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
end
end
- context "when the indirect dependency is in the pinned source" do
+ context "and in another source" do
before do
- # we need a working rack gem in repo3
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
+ end
end
+ end
- gemfile <<-G
- source "file://#{gem_repo2}"
- source "file://#{gem_repo3}" do
- gem "depends_on_rack"
- end
- G
+ it "installs from the same source without any warning" do
+ bundle :install, artifice: "compact_index"
+
+ expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
+
+ # In https://github.com/bundler/bundler/issues/3585 this failed
+ # when there is already a lockfile, and the gems are missing, so try again
+ system_gems []
+ bundle :install, artifice: "compact_index"
+
+ expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
end
+ end
+ end
- context "and not in any other sources" do
- before do
- build_repo(gem_repo2) {}
- end
+ context "when a pinned gem has an indirect dependency in a different source" do
+ before do
+ # In these tests, we need a working myrack gem in repo2 and not repo3
- it "installs from the same source without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ build_repo3 do
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
- context "and in another source" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
- end
+ build_repo gem_repo2 do
+ build_gem "myrack", "1.0.0"
+ end
+ end
- context "when lockfile_uses_separate_rubygems_sources is set" do
- before do
- bundle! "config lockfile_uses_separate_rubygems_sources true"
- bundle! "config disable_multisource true"
+ context "and not in any other sources" do
+ before do
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo2"
+ source "https://gem.repo3" do
+ gem "depends_on_myrack"
end
+ G
+ end
+
+ it "installs from the other source without any warning" do
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0")
+ end
+ end
+ end
+
+ context "when a top-level gem can only be found in an scoped source" do
+ before do
+ build_repo2
- it "installs from the same source without any warning" do
- bundle! :install
+ build_repo3 do
+ build_gem "private_gem_1", "1.0.0"
+ build_gem "private_gem_2", "1.0.0"
+ end
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ gemfile <<-G
+ source "https://gem.repo2"
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle! :install
+ gem "private_gem_1"
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
+ source "https://gem.repo3" do
+ gem "private_gem_2"
end
- end
+ G
end
- context "when the indirect dependency is in a different source" do
- before do
- # In these tests, we need a working rack gem in repo2 and not repo3
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0"
+ it "fails" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/ or installed locally.")
+ end
+ end
+
+ context "when a top-level gem has an indirect dependency" do
+ before do
+ build_repo gem_repo2 do
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
- context "and not in any other sources" do
- before do
- gemfile <<-G
- source "file://#{gem_repo2}"
- source "file://#{gem_repo3}" do
- gem "depends_on_rack"
- end
- G
+ build_repo3 do
+ build_gem "unrelated_gem", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "depends_on_myrack"
+
+ source "https://gem.repo3" do
+ gem "unrelated_gem"
end
+ G
+ end
- it "installs from the other source without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ context "and the dependency is only in the top-level source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "myrack", "1.0.0"
end
end
- context "and in yet another source" do
- before do
- gemfile <<-G
- source "file://localhost#{gem_repo1}"
- source "file://localhost#{gem_repo2}"
- source "file://localhost#{gem_repo3}" do
- gem "depends_on_rack"
- end
- G
- end
+ it "installs the dependency from the top-level source without warning" do
+ bundle :install, artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
+ end
+ end
- it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
- bundle "config major_deprecations true"
- bundle :install
- expect(out).to have_major_deprecation a_string_including("Your Gemfile contains multiple primary sources.")
- expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(out).to include(normalize_uri_file("Installed from: file://localhost#{gem_repo2}"))
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ context "and the dependency is only in a pinned source" do
+ before do
+ update_repo gem_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
+ end
end
end
- context "and only the dependency is pinned" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ it "does not find the dependency" do
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of depends_on_myrack depends on myrack >= 0
+ and myrack >= 0 could not be found in rubygems repository https://gem.repo2/ or installed locally,
+ depends_on_myrack cannot be used.
+ So, because Gemfile depends on depends_on_myrack >= 0,
+ version solving has failed.
+ E
+ end
+ end
+
+ context "and the dependency is in both the top-level and a pinned source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ update_repo gem_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
+ end
+ end
- gemfile <<-G
- source "file://#{gem_repo3}" # contains depends_on_rack
- source "file://#{gem_repo2}" # contains broken rack
+ it "installs the dependency from the top-level source without warning" do
+ bundle :install, artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(run("require 'myrack'; puts MYRACK")).to eq("1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
+ end
+ end
+ end
- gem "depends_on_rack" # installed from gem_repo3
- gem "rack", :source => "file://#{gem_repo1}"
- G
+ context "when a scoped gem has a deeply nested indirect dependency" do
+ before do
+ build_repo3 do
+ build_gem "depends_on_depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "depends_on_myrack"
end
- it "installs the dependency from the pinned source without warning", :bundler => "< 3" do
- bundle :install
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
+ end
+ end
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ gemfile <<-G
+ source "https://gem.repo2"
- # In https://github.com/bundler/bundler/issues/3585 this failed
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle :install
+ source "https://gem.repo3" do
+ gem "depends_on_depends_on_myrack"
+ end
+ G
+ end
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ context "and the dependency is only in the top-level source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "myrack", "1.0.0"
end
end
+
+ it "installs the dependency from the top-level source" do
+ bundle :install, artifice: "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", source: "remote3")
+ end
end
- end
- context "when a top-level gem has an indirect dependency" do
- context "when lockfile_uses_separate_rubygems_sources is set" do
+ context "and the dependency is only in a pinned source" do
before do
- bundle! "config lockfile_uses_separate_rubygems_sources true"
- bundle! "config disable_multisource true"
+ build_repo2
+
+ update_repo gem_repo3 do
+ build_gem "myrack", "1.0.0"
+ end
end
+ it "installs the dependency from the pinned source" do
+ bundle :install, artifice: "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
+ end
+ end
+
+ context "and the dependency is in both the top-level and a pinned source" do
before do
- build_repo gem_repo2 do
- build_gem "depends_on_rack", "1.0.1" do |s|
- s.add_dependency "rack"
+ update_repo gem_repo2 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
end
- build_repo gem_repo3 do
- build_gem "unrelated_gem", "1.0.0"
+ update_repo gem_repo3 do
+ build_gem "myrack", "1.0.0"
end
+ end
- gemfile <<-G
- source "file://#{gem_repo2}"
-
- gem "depends_on_rack"
+ it "installs the dependency from the pinned source without warning" do
+ bundle :install, artifice: "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
+ end
+ end
+ end
- source "file://#{gem_repo3}" do
- gem "unrelated_gem"
- end
- G
+ context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved" do
+ before do
+ build_lib "activesupport", "7.0.0.alpha", path: lib_path("rails/activesupport")
+ build_lib "rails", "7.0.0.alpha", path: lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 7.0.0.alpha"
end
- context "and the dependency is only in the top-level source" do
- before do
- update_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
- end
+ build_repo gem_repo2 do
+ build_gem "activesupport", "6.1.2"
- it "installs all gems without warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
+ build_gem "webpacker", "5.2.1" do |s|
+ s.add_dependency "activesupport", ">= 5.2"
end
end
- context "and the dependency is only in a pinned source" do
- before do
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gemspec :path => "#{lib_path("rails")}"
+
+ gem "webpacker", "~> 5.0"
+ G
+ end
+
+ it "installs all gems without warning" do
+ bundle :install, artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", source: "path@#{lib_path("rails/activesupport")}")
+ expect(the_bundle).to include_gems("rails 7.0.0.alpha", source: "path@#{lib_path("rails")}")
+ end
+ end
+
+ context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source " do
+ before do
+ build_repo3 do
+ build_gem "handsoap", "0.2.5.5" do |s|
+ s.add_dependency "nokogiri", ">= 1.2.3"
end
+ end
- it "does not find the dependency" do
- bundle :install
- expect(out).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources")
+ update_repo gem_repo2 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "racca", "~> 1.4"
end
+
+ build_gem "racca", "1.5.2"
end
- context "and the dependency is in both the top-level and a pinned source" do
- before do
- update_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
+ gemfile <<-G
+ source "https://gem.repo2"
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
+ source "https://gem.repo3" do
+ gem "handsoap"
end
- it "installs the dependency from the top-level source without warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
- end
+ gem "nokogiri"
+ G
+ end
+
+ it "installs from the default source without any warnings or errors and generates a proper lockfile" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo3, "handsoap", "0.2.5.5"
+ c.checksum gem_repo2, "nokogiri", "1.11.1"
+ c.checksum gem_repo2, "racca", "1.5.2"
end
+
+ expected_lockfile = <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ nokogiri (1.11.1)
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ handsoap (0.2.5.5)
+ nokogiri (>= 1.2.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ handsoap!
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", source: "remote3")
+ expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", source: "remote2")
+ expect(lockfile).to eq(expected_lockfile)
+
+ # Even if the gems are already installed
+ FileUtils.rm bundled_app_lock
+ bundle "install --verbose", artifice: "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", source: "remote3")
+ expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", source: "remote2")
+ expect(lockfile).to eq(expected_lockfile)
end
end
context "with a gem that is only found in the wrong source" do
before do
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "not_in_repo1", "1.0.0"
end
- gemfile <<-G
- source "file://#{gem_repo3}"
- gem "not_in_repo1", :source => "file://#{gem_repo1}"
+ install_gemfile <<-G, artifice: "compact_index", raise_on_error: false
+ source "https://gem.repo3"
+ gem "not_in_repo1", :source => "https://gem.repo1"
G
end
it "does not install the gem" do
- bundle :install
- expect(out).to include("Could not find gem 'not_in_repo1'")
+ expect(err).to include("Could not find gem 'not_in_repo1'")
end
end
context "with an existing lockfile" do
before do
- system_gems "rack-0.9.1", "rack-1.0.0", :path => :bundle_path
+ system_gems "myrack-0.9.1", "myrack-1.0.0", path: default_bundle_path
lockfile <<-L
GEM
- remote: file:#{gem_repo1}
- remote: file:#{gem_repo3}
+ remote: https://gem.repo1
+ specs:
+
+ GEM
+ remote: https://gem.repo3
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
- rack!
+ myrack!
L
gemfile <<-G
- source "file://#{gem_repo1}"
- source "file://#{gem_repo3}" do
- gem 'rack'
+ source "https://gem.repo1"
+ source "https://gem.repo3" do
+ gem 'myrack'
end
G
end
- # Reproduction of https://github.com/bundler/bundler/issues/3298
+ # Reproduction of https://github.com/rubygems/bundler/issues/3298
it "does not unlock the installed gem on exec" do
- expect(the_bundle).to include_gems("rack 0.9.1")
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
end
@@ -429,15 +518,16 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_lib "foo"
gemfile <<-G
- gem "rack", :source => "file://#{gem_repo1}"
+ source "https://gem.repo1"
+ gem "myrack", :source => "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
end
it "does not unlock the non-path gem after install" do
- bundle! :install
+ bundle :install, artifice: "compact_index"
- bundle! %(exec ruby -e 'puts "OK"'), :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle %(exec ruby -e 'puts "OK"')
expect(out).to include("OK")
end
@@ -446,75 +536,56 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when an older version of the same gem also ships with Ruby" do
before do
- system_gems "rack-0.9.1"
+ system_gems "myrack-0.9.1"
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack" # shoud come from repo1!
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
+ gem "myrack" # should come from repo1!
G
end
it "installs the gems without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
end
context "when a single source contains multiple locked gems" do
before do
- # 1. With these gems,
+ # With these gems,
build_repo4 do
build_gem "foo", "0.1"
build_gem "bar", "0.1"
end
- # 2. Installing this gemfile will produce...
+ # Installing this gemfile...
gemfile <<-G
- source 'file://#{gem_repo1}'
- gem 'rack'
- gem 'foo', '~> 0.1', :source => 'file://#{gem_repo4}'
- gem 'bar', '~> 0.1', :source => 'file://#{gem_repo4}'
+ source 'https://gem.repo1'
+ gem 'myrack'
+ gem 'foo', '~> 0.1', :source => 'https://gem.repo4'
+ gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
- # 3. this lockfile.
- lockfile <<-L
- GEM
- remote: file:/Users/andre/src/bundler/bundler/tmp/gems/remote1/
- remote: file:/Users/andre/src/bundler/bundler/tmp/gems/remote4/
- specs:
- bar (0.1)
- foo (0.1)
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- bar (~> 0.1)!
- foo (~> 0.1)!
- rack
- L
+ bundle_config "path ../gems/system"
+ bundle :install, artifice: "compact_index"
- bundle! :install, forgotten_command_line_options(:path => "../gems/system")
-
- # 4. Then we add some new versions...
- update_repo4 do
+ # And then we add some new versions...
+ build_repo4 do
build_gem "foo", "0.2"
build_gem "bar", "0.3"
end
end
it "allows them to be unlocked separately" do
- # 5. and install this gemfile, updating only foo.
- install_gemfile <<-G
- source 'file://#{gem_repo1}'
- gem 'rack'
- gem 'foo', '~> 0.2', :source => 'file://#{gem_repo4}'
- gem 'bar', '~> 0.1', :source => 'file://#{gem_repo4}'
+ # And install this gemfile, updating only foo.
+ install_gemfile <<-G, artifice: "compact_index"
+ source 'https://gem.repo1'
+ gem 'myrack'
+ gem 'foo', '~> 0.2', :source => 'https://gem.repo4'
+ gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
- # 6. Which should update foo to 0.2, but not the (locked) bar 0.1
+ # It should update foo to 0.2, but not the (locked) bar 0.1
expect(the_bundle).to include_gems("foo 0.2", "bar 0.1")
end
end
@@ -522,18 +593,21 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "re-resolving" do
context "when there is a mix of sources in the gemfile" do
before do
- build_repo3
+ build_repo3 do
+ build_gem "myrack"
+ end
+
build_lib "path1"
build_lib "path2"
build_git "git1"
build_git "git2"
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
gem "rails"
- source "file://#{gem_repo3}" do
- gem "rack"
+ source "https://gem.repo3" do
+ gem "myrack"
end
gem "path1", :path => "#{lib_path("path1-1.0")}"
@@ -544,7 +618,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "does not re-resolve" do
- bundle :install, :verbose => true
+ bundle :install, artifice: "compact_index", verbose: true
expect(out).to include("using resolution from the lockfile")
expect(out).not_to include("re-resolving dependencies")
end
@@ -553,67 +627,687 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when a gem is installed to system gems" do
before do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
context "and the gemfile changes" do
it "is still able to find that gem from remote sources" do
- source_uri = "file://#{gem_repo1}"
- second_uri = "file://#{gem_repo4}"
-
build_repo4 do
- build_gem "rack", "2.0.1.1.forked"
+ build_gem "myrack", "2.0.1.1.forked"
build_gem "thor", "0.19.1.1.forked"
end
# When this gemfile is installed...
- gemfile <<-G
- source "#{source_uri}"
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
- source "#{second_uri}" do
- gem "rack", "2.0.1.1.forked"
+ source "https://gem.repo4" do
+ gem "myrack", "2.0.1.1.forked"
gem "thor"
end
- gem "rack-obama"
+ gem "myrack-obama"
G
- # It creates this lockfile.
- lockfile <<-L
- GEM
- remote: #{source_uri}/
- remote: #{second_uri}/
- specs:
- rack (2.0.1.1.forked)
- rack-obama (1.0)
- rack
- thor (0.19.1.1.forked)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack (= 2.0.1.1.forked)!
- rack-obama
- thor!
- L
-
# Then we change the Gemfile by adding a version to thor
gemfile <<-G
- source "#{source_uri}"
+ source "https://gem.repo1"
- source "#{second_uri}" do
- gem "rack", "2.0.1.1.forked"
+ source "https://gem.repo4" do
+ gem "myrack", "2.0.1.1.forked"
gem "thor", "0.19.1.1.forked"
end
- gem "rack-obama"
+ gem "myrack-obama"
G
- # But we should still be able to find rack 2.0.1.1.forked and install it
- bundle! :install
+ # But we should still be able to find myrack 2.0.1.1.forked and install it
+ bundle :install, artifice: "compact_index"
+ end
+ end
+ end
+
+ describe "source changed to one containing a higher version of a dependency" do
+ before do
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
+
+ gem "myrack"
+ G
+
+ build_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
+ build_gem "bar"
+ end
+
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
+ s.add_dependency "bar", "=1.0.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo2"
+ gem "myrack"
+ gemspec :path => "#{tmp("gemspec_test")}"
+ G
+ end
+
+ it "conservatively installs the existing locked version" do
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+ end
+
+ context "when Gemfile overrides a gemspec development dependency to change the default source" do
+ before do
+ build_repo4 do
+ build_gem "bar"
+ end
+
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
+ s.add_development_dependency "bar"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gemspec :path => "#{tmp("gemspec_test")}"
+ G
+ end
+
+ it "does not print warnings" do
+ expect(err).to be_empty
+ end
+ end
+
+ it "doesn't update version when a gem uses a source block but a higher version from another source is already installed locally" do
+ build_repo2 do
+ build_gem "example", "0.1.0"
+ end
+
+ build_repo4 do
+ build_gem "example", "1.0.2"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo4"
+
+ gem "example", :source => "https://gem.repo2"
+ G
+
+ bundle "info example"
+ expect(out).to include("example (0.1.0)")
+
+ system_gems "example-1.0.2", path: default_bundle_path, gem_repo: gem_repo4
+
+ bundle "update example --verbose", artifice: "compact_index"
+ expect(out).not_to include("Using example 1.0.2")
+ expect(out).to include("Using example 0.1.0")
+ end
+
+ it "fails immediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "example"
+ end
+ G
+
+ ruby <<~R, raise_on_error: false
+ require 'bundler/setup'
+ R
+
+ expect(last_command).to be_failure
+ expect(err).to include("Could not find gem 'example' in locally installed gems.")
+ end
+
+ it "fails immediately with a helpful error when a non retriable network error happens while resolving sources" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "example"
end
+ G
+
+ bundle "install", artifice: nil, raise_on_error: false
+
+ expect(last_command).to be_failure
+ expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.")
+ end
+
+ context "when an indirect dependency is available from multiple ambiguous sources" do
+ it "raises, suggesting a source block" do
+ build_repo4 do
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack"
+ end
+ build_gem "myrack"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_extra_api", raise_on_error: false
+ source "https://global.source"
+
+ source "https://scoped.source/extra" do
+ gem "depends_on_myrack"
+ end
+
+ source "https://scoped.source" do
+ gem "thin"
+ end
+ G
+ expect(last_command).to be_failure
+ expect(err).to eq <<~EOS.strip
+ The gem 'myrack' was found in multiple relevant sources.
+ * rubygems repository https://scoped.source/
+ * rubygems repository https://scoped.source/extra/
+ You must add this gem to the source block for the source you wish it to be installed from.
+ EOS
+ expect(the_bundle).not_to be_locked
+ end
+ end
+
+ context "when default source includes old gems with nil required_ruby_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_ruby_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://gem.repo4/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", artifice: "compact_index_extra"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ c.checksum gem_repo2, "ruport", "1.7.0.3"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://gem.repo4/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when default source includes old gems with nil required_rubygems_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_rubygems_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://gem.repo4/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", artifice: "compact_index_extra"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ c.checksum gem_repo2, "ruport", "1.7.0.3"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://gem.repo4/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when default source uses the old API and includes old gems with nil required_rubygems_version" do
+ before do
+ build_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_rubygems_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "pdf-writer", "= 1.1.8"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install --verbose", artifice: "endpoint"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "pdf-writer", "1.1.8"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ pdf-writer (1.1.8)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ pdf-writer (= 1.1.8)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when mistakenly adding a top level gem already depended on and cached under the wrong source" do
+ before do
+ build_repo4 do
+ build_gem "some_private_gem", "0.1.0" do |s|
+ s.add_dependency "example", "~> 1.0"
+ end
+ end
+
+ build_repo2 do
+ build_gem "example", "1.0.0"
+ end
+
+ install_gemfile <<~G, artifice: "compact_index"
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ end
+ G
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ gem "example" # MISTAKE, example is not available at gem.repo4
+ end
+ G
+ end
+
+ it "shows a proper error message and does not generate a corrupted lockfile" do
+ expect do
+ bundle :install, artifice: "compact_index", raise_on_error: false, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end.not_to change { lockfile }
+
+ expect(err).to include("Could not find gem 'example' in rubygems repository https://gem.repo4/")
+ end
+ end
+
+ context "when a gem has versions in two sources, but only the locked one has updates" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://main.source/
+ specs:
+ activesupport (1.0)
+ bigdecimal
+ bigdecimal (1.0.0)
+
+ GEM
+ remote: https://main.source/extra/
+ specs:
+ foo (1.0)
+ bigdecimal
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo3 do
+ build_gem "activesupport" do |s|
+ s.add_dependency "bigdecimal"
+ end
+
+ build_gem "bigdecimal", "1.0.0"
+ build_gem "bigdecimal", "3.3.1"
+ end
+
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.add_dependency "bigdecimal"
+ end
+
+ build_gem "bigdecimal", "1.0.0"
+ end
+
+ gemfile <<~G
+ source "https://main.source"
+
+ gem "activesupport"
+
+ source "https://main.source/extra" do
+ gem "foo"
+ end
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "properly upgrades the lockfile when updating that specific gem" do
+ bundle "update bigdecimal --conservative", artifice: "compact_index_extra_api", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo3.to_s }
+
+ expect(lockfile).to eq original_lockfile.gsub("bigdecimal (1.0.0)", "bigdecimal (3.3.1)")
+ end
+ end
+
+ context "when switching a gem with components from rubygems to git source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "7.0.0" do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+ build_gem "actionpack", "7.0.0"
+ build_gem "activerecord", "7.0.0"
+ # propshaft also depends on actionpack, creating the conflict
+ build_gem "propshaft", "1.0.0" do |s|
+ s.add_dependency "actionpack", ">= 7.0.0"
+ end
+ end
+
+ build_git "rails", "7.0.0", path: lib_path("rails") do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+
+ build_git "actionpack", "7.0.0", path: lib_path("rails")
+ build_git "activerecord", "7.0.0", path: lib_path("rails")
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "7.0.0"
+ gem "propshaft"
+ G
+ end
+
+ it "moves component gems to the git source in the lockfile" do
+ expect(lockfile).to include("remote: https://gem.repo2")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+ expect(lockfile).to include("propshaft (1.0.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", git: "#{lib_path("rails")}"
+ gem "propshaft"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include("remote: #{lib_path("rails")}")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+
+ # Component gems should NOT remain in the GEM section
+ # Extract just the GEM section by splitting on GIT first, then GEM
+ gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0]
+ expect(gem_section).not_to include("actionpack (7.0.0)")
+ expect(gem_section).not_to include("activerecord (7.0.0)")
+ end
+ end
+
+ context "when switching a gem with components from rubygems to path source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "7.0.0" do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+ build_gem "actionpack", "7.0.0"
+ build_gem "activerecord", "7.0.0"
+ # propshaft also depends on actionpack, creating the conflict
+ build_gem "propshaft", "1.0.0" do |s|
+ s.add_dependency "actionpack", ">= 7.0.0"
+ end
+ end
+
+ build_lib "rails", "7.0.0", path: lib_path("rails") do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+
+ build_lib "actionpack", "7.0.0", path: lib_path("rails")
+ build_lib "activerecord", "7.0.0", path: lib_path("rails")
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "7.0.0"
+ gem "propshaft"
+ G
+ end
+
+ it "moves component gems to the path source in the lockfile" do
+ expect(lockfile).to include("remote: https://gem.repo2")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+ expect(lockfile).to include("propshaft (1.0.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", path: "#{lib_path("rails")}"
+ gem "propshaft"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include("remote: #{lib_path("rails")}")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+
+ # Component gems should NOT remain in the GEM section
+ # Extract just the GEM section by splitting appropriately
+ gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0]
+ expect(gem_section).not_to include("actionpack (7.0.0)")
+ expect(gem_section).not_to include("activerecord (7.0.0)")
+ end
+ end
+
+ context "when a scoped rubygems source is missing a transitive dependency" do
+ before do
+ build_repo2 do
+ build_gem "fallback_dep", "1.0.0"
+ build_gem "foo", "1.0.0"
+ end
+
+ build_repo3 do
+ build_gem "private_parent", "1.0.0" do |s|
+ s.add_dependency "fallback_dep"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "foo"
+
+ source "https://gem.repo3" do
+ gem "private_parent", "1.0.0"
+ end
+ G
+
+ bundle :install, artifice: "compact_index"
+ end
+
+ it "falls back to the default rubygems source for that dependency" do
+ build_repo2 do
+ build_gem "foo", "2.0.0"
+ end
+
+ system_gems []
+
+ bundle "update foo", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("private_parent 1.0.0", "fallback_dep 1.0.0", "foo 2.0.0")
+ expect(the_bundle).to include_gems("private_parent 1.0.0", source: "remote3")
+ expect(the_bundle).to include_gems("fallback_dep 1.0.0", source: "remote2")
+ end
+ end
+
+ context "when a path gem has a transitive dependency that does not exist in the path source" do
+ before do
+ build_repo2 do
+ build_gem "missing_dep", "1.0.0"
+ build_gem "foo", "1.0.0"
+ end
+
+ build_lib "parent_gem", "1.0.0", path: lib_path("parent_gem") do |s|
+ s.add_dependency "missing_dep"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "foo"
+
+ gem "parent_gem", path: "#{lib_path("parent_gem")}"
+ G
+
+ bundle :install, artifice: "compact_index"
+ end
+
+ it "falls back to the default rubygems source for that dependency when updating" do
+ build_repo2 do
+ build_gem "foo", "2.0.0"
+ end
+
+ system_gems []
+
+ bundle "update foo", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("parent_gem 1.0.0", "missing_dep 1.0.0", "foo 2.0.0")
+ expect(the_bundle).to include_gems("parent_gem 1.0.0", source: "path@#{lib_path("parent_gem")}")
+ expect(the_bundle).to include_gems("missing_dep 1.0.0", source: "remote2")
+ end
+ end
+
+ context "when a git gem has a transitive dependency that does not exist in the git source" do
+ before do
+ build_repo2 do
+ build_gem "missing_dep", "1.0.0"
+ build_gem "foo", "1.0.0"
+ end
+
+ build_git "parent_gem", "1.0.0", path: lib_path("parent_gem") do |s|
+ s.add_dependency "missing_dep"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "foo"
+
+ gem "parent_gem", git: "#{lib_path("parent_gem")}"
+ G
+
+ bundle :install, artifice: "compact_index"
+ end
+
+ it "falls back to the default rubygems source for that dependency when updating" do
+ build_repo2 do
+ build_gem "foo", "2.0.0"
+ end
+
+ system_gems []
+
+ bundle "update foo", artifice: "compact_index"
+
+ expect(the_bundle).to include_gems("parent_gem 1.0.0", "missing_dep 1.0.0", "foo 2.0.0")
+ expect(the_bundle).to include_gems("parent_gem 1.0.0", source: "git@#{lib_path("parent_gem")}")
+ expect(the_bundle).to include_gems("missing_dep 1.0.0", source: "remote2")
end
end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 9c725416d5..97b1d233bf 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -1,113 +1,1972 @@
# frozen_string_literal: true
-RSpec.describe "bundle install with specific_platform enabled" do
- before do
- bundle "config specific_platform true"
-
- build_repo2 do
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
+RSpec.describe "bundle install with specific platforms" do
+ let(:google_protobuf) { <<-G }
+ source "https://gem.repo2"
+ gem "google-protobuf"
+ G
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
+ it "locks to the specific darwin platform" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to include("universal-darwin")
+ expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(
+ "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
+ )
+ end
+ end
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4")
-
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3")
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" }
+ it "still installs the platform specific variant when locked only to ruby, and the platform specific variant has different dependencies" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo4 do
+ build_gem("sass-embedded", "1.72.0") do |s|
+ s.add_dependency "rake"
+ end
- build_gem("google-protobuf", "3.0.0.alpha.4.0")
- build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
- build_gem("google-protobuf", "3.0.0.alpha.3")
- build_gem("google-protobuf", "3.0.0.alpha.2.0")
- build_gem("google-protobuf", "3.0.0.alpha.1.1")
- build_gem("google-protobuf", "3.0.0.alpha.1.0")
+ build_gem("sass-embedded", "1.72.0") do |s|
+ s.platform = "x86_64-darwin-15"
+ end
- build_gem("facter", "2.4.6")
- build_gem("facter", "2.4.6") do |s|
- s.platform = "universal-darwin"
- s.add_runtime_dependency "CFPropertyList"
+ build_gem "rake"
end
- build_gem("CFPropertyList")
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sass-embedded"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rake (1.0)
+ sass-embedded (1.72.0)
+ rake
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sass-embedded
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
+ expect(out).to include("Installing sass-embedded 1.72.0 (x86_64-darwin-15)")
+
+ expect(the_bundle).to include_gem("sass-embedded 1.72.0 x86_64-darwin-15")
end
end
- let(:google_protobuf) { <<-G }
- source "file:#{gem_repo2}"
- gem "google-protobuf"
- G
+ it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+
+ # Consistent location to install and look for gems
+ bundle_config "path vendor/bundle"
+
+ install_gemfile(google_protobuf)
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ google-protobuf (3.0.0.alpha.5.0.5.1)
- context "when on a darwin machine" do
- before { simulate_platform "x86_64-darwin-15" }
+ PLATFORMS
+ ruby
- it "locks to both the specific darwin platform and ruby" do
- install_gemfile!(google_protobuf)
- expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")])
+ DEPENDENCIES
+ google-protobuf
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ # force strict usage of the lockfile by setting frozen mode
+ bundle_config "frozen true"
+
+ # make sure the platform that got actually installed with the old bundler is used
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
- google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- ])
end
+ end
+
+ it "understands that a non-platform specific gem in a new lockfile locked only to ruby doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+
+ # Consistent location to install and look for gems
+ bundle_config "path vendor/bundle"
+
+ gemfile google_protobuf
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.4.0"
+ end
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ google-protobuf (3.0.0.alpha.4.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ google-protobuf
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
+
+ checksums.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.5.0.5.1"
+
+ # make sure the platform that the platform specific dependency is used, since we're only locked to ruby
+ expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
+
+ # make sure we're still only locked to ruby
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ google-protobuf (3.0.0.alpha.5.0.5.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ google-protobuf
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when running on a legacy lockfile locked only to ruby" do
+ # Exercises the legacy lockfile path (use_exact_resolved_specifications? = false)
+ # because most_specific_locked_platform is ruby, matching the generic platform.
+ # Key insight: when target (arm64-darwin-22) != platform (ruby), the code tries
+ # both platforms before falling back, preserving lockfile integrity.
+
+ around do |example|
+ build_repo4 do
+ build_gem "nokogiri", "1.3.10"
+ build_gem "nokogiri", "1.3.10" do |s|
+ s.platform = "arm64-darwin"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.3.10)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-22", &example
+ end
+
+ it "still installs the generic ruby variant if necessary" do
+ bundle "install"
+ expect(the_bundle).to include_gem("nokogiri 1.3.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.3.10 arm64-darwin")
+ end
+
+ it "still installs the generic ruby variant if necessary, even in frozen mode" do
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }
+ expect(the_bundle).to include_gem("nokogiri 1.3.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.3.10 arm64-darwin")
+ end
+ end
+
+ context "when platform-specific gem has incompatible required_ruby_version" do
+ # Key insight: candidate_platforms tries [target, platform, ruby] in order.
+ # Ruby platform is last since it requires compilation, but works when
+ # precompiled gems are incompatible with the current Ruby version.
+ #
+ # Note: This fix requires the lockfile to include both ruby and platform-
+ # specific variants (typical after `bundle lock --add-platform`). If the
+ # lockfile only has platform-specific gems, frozen mode cannot help because
+ # Bundler.setup would still expect the locked (incompatible) gem.
+
+ # Exercises the exact spec path (use_exact_resolved_specifications? = true)
+ # because lockfile has platform-specific entry as most_specific_locked_platform
+ it "falls back to ruby platform in frozen mode when lockfile includes both variants" do
+ build_repo4 do
+ build_gem "nokogiri", "1.18.10"
+ build_gem "nokogiri", "1.18.10" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ # Lockfile has both ruby and platform-specific gem (typical after `bundle lock --add-platform`)
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.10)
+ nokogiri (1.18.10-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }
+ expect(the_bundle).to include_gem("nokogiri 1.18.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.18.10 x86_64-linux")
+ end
+ end
+ end
+
+ it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo2 do
+ build_gem("libv8", "8.4.255.0")
+ build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" }
+
+ build_gem("mini_racer", "1.0.0") do |s|
+ s.add_dependency "libv8"
+ end
+ end
+
+ # Consistent location to install and look for gems
+ bundle_config "path vendor/bundle"
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "libv8"
+ G
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ libv8 (8.4.255.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- it "caches both the universal-darwin and ruby gems when --all-platforms is passed" do
+ bundle "install --verbose"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
+ expect(out).to include("Installing libv8 8.4.255.0 (universal-darwin)")
+
+ bundle "add mini_racer --verbose"
+ expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)")
+ end
+ end
+
+ it "chooses platform specific gems even when resolving upon materialization and the API returns more specific platforms first" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo4 do
+ build_gem("grpc", "1.50.0")
+ build_gem("grpc", "1.50.0") {|s| s.platform = "universal-darwin" }
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "grpc"
+ G
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ grpc (1.50.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ grpc
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", artifice: "compact_index_precompiled_before"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
+ expect(out).to include("Installing grpc 1.50.0 (universal-darwin)")
+ end
+ end
+
+ it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
gemfile(google_protobuf)
- bundle! "package --all-platforms"
- expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]).
- to all(exist)
+ bundle "cache --all-platforms"
+ expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist
+
+ bundle "install --verbose"
+ expect(err).to be_empty
end
+ end
+
+ it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+ gemfile(google_protobuf)
+ bundle_config "cache_all_platforms true"
+ bundle "cache"
+ expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist
- it "uses the platform-specific gem with extra dependencies" do
- install_gemfile! <<-G
- source "file:#{gem_repo2}"
+ bundle "install --verbose"
+ expect(err).to be_empty
+ end
+ end
+
+ it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
+ git = build_git "pg_array_parser", "1.0"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("pg_array_parser-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ pg_array_parser (1.0-java)
+ pg_array_parser (1.0)
+
+ GEM
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms("java")}
+
+ DEPENDENCIES
+ pg_array_parser!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "cache --all-platforms"
+
+ expect(err).to be_empty
+ end
+
+ it "uses the platform-specific gem with extra dependencies" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem_with_different_dependencies_per_platform
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "facter"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_platforms).to include("universal-darwin")
expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0")
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0",
- "facter-2.4.6",
- "facter-2.4.6-universal-darwin"])
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include("CFPropertyList-1.0",
+ "facter-2.4.6-universal-darwin")
end
+ end
- context "when adding a platform via lock --add_platform" do
- it "adds the foreign platform" do
- install_gemfile!(google_protobuf)
- bundle! "lock --add-platform=#{x64_mingw}"
+ context "when adding a platform via lock --add_platform" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
- expect(the_bundle.locked_gems.platforms).to eq([rb, x64_mingw, pl("x86_64-darwin-15")])
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
+ it "adds the foreign platform" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ bundle "lock --add-platform=x64-mingw-ucrt"
+
+ expect(the_bundle.locked_platforms).to include("x64-mingw-ucrt", "universal-darwin")
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(*%w[
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
+ google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw-ucrt
])
end
+ end
- it "falls back on plain ruby when that version doesnt have a platform-specific gem" do
- install_gemfile!(google_protobuf)
- bundle! "lock --add-platform=#{java}"
+ it "falls back on plain ruby when that version doesn't have a platform-specific gem" do
+ simulate_platform "x86_64-darwin-15" do
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ bundle "lock --add-platform=java"
- expect(the_bundle.locked_gems.platforms).to eq([java, rb, pl("x86_64-darwin-15")])
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
- google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- ])
+ expect(the_bundle.locked_platforms).to include("java", "universal-darwin")
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(
+ "google-protobuf-3.0.0.alpha.5.0.5.1",
+ "google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
+ )
+ end
+ end
+ end
+
+ it "installs sorbet-static, which does not provide a pure ruby variant, in absence of a lockfile, just fine", :truffleruby do
+ skip "does not apply to Windows" if Gem.win_platform?
+
+ build_repo2 do
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = Bundler.local_platform }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "sorbet-static", "0.5.6403"
+ G
+
+ bundle "install --verbose"
+ end
+
+ it "installs sorbet-static, which does not provide a pure ruby variant, in presence of a lockfile, just fine", :truffleruby do
+ skip "does not apply to Windows" if Gem.win_platform?
+
+ build_repo2 do
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = Bundler.local_platform }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "sorbet-static", "0.5.6403"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ sorbet-static (0.5.6403-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.6403)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ end
+
+ it "does not resolve if the current platform does not match any of available platform specific variants for a top level dependency" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static", "0.5.6433"
+ G
+
+ error_message = <<~ERROR.strip
+ Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
+ * sorbet-static-0.5.6433-universal-darwin-20
+ * sorbet-static-0.5.6433-x86_64-linux
+ ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+ end
+
+ it "shows a platform mismatch hint when the current platform is not in the lockfile's platforms" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux-musl" }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static", "0.5.6433"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (0.5.6433-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.6433)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", raise_on_error: false
+ end
+
+ expect(err).to include("Your current platform (x86_64-linux) is not included in the lockfile's platforms (x86_64-linux-musl)")
+ expect(err).to include("bundle lock --add-platform x86_64-linux")
+ end
+
+ it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do
+ build_repo4 do
+ build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet", "0.5.6433"
+ G
+
+ error_message = <<~ERROR.strip
+ Could not find compatible versions
+
+ Because every version of sorbet depends on sorbet-static = 0.5.6433
+ and sorbet-static = 0.5.6433 could not be found in rubygems repository https://gem.repo4/ or installed locally for any resolution platforms (arm64-darwin-21),
+ sorbet cannot be used.
+ So, because Gemfile depends on sorbet = 0.5.6433,
+ version solving has failed.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
+ * sorbet-static-0.5.6433-universal-darwin-20
+ * sorbet-static-0.5.6433-x86_64-linux
+ ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", raise_on_error: false
+ end
+
+ expect(err).to include(error_message).once
+ end
+
+ it "does not generate a lockfile if ruby platform is forced and some gem has no ruby variant available" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.9889") {|s| s.platform = Gem::Platform.local }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static", "0.5.9889"
+ G
+
+ bundle "lock", raise_on_error: false, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+
+ expect(err).to include <<~ERROR.rstrip
+ Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.9889)':
+ * sorbet-static-0.5.9889-#{Gem::Platform.local}
+ ERROR
+ end
+
+ it "automatically fixes the lockfile if ruby platform is locked and some gem has no ruby variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_dependency "sorbet", "= 0.5.10160"
+ s.add_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "sorbet", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
+ c.checksum gem_repo4, "sorbet-static-and-runtime", "0.5.10160"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if both ruby platform and a more specific platform are locked, and some gem has no ruby variant available" do
+ build_repo4 do
+ build_gem "nokogiri", "1.12.0"
+ build_gem "nokogiri", "1.12.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem "nokogiri", "1.13.0"
+ build_gem "nokogiri", "1.13.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem("sorbet-static", "0.5.10601") do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+
+ simulate_platform "x86_64-darwin-22" do
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+ end
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.0", "x86_64-darwin"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10601", "x86_64-darwin"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.12.0)
+ nokogiri (1.12.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "update --conservative nokogiri"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.13.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if only ruby platform is locked and some gem has no ruby variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_dependency "sorbet", "= 0.5.10160"
+ s.add_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "sorbet", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
+ c.checksum gem_repo4, "sorbet-static-and-runtime", "0.5.10160"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when adding a gem that introduces dependencies with no ruby platform variants transitively" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.18.2"
+
+ build_gem "nokogiri", "1.18.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem("sorbet", "0.5.11835") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.11835"
+ end
+
+ build_gem "sorbet-static", "0.5.11835" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.2)
+ nokogiri (1.18.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.18.2", "x86_64-linux"
+ c.checksum gem_repo4, "sorbet", "0.5.11835"
+ c.checksum gem_repo4, "sorbet-static", "0.5.11835", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.2)
+ nokogiri (1.18.2-x86_64-linux)
+ sorbet (0.5.11835)
+ sorbet-static (= 0.5.11835)
+ sorbet-static (0.5.11835-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile if multiple platforms locked, but no valid versions of direct dependencies for all of them" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ aarch64-linux
+ arm-linux
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10696", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile without removing other variants if it's missing platform gems, but they are installed locally" do
+ simulate_platform "x86_64-darwin-21" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-20"
+ end
+
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ # Make sure sorbet-static-0.5.10549-universal-darwin-21 is installed
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static", "= 0.5.10549"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-20"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-21"
+ end
+
+ # Make sure the lockfile is missing sorbet-static-0.5.10549-universal-darwin-21
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+ sorbet-static (0.5.10549-universal-darwin-21)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile if locked only to ruby, and some locked specs don't meet locked dependencies" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem("ibandit", "0.7.0") do |s|
+ s.add_dependency "i18n", "~> 0.7.0"
+ end
+
+ build_gem("i18n", "0.7.0.beta1")
+ build_gem("i18n", "0.7.0")
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ibandit", "~> 0.7.0"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ i18n (0.7.0.beta1)
+ ibandit (0.7.0)
+ i18n (~> 0.7.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ ibandit (~> 0.7.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update i18n"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ i18n (0.7.0)
+ ibandit (0.7.0)
+ i18n (~> 0.7.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ ibandit (~> 0.7.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8"
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+
+ gem "tzinfo", "~> 1.2", platform: :#{not_local_tag}
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.8"
+ c.checksum gem_repo4, "nokogiri", "1.13.8", Gem::Platform.local
+ end
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.13.8)
+ nokogiri (1.13.8-#{Gem::Platform.local})
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ nokogiri
+ tzinfo (~> 1.2)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+
+ it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile, and the lockfile only has ruby" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8"
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+
+ gem "tzinfo", "~> 1.2", platforms: %i[windows jruby]
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.8"
+ end
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.13.8)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+ tzinfo (~> 1.2)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+
+ it "does not remove ruby when adding a new gem to the Gemfile" do
+ build_repo4 do
+ build_gem "concurrent-ruby", "1.2.2"
+ build_gem "myrack", "3.0.7"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "concurrent-ruby"
+ gem "myrack"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "concurrent-ruby", "1.2.2"
+ c.checksum gem_repo4, "myrack", "3.0.7"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ concurrent-ruby (1.2.2)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ concurrent-ruby
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ concurrent-ruby (1.2.2)
+ myrack (3.0.7)
+
+ PLATFORMS
+ #{lockfile_platforms(generic_default_locked_platform || local_platform, defaults: ["ruby"])}
+
+ DEPENDENCIES
+ concurrent-ruby
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "can fallback to a source gem when platform gems are incompatible with current ruby version" do
+ setup_multiplatform_gem_with_source_gem
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "my-precompiled-gem"
+ G
+
+ # simulate lockfile which includes both a precompiled gem with:
+ # - Gem the current platform (with incompatible ruby version)
+ # - A source gem with compatible ruby version
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ my-precompiled-gem (3.0.0)
+ my-precompiled-gem (3.0.0-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ my-precompiled-gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+ end
+
+ it "automatically adds the ruby variant to the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
+ #
+ # Given an existing application using native gems (e.g., nokogiri)
+ # And a lockfile generated with a stable ruby version
+ # When want test the application against ruby-head and `bundle install`
+ # Then bundler should fall back to the generic ruby platform gem
+ #
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0"
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri", "1.14.0"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0)
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile when only ruby platform locked, and adding a dependency with subdependencies not valid for ruby" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-static (0.5.10160-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ sorbet
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "locks specific platforms automatically" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0"
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x64-mingw-ucrt"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "java"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "universal-darwin-22"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "arm-linux"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
+ end
+
+ # locks all compatible platforms, excluding Java and Windows
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0)
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ arm-linux
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ FileUtils.rm bundled_app_lock
+
+ bundle "lock"
+
+ checksums.delete "nokogiri", "arm-linux"
+ checksums.checksum gem_repo4, "sorbet-static", "0.5.10696", "universal-darwin-22"
+ checksums.checksum gem_repo4, "sorbet-static", "0.5.10696", "x86_64-linux"
+
+ # locks only platforms compatible with all gems in the bundle
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0)
+ nokogiri (1.14.0-x86_64-linux)
+ sorbet-static (0.5.10696-universal-darwin-22)
+ sorbet-static (0.5.10696-x86_64-linux)
+
+ PLATFORMS
+ universal-darwin-22
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution" do
+ build_repo4 do
+ build_gem "nokogiri", "1.15.5"
+
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{current_ruby_minor}.dev"
+ end
+
+ build_gem "sass-embedded", "1.69.5"
+
+ build_gem "sass-embedded", "1.69.5" do |s|
+ s.platform = "x86_64-linux-gnu"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sass-embedded"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.15.5"
+ c.checksum gem_repo4, "sass-embedded", "1.69.5"
+ c.checksum gem_repo4, "sass-embedded", "1.69.5", "x86_64-linux-gnu"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose"
+
+ # locks all compatible platforms, excluding Java and Windows
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.15.5)
+ sass-embedded (1.69.5)
+ sass-embedded (1.69.5-x86_64-linux-gnu)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sass-embedded
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not add ruby platform gem if it brings extra dependencies not resolved originally" do
+ build_repo4 do
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.add_dependency "mini_portile2", "~> 2.8.2"
+ end
+
+ build_gem "nokogiri", "1.15.5" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.15.5", "x86_64-linux"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose"
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.15.5-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ ["x86_64-linux", "x86_64-linux-musl"].each do |host_platform|
+ describe "on host platform #{host_platform}" do
+ it "adds current musl platform" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-musl"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform host_platform do
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux"
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-musl"
+ end
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rcee_precompiled (0.5.0-x86_64-linux)
+ rcee_precompiled (0.5.0-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+ end
+ end
+
+ it "adds current musl platform, when there are also gnu variants" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-gnu"
+ end
+
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "x86_64-linux-musl"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform "x86_64-linux-musl" do
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-gnu"
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-musl"
+ end
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rcee_precompiled (0.5.0-x86_64-linux-gnu)
+ rcee_precompiled (0.5.0-x86_64-linux-musl)
+
+ PLATFORMS
+ x86_64-linux-gnu
+ x86_64-linux-musl
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not add current platform if there's an equivalent less specific platform among the ones resolved" do
+ build_repo4 do
+ build_gem "rcee_precompiled", "0.5.0" do |s|
+ s.platform = "universal-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rcee_precompiled", "0.5.0"
+ G
+
+ simulate_platform "x86_64-darwin-15" do
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "universal-darwin"
+ end
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rcee_precompiled (0.5.0-universal-darwin)
+
+ PLATFORMS
+ universal-darwin
+
+ DEPENDENCIES
+ rcee_precompiled (= 0.5.0)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not re-resolve when a specific platform, but less specific than the current platform, is locked" do
+ build_repo4 do
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.0)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ nokogiri!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-23" do
+ bundle "install --verbose"
+
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ end
+ end
+
+ it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem" do
+ build_repo4 do
+ build_gem "ffi"
+
+ build_gem "ffi" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ gem "nokogiri"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.0)
+ nokogiri (1.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update nokogiri"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+ end
+
+ it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem, and variants for other platform also locked" do
+ build_repo4 do
+ build_gem "ffi"
+
+ build_gem "ffi" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "ffi" do |s|
+ s.platform = "java"
+ end
+
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ gem "nokogiri"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.0)
+ ffi (1.0-java)
+ nokogiri (1.0)
+
+ PLATFORMS
+ java
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update nokogiri"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+ end
+
+ it "does not remove platform specific gems from lockfile when using a ruby version that does not match their ruby requirements, since they may be useful in other rubies" do
+ build_repo4 do
+ build_gem("google-protobuf", "3.25.5")
+ build_gem("google-protobuf", "3.25.5") do |s|
+ s.required_ruby_version = "< #{current_ruby_minor}.dev"
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "google-protobuf", "~> 3.0"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ google-protobuf (3.25.5)
+ google-protobuf (3.25.5-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ google-protobuf (~> 3.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+
+ private
+
+ def setup_multiplatform_gem
+ build_repo2 do
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw-ucrt" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw-ucrt" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.4.0")
+ build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
+ end
+ end
+
+ def setup_multiplatform_gem_with_different_dependencies_per_platform
+ build_repo2 do
+ build_gem("facter", "2.4.6")
+ build_gem("facter", "2.4.6") do |s|
+ s.platform = "universal-darwin"
+ s.add_dependency "CFPropertyList"
+ end
+ build_gem("CFPropertyList")
+ end
+ end
+
+ def setup_multiplatform_gem_with_source_gem
+ build_repo2 do
+ build_gem("my-precompiled-gem", "3.0.0")
+ build_gem("my-precompiled-gem", "3.0.0") do |s|
+ s.platform = Bundler.local_platform
+
+ # purposely unresolvable
+ s.required_ruby_version = ">= 1000.0.0"
end
end
end
diff --git a/spec/bundler/install/gemfile_spec.rb b/spec/bundler/install/gemfile_spec.rb
index e74c5ffe59..83875a3d0e 100644
--- a/spec/bundler/install/gemfile_spec.rb
+++ b/spec/bundler/install/gemfile_spec.rb
@@ -1,124 +1,171 @@
-# encoding: utf-8
# frozen_string_literal: true
RSpec.describe "bundle install" do
context "with duplicated gems" do
it "will display a warning" do
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+
gem 'rails', '~> 4.0.0'
gem 'rails', '~> 4.0.0'
G
- expect(out).to include("more than once")
+ expect(err).to include("more than once")
end
end
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- bundle :install, :gemfile => bundled_app("NotGemfile")
+ bundle :install, gemfile: bundled_app("NotGemfile")
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "respects lockfile and BUNDLE_LOCKFILE" do
+ gemfile bundled_app("NotGemfile"), <<-G
+ lockfile "ReallyNotGemfile.lock"
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle :install, gemfile: bundled_app("NotGemfile")
+
+ ENV["BUNDLE_GEMFILE"] = "NotGemfile"
+ ENV["BUNDLE_LOCKFILE"] = "ReallyNotGemfile.lock"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "respects BUNDLE_LOCKFILE during bundle install" do
+ ENV["BUNDLE_LOCKFILE"] = "ReallyNotGemfile.lock"
+
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle :install, gemfile: bundled_app("NotGemfile")
+ expect(bundled_app("ReallyNotGemfile.lock")).to exist
+
+ ENV["BUNDLE_GEMFILE"] = "NotGemfile"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with gemfile set via config" do
before do
gemfile bundled_app("NotGemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- bundle "config --local gemfile #{bundled_app("NotGemfile")}"
+ bundle_config "gemfile #{bundled_app("NotGemfile")}"
end
it "uses the gemfile to install" do
bundle "install"
bundle "list"
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- bundle "install"
- bundle "list"
+ bundle "install", dir: bundled_app("subdir")
+ bundle "list", dir: bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
- end
+ expect(out).to include("myrack (1.0.0)")
end
end
- context "with deprecated features" do
- before :each do
- in_app_root
- end
+ it "reports that lib is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
- it "reports that lib is an invalid option" do
- gemfile <<-G
- gem "rack", :lib => "rack"
- G
+ gem "myrack", :lib => "myrack"
+ G
- bundle :install
- expect(out).to match(/You passed :lib as an option for gem 'rack', but it is invalid/)
- end
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :lib as an option for gem 'myrack', but it is invalid/)
end
- context "with prefer_gems_rb set" do
- before { bundle! "config prefer_gems_rb true" }
+ it "reports that type is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
- it "prefers gems.rb to Gemfile" do
- create_file("gems.rb", "gem 'bundler'")
- create_file("Gemfile", "raise 'wrong Gemfile!'")
+ gem "myrack", :type => "development"
+ G
- bundle! :install
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :type as an option for gem 'myrack', but it is invalid/)
+ end
- expect(bundled_app("gems.rb")).to be_file
- expect(bundled_app("Gemfile.lock")).not_to be_file
+ it "reports that gemfile is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
- expect(the_bundle).to include_gem "bundler #{Bundler::VERSION}"
+ gem "myrack", :gemfile => "foo"
+ G
+
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :gemfile as an option for gem 'myrack', but it is invalid/)
+ end
+
+ context "when an internal error happens" do
+ let(:bundler_bug) do
+ create_file("bundler_bug.rb", <<~RUBY)
+ require "bundler"
+
+ module Bundler
+ class Dsl
+ def source(source, *args, &blk)
+ nil.name
+ end
+ end
+ end
+ RUBY
+
+ bundled_app("bundler_bug.rb").to_s
+ end
+
+ it "shows culprit file and line" do
+ skip "ruby-core test setup has always \"lib\" in $LOAD_PATH so `require \"bundler\"` always activates the local version rather than using RubyGems gem activation stuff, causing conflicts" if ruby_core?
+
+ install_gemfile "source 'https://gem.repo1'", requires: [bundler_bug], artifice: nil, raise_on_error: false
+ expect(err).to include("bundler_bug.rb:6")
end
end
- context "with engine specified in symbol" do
+ context "with engine specified in symbol", :jruby_only do
it "does not raise any error parsing Gemfile" do
- simulate_ruby_version "2.3.0" do
- simulate_ruby_engine "jruby", "9.1.2.0" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0"
- G
-
- expect(out).to match(/Bundle complete!/)
- end
- end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
+ G
+
+ expect(out).to match(/Bundle complete!/)
end
it "installation succeeds" do
- simulate_ruby_version "2.3.0" do
- simulate_ruby_engine "jruby", "9.1.2.0" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0"
- gem "rack"
- G
-
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with a Gemfile containing non-US-ASCII characters" do
it "reads the Gemfile with the UTF-8 encoding by default" do
- skip "Ruby 1.8 has no encodings" if RUBY_VERSION < "1.9"
-
install_gemfile <<-G
+ source "https://gem.repo1"
+
str = "Il était une fois ..."
puts "The source encoding is: " + str.encoding.name
G
@@ -129,11 +176,11 @@ RSpec.describe "bundle install" do
end
it "respects the magic encoding comment" do
- skip "Ruby 1.8 has no encodings" if RUBY_VERSION < "1.9"
-
# NOTE: This works thanks to #eval interpreting the magic encoding comment
install_gemfile <<-G
# encoding: iso-8859-1
+ source "https://gem.repo1"
+
str = "Il #{"\xE9".dup.force_encoding("binary")}tait une fois ..."
puts "The source encoding is: " + str.encoding.name
G
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 2acade1166..9db73b84b5 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -7,12 +7,27 @@ RSpec.describe "compact index api" do
it "should use the API" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "has a debug mode" do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "myrack"
+ G
+
+ bundle :install, artifice: "compact_index", env: { "DEBUG_COMPACT_INDEX" => "true" }
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ expect(err).to include("[Bundler::CompactIndexClient] available?")
+ expect(err).to include("[Bundler::CompactIndexClient] fetching versions")
+ expect(err).to include("[Bundler::CompactIndexClient] info(myrack)")
+ expect(err).to include("[Bundler::CompactIndexClient] fetching info/myrack")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should URI encode gem names" do
@@ -21,8 +36,8 @@ RSpec.describe "compact index api" do
gem " sinatra"
G
- bundle :install, :artifice => "compact_index"
- expect(out).to include("' sinatra' is not a valid gem name because it contains whitespace.")
+ bundle :install, artifice: "compact_index", raise_on_error: false
+ expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
it "should handle nested dependencies" do
@@ -31,7 +46,7 @@ RSpec.describe "compact index api" do
gem "rails"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems(
"rails 2.3.2",
@@ -44,23 +59,23 @@ RSpec.describe "compact index api" do
end
it "should handle case sensitivity conflicts" do
- build_repo4 do
- build_gem "rack", "1.0" do |s|
- s.add_runtime_dependency("Rack", "0.1")
+ build_repo4(build_compact_index: false) do
+ build_gem "myrack", "1.0" do |s|
+ s.add_dependency("Myrack", "0.1")
end
- build_gem "Rack", "0.1"
+ build_gem "Myrack", "0.1"
end
- install_gemfile! <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4 }
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
- gem "rack", "1.0"
- gem "Rack", "0.1"
+ gem "myrack", "1.0"
+ gem "Myrack", "0.1"
G
# can't use `include_gems` here since the `require` will conflict on a
# case-insensitive FS
- run! "Bundler.require; puts Gem.loaded_specs.values_at('rack', 'Rack').map(&:full_name)"
- expect(last_command.stdout).to eq("rack-1.0\nRack-0.1")
+ run "Bundler.require; puts Gem.loaded_specs.values_at('myrack', 'Myrack').map(&:full_name)"
+ expect(out).to eq("myrack-1.0\nMyrack-0.1")
end
it "should handle multiple gem dependencies on the same gem" do
@@ -69,20 +84,21 @@ RSpec.describe "compact index api" do
gem "net-sftp"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
- it "should use the endpoint when using --deployment" do
+ it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "compact_index")
+ bundle_config "deployment true"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles git dependencies that are in rubygems" do
@@ -93,17 +109,17 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- git "file:///#{lib_path("foo-1.0")}" do
+ git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "handles git dependencies that are in rubygems using --deployment" do
+ it "handles git dependencies that are in rubygems using deployment mode" do
build_git "foo" do |s|
s.executables = "foobar"
s.add_dependency "rails", "2.3.2"
@@ -111,65 +127,73 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "file:///#{lib_path("foo-1.0")}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
- bundle "install --deployment", :artifice => "compact_index"
+ bundle_config "deployment true"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "doesn't fail if you only have a git gem with no deps when using --deployment" do
+ it "doesn't fail if you only have a git gem with no deps when using deployment mode" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "file:///#{lib_path("foo-1.0")}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
- bundle "install", :artifice => "compact_index"
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "compact_index")
+ bundle "install", artifice: "compact_index"
+ bundle_config "deployment true"
+ bundle :install, artifice: "compact_index"
expect(the_bundle).to include_gems("foo 1.0")
end
- it "falls back when the API errors out" do
- simulate_platform mswin
-
+ it "falls back when the API URL returns 403 Forbidden" do
gemfile <<-G
source "#{source_uri}"
- gem "rcov"
+ gem "myrack"
G
- bundle! :install, :artifice => "windows"
- expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rcov 1.0.0"
+ bundle :install, verbose: true, artifice: "compact_index_forbidden"
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "falls back when the API URL returns 403 Forbidden" do
+ it "falls back when the versions endpoint has a checksum mismatch" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :verbose => true, :artifice => "compact_index_forbidden"
+ bundle :install, verbose: true, artifice: "compact_index_checksum_mismatch"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(out).to include("The checksum of /versions does not match the checksum provided by the server!")
+ expect(out).to include("Calculated checksums #{{ "sha-256" => "8KfZiM/fszVkqhP/m5s9lvE6M9xKu4I1bU4Izddp5Ms=" }.inspect} did not match expected #{{ "sha-256" => "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" }.inspect}")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "falls back when the versions endpoint has a checksum mismatch" do
+ it "shows proper path when permission errors happen", :permissions do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :verbose => true, :artifice => "compact_index_checksum_mismatch"
- expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(out).to include <<-'WARN'
-The checksum of /versions does not match the checksum provided by the server! Something is wrong (local checksum is "\"d41d8cd98f00b204e9800998ecf8427e\"", was expecting "\"123\"").
- WARN
- expect(the_bundle).to include_gems "rack 1.0.0"
+ versions = compact_index_cache_path.join(
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ versions.dirname.mkpath
+ versions.write("created_at")
+ FileUtils.chmod("-r", versions)
+
+ bundle :install, artifice: "compact_index", raise_on_error: false
+
+ expect(err).to include(
+ "There was an error while trying to read from `#{versions}`. It is likely that you need to grant read permissions for that path."
+ )
end
it "falls back when the user's home directory does not exist or is not writable" do
@@ -177,28 +201,28 @@ The checksum of /versions does not match the checksum provided by the server! So
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index_host_redirect"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_host_redirect"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "handles host redirects without Net::HTTP::Persistent" do
+ it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
FileUtils.mkdir_p lib_path
@@ -214,88 +238,93 @@ The checksum of /versions does not match the checksum provided by the server! So
H
end
- bundle! :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
+ bundle :install, artifice: "compact_index_host_redirect", requires: [lib_path("disable_net_http_persistent.rb")]
expect(out).to_not match(/Too many redirects/)
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "times out when Bundler::Fetcher redirects too much" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "compact_index_redirects"
- expect(out).to match(/Too many redirects/)
+ bundle :install, artifice: "compact_index_redirects", raise_on_error: false
+ expect(err).to match(/Too many redirects/)
end
context "when --full-index is specified" do
it "should use the modern index for install" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle "install --full-index", :artifice => "compact_index"
+ bundle "install --full-index", artifice: "compact_index"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the modern index for update" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! "update --full-index", :artifice => "compact_index", :all => bundle_update_requires_all?
+ bundle "update --full-index", artifice: "compact_index", all: true
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
it "does not double check for gems that are only installed locally" do
- system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0]
- bundle! "config --local path.system true"
- ENV["BUNDLER_SPEC_ALL_REQUESTS"] = strip_whitespace(<<-EOS).strip
- #{source_uri}/versions
- #{source_uri}/info/rack
- EOS
-
- install_gemfile! <<-G, :artifice => "compact_index", :verbose => true
- source "#{source_uri}"
- gem "rack"
- G
-
- expect(last_command.stdboth).not_to include "Double checking"
- end
-
- it "fetches again when more dependencies are found in subsequent sources", :bundler => "< 3" do
build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
+ build_gem "net_a" do |s|
+ s.add_dependency "net_b"
+ s.add_dependency "net_build_extensions"
+ end
+
+ build_gem "net_b"
+
+ build_gem "net_build_extensions" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/net_build_extensions.rb", "w") do |f|
+ f.puts "NET_BUILD_EXTENSIONS = 'YES'"
+ end
+ end
+ RUBY
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ system_gems %w[myrack-1.0.0 thin-1.0 net_a-1.0], gem_repo: gem_repo2
+ bundle_config "path.system true"
+ ENV["BUNDLER_SPEC_ALL_REQUESTS"] = <<~EOS.strip
+ #{source_uri}/versions
+ #{source_uri}/info/myrack
+ EOS
+
+ install_gemfile <<-G, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index_extra"
- expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
+ expect(stdboth).not_to include "Double checking"
end
- it "fetches again when more dependencies are found in subsequent sources with source blocks" do
+ it "fetches again when more dependencies are found in subsequent sources" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
- install_gemfile! <<-G, :artifice => "compact_index_extra", :verbose => true
+ install_gemfile <<-G, artifice: "compact_index_extra", verbose: true
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -308,55 +337,33 @@ The checksum of /versions does not match the checksum provided by the server! So
it "fetches gem versions even when those gems are already installed" do
gemfile <<-G
source "#{source_uri}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- bundle! :install, :artifice => "compact_index_extra_api"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_extra_api"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
build_repo4 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
gemfile <<-G
source "#{source_uri}" do; end
source "#{source_uri}/extra"
- gem "rack", "1.2"
- G
- bundle! :install, :artifice => "compact_index_extra_api"
- expect(the_bundle).to include_gems "rack 1.2"
- end
-
- it "considers all possible versions of dependencies from all api gem sources", :bundler => "< 3" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
- build_repo4 do
- build_gem "activesupport", "1.2.0"
- build_gem "somegem", "1.0.0" do |s|
- s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1
- end
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem 'somegem', '1.0.0'
+ gem "myrack", "1.2"
G
-
- bundle! :install, :artifice => "compact_index_extra_api"
-
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
+ bundle :install, artifice: "compact_index_extra_api"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources when using blocks", :bundler => "< 3" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
+ it "resolves indirect dependencies to the most scoped source that includes them" do
+ # In this scenario, the gem "somegem" only exists in repo4. It depends on
+ # specific version of activesupport that exists only in repo1. There
+ # happens also be a version of activesupport in repo4, but not the one that
+ # version 1.0.0 of somegem wants. This test makes sure that bundler tries to
+ # use the version in the most scoped source, even if not compatible, and
+ # gives a resolution error
build_repo4 do
build_gem "activesupport", "1.2.0"
build_gem "somegem", "1.0.0" do |s|
@@ -371,10 +378,9 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle! :install, :artifice => "compact_index_extra_api"
+ bundle :install, artifice: "compact_index_extra_api", raise_on_error: false
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
+ expect(err).to include("Could not find compatible versions")
end
it "prints API output properly with back deps" do
@@ -382,7 +388,7 @@ The checksum of /versions does not match the checksum provided by the server! So
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -392,52 +398,43 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle! :install, :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
expect(out).to include("Fetching gem metadata from http://localgemserver.test/")
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps" do
+ it "does not fetch every spec when doing back deps" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ install_gemfile <<-G, artifice: "compact_index_extra_missing"
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
end
G
- bundle! :install, :artifice => "compact_index_extra_missing"
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps & everything is the compact index" do
+ it "does not fetch every spec when doing back deps & everything is the compact index" do
build_repo4 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
- FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo4("gems/foo-*.gem")]
end
- install_gemfile! <<-G, :artifice => "compact_index_extra_api_missing"
+ install_gemfile <<-G, artifice: "compact_index_extra_api_missing"
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -454,36 +451,16 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'foo'
G
- bundle! :install, :artifice => "compact_index_api_missing"
+ bundle :install, artifice: "compact_index_api_missing"
expect(the_bundle).to include_gems "foo 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- bundle! :install, :artifice => "compact_index_extra"
-
- bundle "install --deployment", :artifice => "compact_index_extra"
- expect(the_bundle).to include_gems "back_deps 1.0"
- end
-
- it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -493,95 +470,55 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle! :install, :artifice => "compact_index_extra"
-
- bundle "install --deployment", :artifice => "compact_index_extra"
+ bundle :install, artifice: "compact_index_extra"
+ bundle_config "deployment true"
+ bundle :install, artifice: "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
it "does not refetch if the only unmet dependency is bundler" do
+ build_repo2 do
+ build_gem "bundler_dep" do |s|
+ s.add_dependency "bundler"
+ end
+ end
+
gemfile <<-G
source "#{source_uri}"
gem "bundler_dep"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle! :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
- it "installs the binstubs", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --binstubs", :artifice => "compact_index"
-
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
-
- it "installs the bins when using --path and uses autoclean", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle", :artifice => "compact_index"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
- it "installs the bins when using --path and uses bundle clean", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle --no-clean", :artifice => "compact_index"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
it "prints post_install_messages" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack-obama'
+ gem 'myrack-obama'
G
- bundle! :install, :artifice => "compact_index"
- expect(out).to include("Post-install message from rack:")
+ bundle :install, artifice: "compact_index"
+ expect(out).to include("Post-install message from myrack:")
end
it "should display the post install message for a dependency" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack_middleware'
+ gem 'myrack_middleware'
G
- bundle! :install, :artifice => "compact_index"
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ bundle :install, artifice: "compact_index"
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
context "when using basic authentication" do
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = URI.parse(source_uri)
+ uri = Gem::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -591,114 +528,100 @@ The checksum of /versions does not match the checksum provided by the server! So
it "passes basic authentication details and strips out creds" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
- G
-
- bundle! :install, :artifice => "compact_index_basic_authentication"
- expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "strips http basic authentication creds for modern index" do
- gemfile <<-G
- source "#{basic_auth_source_uri}"
- gem "rack"
- G
-
- bundle! :install, :artifice => "endopint_marshal_fail_basic_authentication"
- expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "strips http basic auth creds when it can't reach the server" do
- gemfile <<-G
- source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_500"
+ bundle :install, artifice: "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
+ it "passes basic authentication details and strips out creds also in verbose mode" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- source "file://#{gem_repo1}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index_basic_authentication"
- expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
+ bundle :install, verbose: true, artifice: "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not pass the user / password to different hosts on redirect" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index_creds_diff_host"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_creds_diff_host"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
describe "with authentication details in bundle config" do
before do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
it "reads authentication details by host name from bundle config" do
- bundle "config #{source_hostname} #{user}:#{password}"
+ bundle "config set #{source_hostname} #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "reads authentication details by full url from bundle config" do
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
- bundle "config #{source_uri}/ #{user}:#{password}"
+ bundle "config set #{source_uri}/ #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the API" do
- bundle "config #{source_hostname} #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle "config set #{source_hostname} #{user}:#{password}"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "prefers auth supplied in the source uri" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle "config #{source_hostname} otheruser:wrong"
+ bundle "config set #{source_hostname} otheruser:wrong"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_strict_basic_authentication"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
- expect(out).to include("bundle config #{source_hostname} username:password")
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false
+ expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
- bundle "config #{source_hostname} #{user}:wrong"
+ bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
- expect(out).to include("Bad username or password")
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false
+ expect(err).to include("Bad username or password")
+ end
+
+ it "does not fallback to old dependency API if bad authentication is provided" do
+ bundle "config set #{source_hostname} #{user}:wrong"
+
+ bundle :install, artifice: "compact_index_strict_basic_authentication", raise_on_error: false, verbose: true
+ expect(err).to include("Bad username or password")
+ expect(out).to include("HTTP 401 Unauthorized http://user@localgemserver.test/versions")
+ expect(out).not_to include("HTTP 401 Unauthorized http://user@localgemserver.test/api/v1/dependencies")
end
end
@@ -708,11 +631,11 @@ The checksum of /versions does not match the checksum provided by the server! So
it "passes basic authentication details" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_basic_authentication"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
@@ -730,14 +653,14 @@ The checksum of /versions does not match the checksum provided by the server! So
end
end
- it "explains what to do to get it" do
+ it "explains what to do to get it, and includes original error" do
gemfile <<-G
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }
- expect(out).to include("OpenSSL")
+ bundle :install, env: { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }, raise_on_error: false, artifice: nil
+ expect(err).to include("recompile Ruby").and include("cannot load such file")
end
end
@@ -746,195 +669,344 @@ The checksum of /versions does not match the checksum provided by the server! So
# Install a monkeypatch that reproduces the effects of openssl raising
# a certificate validation error when RubyGems tries to connect.
gemfile <<-G
- class Net::HTTP
+ class Gem::Net::HTTP
def start
raise OpenSSL::SSL::SSLError, "certificate verify failed"
end
end
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install
- expect(out).to match(/could not verify the SSL certificate/i)
+ bundle :install, raise_on_error: false
+ expect(err).to match(/could not verify the SSL certificate/i)
end
end
context ".gemrc with sources is present" do
- before do
+ it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
- file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
+ file.puts({ sources: ["https://rubygems.org"] }.to_yaml)
end
- end
-
- after do
- home(".gemrc").rmtree
- end
- it "uses other sources declared in the Gemfile" do
- gemfile <<-G
- source "#{source_uri}"
- gem 'rack'
- G
+ begin
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'myrack'
+ G
- bundle! :install, :artifice => "compact_index_forbidden"
+ bundle :install, artifice: "compact_index_forbidden"
+ ensure
+ FileUtils.rm_rf home(".gemrc")
+ end
end
end
- it "performs partial update with a non-empty range" do
+ it "performs update with etag not-modified" do
+ versions_etag = compact_index_cache_path.join(
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions.etag"
+ )
+ expect(versions_etag.file?).to eq(false)
+
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
- # Initial install creates the cached versions file
- bundle! :install, :artifice => "compact_index"
+ # Initial install creates the cached versions file and etag file
+ bundle :install, artifice: "compact_index"
+
+ expect(versions_etag.file?).to eq(true)
+ previous_content = versions_etag.binread
# Update the Gemfile so we can check subsequent install was successful
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
+ G
+
+ # Second install should match etag
+ bundle :install, artifice: "compact_index_etag_match"
+
+ expect(versions_etag.binread).to eq(previous_content)
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "performs full update when range is ignored" do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'myrack', '0.9.1'
+ G
+
+ # Initial install creates the cached versions file and etag file
+ bundle :install, artifice: "compact_index"
+
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'myrack', '1.0.0'
+ G
+
+ versions = compact_index_cache_path.join(
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ # Modify the cached file. The ranged request will be based on this but,
+ # in this test, the range is ignored so this gets overwritten, allowing install.
+ versions.write "ruining this file"
+
+ bundle :install, artifice: "compact_index_range_ignored"
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "performs partial update with a non-empty range" do
+ build_repo4 do
+ build_gem "myrack", "0.9.1"
+ end
+
+ # Initial install creates the cached versions file
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '0.9.1'
G
- # Second install should make only a partial request to /versions
- bundle! :install, :artifice => "compact_index_partial_update"
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_partial_update", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '1.0.0'
+ G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs partial update while local cache is updated by another process" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack'
+ gem 'myrack'
G
- # Create an empty file to trigger a partial download
- versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
- FileUtils.mkdir_p(File.dirname(versions))
- FileUtils.touch(versions)
+ # Create a partial cache versions file
+ versions = compact_index_cache_path.join(
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+ versions.dirname.mkpath
+ versions.write("created_at")
- bundle! :install, :artifice => "compact_index_concurrent_download"
+ bundle :install, artifice: "compact_index_concurrent_download"
- expect(File.read(versions)).to start_with("created_at")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(versions.read).to start_with("created_at")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "performs a partial update that fails digest check, then a full update" do
+ build_repo4 do
+ build_gem "myrack", "0.9.1"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '0.9.1'
+ G
+
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_partial_update_bad_digest", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '1.0.0'
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no digest" do
+ build_repo4 do
+ build_gem "myrack", "0.9.1"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '0.9.1'
+ G
+
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_partial_update_no_digest_not_incremental", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'myrack', '1.0.0'
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs full update of compact index info cache if range is not satisfiable" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
- rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
+ bundle :install, artifice: "compact_index"
- bundle! :install, :artifice => "compact_index"
+ cache_path = compact_index_cache_path.join("localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5")
- expected_rack_info_content = File.read(rake_info_path)
+ # We must remove the etag so that we don't ignore the range and get a 304 Not Modified.
+ myrack_info_etag_path = File.join(cache_path, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073")
+ File.unlink(myrack_info_etag_path) if File.exist?(myrack_info_etag_path)
- # Modify the cache files. We expect them to be reset to the normal ones when we re-run :install
- File.open(rake_info_path, "w") {|f| f << (expected_rack_info_content + "this is different") }
+ myrack_info_path = File.join(cache_path, "info", "myrack")
+ expected_myrack_info_content = File.read(myrack_info_path)
+
+ # Modify the cache files to make the range not satisfiable
+ File.open(myrack_info_path, "a") {|f| f << "0.9.2 |checksum:c55b525b421fd833a93171ad3d7f04528ca8e87d99ac273f8933038942a5888c" }
# Update the Gemfile so the next install does its normal things
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
# The cache files now being longer means the requested range is going to be not satisfiable
# Bundler must end up requesting the whole file to fix things up.
- bundle! :install, :artifice => "compact_index_range_not_satisfiable"
+ bundle :install, artifice: "compact_index_range_not_satisfiable"
- resulting_rack_info_content = File.read(rake_info_path)
+ resulting_myrack_info_content = File.read(myrack_info_path)
- expect(resulting_rack_info_content).to eq(expected_rack_info_content)
+ expect(resulting_myrack_info_content).to eq(expected_myrack_info_content)
end
it "fails gracefully when the source URI has an invalid scheme" do
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
source "htps://rubygems.org"
- gem "rack"
+ gem "myrack"
G
- expect(exitstatus).to eq(15) if exitstatus
- expect(out).to end_with(<<-E.strip)
+ expect(exitstatus).to eq(15)
+ expect(err).to end_with(<<-E.strip)
The request uri `htps://index.rubygems.org/versions` has an invalid scheme (`htps`). Did you mean `http` or `https`?
E
end
- describe "checksum validation", :rubygems => ">= 2.3.0" do
+ describe "checksum validation" do
+ before do
+ lockfile <<-L
+ GEM
+ remote: #{source_uri}
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ #{checksums_section}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "handles checksums from the server in base64" do
+ api_checksum = checksum_digest(gem_repo1, "myrack", "1.0.0")
+ myrack_checksum = [[api_checksum].pack("H*")].pack("m0")
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => myrack_checksum }
+ source "#{source_uri}"
+ gem "myrack"
+ G
+
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
it "raises when the checksum does not match" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum"
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", raise_on_error: false
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- expect(exitstatus).to eq(19) if exitstatus
- expect(out).
- to include("Bundler cannot continue installing rack (1.0.0).").
- and include("The checksum for the downloaded `rack-1.0.0.gem` does not match the checksum given by the server.").
- and include("This means the contents of the downloaded gem is different from what was uploaded to the server, and could be a potential security issue.").
- and include("To resolve this issue:").
- and include("1. delete the downloaded gem located at: `#{default_bundle_path}/gems/rack-1.0.0/rack-1.0.0.gem`").
- and include("2. run `bundle install`").
- and include("If you wish to continue installing the downloaded gem, and are certain it does not pose a security issue despite the mismatching checksum, do the following:").
- and include("1. run `bundle config disable_checksum_validation true` to turn off checksum verification").
- and include("2. run `bundle install`").
- and match(/\(More info: The expected SHA256 checksum was "#{"ab" * 22}", but the checksum for the downloaded gem was ".+?"\.\)/)
+ gem_path = default_cache_path.dirname.join("myrack-1.0.0.gem")
+
+ expect(exitstatus).to eq(37)
+ expect(err).to eq <<~E.strip
+ Bundler found mismatched checksums. This is a potential security risk.
+ myrack (1.0.0) sha256=2222222222222222222222222222222222222222222222222222222222222222
+ from the API at http://localgemserver.test/
+ #{checksum_to_lock(gem_repo1, "myrack", "1.0.0")}
+ from the gem at #{gem_path}
+
+ If you trust the API at http://localgemserver.test/, to resolve this issue you can:
+ 1. remove the gem at #{gem_path}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
end
it "raises when the checksum is the wrong length" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!" }
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, verbose: true, raise_on_error: false
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- expect(exitstatus).to eq(5) if exitstatus
- expect(out).to include("The given checksum for rack-1.0.0 (\"checksum!\") is not a valid SHA256 hexdigest nor base64digest")
+ expect(exitstatus).to eq(14)
+ expect(err).to include('Invalid checksum for myrack-0.9.1: "checksum!" is not a valid SHA256 hex or base64 digest')
end
it "does not raise when disable_checksum_validation is set" do
- bundle! "config disable_checksum_validation true"
- install_gemfile! <<-G, :artifice => "compact_index_wrong_gem_checksum"
+ bundle_config "disable_checksum_validation true"
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum"
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
end
it "works when cache dir is world-writable" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
File.umask(0000)
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
it "doesn't explode when the API dependencies are wrong" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" }
+ install_gemfile <<-G, artifice: "compact_index_wrong_dependencies", env: { "DEBUG" => "true" }, raise_on_error: false
source "#{source_uri}"
gem "rails"
G
- deps = [Gem::Dependency.new("rake", "= 10.0.2"),
+ deps = [Gem::Dependency.new("rake", "= #{rake_version}"),
Gem::Dependency.new("actionpack", "= 2.3.2"),
Gem::Dependency.new("activerecord", "= 2.3.2"),
Gem::Dependency.new("actionmailer", "= 2.3.2"),
Gem::Dependency.new("activeresource", "= 2.3.2")]
- expect(out).to include(<<-E.strip).and include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies")
-Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API or the lockfile (#{deps.map(&:to_s).join(", ")}).
-Either installing with `--full-index` or running `bundle update rails` should fix the problem.
+ expect(out).to include("rails-2.3.2 from rubygems remote at #{source_uri}/ has corrupted API dependencies")
+ expect(err).to include(<<-E.strip)
+Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API (#{deps.map(&:to_s).join(", ")}).
+Running `bundle update rails` should fix the problem.
E
end
it "does not duplicate specs in the lockfile when updating and a dependency is not installed" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
+ source "https://gem.repo1"
source "#{source_uri}" do
gem "rails"
gem "activemerchant"
end
G
- gem_command! :uninstall, "activemerchant"
- bundle! "update rails", :artifice => "compact_index"
- expect(lockfile.scan(/activemerchant \(/).size).to eq(1)
+ uninstall_gem("activemerchant")
+ bundle "update rails", artifice: "compact_index"
+ count = lockfile.match?("CHECKSUMS") ? 2 : 1 # Once in the specs, and once in CHECKSUMS
+ expect(lockfile.scan(/activemerchant \(/).size).to eq(count)
+ end
+
+ it "handles an API that does not provide checksums info (undocumented, support may get removed)" do
+ install_gemfile <<-G, artifice: "compact_index_no_checksums"
+ source "https://gem.repo1"
+ gem "rake"
+ G
end
end
diff --git a/spec/bundler/install/gems/dependency_api_fallback_spec.rb b/spec/bundler/install/gems/dependency_api_fallback_spec.rb
new file mode 100644
index 0000000000..c7b0c537e4
--- /dev/null
+++ b/spec/bundler/install/gems/dependency_api_fallback_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.describe "gemcutter's dependency API" do
+ context "when Gemcutter API takes too long to respond" do
+ before do
+ bundle_config "timeout 1"
+ end
+
+ it "times out and falls back on the modern index" do
+ install_gemfile <<-G, artifice: "endpoint_timeout"
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(out).to include("Fetching source index from https://gem.repo1/")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index 3cb98db1eb..32a1b98b6d 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -7,12 +7,12 @@ RSpec.describe "gemcutter's dependency API" do
it "should use the API" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should URI encode gem names" do
@@ -21,8 +21,8 @@ RSpec.describe "gemcutter's dependency API" do
gem " sinatra"
G
- bundle :install, :artifice => "endpoint"
- expect(out).to include("' sinatra' is not a valid gem name because it contains whitespace.")
+ bundle :install, artifice: "endpoint", raise_on_error: false
+ expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
it "should handle nested dependencies" do
@@ -31,7 +31,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rails"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}/...")
expect(the_bundle).to include_gems(
"rails 2.3.2",
@@ -49,20 +49,21 @@ RSpec.describe "gemcutter's dependency API" do
gem "net-sftp"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
- it "should use the endpoint when using --deployment" do
+ it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "endpoint")
+ bundle_config "deployment true"
+ bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles git dependencies that are in rubygems" do
@@ -73,17 +74,17 @@ RSpec.describe "gemcutter's dependency API" do
gemfile <<-G
source "#{source_uri}"
- git "file:///#{lib_path("foo-1.0")}" do
+ git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "handles git dependencies that are in rubygems using --deployment" do
+ it "handles git dependencies that are in rubygems using deployment mode" do
build_git "foo" do |s|
s.executables = "foobar"
s.add_dependency "rails", "2.3.2"
@@ -91,40 +92,50 @@ RSpec.describe "gemcutter's dependency API" do
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "file:///#{lib_path("foo-1.0")}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint"
- bundle "install --deployment", :artifice => "endpoint"
+ bundle_config "deployment true"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "doesn't fail if you only have a git gem with no deps when using --deployment" do
+ it "doesn't fail if you only have a git gem with no deps when using deployment mode" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "file:///#{lib_path("foo-1.0")}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
- bundle "install", :artifice => "endpoint"
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint")
+ bundle "install", artifice: "endpoint"
+ bundle_config "deployment true"
+ bundle :install, artifice: "endpoint"
expect(the_bundle).to include_gems("foo 1.0")
end
it "falls back when the API errors out" do
- simulate_platform mswin
+ simulate_platform "x86-mswin32" do
+ build_repo2 do
+ # The rcov gem is platform mswin32, but has no arch
+ build_gem "rcov" do |s|
+ s.platform = Gem::Platform.new([nil, "mswin32", nil])
+ s.write "lib/rcov.rb", "RCOV = '1.0.0'"
+ end
+ end
- gemfile <<-G
- source "#{source_uri}"
- gem "rcov"
- G
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "rcov"
+ G
- bundle :install, :artifice => "windows"
- expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rcov 1.0.0"
+ bundle :install, artifice: "windows", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(out).to include("Fetching source index from #{source_uri}")
+ expect(the_bundle).to include_gems "rcov 1.0.0"
+ end
end
it "falls back when hitting the Gemcutter Dependency Limit" do
@@ -135,10 +146,10 @@ RSpec.describe "gemcutter's dependency API" do
gem "actionmailer"
gem "activeresource"
gem "thin"
- gem "rack"
+ gem "myrack"
gem "rails"
G
- bundle :install, :artifice => "endpoint_fallback"
+ bundle :install, artifice: "endpoint_fallback"
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems(
@@ -148,7 +159,7 @@ RSpec.describe "gemcutter's dependency API" do
"activeresource 2.3.2",
"activesupport 2.3.2",
"thin 1.0.0",
- "rack 1.0.0",
+ "myrack 1.0.0",
"rails 2.3.2"
)
end
@@ -156,39 +167,39 @@ RSpec.describe "gemcutter's dependency API" do
it "falls back when Gemcutter API doesn't return proper Marshal format" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :verbose => true, :artifice => "endpoint_marshal_fail"
+ bundle :install, verbose: true, artifice: "endpoint_marshal_fail"
expect(out).to include("could not fetch from the dependency API, trying the full index")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "falls back when the API URL returns 403 Forbidden" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :verbose => true, :artifice => "endpoint_api_forbidden"
+ bundle :install, verbose: true, artifice: "endpoint_api_forbidden"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_host_redirect"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "endpoint_host_redirect"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "handles host redirects without Net::HTTP::Persistent" do
+ it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
FileUtils.mkdir_p lib_path
@@ -204,69 +215,51 @@ RSpec.describe "gemcutter's dependency API" do
H
end
- bundle :install, :artifice => "endpoint_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
+ bundle :install, artifice: "endpoint_host_redirect", requires: [lib_path("disable_net_http_persistent.rb")]
expect(out).to_not match(/Too many redirects/)
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "timeouts when Bundler::Fetcher redirects too much" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_redirect"
- expect(out).to match(/Too many redirects/)
+ bundle :install, artifice: "endpoint_redirect", raise_on_error: false
+ expect(err).to match(/Too many redirects/)
end
context "when --full-index is specified" do
it "should use the modern index for install" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle "install --full-index", :artifice => "endpoint"
+ bundle "install --full-index", artifice: "endpoint"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the modern index for update" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle! "update --full-index", :artifice => "endpoint", :all => bundle_update_requires_all?
+ bundle "update --full-index", artifice: "endpoint", all: true
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-
- it "fetches again when more dependencies are found in subsequent sources", :bundler => "< 3" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- bundle :install, :artifice => "endpoint_extra"
- expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using blocks" do
+ it "fetches again when more dependencies are found in subsequent sources" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -276,61 +269,39 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
it "fetches gem versions even when those gems are already installed" do
gemfile <<-G
source "#{source_uri}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- bundle :install, :artifice => "endpoint_extra_api"
+ bundle :install, artifice: "endpoint_extra_api"
build_repo4 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
gemfile <<-G
source "#{source_uri}" do; end
source "#{source_uri}/extra"
- gem "rack", "1.2"
+ gem "myrack", "1.2"
G
- bundle :install, :artifice => "endpoint_extra_api"
- expect(the_bundle).to include_gems "rack 1.2"
+ bundle :install, artifice: "endpoint_extra_api"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources", :bundler => "< 3" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
- build_repo4 do
- build_gem "activesupport", "1.2.0"
- build_gem "somegem", "1.0.0" do |s|
- s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1
- end
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem 'somegem', '1.0.0'
- G
-
- bundle! :install, :artifice => "endpoint_extra_api"
-
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
- end
-
- it "considers all possible versions of dependencies from all api gem sources using blocks" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
+ it "resolves indirect dependencies to the most scoped source that includes them" do
+ # In this scenario, the gem "somegem" only exists in repo4. It depends on
+ # specific version of activesupport that exists only in repo1. There
+ # happens also be a version of activesupport in repo4, but not the one that
+ # version 1.0.0 of somegem wants. This test makes sure that bundler tries to
+ # use the version in the most scoped source, even if not compatible, and
+ # gives a resolution error
build_repo4 do
build_gem "activesupport", "1.2.0"
build_gem "somegem", "1.0.0" do |s|
@@ -345,10 +316,9 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra_api"
+ bundle :install, artifice: "compact_index_extra_api", raise_on_error: false
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
+ expect(err).to include("Could not find compatible versions")
end
it "prints API output properly with back deps" do
@@ -356,7 +326,7 @@ RSpec.describe "gemcutter's dependency API" do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -366,48 +336,38 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra"
+ bundle :install, artifice: "endpoint_extra"
expect(out).to include("Fetching gem metadata from http://localgemserver.test/.")
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps", :bundler => "< 3" do
+ it "does not fetch every spec when doing back deps" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ install_gemfile <<-G, artifice: "endpoint_extra_missing"
source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
+ source "#{source_uri}/extra" do
+ gem "back_deps"
+ end
G
- bundle :install, :artifice => "endpoint_extra_missing"
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps using blocks" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
-
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -417,145 +377,71 @@ RSpec.describe "gemcutter's dependency API" do
end
G
- bundle :install, :artifice => "endpoint_extra_missing"
+ bundle :install, artifice: "endpoint_extra"
+ bundle_config "deployment true"
+ bundle "install", artifice: "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "uses the endpoint if all sources support it" do
- gemfile <<-G
- source "#{source_uri}"
-
- gem 'foo'
- G
-
- bundle :install, :artifice => "endpoint_api_missing"
- expect(the_bundle).to include_gems "foo 1.0"
- end
-
- it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do
+ it "does not fetch all marshaled specs" do
build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ build_gem "foo", "1.0"
+ build_gem "foo", "2.0"
end
- gemfile <<-G
+ install_gemfile <<-G, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, verbose: true
source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
- bundle :install, :artifice => "endpoint_extra"
+ gem "foo"
+ G
- bundle "install --deployment", :artifice => "endpoint_extra"
- expect(the_bundle).to include_gems "back_deps 1.0"
+ expect(out).to include("foo-2.0.gemspec.rz")
+ expect(out).not_to include("foo-1.0.gemspec.rz")
end
- it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do
+ it "does not refetch if the only unmet dependency is bundler" do
build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
+ build_gem "bundler_dep" do |s|
+ s.add_dependency "bundler"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
source "#{source_uri}"
- source "#{source_uri}/extra" do
- gem "back_deps"
- end
- G
-
- bundle :install, :artifice => "endpoint_extra"
-
- bundle "install --deployment", :artifice => "endpoint_extra"
- expect(the_bundle).to include_gems "back_deps 1.0"
- end
-
- it "does not refetch if the only unmet dependency is bundler" do
- gemfile <<-G
- source "#{source_uri}"
gem "bundler_dep"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "endpoint"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
- it "installs the binstubs", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --binstubs", :artifice => "endpoint"
-
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
-
- it "installs the bins when using --path and uses autoclean", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle", :artifice => "endpoint"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
- it "installs the bins when using --path and uses bundle clean", :bundler => "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle --no-clean", :artifice => "endpoint"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
it "prints post_install_messages" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack-obama'
+ gem 'myrack-obama'
G
- bundle :install, :artifice => "endpoint"
- expect(out).to include("Post-install message from rack:")
+ bundle :install, artifice: "endpoint"
+ expect(out).to include("Post-install message from myrack:")
end
it "should display the post install message for a dependency" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack_middleware'
+ gem 'myrack_middleware'
G
- bundle :install, :artifice => "endpoint"
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ bundle :install, artifice: "endpoint"
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
context "when using basic authentication" do
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = URI.parse(source_uri)
+ uri = Gem::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -565,114 +451,128 @@ RSpec.describe "gemcutter's dependency API" do
it "passes basic authentication details and strips out creds" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
+ bundle :install, artifice: "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "strips http basic authentication creds for modern index" do
+ it "passes basic authentication details and strips out creds also in verbose mode" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endopint_marshal_fail_basic_authentication"
+ bundle :install, verbose: true, artifice: "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "strips http basic auth creds when it can't reach the server" do
+ it "strips http basic authentication creds for modern index" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_500"
+ bundle :install, artifice: "endpoint_marshal_fail_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
+ it "strips http basic auth creds when it can't reach the server" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- source "file://#{gem_repo1}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
- expect(out).to include("Warning: the gem 'rack' was found in multiple sources.")
+ bundle :install, artifice: "endpoint_500", raise_on_error: false
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
end
it "does not pass the user / password to different hosts on redirect" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_creds_diff_host"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "endpoint_creds_diff_host"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ describe "with host including dashes" do
+ before do
+ gemfile <<-G
+ source "http://local-gemserver.test"
+ gem "myrack"
+ G
+ end
+
+ it "reads authentication details from a valid ENV variable" do
+ bundle :install, artifice: "endpoint_strict_basic_authentication", env: { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" }
+
+ expect(out).to include("Fetching gem metadata from http://local-gemserver.test")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
end
describe "with authentication details in bundle config" do
before do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
it "reads authentication details by host name from bundle config" do
- bundle "config #{source_hostname} #{user}:#{password}"
+ bundle "config set #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "reads authentication details by full url from bundle config" do
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
- bundle "config #{source_uri}/ #{user}:#{password}"
+ bundle "config set #{source_uri}/ #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the API" do
- bundle "config #{source_hostname} #{user}:#{password}"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle "config set #{source_hostname} #{user}:#{password}"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "prefers auth supplied in the source uri" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle "config #{source_hostname} otheruser:wrong"
+ bundle "config set #{source_hostname} otheruser:wrong"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "endpoint_strict_basic_authentication"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
- expect(out).to include("bundle config #{source_hostname} username:password")
+ bundle :install, artifice: "endpoint_strict_basic_authentication", raise_on_error: false
+ expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
- bundle "config #{source_hostname} #{user}:wrong"
+ bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
- expect(out).to include("Bad username or password")
+ bundle :install, artifice: "endpoint_strict_basic_authentication", raise_on_error: false
+ expect(err).to include("Bad username or password")
end
end
@@ -682,11 +582,11 @@ RSpec.describe "gemcutter's dependency API" do
it "passes basic authentication details" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :artifice => "endpoint_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install, artifice: "endpoint_basic_authentication"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
@@ -704,14 +604,14 @@ RSpec.describe "gemcutter's dependency API" do
end
end
- it "explains what to do to get it" do
+ it "explains what to do to get it, and includes original error" do
gemfile <<-G
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }
- expect(out).to include("OpenSSL")
+ bundle :install, artifice: "fail", env: { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }, raise_on_error: false
+ expect(err).to include("recompile Ruby").and include("cannot load such file")
end
end
@@ -720,41 +620,37 @@ RSpec.describe "gemcutter's dependency API" do
# Install a monkeypatch that reproduces the effects of openssl raising
# a certificate validation error when RubyGems tries to connect.
gemfile <<-G
- class Net::HTTP
+ class Gem::Net::HTTP
def start
raise OpenSSL::SSL::SSLError, "certificate verify failed"
end
end
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install
- expect(out).to match(/could not verify the SSL certificate/i)
+ bundle :install, raise_on_error: false
+ expect(err).to match(/could not verify the SSL certificate/i)
end
end
context ".gemrc with sources is present" do
- before do
+ it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
- file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
+ file.puts({ sources: ["https://rubygems.org"] }.to_yaml)
end
- end
-
- after do
- home(".gemrc").rmtree
- end
-
- it "uses other sources declared in the Gemfile" do
- gemfile <<-G
- source "#{source_uri}"
- gem 'rack'
- G
- bundle "install", :artifice => "endpoint_marshal_fail"
+ begin
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'myrack'
+ G
- expect(exitstatus).to eq(0) if exitstatus
+ bundle "install", artifice: "endpoint_marshal_fail"
+ ensure
+ FileUtils.rm_rf home(".gemrc")
+ end
end
end
end
diff --git a/spec/bundler/install/gems/env_spec.rb b/spec/bundler/install/gems/env_spec.rb
index 0dccbbfd24..6d5aa456fe 100644
--- a/spec/bundler/install/gems/env_spec.rb
+++ b/spec/bundler/install/gems/env_spec.rb
@@ -4,104 +4,104 @@ RSpec.describe "bundle install with ENV conditionals" do
describe "when just setting an ENV key as a string" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when just setting an ENV key as a symbol" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
env :BUNDLER_TEST do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when setting a string to match the env" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" => "foo" do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "excludes the gems when the ENV variable is set but does not match the condition" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set and matches the condition" do
ENV["BUNDLER_TEST"] = "foo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when setting a regex to match the env" do
before :each do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" => /foo/ do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "excludes the gems when the ENV variable is set but does not match the condition" do
ENV["BUNDLER_TEST"] = "fo"
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set and matches the condition" do
ENV["BUNDLER_TEST"] = "foobar"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index 736f418ec7..a30b53d6ad 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -3,30 +3,30 @@
RSpec.describe "bundle flex_install" do
it "installs the gems as expected" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
end
it "installs even when the lockfile is invalid" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack', '1.0'
+ source "https://gem.repo1"
+ gem 'myrack', '1.0'
G
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
end
@@ -34,19 +34,19 @@ RSpec.describe "bundle flex_install" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0"
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack-obama", "1.0"
+ source "https://gem.repo2"
+ gem "myrack-obama", "1.0"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0"
end
describe "adding new gems" do
@@ -54,38 +54,38 @@ RSpec.describe "bundle flex_install" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
it "keeps child dependencies pinned" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
G
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
gem "thin"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0", "thin 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0", "thin 1.0"
end
end
@@ -93,43 +93,43 @@ RSpec.describe "bundle flex_install" do
it "removes gems without changing the versions of remaining gems" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.2'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.2"
end
it "removes top level dependencies when removed from the Gemfile while leaving other dependencies intact" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
@@ -138,174 +138,227 @@ RSpec.describe "bundle flex_install" do
it "removes child dependencies" do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem 'rack-obama'
+ source "https://gem.repo2"
+ gem 'myrack-obama'
gem 'activesupport'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0", "activesupport 2.3.5"
update_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem 'activesupport'
G
expect(the_bundle).to include_gems "activesupport 2.3.5"
- expect(the_bundle).not_to include_gems "rack-obama", "rack"
+ expect(the_bundle).not_to include_gems "myrack-obama", "myrack"
end
end
- describe "when Gemfile conflicts with lockfile" do
+ describe "when running bundle install and Gemfile conflicts with lockfile" do
before(:each) do
build_repo2
install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack_middleware"
+ source "https://gem.repo2"
+ gem "myrack_middleware"
G
- expect(the_bundle).to include_gems "rack_middleware 1.0", "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack_middleware 1.0", "myrack 0.9.1"
- build_repo2
- update_repo2 do
- build_gem "rack-obama", "2.0" do |s|
- s.add_dependency "rack", "=1.2"
+ build_repo2 do
+ build_gem "myrack-obama", "2.0" do |s|
+ s.add_dependency "myrack", "=1.2"
end
- build_gem "rack_middleware", "2.0" do |s|
- s.add_dependency "rack", ">=1.0"
+ build_gem "myrack_middleware", "2.0" do |s|
+ s.add_dependency "myrack", ">=1.0"
end
end
gemfile <<-G
- source "file://#{gem_repo2}"
- gem "rack-obama", "2.0"
- gem "rack_middleware"
+ source "https://gem.repo2"
+ gem "myrack-obama", "2.0"
+ gem "myrack_middleware"
G
end
it "does not install gems whose dependencies are not met" do
- bundle :install
- ruby <<-RUBY
+ bundle :install, raise_on_error: false
+ ruby <<-RUBY, raise_on_error: false
require 'bundler/setup'
RUBY
- expect(err).to match(/could not find gem 'rack-obama/i)
+ expect(err).to match(/could not find gem 'myrack-obama/i)
end
- it "suggests bundle update when the Gemfile requires different versions than the lock" do
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "rack":
- In snapshot (Gemfile.lock):
- rack (= 0.9.1)
+ it "discards the locked gems when the Gemfile requires different versions than the lock" do
+ bundle_config "force_ruby_platform true"
- In Gemfile:
- rack-obama (= 2.0) was resolved to 2.0, which depends on
- rack (= 1.2)
+ nice_error = <<~E.strip
+ Could not find compatible versions
+
+ Because myrack-obama >= 2.0 depends on myrack = 1.2
+ and myrack = 1.2 could not be found in rubygems repository https://gem.repo2/ or installed locally,
+ myrack-obama >= 2.0 cannot be used.
+ So, because Gemfile depends on myrack-obama = 2.0,
+ version solving has failed.
+ E
- rack_middleware was resolved to 1.0, which depends on
- rack (= 0.9.1)
+ bundle :install, retry: 0, raise_on_error: false
+ expect(err).to end_with(nice_error)
+ end
+
+ it "does not include conflicts with a single requirement tree, because that can't possibly be a conflict" do
+ bundle_config "force_ruby_platform true"
- Running `bundle update` will rebuild your snapshot from scratch, using only
- the gems in your Gemfile, which may resolve the conflict.
+ bad_error = <<~E.strip
+ Bundler could not find compatible versions for gem "myrack-obama":
+ In Gemfile:
+ myrack-obama (= 2.0)
E
- bundle :install, :retry => 0
- expect(last_command.bundler_err).to end_with(nice_error)
+ bundle "update myrack_middleware", retry: 0, raise_on_error: false
+ expect(err).not_to end_with(bad_error)
end
end
- describe "subtler cases" do
- before :each do
+ describe "when running bundle update and Gemfile conflicts with lockfile" do
+ before(:each) do
+ build_repo4 do
+ build_gem "jekyll-feed", "0.16.0"
+ build_gem "jekyll-feed", "0.15.1"
+
+ build_gem "github-pages", "226" do |s|
+ s.add_dependency "jekyll-feed", "0.15.1"
+ end
+ end
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo4"
+ gem "jekyll-feed", "~> 0.12"
G
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
- gem "rack-obama"
+ source "https://gem.repo4"
+ gem "github-pages", "~> 226"
+ gem "jekyll-feed", "~> 0.12"
G
end
- it "does something" do
- expect do
- bundle "install"
- end.not_to change { File.read(bundled_app("Gemfile.lock")) }
-
- expect(out).to include("rack = 0.9.1")
- expect(out).to include("locked at 1.0.0")
- expect(out).to include("bundle update rack")
- end
-
- it "should work when you update" do
- bundle "update rack"
+ it "discards the conflicting lockfile information and resolves properly" do
+ bundle :update, raise_on_error: false, all: true
+ expect(err).to be_empty
end
end
- describe "when adding a new source" do
- it "updates the lockfile", :bundler => "< 3" do
- build_repo2
- install_gemfile! <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
+ describe "subtler cases" do
+ before :each do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
- install_gemfile! <<-G
- source "file://localhost#{gem_repo1}"
- source "file://localhost#{gem_repo2}"
- gem "rack"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "myrack-obama"
G
+ end
+
+ it "should work when you install" do
+ bundle "install"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ c.checksum gem_repo1, "myrack-obama", "1.0"
+ end
- lockfile_should_be <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- remote: file://localhost#{gem_repo2}/
- specs:
- rack (1.0.0)
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack (= 0.9.1)
+ myrack-obama
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- PLATFORMS
- ruby
+ it "should work when you update" do
+ bundle "update myrack"
- DEPENDENCIES
- rack
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ c.checksum gem_repo1, "myrack-obama", "1.0"
+ end
- BUNDLED WITH
- #{Bundler::VERSION}
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack (= 0.9.1)
+ myrack-obama
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
+ end
- it "updates the lockfile", :bundler => "3" do
+ describe "when adding a new source" do
+ it "updates the lockfile" do
build_repo2
- install_gemfile! <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- install_gemfile! <<-G
- source "file://localhost#{gem_repo1}"
- source "file://localhost#{gem_repo2}" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ source "https://gem.repo2" do
end
- gem "rack"
+ gem "myrack"
G
- lockfile_should_be <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
- PLATFORMS
- #{lockfile_platforms}
+ GEM
+ remote: https://gem.repo2/
+ specs:
- DEPENDENCIES
- rack
+ PLATFORMS
+ #{lockfile_platforms}
- BUNDLED WITH
- #{Bundler::VERSION}
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
@@ -315,37 +368,36 @@ RSpec.describe "bundle flex_install" do
before(:each) do
build_repo2 do
build_gem "capybara", "0.3.9" do |s|
- s.add_dependency "rack", ">= 1.0.0"
+ s.add_dependency "myrack", ">= 1.0.0"
end
- build_gem "rack", "1.1.0"
+ build_gem "myrack", "1.1.0"
build_gem "rails", "3.0.0.rc4" do |s|
- s.add_dependency "rack", "~> 1.1.0"
+ s.add_dependency "myrack", "~> 1.1.0"
end
- build_gem "rack", "1.2.1"
+ build_gem "myrack", "1.2.1"
build_gem "rails", "3.0.0" do |s|
- s.add_dependency "rack", "~> 1.2.1"
+ s.add_dependency "myrack", "~> 1.2.1"
end
end
end
- it "prints the correct error message" do
+ it "resolves them" do
# install Rails 3.0.0.rc
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails", "3.0.0.rc4"
gem "capybara", "0.3.9"
G
# upgrade Rails to 3.0.0 and then install again
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
G
-
- expect(out).to include("Gemfile.lock")
+ expect(err).to be_empty
end
end
end
diff --git a/spec/bundler/install/gems/fund_spec.rb b/spec/bundler/install/gems/fund_spec.rb
new file mode 100644
index 0000000000..8a3a51270a
--- /dev/null
+++ b/spec/bundler/install/gems/fund_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install" do
+ context "with gem sources" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+
+ build_gem "gem_with_dependent_funding", "1.0" do |s|
+ s.add_dependency "has_funding"
+ end
+ end
+ end
+
+ context "when gems include a fund URI" do
+ it "displays the plural fund message after installing" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ expect(out).to include("2 installed gems you directly depend on are looking for funding.")
+ end
+
+ it "displays the singular fund message after installing" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+
+ context "when gems include a fund URI but `ignore_funding_requests` is configured" do
+ before do
+ bundle_config "ignore_funding_requests true"
+ end
+
+ it "does not display the plural fund message after installing" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ expect(out).not_to include("2 installed gems you directly depend on are looking for funding.")
+ end
+
+ it "does not display the singular fund message after installing" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ expect(out).not_to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+
+ context "when gems do not include fund messages" do
+ it "does not display any fund messages" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport"
+ G
+
+ expect(out).not_to include("gem you depend on")
+ end
+ end
+
+ context "when a dependency includes a fund message" do
+ it "does not display the fund message" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem 'gem_with_dependent_funding'
+ G
+
+ expect(out).not_to include("gem you depend on")
+ end
+ end
+ end
+
+ context "with git sources" do
+ context "when gems include fund URI" do
+ it "displays the fund message after installing" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+
+ it "displays the fund message if repo is updated" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ build_git "also_has_funding", "1.1" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.1")}'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+
+ it "displays the fund message if repo is not updated" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ bundle :install
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+
+ bundle :install
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/gemfile_source_header_spec.rb b/spec/bundler/install/gems/gemfile_source_header_spec.rb
new file mode 100644
index 0000000000..dc35c8d741
--- /dev/null
+++ b/spec/bundler/install/gems/gemfile_source_header_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.describe "fetching dependencies with a mirrored source" do
+ let(:mirror) { "https://server.example.org" }
+
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "#{mirror}"
+ gem 'weakling'
+ G
+
+ bundle_config "mirror.#{mirror} https://gem.repo2"
+ end
+
+ it "sets the 'X-Gemfile-Source' and 'User-Agent' headers and bundles successfully" do
+ bundle :install, artifice: "endpoint_mirror_source"
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+end
diff --git a/spec/bundler/install/gems/mirror_probe_spec.rb b/spec/bundler/install/gems/mirror_probe_spec.rb
new file mode 100644
index 0000000000..564062ccf6
--- /dev/null
+++ b/spec/bundler/install/gems/mirror_probe_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+RSpec.describe "fetching dependencies with a not available mirror" do
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'weakling'
+ G
+ end
+
+ context "with a specific fallback timeout" do
+ before do
+ bundle_config_global("BUNDLE_MIRROR__HTTPS://GEM__REPO2/__FALLBACK_TIMEOUT/" => "true",
+ "BUNDLE_MIRROR__HTTPS://GEM__REPO2/" => "https://gem.mirror")
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ bundle :install, env: { "BUNDLER_SPEC_FAKE_RESOLVE" => "gem.mirror" }, verbose: true
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a global fallback timeout" do
+ before do
+ bundle_config_global("BUNDLE_MIRROR__ALL__FALLBACK_TIMEOUT/" => "1",
+ "BUNDLE_MIRROR__ALL" => "https://gem.mirror")
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ bundle :install, env: { "BUNDLER_SPEC_FAKE_RESOLVE" => "gem.mirror" }
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a specific mirror without a fallback timeout" do
+ before do
+ bundle_config_global("BUNDLE_MIRROR__HTTPS://GEM__REPO2/" => "https://gem.mirror")
+ end
+
+ it "fails to install the gem with a timeout error when the mirror is not responding" do
+ bundle :install, artifice: "compact_index_mirror_down", raise_on_error: false
+
+ expect(out).to be_empty
+ expect(err).to eq("Could not reach host gem.mirror. Check your network connection and try again.")
+ end
+ end
+
+ context "with a global mirror without a fallback timeout" do
+ before do
+ bundle_config_global("BUNDLE_MIRROR__ALL" => "https://gem.mirror")
+ end
+
+ it "fails to install the gem with a timeout error when the mirror is not responding" do
+ bundle :install, artifice: "compact_index_mirror_down", raise_on_error: false
+
+ expect(out).to be_empty
+ expect(err).to eq("Could not reach host gem.mirror. Check your network connection and try again.")
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/mirror_spec.rb b/spec/bundler/install/gems/mirror_spec.rb
index 4c35b8f206..e1fbeac454 100644
--- a/spec/bundler/install/gems/mirror_spec.rb
+++ b/spec/bundler/install/gems/mirror_spec.rb
@@ -4,17 +4,17 @@ RSpec.describe "bundle install with a mirror configured" do
describe "when the mirror does not match the gem source" do
before :each do
gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- bundle "config --local mirror.http://gems.example.org http://gem-mirror.example.org"
+ bundle_config "mirror.http://gems.example.org http://gem-mirror.example.org"
end
it "installs from the normal location" do
bundle :install
- expect(out).to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo1}"))
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(out).to include("Fetching gem metadata from https://gem.repo1")
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -22,18 +22,18 @@ RSpec.describe "bundle install with a mirror configured" do
before :each do
gemfile <<-G
# This source is bogus and doesn't have the gem we're looking for
- source "file://localhost#{gem_repo2}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
- bundle "config --local mirror.file://localhost#{gem_repo2} file://localhost#{gem_repo1}"
+ bundle_config "mirror.https://gem.repo2 https://gem.repo1"
end
it "installs the gem from the mirror" do
- bundle :install
- expect(out).to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo1}"))
- expect(out).not_to include(normalize_uri_file("Fetching source index from file://localhost#{gem_repo2}"))
- expect(the_bundle).to include_gems "rack 1.0"
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ expect(out).to include("Fetching gem metadata from https://gem.repo1")
+ expect(out).not_to include("Fetching gem metadata from https://gem.repo2")
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/gems/native_extensions_spec.rb b/spec/bundler/install/gems/native_extensions_spec.rb
index ea616f60d3..d5b10d2c8f 100644
--- a/spec/bundler/install/gems/native_extensions_spec.rb
+++ b/spec/bundler/install/gems/native_extensions_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "installing a gem with native extensions", :ruby_repo do
+RSpec.describe "installing a gem with native extensions" do
it "installs" do
build_repo2 do
build_gem "c_extension" do |s|
@@ -9,7 +9,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
require "mkmf"
name = "c_extension_bundle"
dir_config(name)
- raise "OMG" unless with_config("c_extension") == "hello"
+ raise ArgumentError unless with_config("c_extension") == "hello"
create_makefile(name)
E
@@ -33,14 +33,13 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
end
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "c_extension"
G
- bundle "config build.c_extension --with-c_extension=hello"
+ bundle_config "build.c_extension --with-c_extension=hello"
bundle "install"
- expect(out).not_to include("extconf.rb failed")
expect(out).to include("Installing c_extension 1.0 with native extensions")
run "Bundler.require; puts CExtension.new.its_true"
@@ -54,7 +53,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
require "mkmf"
name = "c_extension_bundle"
dir_config(name)
- raise "OMG" unless with_config("c_extension") == "hello"
+ raise ArgumentError unless with_config("c_extension") == "hello"
create_makefile(name)
E
@@ -76,15 +75,110 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
C
end
- bundle! "config build.c_extension --with-c_extension=hello"
+ bundle_config "build.c_extension --with-c_extension=hello"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
G
- expect(out).not_to include("extconf.rb failed")
+ expect(err).to_not include("warning: conflicting chdir during another chdir block")
- run! "Bundler.require; puts CExtension.new.its_true"
+ run "Bundler.require; puts CExtension.new.its_true"
+ expect(out).to eq("true")
+ end
+
+ it "installs correctly from git when multiple gems with extensions share one repository" do
+ build_repo2 do
+ ["one", "two"].each do |n|
+ build_lib "c_extension_#{n}", "1.0", path: lib_path("gems/c_extension_#{n}") do |s|
+ s.extensions = ["ext/extconf.rb"]
+ s.write "ext/extconf.rb", <<-E
+ require "mkmf"
+ name = "c_extension_bundle_#{n}"
+ dir_config(name)
+ raise ArgumentError unless with_config("c_extension_#{n}") == "#{n}"
+ create_makefile(name)
+ E
+
+ s.write "ext/c_extension_#{n}.c", <<-C
+ #include "ruby.h"
+
+ VALUE c_extension_#{n}_value(VALUE self) {
+ return rb_str_new_cstr("#{n}");
+ }
+
+ void Init_c_extension_bundle_#{n}() {
+ VALUE c_Extension = rb_define_class("CExtension_#{n}", rb_cObject);
+ rb_define_method(c_Extension, "value", c_extension_#{n}_value, 0);
+ }
+ C
+
+ s.write "lib/c_extension_#{n}.rb", <<-C
+ require "c_extension_bundle_#{n}"
+ C
+ end
+ end
+ build_git "gems", path: lib_path("gems"), gemspec: false
+ end
+
+ bundle_config "build.c_extension_one --with-c_extension_one=one"
+ bundle_config "build.c_extension_two --with-c_extension_two=two"
+
+ # 1st time, require only one gem -- only one of the extensions gets built.
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "c_extension_one", :git => #{lib_path("gems").to_s.dump}
+ G
+
+ # 2nd time, require both gems -- we need both extensions to be built now.
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "c_extension_one", :git => #{lib_path("gems").to_s.dump}
+ gem "c_extension_two", :git => #{lib_path("gems").to_s.dump}
+ G
+
+ run "Bundler.require; puts CExtension_one.new.value; puts CExtension_two.new.value"
+ expect(out).to eq("one\ntwo")
+ end
+
+ it "install with multiple build flags" do
+ build_git "c_extension" do |s|
+ s.extensions = ["ext/extconf.rb"]
+ s.write "ext/extconf.rb", <<-E
+ require "mkmf"
+ name = "c_extension_bundle"
+ dir_config(name)
+ raise ArgumentError unless with_config("c_extension") == "hello" && with_config("c_extension_bundle-dir") == "hola"
+ create_makefile(name)
+ E
+
+ s.write "ext/c_extension.c", <<-C
+ #include "ruby.h"
+
+ VALUE c_extension_true(VALUE self) {
+ return Qtrue;
+ }
+
+ void Init_c_extension_bundle() {
+ VALUE c_Extension = rb_define_class("CExtension", rb_cObject);
+ rb_define_method(c_Extension, "its_true", c_extension_true, 0);
+ }
+ C
+
+ s.write "lib/c_extension.rb", <<-C
+ require "c_extension_bundle"
+ C
+ end
+
+ bundle_config "build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
+ G
+
+ run "Bundler.require; puts CExtension.new.its_true"
expect(out).to eq("true")
end
end
diff --git a/spec/bundler/install/gems/no_build_extension_spec.rb b/spec/bundler/install/gems/no_build_extension_spec.rb
new file mode 100644
index 0000000000..31f0170433
--- /dev/null
+++ b/spec/bundler/install/gems/no_build_extension_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with --no-build-extension" do
+ before do
+ build_repo2 do
+ build_gem "with_extension" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/with_extension.rb", "w") do |f|
+ f.puts "WITH_EXTENSION = 'YES'"
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ it "skips building native extensions and warns when no_build_extension is set" do
+ bundle_config "no_build_extension true"
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_extension"
+ gem "rake"
+ G
+
+ bundle :install
+
+ build_complete = default_bundle_path("extensions").join(
+ Gem::Platform.local.to_s,
+ Gem.extension_api_version.to_s,
+ "with_extension-1.0",
+ "gem.build_complete"
+ )
+ expect(build_complete).not_to exist
+ expect(err).to include("with_extension-1.0 contains native extensions that were not built")
+ expect(err).to include("unset no_build_extension and run `bundle pristine with_extension`")
+ end
+
+ it "builds native extensions by default" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_extension"
+ gem "rake"
+ G
+
+ bundle :install
+
+ expect(out).to include("Installing with_extension 1.0 with native extensions")
+ end
+end
diff --git a/spec/bundler/install/gems/no_install_plugin_spec.rb b/spec/bundler/install/gems/no_install_plugin_spec.rb
new file mode 100644
index 0000000000..e040e6b813
--- /dev/null
+++ b/spec/bundler/install/gems/no_install_plugin_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with --no-install-plugin" do
+ before do
+ build_repo2 do
+ build_gem "with_plugin", "1.0" do |s|
+ s.write "lib/rubygems_plugin.rb", "# plugin code"
+ end
+
+ build_gem "with_plugin", "2.0"
+ end
+ end
+
+ let(:plugin_path) { default_bundle_path("plugins", "with_plugin_plugin.rb") }
+
+ it "does not generate the plugin wrapper and warns when no_install_plugin is set" do
+ bundle_config "no_install_plugin true"
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_plugin", "1.0"
+ G
+
+ expect(plugin_path).not_to exist
+ expect(err).to include("with_plugin-1.0 contains plugins that were not installed")
+ expect(err).to include("unset no_install_plugin and run `bundle pristine with_plugin`")
+ end
+
+ it "removes a stale plugin wrapper from a prior version when no_install_plugin is set" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_plugin", "1.0"
+ G
+ expect(plugin_path).to exist
+
+ bundle_config "no_install_plugin true"
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_plugin", "2.0"
+ G
+
+ expect(plugin_path).not_to exist
+ end
+
+ it "generates the plugin wrapper by default" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_plugin", "1.0"
+ G
+
+ expect(plugin_path).to exist
+ end
+end
diff --git a/spec/bundler/install/gems/post_install_spec.rb b/spec/bundler/install/gems/post_install_spec.rb
index c6e348fb65..e49fd2a9a3 100644
--- a/spec/bundler/install/gems/post_install_spec.rb
+++ b/spec/bundler/install/gems/post_install_spec.rb
@@ -5,26 +5,26 @@ RSpec.describe "bundle install" do
context "when gems include post install messages" do
it "should display the post-install messages after installing" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gem 'thin'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
expect(out).to include("Post-install message from thin:")
expect(out).to include("Thin's post install message")
- expect(out).to include("Post-install message from rack-obama:")
- expect(out).to include("Rack-obama's post install message")
+ expect(out).to include("Post-install message from myrack-obama:")
+ expect(out).to include("Myrack-obama's post install message")
end
end
context "when gems do not include post install messages" do
it "should not display any post-install messages" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport"
G
@@ -33,16 +33,16 @@ RSpec.describe "bundle install" do
end
end
- context "when a dependecy includes a post install message" do
+ context "when a dependency includes a post install message" do
it "should display the post install message" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack_middleware'
+ source "https://gem.repo1"
+ gem 'myrack_middleware'
G
bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
end
end
@@ -54,7 +54,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -68,7 +68,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
bundle :install
@@ -77,7 +77,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's 1.1 post install message"
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.1")}'
G
bundle :install
@@ -91,7 +91,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -110,7 +110,7 @@ RSpec.describe "bundle install" do
s.post_install_message = nil
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -123,11 +123,11 @@ RSpec.describe "bundle install" do
context "when ignore post-install messages for gem is set" do
it "doesn't display any post-install messages" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "config ignore_messages.rack true"
+ bundle_config "ignore_messages.myrack true"
bundle :install
expect(out).not_to include("Post-install message")
@@ -137,11 +137,11 @@ RSpec.describe "bundle install" do
context "when ignore post-install messages for all gems" do
it "doesn't display any post-install messages" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "config ignore_messages true"
+ bundle_config "ignore_messages true"
bundle :install
expect(out).not_to include("Post-install message")
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 01c03ac793..111d361aab 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -1,9 +1,72 @@
# frozen_string_literal: true
RSpec.describe "bundle install with install-time dependencies" do
- it "installs gems with implicit rake dependencies", :ruby_repo do
+ before do
+ build_repo2 do
+ build_gem "with_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
+ f.puts "IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ build_gem "another_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
+ f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ # Test complicated gem dependencies for install
+ build_gem "net_a" do |s|
+ s.add_dependency "net_b"
+ s.add_dependency "net_build_extensions"
+ end
+
+ build_gem "net_b"
+
+ build_gem "net_build_extensions" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/net_build_extensions.rb", "w") do |f|
+ f.puts "NET_BUILD_EXTENSIONS = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ build_gem "net_c" do |s|
+ s.add_dependency "net_a"
+ s.add_dependency "net_d"
+ end
+
+ build_gem "net_d"
+
+ build_gem "net_e" do |s|
+ s.add_dependency "net_d"
+ end
+ end
+ end
+
+ it "installs gems with implicit rake dependencies" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "with_implicit_rake_dep"
gem "another_implicit_rake_dep"
gem "rake"
@@ -18,48 +81,69 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to eq("YES\nYES")
end
- it "installs gems with a dependency with no type" do
+ it "installs gems with implicit rake dependencies without rake previously installed" do
+ with_path_as("") do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "with_implicit_rake_dep"
+ gem "another_implicit_rake_dep"
+ gem "rake"
+ G
+ end
+
+ run <<-R
+ require 'implicit_rake_dep'
+ require 'another_implicit_rake_dep'
+ puts IMPLICIT_RAKE_DEP
+ puts ANOTHER_IMPLICIT_RAKE_DEP
+ R
+ expect(out).to eq("YES\nYES")
+ end
+
+ it "does not install gems with a dependency with no type" do
build_repo2
path = "#{gem_repo2}/#{Gem::MARSHAL_SPEC_DIR}/actionpack-2.3.2.gemspec.rz"
- spec = Marshal.load(Bundler.rubygems.inflate(File.read(path)))
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
spec.dependencies.each do |d|
- d.instance_variable_set(:@type, :fail)
+ d.instance_variable_set(:@type, "fail")
end
- File.open(path, "w") do |f|
+ File.open(path, "wb") do |f|
f.write Gem.deflate(Marshal.dump(spec))
end
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem "actionpack", "2.3.2"
G
- expect(the_bundle).to include_gems "actionpack 2.3.2", "activesupport 2.3.2"
+ expect(err).to include("Downloading actionpack-2.3.2 revealed dependencies not in the API (activesupport (= 2.3.2)).")
+
+ expect(the_bundle).not_to include_gems "actionpack 2.3.2", "activesupport 2.3.2"
end
describe "with crazy rubygem plugin stuff" do
it "installs plugins" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "net_b"
G
expect(the_bundle).to include_gems "net_b 1.0"
end
- it "installs plugins depended on by other plugins", :ruby_repo do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ it "installs plugins depended on by other plugins" do
+ install_gemfile <<-G, env: { "DEBUG" => "1" }
+ source "https://gem.repo2"
gem "net_a"
G
expect(the_bundle).to include_gems "net_a 1.0", "net_b 1.0"
end
- it "installs multiple levels of dependencies", :ruby_repo do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
+ it "installs multiple levels of dependencies" do
+ install_gemfile <<-G, env: { "DEBUG" => "1" }
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
@@ -67,34 +151,48 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(the_bundle).to include_gems "net_a 1.0", "net_b 1.0", "net_c 1.0", "net_d 1.0", "net_e 1.0"
end
+ context "with ENV['BUNDLER_DEBUG_RESOLVER'] set" do
+ it "produces debug output" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "net_c"
+ gem "net_e"
+ G
+
+ bundle :install, env: { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
+
+ expect(out).to include("Resolving dependencies...")
+ end
+ end
+
context "with ENV['DEBUG_RESOLVER'] set" do
it "produces debug output" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER" => "1" }
+ bundle :install, env: { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(err).to include("Creating possibility state for net_c")
+ expect(out).to include("Resolving dependencies...")
end
end
context "with ENV['DEBUG_RESOLVER_TREE'] set" do
it "produces debug output" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1" }
+ bundle :install, env: { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
- expect(err).to include(" net_b").
- and include("Starting resolution").
- and include("Finished resolution").
- and include("Attempting to activate")
+ expect(out).to include(" net_b").
+ and include("Resolving dependencies...").
+ and include("Solution found after 1 attempts:").
+ and include("selected net_b 1.0")
end
end
end
@@ -103,19 +201,438 @@ RSpec.describe "bundle install with install-time dependencies" do
context "allows only an older version" do
it "installs the older version" do
build_repo2 do
- build_gem "rack", "9001.0.0" do |s|
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
+ build_gem "myrack", "9001.0.0" do |s|
+ s.required_ruby_version = "> 9000"
+ end
+ end
+
+ install_gemfile <<-G
+ ruby "#{Gem.ruby_version}"
+ source "https://gem.repo2"
+ gem 'myrack'
+ G
+
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
+ end
+
+ it "installs the older version when using servers not implementing the compact index API" do
+ build_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+
+ build_gem "myrack", "9001.0.0" do |s|
s.required_ruby_version = "> 9000"
end
end
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2 }
- ruby "#{RUBY_VERSION}"
- source "http://localgemserver.test/"
- gem 'rack'
+ install_gemfile <<-G, artifice: "endpoint"
+ ruby "#{Gem.ruby_version}"
+ source "https://gem.repo2"
+ gem 'myrack'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(the_bundle).to include_gems("rack 1.2")
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
+ end
+
+ context "when there is a lockfile using the newer incompatible version" do
+ before do
+ build_repo2 do
+ build_gem "parallel_tests", "3.7.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "parallel_tests", "3.8.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'parallel_tests'
+ G
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo2, "parallel_tests", "3.8.0"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ parallel_tests (3.8.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically updates lockfile to use the older version" do
+ bundle "install --verbose"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "parallel_tests", "3.7.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ parallel_tests (3.7.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "gives a meaningful error if we're in frozen mode" do
+ expect do
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ end.not_to change { lockfile }
+
+ expect(err).to eq("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}, which is incompatible with the current version, #{Gem.ruby_version}")
+ end
+ end
+
+ context "with transitive dependencies in a lockfile" do
+ before do
+ build_repo2 do
+ build_gem "rubocop", "1.28.2" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+
+ s.add_dependency "rubocop-ast", ">= 1.17.0", "< 2.0"
+ end
+
+ build_gem "rubocop", "1.35.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+
+ s.add_dependency "rubocop-ast", ">= 1.20.1", "< 2.0"
+ end
+
+ build_gem "rubocop-ast", "1.17.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "rubocop-ast", "1.21.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'rubocop'
+ G
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo2, "rubocop", "1.35.0"
+ c.checksum gem_repo2, "rubocop-ast", "1.21.0"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ rubocop (1.35.0)
+ rubocop-ast (>= 1.20.1, < 2.0)
+ rubocop-ast (1.21.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rubocop
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically updates lockfile to use the older compatible versions" do
+ bundle "install --verbose"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "rubocop", "1.28.2"
+ c.checksum gem_repo2, "rubocop-ast", "1.17.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ rubocop (1.28.2)
+ rubocop-ast (>= 1.17.0, < 2.0)
+ rubocop-ast (1.17.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rubocop
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with a Gemfile and lockfile that don't resolve under the current platform" do
+ before do
+ build_repo4 do
+ build_gem "sorbet", "0.5.10554" do |s|
+ s.add_dependency "sorbet-static", "0.5.10554"
+ end
+
+ build_gem "sorbet-static", "0.5.10554" do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem 'sorbet', '= 0.5.10554'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10554)
+ sorbet-static (= 0.5.10554)
+ sorbet-static (0.5.10554-universal-darwin-21)
+
+ PLATFORMS
+ arm64-darwin-21
+
+ DEPENDENCIES
+ sorbet (= 0.5.10554)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a proper error" do
+ simulate_platform "aarch64-linux" do
+ bundle "install", raise_on_error: false
+ end
+
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static (= 0.5.10554)' valid for all resolution platforms (arm64-darwin-21, aarch64-linux) in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.10554)':
+ * sorbet-static-0.5.10554-universal-darwin-21
+ E
+ expect(err).to include(nice_error)
+ expect(err).to include("Your current platform (aarch64-linux) is not included in the lockfile's platforms (arm64-darwin-21)")
+ expect(err).to include("bundle lock --add-platform aarch64-linux")
+ end
+ end
+
+ context "when adding a new gem that does not resolve under all locked platforms" do
+ before do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "arm-linux"
+ end
+
+ build_gem "sorbet-static", "0.5.10696" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.0-arm-linux)
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ arm-linux
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+
+ bundle "lock", raise_on_error: false
+ end
+ end
+
+ it "raises a proper error" do
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static' valid for all resolution platforms (arm-linux, x86_64-linux) in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static':
+ * sorbet-static-0.5.10696-x86_64-linux
+ E
+ expect(err).to end_with(nice_error)
+ end
+ end
+
+ context "when locked generic variant supports current Ruby, but locked specific variant does not" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.3)
+ nokogiri (1.16.3-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "nokogiri", "1.16.3"
+ build_gem "nokogiri", "1.16.3" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "keeps both variants in the lockfile when installing, and uses the generic one since it's compatible" do
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose"
+
+ expect(lockfile).to eq(original_lockfile)
+ expect(the_bundle).to include_gems("nokogiri 1.16.3")
+ end
+ end
+
+ it "keeps both variants in the lockfile when updating, and uses the generic one since it's compatible" do
+ simulate_platform "x86_64-linux" do
+ bundle "update --verbose"
+
+ expect(lockfile).to eq(original_lockfile)
+ expect(the_bundle).to include_gems("nokogiri 1.16.3")
+ end
+ end
+ end
+
+ it "gives a meaningful error on ruby version mismatches between dependencies" do
+ build_repo4 do
+ build_gem "requires-old-ruby" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ build_lib("foo", path: bundled_app) do |s|
+ s.required_ruby_version = ">= #{Gem.ruby_version}"
+
+ s.add_dependency "requires-old-ruby"
+ end
+
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo4"
+ gemspec
+ G
+
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of foo depends on requires-old-ruby >= 0
+ and every version of requires-old-ruby depends on Ruby < #{Gem.ruby_version},
+ every version of foo requires Ruby < #{Gem.ruby_version}.
+ So, because Gemfile depends on foo >= 0
+ and current Ruby version is = #{Gem.ruby_version},
+ version solving has failed.
+ E
+ end
+
+ it "installs the older version under rate limiting conditions" do
+ build_repo4 do
+ build_gem "myrack", "9001.0.0" do |s|
+ s.required_ruby_version = "> 9000"
+ end
+ build_gem "myrack", "1.2"
+ build_gem "foo1", "1.0"
+ end
+
+ install_gemfile <<-G, artifice: "compact_index_rate_limited"
+ ruby "#{Gem.ruby_version}"
+ source "https://gem.repo4"
+ gem 'myrack'
+ gem 'foo1'
+ G
+
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
+ end
+
+ it "installs the older not platform specific version" do
+ build_repo4 do
+ build_gem "myrack", "9001.0.0" do |s|
+ s.required_ruby_version = "> 9000"
+ end
+ build_gem "myrack", "1.2" do |s|
+ s.platform = "x86-mingw32"
+ s.required_ruby_version = "> 9000"
+ end
+ build_gem "myrack", "1.2"
+ end
+
+ simulate_platform "x86-mingw32" do
+ install_gemfile <<-G, artifice: "compact_index"
+ ruby "#{Gem.ruby_version}"
+ source "https://gem.repo4"
+ gem 'myrack'
+ G
+ end
+
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("myrack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
end
end
@@ -128,31 +645,49 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- let(:ruby_requirement) { %("#{RUBY_VERSION}") }
- let(:error_message_requirement) { "~> #{RUBY_VERSION}.0" }
+ let(:ruby_requirement) { %("#{Gem.ruby_version}") }
+ let(:error_message_requirement) { "= #{Gem.ruby_version}" }
+
+ it "raises a proper error that mentions the current Ruby version during resolution" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
+ gem 'require_ruby'
+ G
+
+ expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
+
+ nice_error = <<~E.strip
+ Could not find compatible versions
+
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
+ E
+ expect(err).to end_with(nice_error)
+ end
shared_examples_for "ruby version conflicts" do
it "raises an error during resolution" do
- install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2 }
- source "http://localgemserver.test/"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
ruby #{ruby_requirement}
gem 'require_ruby'
G
expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
- nice_error = strip_whitespace(<<-E).strip
- Bundler could not find compatible versions for gem "ruby\0":
- In Gemfile:
- ruby\0 (#{error_message_requirement})
+ nice_error = <<~E.strip
+ Could not find compatible versions
- require_ruby was resolved to 1.0, which depends on
- ruby\0 (> 9000)
-
- Could not find gem 'ruby\0 (> 9000)', which is required by gem 'require_ruby', in any of the relevant sources:
- the local ruby installation
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
E
- expect(last_command.bundler_err).to end_with(nice_error)
+ expect(err).to end_with(nice_error)
end
end
@@ -160,7 +695,6 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "with a < requirement" do
let(:ruby_requirement) { %("< 5000") }
- let(:error_message_requirement) { "< 5000" }
it_behaves_like "ruby version conflicts"
end
@@ -168,7 +702,6 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "with a compound requirement" do
let(:reqs) { ["> 0.1", "< 5000"] }
let(:ruby_requirement) { reqs.map(&:dump).join(", ") }
- let(:error_message_requirement) { Gem::Requirement.new(reqs).to_s }
it_behaves_like "ruby version conflicts"
end
@@ -183,13 +716,71 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- install_gemfile <<-G
- source "file://#{gem_repo2}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem 'require_rubygems'
G
- expect(out).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000")
- expect(out).to include("require_rubygems-1.0 requires rubygems version > 9000, which is incompatible with the current version, #{Gem::VERSION}")
+ expect(err).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000")
+ nice_error = <<~E.strip
+ Because every version of require_rubygems depends on RubyGems > 9000
+ and Gemfile depends on require_rubygems >= 0,
+ RubyGems > 9000 is required.
+ So, because current RubyGems version is = #{Gem::VERSION},
+ version solving has failed.
+ E
+ expect(err).to end_with(nice_error)
+ end
+ end
+
+ context "when non platform specific gems bring more dependencies", :truffleruby_only do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "foo", "2.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "bar"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+ end
+
+ it "locks both ruby and current platform, and resolve to ruby variants that install on truffleruby" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "bar", "1.0"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bar (1.0)
+ foo (1.0)
+ bar
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
end
end
end
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index fa7a3bdc27..96a305bb76 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -1,12 +1,18 @@
# frozen_string_literal: true
-RSpec.shared_examples "bundle install --standalone" do
+RSpec.describe "bundle install --standalone" do
shared_examples "common functionality" do
it "still makes the gems available to normal bundler" do
args = expected_gems.map {|k, v| "#{k} #{v}" }
expect(the_bundle).to include_gems(*args)
end
+ it "still makes system gems unavailable to normal bundler" do
+ system_gems "myrack-1.0.0"
+
+ expect(the_bundle).to_not include_gems("myrack")
+ end
+
it "generates a bundle/bundler/setup.rb" do
expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
@@ -21,15 +27,66 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- Dir.chdir(bundled_app) do
- ruby testrb, :no_lib => true
+ ruby testrb
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "makes the gems available without bundler nor rubygems" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nrequire \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
+ end
+ in_bundled_app %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "makes the gems available without bundler via Kernel.require" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nKernel.require \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
end
+ ruby testrb
expect(out).to eq(expected_gems.values.join("\n"))
end
+ it "makes system gems unavailable without bundler" do
+ system_gems "myrack-1.0.0"
+
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ begin
+ require "myrack"
+ rescue LoadError
+ puts "LoadError"
+ end
+ RUBY
+ ruby testrb
+
+ expect(out).to eq("LoadError")
+ end
+
it "works on a different system" do
- FileUtils.mv(bundled_app, "#{bundled_app}2")
+ begin
+ FileUtils.mv(bundled_app, "#{bundled_app}2")
+ rescue Errno::ENOTEMPTY
+ puts "Couldn't rename test app since the target folder has these files: #{Dir.glob("#{bundled_app}2/*")}"
+ raise
+ end
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
@@ -40,9 +97,23 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- Dir.chdir("#{bundled_app}2") do
- ruby testrb, :no_lib => true
+ ruby testrb, dir: "#{bundled_app}2"
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "skips activating gems" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ gem "do_not_activate_me"
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nrequire \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
end
+ in_bundled_app %(#{Gem.ruby} -w -e #{testrb.shellescape})
expect(out).to eq(expected_gems.values.join("\n"))
end
@@ -51,10 +122,11 @@ RSpec.shared_examples "bundle install --standalone" do
describe "with simple gems" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -67,28 +139,162 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
end
- describe "with gems with native extension", :ruby_repo do
+ describe "with default gems and a lockfile", :ruby_repo do
+ it "works and points to the vendored copies, not to the default copies" do
+ base_system_gems "stringio", "psych", "etc", path: scoped_gem_path(bundled_app("bundle"))
+
+ build_gem "foo", "1.0.0", to_system: true, default: true do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0", to_system: true, default: true
+
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+
+ bundle "lock", dir: cwd
+
+ bundle_config "path #{bundled_app("bundle")}"
+
+ bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+
+ load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
+
+ expect(load_path_lines).to eq [
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/bar-1.0.0/lib")',
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/foo-1.0.0/lib")',
+ ]
+ end
+
+ it "works for gems with extensions and points to the vendored copies, not to the default copies" do
+ simulate_platform "arm64-darwin-23" do
+ base_system_gems "stringio", "psych", "etc", "shellwords", "open3", path: scoped_gem_path(bundled_app("bundle"))
+
+ build_gem "baz", "1.0.0", to_system: true, default: true, &:add_c_extension
+
+ build_repo4 do
+ build_gem "baz", "1.0.0", &:add_c_extension
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "baz"
+ G
+
+ bundle_config "path #{bundled_app("bundle")}"
+
+ bundle "lock", dir: cwd
+
+ bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+ end
+
+ load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
+
+ expect(load_path_lines).to eq [
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/arm64-darwin-23/#{Gem.extension_api_version}/baz-1.0.0")',
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/baz-1.0.0/lib")',
+ ]
+ end
+ end
+
+ describe "with Gemfiles using absolute path sources and resulting bundle moved to a folder hierarchy with different nesting" do
before do
- install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
- source "file://#{gem_repo1}"
+ build_lib "minitest", "1.0.0", path: lib_path("minitest")
+
+ Dir.mkdir bundled_app("app")
+
+ gemfile bundled_app("app/Gemfile"), <<-G
+ source "https://gem.repo1"
+ gem "minitest", :path => "#{lib_path("minitest")}"
+ G
+
+ bundle "install", standalone: true, dir: bundled_app("app")
+
+ Dir.mkdir tmp("one_more_level")
+ FileUtils.mv bundled_app, tmp("one_more_level")
+ end
+
+ it "also works" do
+ ruby <<-RUBY, dir: tmp("one_more_level/bundled_app/app")
+ require "./bundle/bundler/setup"
+
+ require "minitest"
+ puts MINITEST
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+ end
+
+ let(:cwd) { bundled_app }
+
+ describe "with Gemfiles using relative path sources and app moved to a different root" do
+ before do
+ FileUtils.mkdir_p bundled_app("app/vendor")
+
+ build_lib "minitest", "1.0.0", path: bundled_app("app/vendor/minitest")
+
+ gemfile bundled_app("app/Gemfile"), <<-G
+ source "https://gem.repo1"
+ gem "minitest", :path => "vendor/minitest"
+ G
+
+ bundle "install", standalone: true, dir: bundled_app("app")
+
+ FileUtils.mv(bundled_app("app"), bundled_app2("app"))
+ end
+
+ it "also works" do
+ ruby <<-RUBY, dir: bundled_app2("app")
+ require "./bundle/bundler/setup"
+
+ require "minitest"
+ puts MINITEST
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+ end
+
+ describe "with gems with native extension" do
+ before do
+ bundle_config "path #{bundled_app("bundle")}"
+ install_gemfile <<-G, standalone: true, dir: cwd
+ source "https://gem.repo1"
gem "very_simple_binary"
G
end
- it "generates a bundle/bundler/setup.rb with the proper paths", :rubygems => "2.4" do
+ it "generates a bundle/bundler/setup.rb with the proper paths" do
expected_path = bundled_app("bundle/bundler/setup.rb")
- extension_line = File.read(expected_path).each_line.find {|line| line.include? "/extensions/" }.strip
- expect(extension_line).to start_with '$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/'
- expect(extension_line).to end_with '/very_simple_binary-1.0"'
+ script_content = File.read(expected_path)
+ expect(script_content).to include("def self.ruby_api_version")
+ expect(script_content).to include("def self.extension_api_version")
+ extension_line = script_content.each_line.find {|line| line.include? "/extensions/" }.strip
+ platform = Gem::Platform.local
+ expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/'
+ expect(extension_line).to end_with platform.to_s + '/#{Gem.extension_api_version}/very_simple_binary-1.0")'
end
end
describe "with gem that has an invalid gemspec" do
before do
- build_git "bar", :gemspec => false do |s|
+ build_git "bar", gemspec: false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
- lib = File.expand_path('../lib/', __FILE__)
+ lib = File.expand_path('lib/', __dir__)
$:.unshift lib unless $:.include?(lib)
require 'bar/version'
@@ -102,14 +308,16 @@ RSpec.shared_examples "bundle install --standalone" do
end
G
end
- install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle_config "path #{bundled_app("bundle")}"
+ install_gemfile <<-G, standalone: true, dir: cwd, raise_on_error: false
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
it "outputs a helpful error message" do
- expect(out).to include("You have one or more invalid gemspecs that need to be fixed.")
- expect(out).to include("bar 1.0 has an invalid gemspec")
+ expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
+ expect(err).to include("bar.gemspec is not valid")
end
end
@@ -118,11 +326,12 @@ RSpec.shared_examples "bundle install --standalone" do
build_git "devise", "1.0"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
gem "devise", :git => "#{lib_path("devise-1.0")}"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -141,15 +350,16 @@ RSpec.shared_examples "bundle install --standalone" do
build_git "devise", "1.0"
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
group :test do
gem "rspec"
- gem "rack-test"
+ gem "myrack-test"
end
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: true, dir: cwd
end
let(:expected_gems) do
@@ -162,91 +372,72 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
it "allows creating a standalone file with limited groups" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => "default")
-
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
-
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: "default", dir: cwd
- expect(last_command.stdout).to eq("2.3.2")
- expect(last_command.stderr).to eq("ZOMG LOAD ERROR")
- end
-
- it "allows --without to limit the groups used in a standalone" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle"), :without => "test").merge(:standalone => true)
-
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
- expect(last_command.stdout).to eq("2.3.2")
- expect(last_command.stderr).to eq("ZOMG LOAD ERROR")
+ expect(out).to eq("2.3.2")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
- it "allows --path to change the location of the standalone bundle", :bundler => "< 3" do
- bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true)
+ it "allows `without` configuration to limit the groups used in a standalone" do
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle_config "without test"
+ bundle :install, standalone: true, dir: cwd
- Dir.chdir(bundled_app) do
- ruby <<-RUBY, :no_lib => true
- $:.unshift File.expand_path("path/to/bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
- expect(last_command.stdout).to eq("2.3.2")
+ expect(out).to eq("2.3.2")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
- it "allows --path to change the location of the standalone bundle", :bundler => "3" do
- bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true)
- path = File.expand_path("path/to/bundle")
+ it "allows `path` configuration to change the location of the standalone bundle" do
+ bundle_config "path path/to/bundle"
+ bundle "install", standalone: true, dir: cwd
- Dir.chdir(bundled_app) do
- ruby <<-RUBY, :no_lib => true
- $:.unshift File.expand_path(#{path.dump})
- require "bundler/setup"
+ ruby <<-RUBY
+ $:.unshift File.expand_path("path/to/bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ RUBY
- expect(last_command.stdout).to eq("2.3.2")
+ expect(out).to eq("2.3.2")
end
- it "allows remembered --without to limit the groups used in a standalone" do
- bundle! :install, forgotten_command_line_options(:without => "test")
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ it "allows `without` to limit the groups used in a standalone" do
+ bundle_config "without test"
+ bundle :install, dir: cwd
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: true, dir: cwd
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
- expect(last_command.stdout).to eq("2.3.2")
- expect(last_command.stderr).to eq("ZOMG LOAD ERROR")
+ expect(out).to eq("2.3.2")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
end
@@ -259,7 +450,8 @@ RSpec.shared_examples "bundle install --standalone" do
source "#{source_uri}"
gem "rails"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :artifice => "endpoint")
+ bundle_config "path #{bundled_app("bundle")}"
+ bundle :install, standalone: true, artifice: "endpoint", dir: cwd
end
let(:expected_gems) do
@@ -272,66 +464,61 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
end
end
+end
- describe "with --binstubs", :bundler => "< 3" do
- before do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
- G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :binstubs => true)
- end
+RSpec.describe "bundle install --standalone run in a subdirectory" do
+ let(:cwd) { bundled_app("bob").tap(&:mkpath) }
- let(:expected_gems) do
- {
- "actionpack" => "2.3.2",
- "rails" => "2.3.2",
- }
- end
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ G
+ end
- include_examples "common functionality"
+ it "generates the script in the proper place" do
+ bundle :install, standalone: true, dir: cwd
- it "creates stubs that use the standalone load path" do
- Dir.chdir(bundled_app) do
- expect(`bin/rails -v`.chomp).to eql "2.3.2"
- end
- end
+ expect(bundled_app("bundle/bundler/setup.rb")).to exist
+ end
- it "creates stubs that can be executed from anywhere" do
- require "tmpdir"
- Dir.chdir(Dir.tmpdir) do
- sys_exec!(%(#{bundled_app("bin/rails")} -v))
- expect(out).to eq("2.3.2")
- end
+ context "when path set to a relative path" do
+ before do
+ bundle_config "path bundle"
end
- it "creates stubs that can be symlinked" do
- pending "File.symlink is unsupported on Windows" if Bundler::WINDOWS
+ it "generates the script in the proper place" do
+ bundle :install, standalone: true, dir: cwd
- symlink_dir = tmp("symlink")
- FileUtils.mkdir_p(symlink_dir)
- symlink = File.join(symlink_dir, "rails")
-
- File.symlink(bundled_app("bin/rails"), symlink)
- sys_exec!("#{symlink} -v")
- expect(out).to eq("2.3.2")
- end
-
- it "creates stubs with the correct load path" do
- extension_line = File.read(bundled_app("bin/rails")).each_line.find {|line| line.include? "$:.unshift" }.strip
- expect(extension_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath)
+ expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
end
end
-RSpec.describe "bundle install --standalone" do
- include_examples("bundle install --standalone")
-end
-
-RSpec.describe "bundle install --standalone run in a subdirectory" do
+RSpec.describe "bundle install --standalone --local" do
before do
- Dir.chdir(bundled_app("bob").tap(&:mkpath))
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ system_gems "myrack-1.0.0", path: default_bundle_path
end
- include_examples("bundle install --standalone")
+ it "generates script pointing to system gems" do
+ bundle "install --standalone --local --verbose"
+
+ expect(out).to include("Using myrack 1.0.0")
+
+ load_error_ruby <<-RUBY, "spec"
+ require "./bundler/setup"
+
+ require "myrack"
+ puts MYRACK
+ require "spec"
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
+ end
end
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
deleted file mode 100644
index 1781451c98..0000000000
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ /dev/null
@@ -1,178 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "when using sudo", :sudo => true do
- describe "and BUNDLE_PATH is writable" do
- context "but BUNDLE_PATH/build_info is not writable" do
- before do
- bundle! "config path.system true"
- subdir = system_gem_path("cache")
- subdir.mkpath
- sudo "chmod u-w #{subdir}"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- expect(out).to_not match(/an error occurred/i)
- expect(system_gem_path("cache/rack-1.0.0.gem")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
- end
- end
-
- describe "and GEM_HOME is owned by root" do
- before :each do
- bundle! "config path.system true"
- chown_system_gems_to_root
- end
-
- it "installs" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", '1.0'
- gem "thin"
- G
-
- expect(system_gem_path("gems/rack-1.0.0")).to exist
- expect(system_gem_path("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs rake and a gem dependent on rake in the same session" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rake"
- gem "another_implicit_rake_dep"
- G
- bundle "install"
- expect(system_gem_path("gems/another_implicit_rake_dep-1.0")).to exist
- end
-
- it "installs when BUNDLE_PATH is owned by root" do
- bundle! "config global_path_appends_ruby_scope false" # consistency in tests between 1.x and 2.x modes
-
- bundle_path = tmp("owned_by_root")
- FileUtils.mkdir_p bundle_path
- sudo "chown -R root #{bundle_path}"
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join("gems/rack-1.0.0")).to exist
- expect(bundle_path.join("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs when BUNDLE_PATH does not exist" do
- bundle! "config global_path_appends_ruby_scope false" # consistency in tests between 1.x and 2.x modes
-
- root_path = tmp("owned_by_root")
- FileUtils.mkdir_p root_path
- sudo "chown -R root #{root_path}"
- bundle_path = root_path.join("does_not_exist")
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join("gems/rack-1.0.0")).to exist
- expect(bundle_path.join("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs extensions/ compiled by RubyGems 2.2", :rubygems => "2.2" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "very_simple_binary"
- G
-
- expect(system_gem_path("gems/very_simple_binary-1.0")).to exist
- binary_glob = system_gem_path("extensions/*/*/very_simple_binary-1.0")
- expect(Dir.glob(binary_glob).first).to be
- end
- end
-
- describe "and BUNDLE_PATH is not writable" do
- before do
- sudo "chmod ugo-w #{default_bundle_path}"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", '1.0'
- G
-
- expect(default_bundle_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "cleans up the tmpdirs generated" do
- require "tmpdir"
- Dir.glob("#{Dir.tmpdir}/bundler*").each do |tmpdir|
- FileUtils.remove_entry_secure(tmpdir)
- end
-
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- tmpdirs = Dir.glob("#{Dir.tmpdir}/bundler*")
-
- expect(tmpdirs).to be_empty
- end
- end
-
- describe "and GEM_HOME is not writable" do
- it "installs" do
- bundle! "config path.system true"
- gem_home = tmp("sudo_gem_home")
- sudo "mkdir -p #{gem_home}"
- sudo "chmod ugo-w #{gem_home}"
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", '1.0'
- G
-
- bundle :install, :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
- expect(gem_home.join("bin/rackup")).to exist
- expect(the_bundle).to include_gems "rack 1.0", :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
- end
- end
-
- describe "and root runs install" do
- let(:warning) { "Don't run Bundler as root." }
-
- before do
- gemfile %(source "file://#{gem_repo1}")
- end
-
- it "warns against that" do
- bundle :install, :sudo => true
- expect(out).to include(warning)
- end
-
- context "when ENV['BUNDLE_SILENCE_ROOT_WARNING'] is set" do
- it "skips the warning" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => true }
- expect(out).to_not include(warning)
- end
- end
-
- context "when silence_root_warning = false" do
- it "warns against that" do
- bundle :install, :sudo => true, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
- expect(out).to include(warning)
- end
- end
- end
-end
diff --git a/spec/bundler/install/gems/win32_spec.rb b/spec/bundler/install/gems/win32_spec.rb
index ad758b94fa..be37673aa1 100644
--- a/spec/bundler/install/gems/win32_spec.rb
+++ b/spec/bundler/install/gems/win32_spec.rb
@@ -2,25 +2,24 @@
RSpec.describe "bundle install with win32-generated lockfile" do
it "should read lockfile" do
- File.open(bundled_app("Gemfile.lock"), "wb") do |f|
+ File.open(bundled_app_lock, "wb") do |f|
f << "GEM\r\n"
- f << " remote: file:#{gem_repo1}/\r\n"
+ f << " remote: https://gem.repo1/\r\n"
f << " specs:\r\n"
f << "\r\n"
- f << " rack (1.0.0)\r\n"
+ f << " myrack (1.0.0)\r\n"
f << "\r\n"
f << "PLATFORMS\r\n"
f << " ruby\r\n"
f << "\r\n"
f << "DEPENDENCIES\r\n"
- f << " rack\r\n"
+ f << " myrack\r\n"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 666707b295..fb2271c830 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -1,63 +1,66 @@
-# encoding: utf-8
# frozen_string_literal: true
RSpec.describe "bundle install" do
describe "when a gem has a YAML gemspec" do
before :each do
build_repo2 do
- build_gem "yaml_spec", :gemspec => :yaml
+ build_gem "yaml_spec", gemspec: :yaml
end
end
it "still installs correctly" do
gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "yaml_spec"
G
bundle :install
- expect(err).to lack_errors
+ expect(err).to be_empty
end
it "still installs correctly when using path" do
- build_lib "yaml_spec", :gemspec => :yaml
+ build_lib "yaml_spec", gemspec: :yaml
install_gemfile <<-G
+ source "https://gem.repo1"
gem 'yaml_spec', :path => "#{lib_path("yaml_spec-1.0")}"
G
- expect(err).to lack_errors
+ expect(err).to be_empty
end
end
it "should use gemspecs in the system cache when available" do
gemfile <<-G
- source "http://localtestserver.gem"
- gem 'rack'
+ source "http://localgemserver.test"
+ gem 'myrack'
G
+ system_gems "myrack-1.0.0", path: default_bundle_path
+
FileUtils.mkdir_p "#{default_bundle_path}/specifications"
- File.open("#{default_bundle_path}/specifications/rack-1.0.0.gemspec", "w+") do |f|
+ File.open("#{default_bundle_path}/specifications/myrack-1.0.0.gemspec", "w+") do |f|
spec = Gem::Specification.new do |s|
- s.name = "rack"
+ s.name = "myrack"
s.version = "1.0.0"
- s.add_runtime_dependency "activesupport", "2.3.2"
+ s.add_dependency "activesupport", "2.3.2"
end
f.write spec.to_ruby
end
- bundle :install, :artifice => "endpoint_marshal_fail" # force gemspec load
- expect(the_bundle).to include_gems "activesupport 2.3.2"
+ bundle :install, artifice: "endpoint_marshal_fail" # force gemspec load
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.2"
end
it "does not hang when gemspec has incompatible encoding" do
- create_file "foo.gemspec", <<-G
+ create_file("foo.gemspec", <<-G)
Gem::Specification.new do |gem|
gem.name = "pry-byebug"
gem.version = "3.4.2"
- gem.author = "David Rodriguez"
+ gem.author = "David Rodríguez"
gem.summary = "Good stuff"
end
G
- install_gemfile <<-G, :env => { "LANG" => "C" }
+ install_gemfile <<-G, env: { "LANG" => "C" }
+ source "https://gem.repo1"
gemspec
G
@@ -65,8 +68,6 @@ RSpec.describe "bundle install" do
end
it "reads gemspecs respecting their encoding" do
- skip "Unicode is not supported on Ruby 1.x without extra work" if RUBY_VERSION < "2.0"
-
create_file "version.rb", <<-RUBY
module Persistent💎
VERSION = "0.0.1"
@@ -85,6 +86,7 @@ RSpec.describe "bundle install" do
G
install_gemfile <<-G
+ source "https://gem.repo1"
gemspec
G
@@ -92,63 +94,86 @@ RSpec.describe "bundle install" do
end
context "when ruby version is specified in gemspec and gemfile" do
- it "installs when patch level is not specified and the version matches" do
- build_lib("foo", :path => bundled_app) do |s|
+ it "installs when patch level is not specified and the version matches",
+ if: RUBY_PATCHLEVEL >= 0 do
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "~> #{RUBY_VERSION}.0"
end
install_gemfile <<-G
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby'
+ source "https://gem.repo1"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
end
it "installs when patch level is specified and the version still matches the current version",
- :if => RUBY_PATCHLEVEL >= 0 do
- build_lib("foo", :path => bundled_app) do |s|
+ if: RUBY_PATCHLEVEL >= 0 do
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{RUBY_PATCHLEVEL}'
+ source "https://gem.repo1"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
end
- it "fails and complains about patchlevel on patchlevel mismatch",
- :if => RUBY_PATCHLEVEL >= 0 do
+ it "installs gems ignoring the mismatch even when patchlevel is mismatch",
+ if: RUBY_PATCHLEVEL >= 0 do
patchlevel = RUBY_PATCHLEVEL.to_i + 1
- build_lib("foo", :path => bundled_app) do |s|
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = "#{RUBY_VERSION}.#{patchlevel}"
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{patchlevel}'
+ source "https://gem.repo1"
gemspec
G
- expect(out).to include("Ruby patchlevel")
- expect(out).to include("but your Gemfile specified")
- expect(exitstatus).to eq(18) if exitstatus
+ expect(the_bundle).to include_gems "foo 1.0"
end
it "fails and complains about version on version mismatch" do
version = Gem::Requirement.create(RUBY_VERSION).requirements.first.last.bump.version
- build_lib("foo", :path => bundled_app) do |s|
+ build_lib("foo", path: bundled_app) do |s|
s.required_ruby_version = version
end
- install_gemfile <<-G
+ install_gemfile <<-G, raise_on_error: false
ruby '#{version}', :engine_version => '#{version}', :engine => 'ruby'
+ source "https://gem.repo1"
gemspec
G
- expect(out).to include("Ruby version")
- expect(out).to include("but your Gemfile specified")
- expect(exitstatus).to eq(18) if exitstatus
+ expect(err).to include("Ruby version")
+ expect(err).to include("but your Gemfile specified")
+ expect(exitstatus).to eq(18)
+ end
+
+ it "validates gemspecs just once when everything installed and lockfile up to date" do
+ build_lib "foo"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec path: "#{lib_path("foo-1.0")}"
+
+ module Monkey
+ def validate(spec)
+ puts "Validate called on \#{spec.full_name}"
+ end
+ end
+ Bundler.rubygems.extend(Monkey)
+ G
+
+ bundle "install"
+
+ expect(out).to include("Validate called on foo-1.0").once
end
end
end
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index 48086a86c7..1172d661ae 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -2,50 +2,78 @@
RSpec.describe "bundle install" do
context "git sources" do
- it "displays the revision hash of the gem repository", :bundler => "< 3" do
- build_git "foo", "1.0", :path => lib_path("foo")
+ it "displays the revision hash of the gem repository" do
+ build_git "foo", "1.0", path: lib_path("foo")
- install_gemfile <<-G
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+ end
+
+ it "displays the revision hash of the gem repository when passed a relative local path" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ relative_path = lib_path("foo").relative_path_from(bundled_app)
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{relative_path}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{relative_path} (at main@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+ end
+
+ it "displays the correct default branch", git: ">= 2.28.0" do
+ build_git "foo", "1.0", path: lib_path("foo"), default_branch: "non-standard"
+
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo")}"
G
- bundle! :install
- expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master@#{revision_for(lib_path("foo"))[0..6]})")
- expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at non-standard@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
end
- it "displays the ref of the gem repository when using branch~num as a ref", :bundler => "< 3" do
- build_git "foo", "1.0", :path => lib_path("foo")
+ it "displays the ref of the gem repository when using branch~num as a ref" do
+ skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform?
+
+ build_git "foo", "1.0", path: lib_path("foo")
rev = revision_for(lib_path("foo"))[0..6]
- update_git "foo", "2.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "2.0", path: lib_path("foo"), gemspec: true
rev2 = revision_for(lib_path("foo"))[0..6]
- update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "3.0", path: lib_path("foo"), gemspec: true
- install_gemfile! <<-G
- gem "foo", :git => "#{lib_path("foo")}", :ref => "master~2"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}", :ref => "main~2"
G
- bundle! :install
- expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master~2@#{rev})")
- expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main~2@#{rev})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
- update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true
+ update_git "foo", "4.0", path: lib_path("foo"), gemspec: true
- bundle! :update, :all => bundle_update_requires_all?
- expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at master~2@#{rev2})")
- expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}"
+ bundle :update, all: true, verbose: true
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at main~2@#{rev2})")
+ expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
end
- it "should allows git repos that are missing but not being installed" do
+ it "allows git repos that are missing but not being installed" do
revision = build_git("foo").ref_for("HEAD")
gemfile <<-G
- gem "foo", :git => "file://#{lib_path("foo-1.0")}", :group => :development
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :group => :development
G
lockfile <<-L
GIT
- remote: file://#{lib_path("foo-1.0")}
+ remote: #{lib_path("foo-1.0")}
revision: #{revision}
specs:
foo (1.0)
@@ -57,9 +85,285 @@ RSpec.describe "bundle install" do
foo!
L
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle", :without => "development")
+ bundle_config "path vendor/bundle"
+ bundle_config "without development"
+ bundle :install
expect(out).to include("Bundle complete!")
end
+
+ it "allows multiple gems from the same git source" do
+ build_repo2 do
+ build_lib "foo", "1.0", path: lib_path("gems/foo")
+ build_lib "zebra", "2.0", path: lib_path("gems/zebra")
+ build_git "gems", path: lib_path("gems"), gemspec: false
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "foo", :git => "#{lib_path("gems")}", :glob => "foo/*.gemspec"
+ gem "zebra", :git => "#{lib_path("gems")}", :glob => "zebra/*.gemspec"
+ G
+
+ bundle "info foo"
+ expect(out).to include("* foo (1.0 #{revision_for(lib_path("gems"))[0..6]})")
+
+ bundle "info zebra"
+ expect(out).to include("* zebra (2.0 #{revision_for(lib_path("gems"))[0..6]})")
+ end
+
+ it "should always sort dependencies in the same order" do
+ # This Gemfile + lockfile had a problem where the first
+ # `bundle install` would change the order, but the second would
+ # change it back.
+
+ # NOTE: both gems MUST have the same path! It has to be two gems in one repo.
+
+ test = build_git "test", "1.0.0", path: lib_path("test-and-other")
+ other = build_git "other", "1.0.0", path: lib_path("test-and-other")
+ test_ref = test.ref_for("HEAD")
+ other_ref = other.ref_for("HEAD")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "test", git: #{test.path.to_s.inspect}
+ gem "other", ref: #{other_ref.inspect}, git: #{other.path.to_s.inspect}
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{test.path}
+ revision: #{test_ref}
+ specs:
+ test (1.0.0)
+
+ GIT
+ remote: #{other.path}
+ revision: #{other_ref}
+ ref: #{other_ref}
+ specs:
+ other (1.0.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ other!
+ test!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ # If GH#6743 is present, the first `bundle install` will change the
+ # lockfile, by flipping the order (`other` would be moved to the top).
+ #
+ # The second `bundle install` would then change the lockfile back
+ # to the original.
+ #
+ # The fix makes it so it may change it once, but it will not change
+ # it a second time.
+ #
+ # So, we run `bundle install` once, and store the value of the
+ # modified lockfile.
+ bundle :install
+ modified_lockfile = lockfile
+
+ # If GH#6743 is present, the second `bundle install` would change the
+ # lockfile back to what it was originally.
+ #
+ # This `expect` makes sure it doesn't change a second time.
+ bundle :install
+ expect(lockfile).to eq(modified_lockfile)
+
+ expect(out).to include("Bundle complete!")
+ end
+
+ it "allows older revisions of git source when clean true" do
+ build_git "foo", "1.0", path: lib_path("foo")
+ rev = revision_for(lib_path("foo"))
+
+ bundle_config "path vendor/bundle"
+ bundle_config "clean true"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main@#{rev[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ old_lockfile = lockfile
+
+ update_git "foo", "2.0", path: lib_path("foo"), gemspec: true
+ rev2 = revision_for(lib_path("foo"))
+
+ bundle :update, all: true, verbose: true
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at main@#{rev2[0..6]})")
+ expect(out).to include("Removing foo (#{rev[0..11]})")
+ expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
+
+ lockfile(old_lockfile)
+
+ bundle :install, verbose: true
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main@#{rev[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+ end
+
+ context "when install directory exists" do
+ let(:checkout_confirmation_log_message) { "Checking out revision" }
+ let(:using_foo_confirmation_log_message) { "Using foo 1.0 from #{lib_path("foo")} (at main@#{revision_for(lib_path("foo"))[0..6]})" }
+
+ context "and no contents besides .git directory are present" do
+ it "reinstalls gem" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ gemfile = <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # validate that the installed directory exists and has some expected contents
+ install_directory = default_bundle_path("bundler/gems/foo-#{revision_for(lib_path("foo"))[0..11]}")
+ dot_git_directory = install_directory.join(".git")
+ lib_directory = install_directory.join("lib")
+ gemspec = install_directory.join("foo.gemspec")
+ expect([install_directory, dot_git_directory, lib_directory, gemspec]).to all exist
+
+ # remove all elements in the install directory except .git directory
+ FileUtils.rm_r(lib_directory)
+ gemspec.delete
+
+ expect(dot_git_directory).to exist
+ expect(lib_directory).not_to exist
+ expect(gemspec).not_to exist
+
+ # rerun bundle install
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # validate that it reinstalls all components
+ expect([install_directory, dot_git_directory, lib_directory, gemspec]).to all exist
+ end
+ end
+
+ context "and contents besides .git directory are present" do
+ # we want to confirm that the change to try to detect partial installs and reinstall does not
+ # result in repeatedly reinstalling the gem when it is fully installed
+ it "does not reinstall gem" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ gemfile = <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # rerun bundle install
+ install_gemfile gemfile, verbose: true
+
+ # it isn't altogether straight-forward to validate that bundle didn't do soething on the second run, however,
+ # the presence of the 2nd log message confirms install got past the point that it would have logged the above if
+ # it was going to
+ expect(out).not_to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ end
+ end
+ end
+ end
+
+ describe "with excluded groups" do
+ it "works if you exclude a group with a git gem", ruby: ">= 3.3" do
+ build_git "production_gem", "1.0"
+ build_git "development_gem", "1.0"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "production_gem", :git => "#{lib_path("production_gem-1.0")}"
+
+ group :development do
+ gem "development_gem", :git => "#{lib_path("development_gem-1.0")}"
+ end
+ G
+
+ # First install all groups to create lockfile
+ bundle :install
+
+ # Set without and reinstall
+ bundle_config "without development"
+ bundle :install
+
+ # Verify only production gem is available
+ expect(the_bundle).to include_gems("production_gem 1.0")
+ expect(the_bundle).not_to include_gems("development_gem 1.0")
+ end
+
+ it "resolves indirect dependencies from a git source not in the requested groups" do
+ build_lib "activesupport", "1.0", path: lib_path("rails/activesupport")
+ build_git "activerecord", "1.0", path: lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 1.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "activerecord", :git => "#{lib_path("rails")}"
+
+ group :ci do
+ gem "myrack"
+ end
+ G
+
+ bundle_config "only ci"
+ bundle :install
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ expect(the_bundle).not_to include_gems("activerecord 1.0")
+ end
+
+ it "resolves indirect dependencies from a git source not in the requested groups (without compact_index dependency API)" do
+ build_lib "activesupport", "1.0", path: lib_path("rails/activesupport")
+ build_git "activerecord", "1.0", path: lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 1.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "activerecord", :git => "#{lib_path("rails")}"
+
+ group :ci do
+ gem "myrack"
+ end
+ G
+
+ # Force the RubygemsAggregate code path in find_source_requirements by
+ # making the dependency API unavailable.
+ bundle_config "only ci"
+ bundle :install, artifice: "endpoint_api_forbidden"
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ expect(the_bundle).not_to include_gems("activerecord 1.0")
+ end
end
end
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index e41e7e0157..4cffa65b2a 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -1,231 +1,301 @@
# frozen_string_literal: true
RSpec.describe "global gem caching" do
- before { bundle! "config global_gem_cache true" }
+ # Uses subprocess because this setting must apply across multiple app directories (bundled_app and bundled_app2)
+ before { bundle "config set global_gem_cache true" }
describe "using the cross-application user cache" do
let(:source) { "http://localgemserver.test" }
let(:source2) { "http://gemserver.example.org" }
+ def cache_base
+ # Use the unified global gem cache path if available (from RubyGems),
+ # otherwise fall back to the Bundler-specific cache location
+ if Gem.respond_to?(:global_gem_cache_path)
+ Pathname.new(Gem.global_gem_cache_path)
+ else
+ home(".bundle", "cache", "gems")
+ end
+ end
+
def source_global_cache(*segments)
- home(".bundle", "cache", "gems", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments)
+ cache_base.join("localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments)
end
def source2_global_cache(*segments)
- home(".bundle", "cache", "gems", "gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments)
+ cache_base.join("gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments)
end
it "caches gems into the global cache on download" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
end
it "uses globally cached gems if they exist" do
source_global_cache.mkpath
- FileUtils.cp(gem_repo1("gems/rack-1.0.0.gem"), source_global_cache("rack-1.0.0.gem"))
+ FileUtils.cp(gem_repo1("gems/myrack-1.0.0.gem"), source_global_cache("myrack-1.0.0.gem"))
- install_gemfile! <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
- gem "rack"
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "shows a proper error message if a cached gem is corrupted" do
+ skip "This example is not working on ruby/ruby repo" if ruby_core?
+
+ source_global_cache.mkpath
+ FileUtils.touch(source_global_cache("myrack-1.0.0.gem"))
+
+ install_gemfile <<-G, artifice: "compact_index_no_gem", raise_on_error: false
+ source "#{source}"
+ gem "myrack"
+ G
+
+ expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("myrack-1.0.0.gem")}")
+ end
+
+ it "uses a shorter path for the cache to not hit filesystem limits" do
+ install_gemfile <<-G, artifice: "compact_index", verbose: true
+ source "http://#{"a" * 255}.test"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ source_segment = "a" * 222 + ".a3cb26de2edfce9f509a65c611d99c4b"
+ source_cache = cache_base.join(source_segment)
+ cached_gem = source_cache.join("myrack-1.0.0.gem")
+ expect(cached_gem).to exist
+ ensure
+ # We cleanup dummy files created by this spec manually because due to a
+ # Ruby on Windows bug, `FileUtils.rm_rf` (run in our global after hook)
+ # cannot traverse directories with such long names. So we delete
+ # everything explicitly to workaround the bug. An alternative workaround
+ # would be to shell out to `rm -rf`. That also works fine, but I went with
+ # the more verbose and explicit approach. This whole ensure block can be
+ # removed once/if https://bugs.ruby-lang.org/issues/21177 is fixed, and
+ # once the fix propagates to all supported rubies.
+ File.delete cached_gem
+ Dir.rmdir source_cache
+
+ File.delete compact_index_cache_path.join(source_segment, "info", "myrack")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info")
+ File.delete compact_index_cache_path.join(source_segment, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info-etags")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info-special-characters")
+ File.delete compact_index_cache_path.join(source_segment, "versions")
+ File.delete compact_index_cache_path.join(source_segment, "versions.etag")
+ Dir.rmdir compact_index_cache_path.join(source_segment)
end
describe "when the same gem from different sources is installed" do
it "should use the appropriate one from the global cache" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ bundle_config "path.system true"
+
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- FileUtils.rm_r(default_bundle_path)
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- # rack 1.0.0 is not installed and it is in the global cache
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ # myrack 1.0.0 is not installed and it is in the global cache
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- FileUtils.rm_r(default_bundle_path)
- expect(the_bundle).not_to include_gems "rack 0.9.1"
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
- # rack 0.9.1 is not installed and it is in the global cache
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ # myrack 0.9.1 is not installed and it is in the global cache
gemfile <<-G
source "#{source}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- bundle! :install, :artifice => "compact_index_no_gem"
- # rack 1.0.0 is installed and rack 0.9.1 is not
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(the_bundle).not_to include_gems "rack 0.9.1"
- FileUtils.rm_r(default_bundle_path)
+ bundle :install, artifice: "compact_index_no_gem"
+ # myrack 1.0.0 is installed and myrack 0.9.1 is not
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ pristine_system_gems
gemfile <<-G
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- bundle! :install, :artifice => "compact_index_no_gem"
- # rack 0.9.1 is installed and rack 1.0.0 is not
- expect(the_bundle).to include_gems "rack 0.9.1"
- expect(the_bundle).not_to include_gems "rack 1.0.0"
+ bundle :install, artifice: "compact_index_no_gem"
+ # myrack 0.9.1 is installed and myrack 1.0.0 is not
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
end
it "should not install if the wrong source is provided" do
+ bundle_config "path.system true"
+
gemfile <<-G
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- bundle! :install, :artifice => "compact_index"
- FileUtils.rm_r(default_bundle_path)
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- # rack 1.0.0 is not installed and it is in the global cache
+ bundle :install, artifice: "compact_index"
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ # myrack 1.0.0 is not installed and it is in the global cache
gemfile <<-G
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- bundle! :install, :artifice => "compact_index"
- FileUtils.rm_r(default_bundle_path)
- expect(the_bundle).not_to include_gems "rack 0.9.1"
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
- # rack 0.9.1 is not installed and it is in the global cache
+ bundle :install, artifice: "compact_index"
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ # myrack 0.9.1 is not installed and it is in the global cache
gemfile <<-G
source "#{source2}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem"
- expect(out).to include("Internal Server Error 500")
- # rack 1.0.0 is not installed and rack 0.9.1 is not
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(the_bundle).not_to include_gems "rack 0.9.1"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ bundle :install, artifice: "compact_index_no_gem", raise_on_error: false
+ expect(err).to include("Internal Server Error 500")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ # myrack 1.0.0 is not installed and myrack 0.9.1 is not
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
gemfile <<-G
source "#{source}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem"
- expect(out).to include("Internal Server Error 500")
- # rack 0.9.1 is not installed and rack 1.0.0 is not
- expect(the_bundle).not_to include_gems "rack 0.9.1"
- expect(the_bundle).not_to include_gems "rack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ bundle :install, artifice: "compact_index_no_gem", raise_on_error: false
+ expect(err).to include("Internal Server Error 500")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ # myrack 0.9.1 is not installed and myrack 1.0.0 is not
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
end
end
describe "when installing gems from a different directory" do
it "uses the global cache as a source" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ bundle_config "path.system true"
+
+ install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
gem "activesupport"
G
# Both gems are installed and in the global cache
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- FileUtils.rm_r(default_bundle_path)
+ pristine_system_gems
# Both gems are now only in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0"
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- install_gemfile! <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- # rack is installed and both are in the global cache
- expect(the_bundle).to include_gems "rack 1.0.0"
+ # myrack is installed and both are in the global cache
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- Dir.chdir bundled_app2 do
- create_file bundled_app2("gems.rb"), <<-G
- source "#{source}"
- gem "activesupport"
- G
-
- # Neither gem is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source_global_cache("activesupport-2.3.5.gem")).to exist
-
- # Install using the global cache instead of by downloading the .gem
- # from the server
- bundle! :install, :artifice => "compact_index_no_gem"
-
- # activesupport is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(the_bundle).to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- end
+ create_file bundled_app2("gems.rb"), <<-G
+ source "#{source}"
+ gem "activesupport"
+ G
+
+ # Neither gem is installed and both are in the global cache
+ expect(the_bundle).not_to include_gems "myrack 1.0.0", dir: bundled_app2
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", dir: bundled_app2
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source_global_cache("activesupport-2.3.5.gem")).to exist
+
+ # Install using the global cache instead of by downloading the .gem
+ # from the server
+ bundle :install, artifice: "compact_index_no_gem", dir: bundled_app2
+
+ # activesupport is installed and both are in the global cache
+ expect(the_bundle).not_to include_gems "myrack 1.0.0", dir: bundled_app2
+ expect(the_bundle).to include_gems "activesupport 2.3.5", dir: bundled_app2
+
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source_global_cache("activesupport-2.3.5.gem")).to exist
end
end
end
- describe "extension caching", :ruby_repo, :rubygems => "2.2" do
+ describe "extension caching" do
it "works" do
+ skip "gets incorrect ref in path" if Gem.win_platform?
+ skip "fails for unknown reason when run by ruby-core" if ruby_core?
+
build_git "very_simple_git_binary", &:add_c_extension
build_lib "very_simple_path_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))[0, 12]
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "very_simple_binary"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}"
gem "very_simple_path_binary", :path => "#{lib_path("very_simple_path_binary-1.0")}"
G
- gem_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
- Digest(:MD5).hexdigest("#{gem_repo1}/"), "very_simple_binary-1.0")
- git_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
+ gem_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
+ "gem.repo1.443.#{Digest(:MD5).hexdigest("gem.repo1.443./")}", "very_simple_binary-1.0")
+ git_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
"very_simple_git_binary-1.0-#{revision}", "very_simple_git_binary-1.0")
cached_extensions = Pathname.glob(home(".bundle", "cache", "extensions", "*", "*", "*", "*", "*")).sort
expect(cached_extensions).to eq [gem_binary_cache, git_binary_cache].sort
- run! <<-R
+ run <<-R
require 'very_simple_binary_c'; puts ::VERY_SIMPLE_BINARY_IN_C
require 'very_simple_git_binary_c'; puts ::VERY_SIMPLE_GIT_BINARY_IN_C
R
expect(out).to eq "VERY_SIMPLE_BINARY_IN_C\nVERY_SIMPLE_GIT_BINARY_IN_C"
- FileUtils.rm Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
+ FileUtils.rm_r Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
gem_binary_cache.join("very_simple_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
git_binary_cache.join("very_simple_git_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
- bundle! "config --local path different_path"
- bundle! :install
+ bundle_config "path different_path"
+ bundle :install
expect(Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]).to all(end_with(".rb"))
- run! <<-R
+ run <<-R
require 'very_simple_binary_c'
require 'very_simple_git_binary_c'
R
diff --git a/spec/bundler/install/path_spec.rb b/spec/bundler/install/path_spec.rb
index 94f38c9290..49360e511e 100644
--- a/spec/bundler/install/path_spec.rb
+++ b/spec/bundler/install/path_spec.rb
@@ -1,96 +1,87 @@
# frozen_string_literal: true
RSpec.describe "bundle install" do
- describe "with --path" do
+ describe "with path configured" do
before :each do
- build_gem "rack", "1.0.0", :to_system => true do |s|
- s.write "lib/rack.rb", "puts 'FAIL'"
+ build_gem "myrack", "1.0.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "puts 'FAIL'"
end
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- it "does not use available system gems with bundle --path vendor/bundle", :bundler => "< 3" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ it "does not use available system gems with `vendor/bundle" do
+ bundle_config "path vendor/bundle"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "uses system gems with `path.system` configured with more priority than `path`" do
+ bundle_config "path.system true"
+ bundle_config_global "path vendor/bundle"
+ bundle :install
+ run "require 'myrack'", raise_on_error: false
+ expect(out).to include("FAIL")
end
it "handles paths with regex characters in them" do
dir = bundled_app("bun++dle")
dir.mkpath
- Dir.chdir(dir) do
- bundle! :install, forgotten_command_line_options(:path => dir.join("vendor/bundle"))
- expect(out).to include("installed into `./vendor/bundle`")
- end
+ bundle_config "path #{dir.join("vendor/bundle")}"
+ bundle :install, dir: dir
+ expect(out).to include("installed into `./vendor/bundle`")
- dir.rmtree
+ FileUtils.rm_rf dir
end
- it "prints a warning to let the user know what has happened with bundle --path vendor/bundle" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ it "prints a message to let the user know where gems where installed" do
+ bundle_config "path vendor/bundle"
+ bundle :install
expect(out).to include("gems are installed into `./vendor/bundle`")
end
- it "disallows --path vendor/bundle --system", :bundler => "< 3" do
- bundle "install --path vendor/bundle --system"
- expect(out).to include("Please choose only one option.")
- expect(exitstatus).to eq(15) if exitstatus
+ it "installs the bundle relatively to repository root, when Bundler run from the same directory" do
+ bundle "config set path vendor/bundle", dir: bundled_app.parent
+ bundle "install --gemfile='#{bundled_app}/Gemfile'", dir: bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/vendor/bundle`")
+ expect(bundled_app("vendor/bundle")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "remembers to disable system gems after the first time with bundle --path vendor/bundle", :bundler => "< 3" do
- bundle "install --path vendor/bundle"
- FileUtils.rm_rf bundled_app("vendor")
- bundle "install"
-
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ it "installs the bundle relatively to repository root, when Bundler run from a different directory" do
+ bundle "config set path vendor/bundle", dir: bundled_app
+ bundle "install --gemfile='#{bundled_app}/Gemfile'", dir: bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/vendor/bundle`")
+ expect(bundled_app("vendor/bundle")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- context "with path_relative_to_cwd set to true" do
- before { bundle! "config path_relative_to_cwd true" }
+ it "installs the standalone bundle relative to the cwd" do
+ bundle :install, gemfile: bundled_app_gemfile, standalone: true, dir: bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/bundle`")
+ expect(bundled_app("bundle")).to be_directory
+ expect(bundled_app("bundle/ruby")).to be_directory
- it "installs the bundle relatively to current working directory", :bundler => "< 3" do
- Dir.chdir(bundled_app.parent) do
- bundle! "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle"
- expect(out).to include("installed into `./vendor/bundle`")
- expect(bundled_app("../vendor/bundle")).to be_directory
- end
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "installs the standalone bundle relative to the cwd" do
- Dir.chdir(bundled_app.parent) do
- bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true
- expect(out).to include("installed into `./bundled_app/bundle`")
- expect(bundled_app("bundle")).to be_directory
- expect(bundled_app("bundle/ruby")).to be_directory
- end
-
- bundle! "config unset path"
-
- Dir.chdir(bundled_app("subdir").tap(&:mkpath)) do
- bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true
- expect(out).to include("installed into `../bundle`")
- expect(bundled_app("bundle")).to be_directory
- expect(bundled_app("bundle/ruby")).to be_directory
- end
- end
+ bundle :install, gemfile: bundled_app_gemfile, standalone: true, dir: bundled_app("subdir").tap(&:mkpath)
+ expect(out).to include("installed into `../bundle`")
+ expect(bundled_app("bundle")).to be_directory
+ expect(bundled_app("bundle/ruby")).to be_directory
end
end
describe "when BUNDLE_PATH or the global path config is set" do
before :each do
- build_lib "rack", "1.0.0", :to_system => true do |s|
- s.write "lib/rack.rb", "raise 'FAIL'"
+ build_lib "myrack", "1.0.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "raise 'FAIL'"
end
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -98,7 +89,7 @@ RSpec.describe "bundle install" do
if type == :env
ENV["BUNDLE_PATH"] = location
elsif type == :global
- bundle! "config path #{location}", "no-color" => nil
+ bundle "config set path #{location}", "no-color" => nil
end
end
@@ -106,151 +97,118 @@ RSpec.describe "bundle install" do
context "when set via #{type}" do
it "installs gems to a path if one is specified" do
set_bundle_path(type, bundled_app("vendor2").to_s)
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
expect(bundled_app("vendor2")).not_to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- context "with global_path_appends_ruby_scope set", :bundler => "3" do
- it "installs gems to ." do
- set_bundle_path(type, ".")
- bundle! "config --global disable_shared_gems true"
+ it "installs gems to ." do
+ set_bundle_path(type, ".")
+ bundle_config_global "disable_shared_gems true"
- bundle! :install
+ bundle :install
- paths_to_exist = %w[cache/rack-1.0.0.gem gems/rack-1.0.0 specifications/rack-1.0.0.gemspec].map {|path| bundled_app(Bundler.ruby_scope, path) }
- expect(paths_to_exist).to all exist
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "installs gems to the path" do
- set_bundle_path(type, bundled_app("vendor").to_s)
-
- bundle! :install
-
- expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "installs gems to the path relative to root when relative" do
- set_bundle_path(type, "vendor")
-
- FileUtils.mkdir_p bundled_app("lol")
- Dir.chdir(bundled_app("lol")) do
- bundle! :install
- end
-
- expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ paths_to_exist = %w[cache/myrack-1.0.0.gem gems/myrack-1.0.0 specifications/myrack-1.0.0.gemspec].map {|path| bundled_app(Bundler.ruby_scope, path) }
+ expect(paths_to_exist).to all exist
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- context "with global_path_appends_ruby_scope unset", :bundler => "< 3" do
- it "installs gems to ." do
- set_bundle_path(type, ".")
- bundle! "config --global disable_shared_gems true"
-
- bundle! :install
-
- expect([bundled_app("cache/rack-1.0.0.gem"), bundled_app("gems/rack-1.0.0"), bundled_app("specifications/rack-1.0.0.gemspec")]).to all exist
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ it "installs gems to the path" do
+ set_bundle_path(type, bundled_app("vendor").to_s)
- it "installs gems to BUNDLE_PATH with #{type}" do
- set_bundle_path(type, bundled_app("vendor").to_s)
+ bundle :install
- bundle :install
-
- expect(bundled_app("vendor/gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ expect(bundled_app("vendor", Bundler.ruby_scope, "gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
- it "installs gems to BUNDLE_PATH relative to root when relative" do
- set_bundle_path(type, "vendor")
+ it "installs gems to the path relative to root when relative" do
+ set_bundle_path(type, "vendor")
- FileUtils.mkdir_p bundled_app("lol")
- Dir.chdir(bundled_app("lol")) do
- bundle :install
- end
+ FileUtils.mkdir_p bundled_app("lol")
+ bundle :install, dir: bundled_app("lol")
- expect(bundled_app("vendor/gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ expect(bundled_app("vendor", Bundler.ruby_scope, "gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
it "installs gems to BUNDLE_PATH from .bundle/config" do
- config "BUNDLE_PATH" => bundled_app("vendor/bundle").to_s
+ bundle_config "BUNDLE_PATH" => bundled_app("vendor/bundle").to_s
bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "sets BUNDLE_PATH as the first argument to bundle install" do
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle_config "path ./vendor/bundle"
+ bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "disables system gems when passing a path to install" do
# This is so that vendored gems can be distributed to others
- build_gem "rack", "1.1.0", :to_system => true
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ build_gem "myrack", "1.1.0", to_system: true
+ bundle_config "path ./vendor/bundle"
+ bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "re-installs gems whose extensions have been deleted", :ruby_repo, :rubygems => ">= 2.3" do
- build_lib "very_simple_binary", "1.0.0", :to_system => true do |s|
+ it "re-installs gems whose extensions have been deleted" do
+ build_lib "very_simple_binary", "1.0.0", to_system: true do |s|
s.write "lib/very_simple_binary.rb", "raise 'FAIL'"
end
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "very_simple_binary"
G
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle_config "path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
- expect(the_bundle).to include_gems "very_simple_binary 1.0", :source => "remote1"
+ expect(the_bundle).to include_gems "very_simple_binary 1.0", source: "remote1"
- vendored_gems("extensions").rmtree
+ FileUtils.rm_rf vendored_gems("extensions")
- run "require 'very_simple_binary_c'"
+ run "require 'very_simple_binary_c'", raise_on_error: false
expect(err).to include("Bundler::GemNotFound")
- bundle :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle_config "path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
- expect(the_bundle).to include_gems "very_simple_binary 1.0", :source => "remote1"
+ expect(the_bundle).to include_gems "very_simple_binary 1.0", source: "remote1"
end
end
describe "to a file" do
before do
- in_app_root do
- FileUtils.touch "bundle"
- end
+ FileUtils.touch bundled_app("bundle")
end
it "reports the file exists" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, forgotten_command_line_options(:path => "bundle")
- expect(out).to include("file already exists")
+ bundle_config "path bundle"
+ bundle :install, raise_on_error: false
+ expect(err).to include("file already exists")
end
end
end
diff --git a/spec/bundler/install/post_bundle_message_spec.rb b/spec/bundler/install/post_bundle_message_spec.rb
deleted file mode 100644
index 394134f523..0000000000
--- a/spec/bundler/install/post_bundle_message_spec.rb
+++ /dev/null
@@ -1,206 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "post bundle message" do
- before :each do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", "2.3.5", :group => [:emo, :test]
- group :test do
- gem "rspec"
- end
- gem "rack-obama", :group => :obama
- G
- end
-
- let(:bundle_path) { "./.bundle" }
- let(:bundle_show_system_message) { "Use `bundle info [gemname]` to see where a bundled gem is installed." }
- let(:bundle_show_path_message) { "Bundled gems are installed into `#{bundle_path}`" }
- let(:bundle_complete_message) { "Bundle complete!" }
- let(:bundle_updated_message) { "Bundle updated!" }
- let(:installed_gems_stats) { "4 Gemfile dependencies, 5 gems now installed." }
- let(:bundle_show_message) { Bundler::VERSION.split(".").first.to_i < 3 ? bundle_show_system_message : bundle_show_path_message }
-
- describe "for fresh bundle install" do
- it "without any options" do
- bundle :install
- expect(out).to include(bundle_show_message)
- expect(out).not_to include("Gems in the group")
- expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
- end
-
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the group emo were not installed")
- expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
- end
-
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
- expect(out).to include(bundle_complete_message)
- expect(out).to include("4 Gemfile dependencies, 3 gems now installed.")
- end
-
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
- expect(out).to include(bundle_complete_message)
- expect(out).to include("4 Gemfile dependencies, 2 gems now installed.")
- end
-
- describe "with --path and" do
- let(:bundle_path) { "./vendor" }
-
- it "without any options" do
- bundle! :install, forgotten_command_line_options(:path => "vendor")
- expect(out).to include(bundle_show_path_message)
- expect(out).to_not include("Gems in the group")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo", :path => "vendor")
- expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the group emo were not installed")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test", :path => "vendor")
- expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test", :path => "vendor")
- expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with an absolute --path inside the cwd" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("cache"))
- expect(out).to include("Bundled gems are installed into `./cache`")
- expect(out).to_not include("Gems in the group")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with an absolute --path outside the cwd" do
- bundle! :install, forgotten_command_line_options(:path => tmp("not_bundled_app"))
- expect(out).to include("Bundled gems are installed into `#{tmp("not_bundled_app")}`")
- expect(out).to_not include("Gems in the group")
- expect(out).to include(bundle_complete_message)
- end
- end
-
- describe "with misspelled or non-existent gem name" do
- it "should report a helpful error message", :bundler => "< 3" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "not-a-gem", :group => :development
- G
- expect(out).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.")
- end
-
- it "should report a helpful error message", :bundler => "3" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "not-a-gem", :group => :development
- G
- expect(out).to include normalize_uri_file(<<-EOS.strip)
-Could not find gem 'not-a-gem' in rubygems repository file://localhost#{gem_repo1}/ or installed locally.
-The source does not contain any versions of 'not-a-gem'
- EOS
- end
-
- it "should report a helpful error message with reference to cache if available" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- G
- bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "not-a-gem", :group => :development
- G
- expect(out).to include("Could not find gem 'not-a-gem' in").
- and include("or in gems cached in vendor/cache.")
- end
- end
- end
-
- describe "for second bundle install run" do
- it "without any options" do
- 2.times { bundle :install }
- expect(out).to include(bundle_show_message)
- expect(out).to_not include("Gems in the groups")
- expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
- end
-
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- bundle! :install
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the group emo were not installed")
- expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
- end
-
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
- bundle! :install
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
- expect(out).to include(bundle_complete_message)
- end
-
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
- bundle :install
- expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
- expect(out).to include(bundle_complete_message)
- end
- end
-
- describe "for bundle update" do
- it "without any options" do
- bundle! :update, :all => bundle_update_requires_all?
- expect(out).not_to include("Gems in the groups")
- expect(out).to include(bundle_updated_message)
- end
-
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- bundle! :update, :all => bundle_update_requires_all?
- expect(out).to include("Gems in the group emo were not installed")
- expect(out).to include(bundle_updated_message)
- end
-
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
- bundle! :update, :all => bundle_update_requires_all?
- expect(out).to include("Gems in the groups emo and test were not installed")
- expect(out).to include(bundle_updated_message)
- end
-
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
- bundle! :update, :all => bundle_update_requires_all?
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
- expect(out).to include(bundle_updated_message)
- end
- end
-end
diff --git a/spec/bundler/install/prereleases_spec.rb b/spec/bundler/install/prereleases_spec.rb
index 7af8c3b304..9f764d127c 100644
--- a/spec/bundler/install/prereleases_spec.rb
+++ b/spec/bundler/install/prereleases_spec.rb
@@ -1,10 +1,19 @@
# frozen_string_literal: true
RSpec.describe "bundle install" do
+ before do
+ build_repo2 do
+ build_gem "not_released", "1.0.pre"
+
+ build_gem "has_prerelease", "1.0"
+ build_gem "has_prerelease", "1.1.pre"
+ end
+ end
+
describe "when prerelease gems are available" do
it "finds prereleases" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "not_released"
G
expect(the_bundle).to include_gems "not_released 1.0.pre"
@@ -12,7 +21,7 @@ RSpec.describe "bundle install" do
it "uses regular releases if available" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "has_prerelease"
G
expect(the_bundle).to include_gems "has_prerelease 1.0"
@@ -20,7 +29,7 @@ RSpec.describe "bundle install" do
it "uses prereleases if requested" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo2"
gem "has_prerelease", "1.1.pre"
G
expect(the_bundle).to include_gems "has_prerelease 1.1.pre"
@@ -29,13 +38,17 @@ RSpec.describe "bundle install" do
describe "when prerelease gems are not available" do
it "still works" do
- build_repo3
+ build_repo3 do
+ build_gem "myrack"
+ end
+ FileUtils.rm_r Dir[gem_repo3("prerelease*")]
+
install_gemfile <<-G
- source "file://#{gem_repo3}"
- gem "rack"
+ source "https://gem.repo3"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb
index be8fd04fdd..b096291d1a 100644
--- a/spec/bundler/install/process_lock_spec.rb
+++ b/spec/bundler/install/process_lock_spec.rb
@@ -8,28 +8,106 @@ RSpec.describe "process lock spec" do
thread = Thread.new do
Bundler::ProcessLock.lock(default_bundle_path) do
sleep 1 # ignore quality_spec
- expect(the_bundle).not_to include_gems "rack 1.0"
+ expect(the_bundle).not_to include_gems "myrack 1.0"
end
end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
thread.join
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
- context "when creating a lock raises Errno::ENOTSUP", :ruby => ">= 1.9" do
+ context "when creating a lock raises Errno::ENOTSUP" do
before { allow(File).to receive(:open).and_raise(Errno::ENOTSUP) }
- it "skips creating the lock file and yields" do
+ it "skips creating the lockfile and yields" do
processed = false
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
expect(processed).to eq true
end
end
+
+ context "when creating a lock raises Errno::EPERM" do
+ before { allow(File).to receive(:open).and_raise(Errno::EPERM) }
+
+ it "skips creating the lockfile and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
+
+ context "when creating a lock raises Errno::EROFS" do
+ before { allow(File).to receive(:open).and_raise(Errno::EROFS) }
+
+ it "skips creating the lockfile and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
+
+ it "refreshes gem specification cache after waiting for lock" do
+ build_repo2 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ # First, install the gem so it's available
+ bundle "install"
+ expect(out).to include("Installing myrack")
+
+ # Queue for thread-safe communication
+ lock_acquired = Queue.new
+ can_release_lock = Queue.new
+ install_output = Queue.new
+
+ # Thread holds lock (simulating another bundle process that just finished installing)
+ thread = Thread.new do
+ Bundler::ProcessLock.lock(default_bundle_path) do
+ # Signal that we have the lock
+ lock_acquired << true
+ # Wait until main thread signals we can release
+ can_release_lock.pop
+ end
+ end
+
+ # Wait for thread to acquire lock
+ lock_acquired.pop
+
+ # Start another install in a thread - it will wait for the lock
+ install_thread = Thread.new do
+ bundle "install", verbose: true
+ install_output << out
+ end
+
+ # Give subprocess time to start and begin waiting for lock
+ sleep 0.5
+
+ # Signal thread to release the lock
+ can_release_lock << true
+
+ # Wait for both threads to complete
+ thread.join
+ install_thread.join
+
+ second_install_out = install_output.pop
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ # The second install should have refreshed its cache after acquiring
+ # the lock and seen that myrack was already installed
+ expect(second_install_out).to include("Using myrack")
+ end
end
end
diff --git a/spec/bundler/install/redownload_spec.rb b/spec/bundler/install/redownload_spec.rb
deleted file mode 100644
index f9caeed58a..0000000000
--- a/spec/bundler/install/redownload_spec.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle install", :bundler => "< 3", :ruby => ">= 2.0" do
- before :each do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- end
-
- before { bundle "config major_deprecations yes" }
-
- shared_examples_for "an option to force redownloading gems" do
- it "re-installs installed gems" do
- rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb")
-
- bundle! :install
- rack_lib.open("w") {|f| f.write("blah blah blah") }
- bundle! :install, flag => true
-
- expect(out).to include "Installing rack 1.0.0"
- expect(rack_lib.open(&:read)).to eq("RACK = '1.0.0'\n")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "works on first bundle install" do
- bundle! :install, flag => true
-
- expect(out).to include "Installing rack 1.0.0"
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- context "with a git gem" do
- let!(:ref) { build_git("foo", "1.0").ref_for("HEAD", 11) }
-
- before do
- gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}"
- G
- end
-
- it "re-installs installed gems" do
- foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb")
-
- bundle! :install
- foo_lib.open("w") {|f| f.write("blah blah blah") }
- bundle! :install, flag => true
-
- expect(foo_lib.open(&:read)).to eq("FOO = '1.0'\n")
- expect(the_bundle).to include_gems "foo 1.0"
- end
-
- it "works on first bundle install" do
- bundle! :install, flag => true
-
- expect(the_bundle).to include_gems "foo 1.0"
- end
- end
- end
-
- describe "with --force" do
- it_behaves_like "an option to force redownloading gems" do
- let(:flag) { "force" }
- end
-
- it "shows a deprecation when single flag passed" do
- bundle! "install --force"
- expect(out).to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
-
- it "shows a deprecation when multiple flags passed" do
- bundle! "install --no-color --force"
- expect(out).to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
- end
-
- describe "with --redownload" do
- it_behaves_like "an option to force redownloading gems" do
- let(:flag) { "redownload" }
- end
-
- it "does not show a deprecation when single flag passed" do
- bundle! "install --redownload"
- expect(out).not_to include "[DEPRECATED FOR 2.0] The `--force` option has been renamed to `--redownload`"
- end
-
- it "does not show a deprecation when single multiple flags passed" do
- bundle! "install --no-color --redownload"
- expect(out).not_to include "[DEPRECATED FOR 2.0] The `--force` option has been renamed to `--redownload`"
- end
- end
-end
diff --git a/spec/bundler/install/security_policy_spec.rb b/spec/bundler/install/security_policy_spec.rb
index 7be09d6bd4..e7f64dc227 100644
--- a/spec/bundler/install/security_policy_spec.rb
+++ b/spec/bundler/install/security_policy_spec.rb
@@ -9,38 +9,35 @@ RSpec.describe "policies with unsigned gems" do
before do
build_security_repo
gemfile <<-G
- source "file://#{security_repo}"
- gem "rack"
+ source "https://gems.security"
+ gem "myrack"
gem "signed_gem"
G
end
it "will work after you try to deploy without a lock" do
- bundle "install --deployment"
+ bundle "install --deployment", raise_on_error: false
bundle :install
- expect(exitstatus).to eq(0) if exitstatus
- expect(the_bundle).to include_gems "rack 1.0", "signed_gem 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0", "signed_gem 1.0"
end
it "will fail when given invalid security policy" do
- bundle "install --trust-policy=InvalidPolicyName"
- expect(out).to include("RubyGems doesn't know about trust policy")
+ bundle "install --trust-policy=InvalidPolicyName", raise_on_error: false
+ expect(err).to include("RubyGems doesn't know about trust policy")
end
it "will fail with High Security setting due to presence of unsigned gem" do
- bundle "install --trust-policy=HighSecurity"
- expect(out).to include("security policy didn't allow")
+ bundle "install --trust-policy=HighSecurity", raise_on_error: false
+ expect(err).to include("security policy didn't allow")
end
- # This spec will fail on RubyGems 2 rc1 due to a bug in policy.rb. the bug is fixed in rc3.
- it "will fail with Medium Security setting due to presence of unsigned gem", :unless => ENV["RGV"] == "v2.0.0.rc.1" do
- bundle "install --trust-policy=MediumSecurity"
- expect(out).to include("security policy didn't allow")
+ it "will fail with Medium Security setting due to presence of unsigned gem" do
+ bundle "install --trust-policy=MediumSecurity", raise_on_error: false
+ expect(err).to include("security policy didn't allow")
end
it "will succeed with no policy" do
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -48,30 +45,28 @@ RSpec.describe "policies with signed gems and no CA" do
before do
build_security_repo
gemfile <<-G
- source "file://#{security_repo}"
+ source "https://gems.security"
gem "signed_gem"
G
end
it "will fail with High Security setting, gem is self-signed" do
- bundle "install --trust-policy=HighSecurity"
- expect(out).to include("security policy didn't allow")
+ bundle "install --trust-policy=HighSecurity", raise_on_error: false
+ expect(err).to include("security policy didn't allow")
end
it "will fail with Medium Security setting, gem is self-signed" do
- bundle "install --trust-policy=MediumSecurity"
- expect(out).to include("security policy didn't allow")
+ bundle "install --trust-policy=MediumSecurity", raise_on_error: false
+ expect(err).to include("security policy didn't allow")
end
it "will succeed with Low Security setting, low security accepts self signed gem" do
bundle "install --trust-policy=LowSecurity"
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "signed_gem 1.0"
end
it "will succeed with no policy" do
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "signed_gem 1.0"
end
end
diff --git a/spec/bundler/install/yanked_spec.rb b/spec/bundler/install/yanked_spec.rb
index 7c4b98bfdf..c92af7bfb0 100644
--- a/spec/bundler/install/yanked_spec.rb
+++ b/spec/bundler/install/yanked_spec.rb
@@ -1,71 +1,254 @@
# frozen_string_literal: true
RSpec.context "when installing a bundle that includes yanked gems" do
- before(:each) do
+ it "throws an error when the original gem version is yanked" do
build_repo4 do
build_gem "foo", "9.0.0"
end
- end
- it "throws an error when the original gem version is yanked" do
lockfile <<-L
GEM
- remote: file://#{gem_repo4}
+ remote: https://gem.repo4
specs:
foo (10.0.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
foo (= 10.0.0)
L
- install_gemfile <<-G
- source "file://#{gem_repo4}"
- gem "foo", "10.0.0"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo4"
+ gem "foo", "10.0.0"
G
- expect(out).to include("Your bundle is locked to foo (10.0.0)")
+ expect(err).to include("Your bundle is locked to foo (10.0.0)")
+ end
+
+ context "when a platform specific yanked version is included in the lockfile, and a generic variant is available remotely" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actiontext (6.1.6)
+ nokogiri (>= 1.8)
+ foo (1.0.0)
+ nokogiri (1.13.8-#{Bundler.local_platform})
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ actiontext (= 6.1.6)
+ foo (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ skip "Materialization on Windows is not yet strict, so the example does not detect the gem has been yanked" if Gem.win_platform?
+
+ build_repo4 do
+ build_gem "foo", "1.0.0"
+ build_gem "foo", "1.0.1"
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.6" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "nokogiri", "1.13.8"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "foo", "1.0.0"
+ gem "actiontext", "6.1.6"
+ G
+
+ lockfile original_lockfile
+ end
+
+ context "and a re-resolve is necessary" do
+ before do
+ gemfile gemfile.sub('"foo", "1.0.0"', '"foo", "1.0.1"')
+ end
+
+ it "reresolves, and replaces the yanked gem with the generic version, printing a warning, when the old index is used" do
+ bundle "install", artifice: "endpoint", verbose: true
+
+ expect(out).to include("Installing nokogiri 1.13.8").and include("Installing foo 1.0.1")
+ expect(lockfile).to eq(original_lockfile.sub("nokogiri (1.13.8-#{Bundler.local_platform})", "nokogiri (1.13.8)").gsub("1.0.0", "1.0.1"))
+ expect(err).to include("Some locked specs have possibly been yanked (nokogiri-1.13.8-#{Bundler.local_platform}). Ignoring them...")
+ end
+
+ it "reresolves, and replaces the yanked gem with the generic version, printing a warning, when the compact index API is used" do
+ bundle "install", artifice: "compact_index", verbose: true
+
+ expect(out).to include("Installing nokogiri 1.13.8").and include("Installing foo 1.0.1")
+ expect(lockfile).to eq(original_lockfile.sub("nokogiri (1.13.8-#{Bundler.local_platform})", "nokogiri (1.13.8)").gsub("1.0.0", "1.0.1"))
+ expect(err).to include("Some locked specs have possibly been yanked (nokogiri-1.13.8-#{Bundler.local_platform}). Ignoring them...")
+ end
+ end
+
+ it "reports the yanked gem properly when the old index is used" do
+ bundle "install", artifice: "endpoint", raise_on_error: false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
+
+ it "reports the yanked gem properly when the compact index API is used" do
+ bundle "install", artifice: "compact_index", raise_on_error: false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
end
it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do
- install_gemfile <<-G
- source "file://#{gem_repo4}"
- gem "foo", "10.0.0"
+ build_repo4 do
+ build_gem "foo", "9.0.0"
+ end
+
+ bundle_config "force_ruby_platform true"
+
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo4"
+ gem "foo", "10.0.0"
+ G
+
+ expect(err).not_to include("Your bundle is locked to foo (10.0.0)")
+ expect(err).to include("Could not find gem 'foo (= 10.0.0)' in")
+ end
+end
+
+RSpec.context "when resolving a bundle that includes yanked gems, but unlocking an unrelated gem" do
+ before(:each) do
+ build_repo4 do
+ build_gem "foo", "10.0.0"
+
+ build_gem "bar", "1.0.0"
+ build_gem "bar", "2.0.0"
+ end
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ foo (9.0.0)
+ bar (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ gem "bar"
G
+ end
+
+ it "does not update the yanked gem" do
+ bundle "lock --update bar"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bar (2.0.0)
+ foo (9.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ bar
+ foo
- expect(out).not_to include("Your bundle is locked to foo (10.0.0)")
- expect(out).to include("Could not find gem 'foo (= 10.0.0)' in")
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
end
RSpec.context "when using gem before installing" do
it "does not suggest the author has yanked the gem" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
lockfile <<-L
- GEM
- remote: file://#{gem_repo1}
- specs:
- rack (0.9.1)
+ GEM
+ remote: https://gem.repo1
+ specs:
+ myrack (0.9.1)
- PLATFORMS
- ruby
+ PLATFORMS
+ #{lockfile_platforms}
- DEPENDENCIES
- rack (= 0.9.1)
+ DEPENDENCIES
+ myrack (= 0.9.1)
+ L
+
+ bundle :list, raise_on_error: false
+
+ expect(err).to include("Could not find myrack-0.9.1 in locally installed gems")
+ expect(err).to_not include("Your bundle is locked to myrack (0.9.1) from")
+ expect(err).to_not include("If you haven't changed sources, that means the author of myrack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of myrack (0.9.1) that hasn't been removed in order to install.")
+
+ # Check error message is still correct when multiple platforms are locked
+ lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
+
+ bundle :list, raise_on_error: false
+ expect(err).to include("Could not find myrack-0.9.1 in locally installed gems")
+ end
+
+ it "does not suggest the author has yanked the gem when using more than one gem, but shows all gems that couldn't be found in the source" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "myrack_middleware", "1.0"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack (= 0.9.1)
+ myrack_middleware (1.0)
L
- bundle :list
+ bundle :list, raise_on_error: false
- expect(out).to include("Could not find rack-0.9.1 in any of the sources")
- expect(out).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.")
- expect(out).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
- expect(out).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
+ expect(err).to include("Could not find myrack-0.9.1, myrack_middleware-1.0 in locally installed gems")
+ expect(err).to include("Install missing gems with `bundle install`.")
+ expect(err).to_not include("Your bundle is locked to myrack (0.9.1) from")
+ expect(err).to_not include("If you haven't changed sources, that means the author of myrack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of myrack (0.9.1) that hasn't been removed in order to install.")
end
end
diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb
index 14b80483ee..c9f76115dc 100644
--- a/spec/bundler/lock/git_spec.rb
+++ b/spec/bundler/lock/git_spec.rb
@@ -1,19 +1,76 @@
# frozen_string_literal: true
RSpec.describe "bundle lock with git gems" do
- before :each do
+ let(:install_gemfile_with_foo_as_a_git_dependency) do
build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
end
it "doesn't break right after running lock" do
+ install_gemfile_with_foo_as_a_git_dependency
+
expect(the_bundle).to include_gems "foo 1.0.0"
end
+ it "doesn't print errors even if running lock after removing the cache" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ FileUtils.rm_r(Dir[default_cache_path("git/foo-1.0-*")].first)
+
+ bundle "lock --verbose"
+
+ expect(err).to be_empty
+ end
+
+ it "prints a proper error when changing a locked Gemfile to point to a bad branch" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad"
+ G
+
+ bundle "lock --update foo", env: { "LANG" => "en" }, raise_on_error: false
+
+ expect(err).to include("Revision bad does not exist in the repository")
+ end
+
+ it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{"a" * 40}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", raise_on_error: false
+
+ expect(err).to include("Revision #{"a" * 40} does not exist in the repository")
+ end
+
it "locks a git source to the current ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
update_git "foo"
bundle :install
@@ -25,10 +82,177 @@ RSpec.describe "bundle lock with git gems" do
expect(out).to eq("WIN")
end
+ it "properly clones a git source locked to an out of date ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ update_git "foo"
+
+ bundle :install, env: { "BUNDLE_PATH" => "foo" }
+ expect(err).to be_empty
+ end
+
+ it "properly fetches a git source locked to an unreachable ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ # Create a commit and make it unreachable
+ git "checkout -b foo ", lib_path("foo-1.0")
+ unreachable_sha = update_git("foo").ref_for("HEAD")
+ git "checkout main ", lib_path("foo-1.0")
+ git "branch -D foo ", lib_path("foo-1.0")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{unreachable_sha}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(err).to be_empty
+ end
+
+ it "properly fetches a git source locked to an annotated tag" do
+ install_gemfile_with_foo_as_a_git_dependency
+
+ # Create an annotated tag
+ git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0"))
+ annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0"))
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{annotated_tag}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(err).to be_empty
+ end
+
it "provides correct #full_gem_path" do
+ install_gemfile_with_foo_as_a_git_dependency
+
run <<-RUBY
puts Bundler.rubygems.find_name('foo').first.full_gem_path
RUBY
expect(out).to eq(bundle("info foo --path"))
end
+
+ it "does not lock versions that don't exist in the repository when changing a GEM transitive dep to a GIT direct dep" do
+ build_repo4 do
+ build_gem "activesupport", "8.0.0" do |s|
+ s.add_dependency "securerandom"
+ end
+
+ build_gem "securerandom", "0.3.1"
+ end
+
+ path = lib_path("securerandom")
+
+ build_git "securerandom", "0.3.2", path: path
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ activesupport (8.0.0)
+ securerandom
+ securerandom (0.3.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "activesupport"
+ gem "securerandom", git: "#{path}"
+ G
+
+ bundle "lock"
+
+ expect(lockfile).to include("securerandom (0.3.2)")
+ end
+
+ it "does not lock versions that don't exist in the repository when changing a GIT direct dep to a GEM direct dep" do
+ build_repo4 do
+ build_gem "ruby-lsp", "0.16.1"
+ end
+
+ path = lib_path("ruby-lsp")
+ revision = build_git("ruby-lsp", "0.16.2", path: path).ref_for("HEAD")
+
+ lockfile <<~L
+ GIT
+ remote: #{path}
+ revision: #{revision}
+ specs:
+ ruby-lsp (0.16.2)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruby-lsp!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "ruby-lsp"
+ G
+
+ bundle "lock"
+
+ expect(lockfile).to include("ruby-lsp (0.16.1)")
+ end
end
diff --git a/spec/bundler/lock/lockfile_bundler_1_spec.rb b/spec/bundler/lock/lockfile_bundler_1_spec.rb
deleted file mode 100644
index 851fbea99a..0000000000
--- a/spec/bundler/lock/lockfile_bundler_1_spec.rb
+++ /dev/null
@@ -1,1386 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "the lockfile format", :bundler => "< 3" do
- include Bundler::GemHelpers
-
- before { ENV["BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD"] = "TRUE" }
-
- it "generates a simple lockfile for a single source, gem" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "updates the lockfile's bundler version if current ver. is newer" do
- lockfile <<-L
- GIT
- remote: git://github.com/nex3/haml.git
- revision: 8a2271f
- specs:
-
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- omg!
- rack
-
- BUNDLED WITH
- 1.8.2
- L
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not update the lockfile's bundler version if nothing changed during bundle install", :ruby_repo do
- version = "#{Bundler::VERSION.split(".").first}.0.0.0.a"
-
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{version}
- L
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{version}
- G
- end
-
- it "updates the lockfile's bundler version if not present" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
- L
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack", "> 0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack (> 0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "outputs a warning if the current is older than lockfile's bundler version" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- 9999999.1.0
- L
-
- simulate_bundler_version "9999999.0.0" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
- end
-
- warning_message = "the running version of Bundler (9999999.0.0) is older " \
- "than the version that created the lockfile (9999999.1.0)"
- expect(out.scan(warning_message).size).to eq(1)
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
- #{specific_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- 9999999.1.0
- G
- end
-
- it "errors if the current is a major version older than lockfile's bundler version" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- 9999999.0.0
- L
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
-
- expect(exitstatus > 0) if exitstatus
- expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.")
- end
-
- it "shows a friendly error when running with a new bundler 2 lockfile" do
- lockfile <<-L
- GEM
- remote: https://rails-assets.org/
- specs:
- rails-assets-bootstrap (3.3.4)
- rails-assets-jquery (>= 1.9.1)
- rails-assets-jquery (2.1.4)
-
- GEM
- remote: https://rubygems.org/
- specs:
- rake (10.4.2)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rails-assets-bootstrap!
- rake
-
- BUNDLED WITH
- 9999999.0.0
- L
-
- install_gemfile <<-G
- source 'https://rubygems.org'
- gem 'rake'
-
- source 'https://rails-assets.org' do
- gem 'rails-assets-bootstrap'
- end
- G
-
- expect(exitstatus > 0) if exitstatus
- expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.")
- end
-
- it "warns when updating bundler major version" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- 1.10.0
- L
-
- simulate_bundler_version "9999999.0.0" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
- end
-
- expect(out).to include("Warning: the lockfile is being updated to Bundler " \
- "9999999, after which you will be unable to return to Bundler 1.")
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
- #{specific_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- 9999999.0.0
- G
- end
-
- it "generates a simple lockfile for a single source, gem with dependencies" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack-obama"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack-obama
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a simple lockfile for a single source, gem with a version requirement" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack-obama", ">= 1.0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack-obama (>= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a lockfile wihout credentials for a configured source" do
- bundle "config http://localgemserver.test/ user:pass"
-
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
- source "http://localgemserver.test/"
- source "http://user:pass@othergemserver.test/"
-
- gem "rack-obama", ">= 1.0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: http://localgemserver.test/
- remote: http://user:pass@othergemserver.test/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack-obama (>= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates lockfiles with multiple requirements" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "net-sftp"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- net-sftp (1.1.1)
- net-ssh (>= 1.0.0, < 1.99.0)
- net-ssh (1.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- net-sftp
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
-
- expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0"
- end
-
- it "generates a simple lockfile for a single pinned source, gem with a version requirement" do
- git = build_git "foo"
-
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}"
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not asplode when a platform specific dependency is present and the Gemfile has not been resolved on that platform" do
- build_lib "omg", :path => lib_path("omg")
-
- gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- platforms :#{not_local_tag} do
- gem "omg", :path => "#{lib_path("omg")}"
- end
-
- gem "rack"
- G
-
- lockfile <<-L
- GIT
- remote: git://github.com/nex3/haml.git
- revision: 8a2271f
- specs:
-
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{not_local}
-
- DEPENDENCIES
- omg!
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- bundle "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "serializes global git sources" do
- git = build_git "foo"
-
- install_gemfile <<-G
- git "#{lib_path("foo-1.0")}" do
- gem "foo"
- end
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a lockfile with a ref for a single pinned source, git gem with a branch requirement" do
- git = build_git "foo"
- update_git "foo", :branch => "omg"
-
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("omg")}
- branch: omg
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a lockfile with a ref for a single pinned source, git gem with a tag requirement" do
- git = build_git "foo"
- update_git "foo", :tag => "omg"
-
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg"
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("omg")}
- tag: omg
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "serializes pinned path sources to the lockfile" do
- build_lib "foo"
-
- install_gemfile <<-G
- gem "foo", :path => "#{lib_path("foo-1.0")}"
- G
-
- lockfile_should_be <<-G
- PATH
- remote: #{lib_path("foo-1.0")}
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "serializes pinned path sources to the lockfile even when packaging" do
- build_lib "foo"
-
- install_gemfile! <<-G
- gem "foo", :path => "#{lib_path("foo-1.0")}"
- G
-
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
- bundle! :install, :local => true
-
- lockfile_should_be <<-G
- PATH
- remote: #{lib_path("foo-1.0")}
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "sorts serialized sources by type" do
- build_lib "foo"
- bar = build_git "bar"
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- gem "foo", :path => "#{lib_path("foo-1.0")}"
- gem "bar", :git => "#{lib_path("bar-1.0")}"
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("bar-1.0")}
- revision: #{bar.ref_for("master")}
- specs:
- bar (1.0)
-
- PATH
- remote: #{lib_path("foo-1.0")}
- specs:
- foo (1.0)
-
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- bar!
- foo!
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "lists gems alphabetically" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "thin"
- gem "actionpack"
- gem "rack-obama"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- actionpack (2.3.2)
- activesupport (= 2.3.2)
- activesupport (2.3.2)
- rack (1.0.0)
- rack-obama (1.0)
- rack
- thin (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- actionpack
- rack-obama
- thin
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "orders dependencies' dependencies in alphabetical order" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rails"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- actionmailer (2.3.2)
- activesupport (= 2.3.2)
- actionpack (2.3.2)
- activesupport (= 2.3.2)
- activerecord (2.3.2)
- activesupport (= 2.3.2)
- activeresource (2.3.2)
- activesupport (= 2.3.2)
- activesupport (2.3.2)
- rails (2.3.2)
- actionmailer (= 2.3.2)
- actionpack (= 2.3.2)
- activerecord (= 2.3.2)
- activeresource (= 2.3.2)
- rake (= 10.0.2)
- rake (10.0.2)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rails
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "orders dependencies by version" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem 'double_deps'
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- double_deps (1.0)
- net-ssh
- net-ssh (>= 1.0.0)
- net-ssh (1.0)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- double_deps
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add the :require option to the lockfile" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack-obama", ">= 1.0", :require => "rack/obama"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack-obama (>= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add the :group option to the lockfile" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack-obama", ">= 1.0", :group => :test
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rack-obama (>= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "stores relative paths when the path is provided in a relative fashion and in Gemfile dir" do
- build_lib "foo", :path => bundled_app("foo")
-
- install_gemfile <<-G
- path "foo"
- gem "foo"
- G
-
- lockfile_should_be <<-G
- PATH
- remote: foo
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "stores relative paths when the path is provided in a relative fashion and is above Gemfile dir" do
- build_lib "foo", :path => bundled_app(File.join("..", "foo"))
-
- install_gemfile <<-G
- path "../foo"
- gem "foo"
- G
-
- lockfile_should_be <<-G
- PATH
- remote: ../foo
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "stores relative paths when the path is provided in an absolute fashion but is relative" do
- build_lib "foo", :path => bundled_app("foo")
-
- install_gemfile <<-G
- path File.expand_path("../foo", __FILE__)
- gem "foo"
- G
-
- lockfile_should_be <<-G
- PATH
- remote: foo
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "stores relative paths when the path is provided for gemspec" do
- build_lib("foo", :path => tmp.join("foo"))
-
- install_gemfile <<-G
- gemspec :path => "../foo"
- G
-
- lockfile_should_be <<-G
- PATH
- remote: ../foo
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "keeps existing platforms in the lockfile" do
- lockfile <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- java
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
-
- gem "rack"
- G
-
- platforms = ["java", generic_local_platform.to_s].sort
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{platforms[0]}
- #{platforms[1]}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "persists the spec's platform to the lockfile" do
- build_gem "platform_specific", "1.0.0", :to_system => true do |s|
- s.platform = Gem::Platform.new("universal-java-16")
- end
-
- simulate_platform "universal-java-16"
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "platform_specific"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- platform_specific (1.0-java)
-
- PLATFORMS
- java
-
- DEPENDENCIES
- platform_specific
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add duplicate gems" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- G
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "activesupport"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- activesupport (2.3.5)
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- activesupport
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add duplicate dependencies" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "rack"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add duplicate dependencies with versions" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack", "1.0"
- gem "rack", "1.0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack (= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "does not add duplicate dependencies in different groups" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack", "1.0", :group => :one
- gem "rack", "1.0", :group => :two
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack (= 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "raises if two different versions are used" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack", "1.0"
- gem "rack", "1.1"
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- expect(out).to include "rack (= 1.0) and rack (= 1.1)"
- end
-
- it "raises if two different sources are used" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack"
- gem "rack", :git => "git://hubz.com"
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- expect(out).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)"
- end
-
- it "works correctly with multiple version dependencies" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack", "> 0.9", "< 1.0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (0.9.1)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack (> 0.9, < 1.0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "captures the Ruby version in the lockfile" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- ruby '#{RUBY_VERSION}'
- gem "rack", "> 0.9", "< 1.0"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (0.9.1)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack (> 0.9, < 1.0)
-
- RUBY VERSION
- ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- # Some versions of the Bundler 1.1 RC series introduced corrupted
- # lockfiles. There were two major problems:
- #
- # * multiple copies of the same GIT section appeared in the lockfile
- # * when this happened, those sections got multiple copies of gems
- # in those sections.
- it "fixes corrupted lockfiles" do
- build_git "omg", :path => lib_path("omg")
- revision = revision_for(lib_path("omg"))
-
- gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "omg", :git => "#{lib_path("omg")}", :branch => 'master'
- G
-
- bundle "install --path vendor"
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Create a Gemfile.lock that has duplicate GIT sections
- lockfile <<-L
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
-
- PLATFORMS
- #{local}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install"
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Confirm that duplicate specs do not appear
- lockfile_should_be(<<-L)
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
-
- PLATFORMS
- #{local}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
- it "raises a helpful error message when the lockfile is missing deps" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack_middleware (1.0)
-
- PLATFORMS
- #{local}
-
- DEPENDENCIES
- rack_middleware
- L
-
- install_gemfile <<-G
- source "file:#{gem_repo1}"
- gem "rack_middleware"
- G
-
- expect(out).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (#{Gem::Dependency.new("rack", "= 0.9.1")}).").
- and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
- end
-
- describe "a line ending" do
- def set_lockfile_mtime_to_known_value
- time = Time.local(2000, 1, 1, 0, 0, 0)
- File.utime(time, time, bundled_app("Gemfile.lock"))
- end
- before(:each) do
- build_repo2
-
- install_gemfile <<-G
- source "file://localhost#{gem_repo2}"
- gem "rack"
- G
- set_lockfile_mtime_to_known_value
- end
-
- it "generates Gemfile.lock with \\n line endings" do
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- context "during updates" do
- it "preserves Gemfile.lock \\n line endings" do
- update_repo2
-
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
- end
-
- it "preserves Gemfile.lock \\n\\r line endings" do
- update_repo2
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
- set_lockfile_mtime_to_known_value
-
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
- end
- end
-
- context "when nothing changes" do
- it "preserves Gemfile.lock \\n line endings" do
- expect do
- ruby <<-RUBY
- require 'rubygems'
- require 'bundler'
- Bundler.setup
- RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
- end
-
- it "preserves Gemfile.lock \\n\\r line endings" do
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
- set_lockfile_mtime_to_known_value
-
- expect do
- ruby <<-RUBY
- require 'rubygems'
- require 'bundler'
- Bundler.setup
- RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
- end
- end
- end
-
- it "refuses to install if Gemfile.lock contains conflict markers" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- <<<<<<<
- rack (1.0.0)
- =======
- rack (1.0.1)
- >>>>>>>
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- install_gemfile(<<-G)
- source "file://localhost#{gem_repo1}"
- gem "rack"
- G
-
- expect(last_command.bundler_err).to match(/your Gemfile.lock contains merge conflicts/i)
- expect(last_command.bundler_err).to match(/git checkout HEAD -- Gemfile.lock/i)
- end
-end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 9e2fb3b2dd..654ac02aa7 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -1,35 +1,41 @@
# frozen_string_literal: true
-RSpec.describe "the lockfile format", :bundler => "3" do
- include Bundler::GemHelpers
-
- before { ENV["BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD"] = "TRUE" }
+RSpec.describe "the lockfile format" do
+ before do
+ build_repo2
+ end
it "generates a simple lockfile for a single source, gem" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "updates the lockfile's bundler version if current ver. is newer" do
+ it "updates the lockfile's bundler version if current ver. is newer, and version was forced through BUNDLER_VERSION" do
+ system_gems "bundler-1.8.2"
+
lockfile <<-L
GIT
remote: git://github.com/nex3/haml.git
@@ -37,348 +43,373 @@ RSpec.describe "the lockfile format", :bundler => "3" do
specs:
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
omg!
- rack
+ myrack
BUNDLED WITH
1.8.2
L
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ install_gemfile <<-G, verbose: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
- lockfile_should_be <<-G
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.")
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "does not update the lockfile's bundler version if nothing changed during bundle install" do
- version = "#{Bundler::VERSION.split(".").first}.0.0.0.a"
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version" do
+ version = "2.3.0"
+
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+
+ build_bundler version
+ end
lockfile <<-L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo4/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
#{version}
L
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo4"
- gem "rack"
+ gem "myrack"
G
- lockfile_should_be <<-G
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
+ expect(out).to include("Using bundler #{version}")
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo4/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
#{version}
G
end
- it "updates the lockfile's bundler version if not present" do
+ it "adds the BUNDLED WITH section if not present" do
lockfile <<-L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
L
install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ source "https://gem.repo2"
- gem "rack", "> 0"
+ gem "myrack", "> 0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0)
+ myrack (> 0)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "outputs a warning if the current is older than lockfile's bundler version" do
+ it "update the bundler major version just fine" do
+ current_version = Bundler::VERSION
+ older_major = previous_major(current_version)
+
+ system_gems "bundler-#{older_major}"
+
lockfile <<-L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- #{generic_local_platform}
+ #{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- 9999999.1.0
+ #{older_major}
L
- simulate_bundler_version "9999999.0.0" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
+ install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ source "https://gem.repo2/"
- gem "rack"
- G
- end
+ gem "myrack"
+ G
- warning_message = "the running version of Bundler (9999999.0.0) is older " \
- "than the version that created the lockfile (9999999.1.0)"
- expect(last_command.bundler_err).to include warning_message
+ expect(err).to be_empty
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- 9999999.1.0
+ #{current_version}
G
end
- it "errors if the current is a major version older than lockfile's bundler version" do
- lockfile <<-L
+ it "generates a simple lockfile for a single source, gem with dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo2/"
+
+ gem "myrack-obama"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack-obama
+ #{checksums}
BUNDLED WITH
- 9999999.0.0
- L
+ #{Bundler::VERSION}
+ G
+ end
+ it "generates a simple lockfile for a single source, gem with a version requirement" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack-obama", ">= 1.0"
G
- expect(last_command).to be_failure
- expect(last_command.bundler_err).to include("You must use Bundler 9999999 or greater with this lockfile.")
- end
-
- it "shows a friendly error when running with a new bundler 2 lockfile" do
- lockfile <<-L
- GEM
- remote: https://rails-assets.org/
- specs:
- rails-assets-bootstrap (3.3.4)
- rails-assets-jquery (>= 1.9.1)
- rails-assets-jquery (2.1.4)
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+ expect(lockfile).to eq <<~G
GEM
- remote: https://rubygems.org/
+ remote: https://gem.repo2/
specs:
- rake (10.4.2)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
- rails-assets-bootstrap!
- rake
-
+ myrack-obama (>= 1.0)
+ #{checksums}
BUNDLED WITH
- 9999999.0.0
- L
-
- install_gemfile <<-G
- source 'https://rubygems.org'
- gem 'rake'
-
- source 'https://rails-assets.org' do
- gem 'rails-assets-bootstrap'
- end
+ #{Bundler::VERSION}
G
-
- expect(last_command).to be_failure
- expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.")
end
- it "warns when updating bundler major version" do
- lockfile <<-L
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
+ it "generates a lockfile without credentials" do
+ bundle "config set https://localgemserver.test/ user:pass"
- PLATFORMS
- #{generic_local_platform}
+ install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
+ source "https://gem.repo1"
- DEPENDENCIES
- rack
+ source "https://localgemserver.test/" do
- BUNDLED WITH
- 1.10.0
- L
+ end
- simulate_bundler_version "9999999.0.0" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://user:pass@othergemserver.test/" do
+ gem "myrack-obama", ">= 1.0"
+ end
+ G
- gem "rack"
- G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
- expect(out).to include("Warning: the lockfile is being updated to Bundler " \
- "9999999, after which you will be unable to return to Bundler 1.")
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ GEM
+ remote: https://localgemserver.test/
+ specs:
- lockfile_should_be <<-G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://othergemserver.test/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack-obama (>= 1.0)!
+ #{checksums}
BUNDLED WITH
- 9999999.0.0
+ #{Bundler::VERSION}
G
end
- it "generates a simple lockfile for a single source, gem with dependencies" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ it "does not add credentials to lockfile when it does not have them already" do
+ bundle "config set http://localgemserver.test/ user:pass"
- gem "rack-obama"
- G
+ gemfile <<~G
+ source "https://gem.repo1"
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{lockfile_platforms}
+ source "http://localgemserver.test/" do
- DEPENDENCIES
- rack-obama
+ end
- BUNDLED WITH
- #{Bundler::VERSION}
+ source "http://user:pass@othergemserver.test/" do
+ gem "myrack-obama", ">= 1.0"
+ end
G
- end
- it "generates a simple lockfile for a single source, gem with a version requirement" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
- gem "rack-obama", ">= 1.0"
- G
+ lockfile_without_credentials = <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
- lockfile_should_be <<-G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: http://othergemserver.test/
+ specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ GEM
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
-
+ myrack-obama (>= 1.0)!
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
- G
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_without_credentials
+
+ # when not re-resolving
+ bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true
+ expect(lockfile).to eq lockfile_without_credentials
+
+ # when re-resolving with full unlock
+ bundle "update", artifice: "endpoint_strict_basic_authentication"
+ expect(lockfile).to eq lockfile_without_credentials
+
+ # when re-resolving without ful unlocking
+ bundle "update myrack-obama", artifice: "endpoint_strict_basic_authentication"
+ expect(lockfile).to eq lockfile_without_credentials
end
- it "generates a lockfile without credentials for a configured source" do
- bundle "config http://localgemserver.test/ user:pass"
+ it "keeps credentials in lockfile if already there" do
+ bundle "config set http://localgemserver.test/ user:pass"
+
+ gemfile <<~G
+ source "https://gem.repo1"
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
source "http://localgemserver.test/" do
end
source "http://user:pass@othergemserver.test/" do
- gem "rack-obama", ">= 1.0"
+ gem "myrack-obama", ">= 1.0"
end
G
- lockfile_should_be <<-G
- GEM
- specs:
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+ lockfile_with_credentials = <<~L
GEM
remote: http://localgemserver.test/
specs:
@@ -386,30 +417,45 @@ RSpec.describe "the lockfile format", :bundler => "3" do
GEM
remote: http://user:pass@othergemserver.test/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)!
-
+ myrack-obama (>= 1.0)!
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
- G
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_with_credentials
+
+ bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true
+
+ expect(lockfile).to eq lockfile_with_credentials
end
it "generates lockfiles with multiple requirements" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
gem "net-sftp"
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "net-sftp", "1.1.1"
+ c.checksum gem_repo2, "net-ssh", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
net-sftp (1.1.1)
net-ssh (>= 1.0.0, < 1.99.0)
@@ -420,29 +466,35 @@ RSpec.describe "the lockfile format", :bundler => "3" do
DEPENDENCIES
net-sftp
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0"
end
- it "generates a simple lockfile for a single pinned source, gem with a version requirement", :bundler => "< 3" do
+ it "generates a simple lockfile for a single pinned source, gem with a version requirement" do
git = build_git "foo"
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
+ revision: #{git.ref_for("main")}
specs:
foo (1.0)
GEM
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -450,51 +502,23 @@ RSpec.describe "the lockfile format", :bundler => "3" do
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a simple lockfile for a single pinned source, gem with a version requirement" do
- git = build_git "foo"
-
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}"
- G
-
- lockfile_should_be <<-G
- GEM
- specs:
-
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
- specs:
- foo (1.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not asplode when a platform specific dependency is present and the Gemfile has not been resolved on that platform" do
- build_lib "omg", :path => lib_path("omg")
+ build_lib "omg", path: lib_path("omg")
gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
platforms :#{not_local_tag} do
gem "omg", :path => "#{lib_path("omg")}"
end
- gem "rack"
+ gem "myrack"
G
lockfile <<-L
@@ -504,67 +528,75 @@ RSpec.describe "the lockfile format", :bundler => "3" do
specs:
GEM
- remote: file://localhost#{gem_repo1}//
+ remote: https://gem.repo2//
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{not_local}
DEPENDENCIES
omg!
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle! "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle "install"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "serializes global git sources" do
git = build_git "foo"
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
+ revision: #{git.ref_for("main")}
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "generates a lockfile with a ref for a single pinned source, git gem with a branch requirement" do
git = build_git "foo"
- update_git "foo", :branch => "omg"
+ update_git "foo", branch: "omg"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
@@ -572,29 +604,35 @@ RSpec.describe "the lockfile format", :bundler => "3" do
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "generates a lockfile with a ref for a single pinned source, git gem with a tag requirement" do
git = build_git "foo"
- update_git "foo", :tag => "omg"
+ update_git "foo", tag: "omg"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg"
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
@@ -602,71 +640,173 @@ RSpec.describe "the lockfile format", :bundler => "3" do
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
+ it "is conservative with dependencies of git gems" do
+ build_repo4 do
+ build_gem "orm_adapter", "0.4.1"
+ build_gem "orm_adapter", "0.5.0"
+ end
+
+ FileUtils.mkdir_p lib_path("ckeditor/lib")
+
+ @remote = build_git("ckeditor_remote", bare: true)
+
+ build_git "ckeditor", path: lib_path("ckeditor") do |s|
+ s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.7'"
+ s.version = "4.0.7"
+ s.add_dependency "orm_adapter"
+ end
+
+ update_git "ckeditor", path: lib_path("ckeditor"), remote: @remote.path
+ update_git "ckeditor", path: lib_path("ckeditor"), tag: "v4.0.7"
+ old_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.7"
+
+ update_git "ckeditor", path: lib_path("ckeditor"), gemspec: true do |s|
+ s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.8'"
+ s.version = "4.0.8"
+ s.add_dependency "orm_adapter"
+ end
+ update_git "ckeditor", path: lib_path("ckeditor"), tag: "v4.0.8"
+
+ new_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.8"
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "ckeditor", :git => "#{@remote.path}", :tag => "v4.0.8"
+ G
+
+ lockfile <<~L
+ GIT
+ remote: #{@remote.path}
+ revision: #{old_git.ref_for("v4.0.7")}
+ tag: v4.0.7
+ specs:
+ ckeditor (4.0.7)
+ orm_adapter
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ orm_adapter (0.4.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ckeditor!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ # Bumps the git gem, but keeps its dependency locked
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: #{@remote.path}
+ revision: #{new_git.ref_for("v4.0.8")}
+ tag: v4.0.8
+ specs:
+ ckeditor (4.0.8)
+ orm_adapter
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ orm_adapter (0.4.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ckeditor!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
it "serializes pinned path sources to the lockfile" do
build_lib "foo"
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo-1.0")}
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "serializes pinned path sources to the lockfile even when packaging" do
build_lib "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
- bundle! :install, :local => true
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
- lockfile_should_be <<-G
- GEM
- specs:
+ bundle :cache
+ bundle :install, local: true
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo-1.0")}
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -674,23 +814,24 @@ RSpec.describe "the lockfile format", :bundler => "3" do
build_lib "foo"
bar = build_git "bar"
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.no_checksum "bar", "1.0"
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack"
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo1}/
- specs:
- rack (1.0.0)
-
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("bar-1.0")}
- revision: #{bar.ref_for("master")}
+ revision: #{bar.ref_for("main")}
specs:
bar (1.0)
@@ -699,64 +840,115 @@ RSpec.describe "the lockfile format", :bundler => "3" do
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
bar!
foo!
- rack
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "removes redundant sources" do
+ install_gemfile <<-G
+ source "https://gem.repo2/"
+
+ gem "myrack", :source => "https://gem.repo2/"
+ G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack!
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "lists gems alphabetically" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
gem "thin"
gem "actionpack"
- gem "rack-obama"
+ gem "myrack-obama"
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "actionpack", "2.3.2"
+ c.checksum gem_repo2, "activesupport", "2.3.2"
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ c.checksum gem_repo2, "thin", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
actionpack (2.3.2)
activesupport (= 2.3.2)
activesupport (2.3.2)
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
thin (1.0)
- rack
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
actionpack
- rack-obama
+ myrack-obama
thin
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "orders dependencies' dependencies in alphabetical order" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
gem "rails"
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "actionmailer", "2.3.2"
+ c.checksum gem_repo2, "actionpack", "2.3.2"
+ c.checksum gem_repo2, "activerecord", "2.3.2"
+ c.checksum gem_repo2, "activeresource", "2.3.2"
+ c.checksum gem_repo2, "activesupport", "2.3.2"
+ c.checksum gem_repo2, "rails", "2.3.2"
+ c.checksum gem_repo2, "rake", rake_version
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -772,29 +964,44 @@ RSpec.describe "the lockfile format", :bundler => "3" do
actionpack (= 2.3.2)
activerecord (= 2.3.2)
activeresource (= 2.3.2)
- rake (= 10.0.2)
- rake (10.0.2)
+ rake (= #{rake_version})
+ rake (#{rake_version})
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
rails
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "orders dependencies by version" do
+ update_repo2 do
+ # Capistrano did this (at least until version 2.5.10)
+ # RubyGems 2.2 doesn't allow the specifying of a dependency twice
+ # See https://github.com/ruby/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f
+ build_gem "double_deps", "1.0", skip_validation: true do |s|
+ s.add_dependency "net-ssh", ">= 1.0.0"
+ s.add_dependency "net-ssh"
+ end
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2"
gem 'double_deps'
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "double_deps", "1.0"
+ c.checksum gem_repo2, "net-ssh", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
double_deps (1.0)
net-ssh
@@ -806,563 +1013,1343 @@ RSpec.describe "the lockfile format", :bundler => "3" do
DEPENDENCIES
double_deps
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add the :require option to the lockfile" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
- gem "rack-obama", ">= 1.0", :require => "rack/obama"
+ gem "myrack-obama", ">= 1.0", :require => "myrack/obama"
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
-
+ myrack-obama (>= 1.0)
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add the :group option to the lockfile" do
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
- gem "rack-obama", ">= 1.0", :group => :test
+ gem "myrack-obama", ">= 1.0", :group => :test
G
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
-
+ myrack-obama (>= 1.0)
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in a relative fashion and in Gemfile dir" do
- build_lib "foo", :path => bundled_app("foo")
+ build_lib "foo", path: bundled_app("foo")
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
install_gemfile <<-G
+ source "https://gem.repo1"
path "foo" do
gem "foo"
end
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in a relative fashion and is above Gemfile dir" do
- build_lib "foo", :path => bundled_app(File.join("..", "foo"))
+ build_lib "foo", path: bundled_app(File.join("..", "foo"))
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
install_gemfile <<-G
+ source "https://gem.repo1"
path "../foo" do
gem "foo"
end
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in an absolute fashion but is relative" do
- build_lib "foo", :path => bundled_app("foo")
+ build_lib "foo", path: bundled_app("foo")
install_gemfile <<-G
- path File.expand_path("../foo", __FILE__) do
+ source "https://gem.repo1"
+ path File.expand_path("foo", __dir__) do
gem "foo"
end
G
- lockfile_should_be <<-G
- GEM
- specs:
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided for gemspec" do
- build_lib("foo", :path => tmp.join("foo"))
+ build_lib("foo", path: tmp("foo"))
+
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
install_gemfile <<-G
+ source "https://gem.repo1"
gemspec :path => "../foo"
G
- lockfile_should_be <<-G
- GEM
- specs:
-
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
foo (1.0)
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "keeps existing platforms in the lockfile" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "myrack", "1.0.0"
+ end
+
lockfile <<-G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
java
DEPENDENCIES
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack"
G
- lockfile_should_be <<-G
+ checksums.checksum(gem_repo2, "myrack", "1.0.0")
+
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- #{lockfile_platforms "java", generic_local_platform, specific_local_platform}
+ #{lockfile_platforms("java", local_platform, defaults: [])}
DEPENDENCIES
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "persists the spec's platform to the lockfile" do
+ it "adds compatible platform specific variants to the lockfile, even if resolution fallback to ruby due to some other incompatible platform specific variant" do
+ simulate_platform "arm64-darwin-23" do
+ build_repo4 do
+ build_gem "google-protobuf", "3.25.1"
+ build_gem "google-protobuf", "3.25.1" do |s|
+ s.platform = "arm64-darwin-23"
+ end
+ build_gem "google-protobuf", "3.25.1" do |s|
+ s.platform = "x64-mingw-ucrt"
+ s.required_ruby_version = "> #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "google-protobuf"
+ G
+ bundle "lock --add-platform x64-mingw-ucrt"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "google-protobuf", "3.25.1"
+ c.checksum gem_repo4, "google-protobuf", "3.25.1", "arm64-darwin-23"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ google-protobuf (3.25.1)
+ google-protobuf (3.25.1-arm64-darwin-23)
+
+ PLATFORMS
+ arm64-darwin-23
+ ruby
+ x64-mingw-ucrt
+
+ DEPENDENCIES
+ google-protobuf
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "persists the spec's specific platform to the lockfile" do
build_repo2 do
build_gem "platform_specific", "1.0" do |s|
s.platform = Gem::Platform.new("universal-java-16")
end
end
- simulate_platform "universal-java-16"
+ simulate_platform "universal-java-16" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "platform_specific"
+ G
- install_gemfile! <<-G
- source "file://localhost#{gem_repo2}"
- gem "platform_specific"
- G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "platform_specific", "1.0", "universal-java-16"
+ end
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
- platform_specific (1.0-java)
- platform_specific (1.0-universal-java-16)
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ platform_specific (1.0-universal-java-16)
- PLATFORMS
- java
- universal-java-16
-
- DEPENDENCIES
- platform_specific
+ PLATFORMS
+ universal-java-16
- BUNDLED WITH
- #{Bundler::VERSION}
- G
+ DEPENDENCIES
+ platform_specific
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
it "does not add duplicate gems" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "activesupport", "2.3.5")
+ c.checksum(gem_repo2, "myrack", "1.0.0")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
G
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
gem "activesupport"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
activesupport
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
+ gem "myrack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies with versions" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack", "1.0"
- gem "rack", "1.0"
+ source "https://gem.repo2/"
+ gem "myrack", "1.0"
+ gem "myrack", "1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 1.0)
-
+ myrack (= 1.0)
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies in different groups" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack", "1.0", :group => :one
- gem "rack", "1.0", :group => :two
+ source "https://gem.repo2/"
+ gem "myrack", "1.0", :group => :one
+ gem "myrack", "1.0", :group => :two
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 1.0)
-
+ myrack (= 1.0)
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "raises if two different versions are used" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack", "1.0"
- gem "rack", "1.1"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2/"
+ gem "myrack", "1.0"
+ gem "myrack", "1.1"
G
- expect(bundled_app("Gemfile.lock")).not_to exist
- expect(out).to include "rack (= 1.0) and rack (= 1.1)"
+ expect(bundled_app_lock).not_to exist
+ expect(err).to include "myrack (= 1.0) and myrack (= 1.1)"
end
it "raises if two different sources are used" do
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack"
- gem "rack", :git => "git://hubz.com"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2/"
+ gem "myrack"
+ gem "myrack", :git => "git://hubz.com"
G
- expect(bundled_app("Gemfile.lock")).not_to exist
- expect(out).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)"
+ expect(bundled_app_lock).not_to exist
+ expect(err).to include "myrack (>= 0) should come from an unspecified source and git://hubz.com"
end
it "works correctly with multiple version dependencies" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "0.9.1")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "rack", "> 0.9", "< 1.0"
+ source "https://gem.repo2/"
+ gem "myrack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0.9, < 1.0)
-
+ myrack (> 0.9, < 1.0)
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "captures the Ruby version in the lockfile" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "0.9.1")
+ end
+
install_gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- ruby '#{RUBY_VERSION}'
- gem "rack", "> 0.9", "< 1.0"
+ source "https://gem.repo2/"
+ ruby '#{Gem.ruby_version}'
+ gem "myrack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0.9, < 1.0)
-
+ myrack (> 0.9, < 1.0)
+ #{checksums}
RUBY VERSION
- ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- # Some versions of the Bundler 1.1 RC series introduced corrupted
- # lockfiles. There were two major problems:
- #
- # * multiple copies of the same GIT section appeared in the lockfile
- # * when this happened, those sections got multiple copies of gems
- # in those sections.
- it "fixes corrupted lockfiles" do
- build_git "omg", :path => lib_path("omg")
- revision = revision_for(lib_path("omg"))
+ it "automatically fixes the lockfile when it's missing deps" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
- gemfile <<-G
- source "file://localhost#{gem_repo1}/"
- gem "omg", :git => "#{lib_path("omg")}", :branch => 'master'
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a clear error when frozen mode is set and lockfile is missing deps, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack_middleware"
G
- bundle! :install, forgotten_command_line_options(:path => "vendor")
- expect(the_bundle).to include_gems "omg 1.0"
+ expect(err).to include("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0")
+ expect(err).to include("myrack: gemspec specifies = 0.9.1, not in lockfile")
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
+ end
- # Create a Gemfile.lock that has duplicate GIT sections
+ it "raises a clear error when frozen mode is set and lockfile is missing entries in CHECKSUMS section, and does not install any gems" do
lockfile <<-L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo2/
specs:
+ myrack_middleware (1.0)
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ CHECKSUMS
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ expect(err).to eq <<~L.strip
+ Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set
+
+ Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
+ L
+
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
+ end
+
+ it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ CHECKSUMS
+ myrack (0.9.1)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ expect(err).to eq <<~L.strip
+ Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set
+
+ Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
+ L
+
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ end
+
+ it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack_middleware (1.0)
+ other_dep (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "other_dep"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+ other_dep (= 0.9)
+ other_dep (0.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it's missing multiple deps, they conflict with other locked deps, but conflicts are fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ end
+
+ build_gem "another_dep_middleware", "1.0" do |s|
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack_middleware (1.0)
+ another_dep_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ another_dep_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "another_dep_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ another_dep_middleware (1.0)
+ other_dep (= 0.9)
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+ other_dep (0.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ another_dep_middleware
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a resolution error when lockfile is missing deps, they conflict with other locked deps, and conflicts are not fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack_middleware (1.0)
+ other_dep (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "other_dep", "1.0"
+ G
+
+ expect(err).to eq <<~ERROR.strip
+ Could not find compatible versions
+
+ Because every version of myrack_middleware depends on other_dep = 0.9
+ and Gemfile depends on myrack_middleware >= 0,
+ other_dep = 0.9 is required.
+ So, because Gemfile depends on other_dep = 1.0,
+ version solving has failed.
+ ERROR
+ end
+
+ it "regenerates a lockfile with no specs" do
+ build_repo4 do
+ build_gem "indirect_dependency", "1.2.3" do |s|
+ s.metadata["funding_uri"] = "https://example.com/donate"
+ end
+
+ build_gem "direct_dependency", "4.5.6" do |s|
+ s.add_dependency "indirect_dependency", ">= 0"
+ end
+ end
+
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ direct_dependency
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "direct_dependency"
+ G
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ direct_dependency (4.5.6)
+ indirect_dependency
+ indirect_dependency (1.2.3)
+
+ PLATFORMS
+ #{lockfile_platforms(generic_default_locked_platform || local_platform, defaults: ["ruby"])}
+
+ DEPENDENCIES
+ direct_dependency
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "automatically fixes the lockfile when it's missing deps and the full index is in use" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "myrack_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
specs:
- omg (1.0)
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version, and with no explicit Gemfile requirement" do
+ git = build_git "foo"
+
+ gemfile <<~G
+ source "https://gem.repo1/"
+ gem "foo", git: "#{lib_path("foo-1.0")}"
+ G
+
+ # If the lockfile erroneously lists platform versions of the gem
+ # that don't match the locked version of the git repo we should remove them.
+ lockfile <<~L
GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
specs:
- omg (1.0)
+ foo (1.1-x86_64-linux-gnu)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- omg!
+ foo!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- FileUtils.rm_rf(bundled_app("vendor"))
bundle "install"
- expect(the_bundle).to include_gems "omg 1.0"
- # Confirm that duplicate specs do not appear
- lockfile_should_be(<<-L)
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version" do
+ git = build_git "foo"
+
+ gemfile <<~G
+ source "https://gem.repo1/"
+ gem "foo", "= 1.0", git: "#{lib_path("foo-1.0")}"
+ G
+
+ # If the lockfile erroneously lists platform versions of the gem
+ # that don't match the locked version of the git repo we should remove them.
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
+ foo (1.1-x86_64-linux-gnu)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo (= 1.0)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+ expect(lockfile).to eq <<~L
GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
specs:
- omg (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- omg!
+ foo (= 1.0)!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
- it "raises a helpful error message when the lockfile is missing deps" do
- lockfile <<-L
+ it "automatically fixes the lockfile when it has incorrect deps, keeping the locked version" do
+ build_repo4 do
+ build_gem "net-smtp", "0.5.0" do |s|
+ s.add_dependency "net-protocol"
+ end
+
+ build_gem "net-smtp", "0.5.1" do |s|
+ s.add_dependency "net-protocol"
+ end
+
+ build_gem "net-protocol", "0.2.2"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "net-smtp"
+ G
+
+ lockfile <<~L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: #{file_uri_for(gem_repo4)}/
specs:
- rack_middleware (1.0)
+ net-protocol (0.2.2)
+ net-smtp (0.5.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack_middleware
+ net-smtp
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
- install_gemfile <<-G
- source "file://localhost#{gem_repo1}"
- gem "rack_middleware"
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ net-protocol (0.2.2)
+ net-smtp (0.5.0)
+ net-protocol
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ net-smtp
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "successfully updates the lockfile when a new gem is added in the Gemfile includes a gem that shouldn't be included" do
+ build_repo4 do
+ build_gem "logger", "1.7.0"
+ build_gem "rack", "3.2.0"
+ build_gem "net-smtp", "0.5.0"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "logger"
+ gem "net-smtp"
+
+ install_if -> { false } do
+ gem 'rack', github: 'rack/rack'
+ end
G
- expect(out).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (#{Gem::Dependency.new("rack", "= 0.9.1")}).").
- and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
+ lockfile <<~L
+ GIT
+ remote: https://github.com/rack/rack.git
+ revision: 2fface9ac09fc582a81386becd939c987ad33f99
+ specs:
+ rack (3.2.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ logger (1.7.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ logger
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: https://github.com/rack/rack.git
+ revision: 2fface9ac09fc582a81386becd939c987ad33f99
+ specs:
+ rack (3.2.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ logger (1.7.0)
+ net-smtp (0.5.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ logger
+ net-smtp
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ shared_examples_for "a lockfile missing dependent specs" do
+ it "auto-heals" do
+ build_repo4 do
+ build_gem "minitest-bisect", "1.6.0" do |s|
+ s.add_dependency "path_expander", "~> 1.1"
+ end
+
+ build_gem "path_expander", "1.1.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "minitest-bisect"
+ G
+
+ # Corrupt lockfile (completely missing path_expander)
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ minitest-bisect (1.6.0)
+
+ PLATFORMS
+ #{platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", gem_repo: gem_repo4
+ bundle :install
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+ path_expander (1.1.1)
+
+ PLATFORMS
+ #{platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with just specific platform" do
+ let(:platforms) { lockfile_platforms }
+
+ it_behaves_like "a lockfile missing dependent specs"
+ end
+
+ context "with both ruby and specific platform" do
+ let(:platforms) { lockfile_platforms("ruby") }
+
+ it_behaves_like "a lockfile missing dependent specs"
+ end
+
+ it "auto-heals when the lockfile is missing specs" do
+ build_repo4 do
+ build_gem "minitest-bisect", "1.6.0" do |s|
+ s.add_dependency "path_expander", "~> 1.1"
+ end
+
+ build_gem "path_expander", "1.1.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "minitest-bisect"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ expect(out).to include("re-resolving dependencies because your lockfile includes \"minitest-bisect\" but not some of its dependencies")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+ path_expander (1.1.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
describe "a line ending" do
def set_lockfile_mtime_to_known_value
time = Time.local(2000, 1, 1, 0, 0, 0)
- File.utime(time, time, bundled_app("Gemfile.lock"))
+ File.utime(time, time, bundled_app_lock)
end
before(:each) do
build_repo2
install_gemfile <<-G
- source "file://localhost#{gem_repo2}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
set_lockfile_mtime_to_known_value
end
it "generates Gemfile.lock with \\n line endings" do
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(File.read(bundled_app_lock)).not_to match("\r\n")
+ expect(the_bundle).to include_gems "myrack 1.0"
end
context "during updates" do
it "preserves Gemfile.lock \\n line endings" do
- update_repo2
-
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+ end
+
+ expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) }
+ expect(File.read(bundled_app_lock)).not_to match("\r\n")
+ expect(the_bundle).to include_gems "myrack 1.2"
end
it "preserves Gemfile.lock \\n\\r line endings" do
- update_repo2
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
+ skip "needs to be adapted" if Gem.win_platform?
+
+ update_repo2 do
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
+ end
+ end
+
+ win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n")
+ File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) }
set_lockfile_mtime_to_known_value
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
+ expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) }
+ expect(File.read(bundled_app_lock)).to match("\r\n")
+
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
@@ -1370,25 +2357,23 @@ RSpec.describe "the lockfile format", :bundler => "3" do
it "preserves Gemfile.lock \\n line endings" do
expect do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup
RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ end.not_to change { File.mtime(bundled_app_lock) }
end
it "preserves Gemfile.lock \\n\\r line endings" do
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
+ win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n")
+ File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) }
set_lockfile_mtime_to_known_value
expect do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup
RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ end.not_to change { File.mtime(bundled_app_lock) }
end
end
end
@@ -1396,30 +2381,36 @@ RSpec.describe "the lockfile format", :bundler => "3" do
it "refuses to install if Gemfile.lock contains conflict markers" do
lockfile <<-L
GEM
- remote: file://localhost#{gem_repo1}//
+ remote: https://gem.repo2//
specs:
<<<<<<<
- rack (1.0.0)
+ myrack (1.0.0)
=======
- rack (1.0.1)
+ myrack (1.0.1)
>>>>>>>
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- install_gemfile(<<-G)
- source "file://localhost#{gem_repo1}/"
- gem "rack"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2/"
+ gem "myrack"
G
- expect(last_command.bundler_err).to match(/your Gemfile.lock contains merge conflicts/i)
- expect(last_command.bundler_err).to match(/git checkout HEAD -- Gemfile.lock/i)
+ expect(err).to match(/your Gemfile.lock contains merge conflicts/i)
+ expect(err).to match(/git checkout HEAD -- Gemfile.lock/i)
+ end
+
+ private
+
+ def previous_major(version)
+ version.split(".").map.with_index {|v, i| i == 0 ? v.to_i - 1 : v }.join(".")
end
end
diff --git a/spec/bundler/other/bundle_ruby_spec.rb b/spec/bundler/other/bundle_ruby_spec.rb
deleted file mode 100644
index fbca31d0a0..0000000000
--- a/spec/bundler/other/bundle_ruby_spec.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle_ruby", :bundler => "< 3" do
- context "without patchlevel" do
- it "returns the ruby version" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.9.3")
- end
-
- it "engine defaults to MRI" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3"
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.9.3")
- end
-
- it "handles jruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.8.7 (jruby 1.6.5)")
- end
-
- it "handles rbx" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.8.7 (rbx 1.2.4)")
- end
-
- it "handles truffleruby", :rubygems => ">= 2.1.0" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "2.5.1", :engine => 'truffleruby', :engine_version => '1.0.0-rc6'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 2.5.1 (truffleruby 1.0.0-rc6)")
- end
-
- it "raises an error if engine is used but engine version is not" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'rbx'
-
- gem "foo"
- G
-
- bundle_ruby
- expect(exitstatus).not_to eq(0) if exitstatus
-
- bundle_ruby
- expect(out).to include("Please define :engine_version")
- end
-
- it "raises an error if engine_version is used but engine is not" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle_ruby
- expect(exitstatus).not_to eq(0) if exitstatus
-
- bundle_ruby
- expect(out).to include("Please define :engine")
- end
-
- it "raises an error if engine version doesn't match ruby version for MRI" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle_ruby
- expect(exitstatus).not_to eq(0) if exitstatus
-
- bundle_ruby
- expect(out).to include("ruby_version must match the :engine_version for MRI")
- end
-
- it "should print if no ruby version is specified" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("No ruby version specified")
- end
- end
-
- context "when using patchlevel" do
- it "returns the ruby version" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3", :patchlevel => '429', :engine => 'ruby', :engine_version => '1.9.3'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.9.3p429")
- end
-
- it "handles an engine" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3", :patchlevel => '392', :engine => 'jruby', :engine_version => '1.7.4'
-
- gem "foo"
- G
-
- bundle_ruby
-
- expect(out).to include("ruby 1.9.3p392 (jruby 1.7.4)")
- end
- end
-end
diff --git a/spec/bundler/other/cli_dispatch_spec.rb b/spec/bundler/other/cli_dispatch_spec.rb
index d17819b394..a2c745b070 100644
--- a/spec/bundler/other/cli_dispatch_spec.rb
+++ b/spec/bundler/other/cli_dispatch_spec.rb
@@ -2,28 +2,19 @@
RSpec.describe "bundle command names" do
it "work when given fully" do
- bundle "install"
- expect(last_command.bundler_err).to eq("Could not locate Gemfile")
- expect(last_command.stdboth).not_to include("Ambiguous command")
+ bundle "install", raise_on_error: false
+ expect(err).to eq("Could not locate Gemfile")
+ expect(stdboth).not_to include("Ambiguous command")
end
it "work when not ambiguous" do
- bundle "ins"
- expect(last_command.bundler_err).to eq("Could not locate Gemfile")
- expect(last_command.stdboth).not_to include("Ambiguous command")
+ bundle "ins", raise_on_error: false
+ expect(err).to eq("Could not locate Gemfile")
+ expect(stdboth).not_to include("Ambiguous command")
end
it "print a friendly error when ambiguous" do
- bundle "in"
- expect(last_command.bundler_err).to eq("Ambiguous command in matches [info, init, inject, install]")
- end
-
- context "when cache_command_is_package is set" do
- before { bundle! "config cache_command_is_package true" }
-
- it "dispatches `bundle cache` to the package command" do
- bundle "cache --verbose"
- expect(last_command.stdout).to start_with "Running `bundle package --verbose`"
- end
+ bundle "in", raise_on_error: false
+ expect(err).to eq("Ambiguous command in matches [info, init, install]")
end
end
diff --git a/spec/bundler/other/cli_man_pages_spec.rb b/spec/bundler/other/cli_man_pages_spec.rb
new file mode 100644
index 0000000000..4e8f155309
--- /dev/null
+++ b/spec/bundler/other/cli_man_pages_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle commands" do
+ it "expects all commands to have all options and subcommands documented" do
+ check_commands!(Bundler::CLI)
+
+ Bundler::CLI.subcommand_classes.each_value do |klass|
+ check_commands!(klass)
+ end
+ end
+
+ private
+
+ def check_commands!(command_class)
+ command_class.commands.each do |command_name, command|
+ if command.is_a?(Bundler::Thor::HiddenCommand)
+ man_page = man_page(command_name)
+ expect(man_page).not_to exist
+ expect(main_man_page.read).not_to include("bundle #{command_name}")
+ elsif command_class == Bundler::CLI
+ man_page = man_page(command_name)
+ expect(man_page).to exist
+
+ check_options!(command, man_page)
+ else
+ man_page = man_page(command.ancestor_name)
+ expect(man_page).to exist
+
+ check_options!(command, man_page)
+ check_subcommand!(command_name, man_page)
+ end
+ end
+ end
+
+ def check_options!(command, man_page)
+ command.options.each do |_, option|
+ check_option!(option, man_page)
+ end
+ end
+
+ def check_option!(option, man_page)
+ man_page_content = man_page.read
+
+ aliases = option.aliases
+ formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases
+
+ help = if option.type == :boolean
+ "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:"
+ elsif option.enum
+ formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default
+ "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:"
+ else
+ names = [option.switch_name, *aliases]
+ value =
+ case option.type
+ when :array then "<list>"
+ when :numeric then "<number>"
+ else option.name.upcase
+ end
+
+ value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}"
+
+ "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:"
+ end
+
+ if option.banner.include?("(removed)")
+ expect(man_page_content).not_to include(help)
+ else
+ expect(man_page_content).to include(help)
+ end
+ end
+
+ def check_subcommand!(name, man_page)
+ expect(man_page.read).to match(name)
+ end
+
+ def append_aliases(text, aliases)
+ return text if aliases.empty?
+
+ "#{text}, #{aliases}"
+ end
+
+ def prepend_aliases(text, aliases)
+ return text if aliases.empty?
+
+ "#{aliases}, #{text}"
+ end
+
+ def man_page_content(command_name)
+ man_page(command_name).read
+ end
+
+ def man_page(command_name)
+ source_root.join("lib/bundler/man/bundle-#{command_name}.1.ronn")
+ end
+
+ def main_man_page
+ source_root.join("lib/bundler/man/bundle.1.ronn")
+ end
+end
diff --git a/spec/bundler/other/compatibility_guard_spec.rb b/spec/bundler/other/compatibility_guard_spec.rb
deleted file mode 100644
index ac05ebd918..0000000000
--- a/spec/bundler/other/compatibility_guard_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundler compatibility guard" do
- context "when the bundler version is 2+" do
- before { simulate_bundler_version "2.0.a" }
-
- context "when running on Ruby < 2.3", :ruby => "< 2.3" do
- before { simulate_rubygems_version "2.6.11" }
-
- it "raises a friendly error" do
- bundle :version
- expect(err).to eq("Bundler 2 requires Ruby 2.3 or later. Either install bundler 1 or update to a supported Ruby version.")
- end
- end
-
- context "when running on RubyGems < 2.5", :ruby => ">= 2.5" do
- before { simulate_rubygems_version "1.3.6" }
-
- it "raises a friendly error" do
- bundle :version
- expect(err).to eq("Bundler 2 requires RubyGems 2.5 or later. Either install bundler 1 or update to a supported RubyGems version.")
- end
- end
- end
-end
diff --git a/spec/bundler/other/ext_spec.rb b/spec/bundler/other/ext_spec.rb
index 3f6f8b4928..a883eefe06 100644
--- a/spec/bundler/other/ext_spec.rb
+++ b/spec/bundler/other/ext_spec.rb
@@ -1,66 +1,50 @@
# frozen_string_literal: true
-RSpec.describe "Gem::Specification#match_platform" do
+RSpec.describe "Gem::Specification#installable_on_platform?" do
it "does not match platforms other than the gem platform" do
darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10"
- expect(darwin.match_platform(pl("java"))).to eq(false)
+ expect(darwin.installable_on_platform?(pl("java"))).to eq(false)
end
context "when platform is a string" do
it "matches when platform is a string" do
lazy_spec = Bundler::LazySpecification.new("lol", "1.0", "universal-mingw32")
- expect(lazy_spec.match_platform(pl("x86-mingw32"))).to eq(true)
- expect(lazy_spec.match_platform(pl("x64-mingw32"))).to eq(true)
+ expect(lazy_spec.installable_on_platform?(pl("x86-mingw32"))).to eq(true)
+ expect(lazy_spec.installable_on_platform?(pl("x64-mingw32"))).to eq(true)
end
end
end
-RSpec.describe "Bundler::GemHelpers#generic" do
- include Bundler::GemHelpers
-
- it "converts non-windows platforms into ruby" do
- expect(generic(pl("x86-darwin-10"))).to eq(pl("ruby"))
- expect(generic(pl("ruby"))).to eq(pl("ruby"))
- end
-
- it "converts java platform variants into java" do
- expect(generic(pl("universal-java-17"))).to eq(pl("java"))
- expect(generic(pl("java"))).to eq(pl("java"))
- end
-
- it "converts mswin platform variants into x86-mswin32" do
- expect(generic(pl("mswin32"))).to eq(pl("x86-mswin32"))
- expect(generic(pl("i386-mswin32"))).to eq(pl("x86-mswin32"))
- expect(generic(pl("x86-mswin32"))).to eq(pl("x86-mswin32"))
- end
-
- it "converts 32-bit mingw platform variants into x86-mingw32" do
- expect(generic(pl("mingw32"))).to eq(pl("x86-mingw32"))
- expect(generic(pl("i386-mingw32"))).to eq(pl("x86-mingw32"))
- expect(generic(pl("x86-mingw32"))).to eq(pl("x86-mingw32"))
- end
-
- it "converts 64-bit mingw platform variants into x64-mingw32" do
- expect(generic(pl("x64-mingw32"))).to eq(pl("x64-mingw32"))
- expect(generic(pl("x86_64-mingw32"))).to eq(pl("x64-mingw32"))
- end
-end
-
RSpec.describe "Gem::SourceIndex#refresh!" do
before do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- it "does not explode when called", :rubygems => "1.7" do
- run "Gem.source_index.refresh!"
- run "Gem::SourceIndex.new([]).refresh!"
+ it "does not explode when called" do
+ run "Gem.source_index.refresh!", raise_on_error: false
+ run "Gem::SourceIndex.new([]).refresh!", raise_on_error: false
+ end
+end
+
+RSpec.describe "Gem::NameTuple" do
+ describe "#initialize" do
+ it "creates a Gem::NameTuple with equality regardless of platform type" do
+ gem_platform = Gem::NameTuple.new "a", v("1"), pl("x86_64-linux")
+ str_platform = Gem::NameTuple.new "a", v("1"), "x86_64-linux"
+ expect(gem_platform).to eq(str_platform)
+ expect(gem_platform.hash).to eq(str_platform.hash)
+ expect(gem_platform.to_a).to eq(str_platform.to_a)
+ end
end
- it "does not explode when called", :rubygems => "< 1.7" do
- run "Gem.source_index.refresh!"
- run "Gem::SourceIndex.from_gems_in([]).refresh!"
+ describe "#lock_name" do
+ it "returns the lock name" do
+ expect(Gem::NameTuple.new("a", v("1.0.0"), pl("x86_64-linux")).lock_name).to eq("a (1.0.0-x86_64-linux)")
+ expect(Gem::NameTuple.new("a", v("1.0.0"), "ruby").lock_name).to eq("a (1.0.0)")
+ expect(Gem::NameTuple.new("a", v("1.0.0")).lock_name).to eq("a (1.0.0)")
+ end
end
end
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index 32827dbd54..ab7589d698 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -1,282 +1,798 @@
# frozen_string_literal: true
-RSpec.describe "major deprecations", :bundler => "< 3" do
- let(:warnings) { last_command.bundler_err } # change to err in 2.0
- let(:warnings_without_version_messages) { warnings.gsub(/#{Spec::Matchers::MAJOR_DEPRECATION}Bundler will only support ruby(gems)? >= .*/, "") }
+RSpec.describe "major deprecations" do
+ let(:warnings) { err }
- context "in a .99 version" do
+ describe "Bundler" do
before do
- simulate_bundler_version "1.99.1"
- bundle "config --delete major_deprecations"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
end
- it "prints major deprecations without being configured" do
- ruby <<-R
- require "bundler"
- Bundler::SharedHelpers.major_deprecation(Bundler::VERSION)
- R
+ describe ".clean_env" do
+ before do
+ source = "Bundler.clean_env"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
+ end
- expect(warnings).to have_major_deprecation("1.99.1")
+ it "is removed in favor of .unbundled_env and shows a helpful error message about it" do
+ expect(err).to include \
+ "`Bundler.clean_env` has been removed in favor of `Bundler.unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`" \
+ end
end
- end
- before do
- bundle "config major_deprecations true"
+ describe ".with_clean_env" do
+ before do
+ source = "Bundler.with_clean_env {}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
+ end
- create_file "gems.rb", <<-G
- source "file:#{gem_repo1}"
- ruby #{RUBY_VERSION.dump}
- gem "rack"
- G
- bundle! "install"
- end
+ it "is removed in favor of .unbundled_env and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.with_clean_env` has been removed in favor of `Bundler.with_unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
+ )
+ end
+ end
+
+ describe ".clean_system" do
+ before do
+ source = "Bundler.clean_system('ls')"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
+ end
- describe "bundle_ruby" do
- it "prints a deprecation" do
- bundle_ruby
- warnings.gsub! "\nruby #{RUBY_VERSION}", ""
- expect(warnings).to have_major_deprecation "the bundle_ruby executable has been removed in favor of `bundle platform --ruby`"
+ it "is removed in favor of .unbundled_system and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.clean_system` has been removed in favor of `Bundler.unbundled_system`. " \
+ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system`" \
+ )
+ end
end
- end
- describe "Bundler" do
- describe ".clean_env" do
- it "is deprecated in favor of .original_env" do
- source = "Bundler.clean_env"
- bundle "exec ruby -e #{source.dump}"
- expect(warnings).to have_major_deprecation "`Bundler.clean_env` has weird edge cases, use `.original_env` instead"
+ describe ".clean_exec" do
+ before do
+ source = "Bundler.clean_exec('ls')"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
+ end
+
+ it "is removed in favor of .unbundled_exec and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.clean_exec` has been removed in favor of `Bundler.unbundled_exec`. " \
+ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec`" \
+ )
end
end
describe ".environment" do
- it "is deprecated in favor of .load" do
+ before do
source = "Bundler.environment"
- bundle "exec ruby -e #{source.dump}"
- expect(warnings).to have_major_deprecation "Bundler.environment has been removed in favor of Bundler.load"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
+ end
+
+ it "is removed in favor of .load and shows a helpful error message about it" do
+ expect(err).to include "Bundler.environment has been removed in favor of Bundler.load"
end
end
+ end
- shared_examples_for "environmental deprecations" do |trigger|
- describe "ruby version", :ruby => "< 2.0" do
- it "requires a newer ruby version" do
- instance_eval(&trigger)
- expect(warnings).to have_major_deprecation "Bundler will only support ruby >= 2.0, you are running #{RUBY_VERSION}"
- end
+ describe "bundle exec --no-keep-file-descriptors" do
+ before do
+ bundle "exec --no-keep-file-descriptors -e 1", raise_on_error: false
+ end
+
+ it "is removed and shows a helpful error message about it" do
+ expect(err).to include "The `--no-keep-file-descriptors` has been removed. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
+ end
+ end
+
+ describe "bundle update --quiet" do
+ it "does not print any deprecations" do
+ bundle :update, quiet: true, raise_on_error: false
+ expect(deprecations).to be_empty
+ end
+ end
+
+ context "bundle check --path" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "check --path vendor/bundle", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set path 'vendor/bundle'`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle check --path=" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "check --path=vendor/bundle", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set path 'vendor/bundle'`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle binstubs --path=" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "binstubs myrack --path=binpath", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set bin 'binpath'`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --all" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --all --verbose", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--all` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set cache_all true`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --no-all" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --no-all", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--no-all` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set cache_all false`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --path" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --path foo", raise_on_error: false
+ end
+
+ it "should print a removal error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because its semantics were unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --path=" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --path=foo", raise_on_error: false
+ end
+
+ it "should print a deprecation warning" do
+ expect(err).to include(
+ "The `--path` flag has been removed because its semantics were unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --frozen" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --frozen", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--frozen` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set frozen true`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --no-prune" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --no-prune", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--no-prune` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set no_prune true`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ describe "bundle config" do
+ describe "old list interface" do
+ before do
+ bundle "config"
end
- describe "rubygems version", :rubygems => "< 2.0" do
- it "requires a newer rubygems version" do
- instance_eval(&trigger)
- expect(warnings).to have_major_deprecation "Bundler will only support rubygems >= 2.0, you are running #{Gem::VERSION}"
- end
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config list` instead.")
end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "-rbundler/setup" do
- it_behaves_like "environmental deprecations", proc { ruby "require 'bundler/setup'" }
+ describe "old get interface" do
+ before do
+ bundle "config waka", raise_on_error: false
+ end
+
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config get waka` instead.")
+ end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "Bundler.setup" do
- it_behaves_like "environmental deprecations", proc { ruby "require 'bundler'; Bundler.setup" }
+ describe "old set interface" do
+ before do
+ bundle "config waka wakapun"
+ end
+
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set waka wakapun` instead.")
+ end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "bundle check" do
- it_behaves_like "environmental deprecations", proc { bundle :check }
+ describe "old set interface with --local" do
+ before do
+ bundle "config --local waka wakapun"
+ end
+
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set --local waka wakapun` instead.")
+ end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "bundle update --quiet" do
- it "does not print any deprecations" do
- bundle :update, :quiet => true
- expect(warnings_without_version_messages).not_to have_major_deprecation
+ describe "old set interface with --global" do
+ before do
+ bundle "config --global waka wakapun"
+ end
+
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set --global waka wakapun` instead.")
end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "bundle update" do
+ describe "old unset interface" do
before do
- create_file("gems.rb", "")
- bundle! "install"
+ bundle "config --delete waka"
end
- it "warns when no options are given" do
- bundle! "update"
- expect(warnings).to have_major_deprecation a_string_including("Pass --all to `bundle update` to update everything")
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset waka` instead.")
end
- it "does not warn when --all is passed" do
- bundle! "update --all"
- expect(warnings_without_version_messages).not_to have_major_deprecation
+ pending "fails with a helpful error", bundler: "5"
+ end
+
+ describe "old unset interface with --local" do
+ before do
+ bundle "config --delete --local waka"
end
+
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset --local waka` instead.")
+ end
+
+ pending "fails with a helpful error", bundler: "5"
end
- describe "bundle install --binstubs" do
- it "should output a deprecation warning" do
- gemfile <<-G
- gem 'rack'
- G
+ describe "old unset interface with --global" do
+ before do
+ bundle "config --delete --global waka"
+ end
- bundle :install, :binstubs => true
- expect(warnings).to have_major_deprecation a_string_including("The --binstubs option will be removed")
+ it "warns", bundler: "4" do
+ expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset --global waka` instead.")
end
+
+ pending "fails with a helpful error", bundler: "5"
+ end
+ end
+
+ describe "bundle update" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "warns when no options are given", bundler: "4" do
+ bundle "update"
+ expect(deprecations).to include("Pass --all to `bundle update` to update everything")
+ end
+
+ pending "fails with a helpful error when no options are given", bundler: "5"
+
+ it "does not warn when --all is passed" do
+ bundle "update --all"
+ expect(deprecations).to be_empty
end
end
- context "when bundle is run" do
+ describe "bundle install --binstubs" do
+ before do
+ install_gemfile <<-G, binstubs: true, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include("The --binstubs option has been removed in favor of `bundle binstubs --all`")
+ end
+ end
+
+ context "bundle install with both gems.rb and Gemfile present" do
it "should not warn about gems.rb" do
- create_file "gems.rb", <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ gemfile "gems.rb", <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :install
- expect(warnings_without_version_messages).not_to have_major_deprecation
+ expect(deprecations).to be_empty
end
- it "should print a Gemfile deprecation warning" do
- create_file "gems.rb"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ it "should print a proper warning, and use gems.rb" do
+ gemfile "gems.rb", "source 'https://gem.repo1'"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gem "rack 1.0"
- expect(warnings).to have_major_deprecation a_string_including("gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock.")
+ expect(warnings).to include(
+ "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
+ )
+
+ expect(the_bundle).not_to include_gem "myrack 1.0"
end
+ end
- context "with flags" do
- it "should print a deprecation warning about autoremembering flags" do
- install_gemfile <<-G, :path => "vendor/bundle"
- source "file://#{gem_repo1}"
- gem "rack"
- G
+ context "bundle install with flags" do
+ before do
+ bundle_config "path vendor/bundle"
- expect(warnings).to have_major_deprecation a_string_including(
- "flags passed to commands will no longer be automatically remembered."
- )
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ {
+ "clean" => ["clean", "true"],
+ "deployment" => ["deployment", "true"],
+ "frozen" => ["frozen", "true"],
+ "no-deployment" => ["deployment", "false"],
+ "no-prune" => ["no_prune", "true"],
+ "path" => ["path", "'vendor/bundle'"],
+ "shebang" => ["shebang", "'ruby27'"],
+ "system" => ["path.system", "true"],
+ "without" => ["without", "'development'"],
+ "with" => ["with", "'development'"],
+ }.each do |name, expectations|
+ option_name, value = *expectations
+ flag_name = "--#{name}"
+ args = %w[true false].include?(value) ? flag_name : "#{flag_name} #{value}"
+
+ context "with the #{flag_name} flag" do
+ before do
+ bundle "install" # to create a lockfile, which deployment or frozen need
+
+ bundle "install #{args}", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `#{flag_name}` flag has been removed because it relied on " \
+ "being remembered across bundler invocations, which bundler no " \
+ "longer does. Instead please use `bundle config set " \
+ "#{option_name} #{value}`, and stop using this flag"
+ )
+ end
end
end
end
+ context "bundle install with multiple sources" do
+ before do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo3"
+ source "https://gem.repo1"
+ G
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
+ )
+ end
+
+ it "doesn't show lockfile deprecations if there's a lockfile" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo3/
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ bundle "install", raise_on_error: false
+
+ expect(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
+ )
+ expect(err).not_to include(
+ "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
+ "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
+ )
+ bundle_config "frozen true"
+ bundle "install", raise_on_error: false
+
+ expect(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
+ )
+ expect(err).not_to include(
+ "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
+ "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
+ )
+ end
+ end
+
+ context "bundle install with a lockfile with a single rubygems section with multiple remotes" do
+ before do
+ build_repo3 do
+ build_gem "myrack", "0.9.1"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ source "https://gem.repo3" do
+ gem 'myrack'
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo1/
+ remote: https://gem.repo3/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ myrack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "shows an error" do
+ bundle "install", raise_on_error: false
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.")
+ end
+ end
+
+ context "bundle install with a lockfile including X64_MINGW_LEGACY platform" do
+ before do
+ gemfile <<~G
+ source "https://gem.repo1"
+ gem "rake"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (10.3.2)
+
+ PLATFORMS
+ ruby
+ x64-mingw32
+
+ DEPENDENCIES
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "warns a helpful error" do
+ bundle "install", raise_on_error: false
+
+ expect(err).to include("Found x64-mingw32 in lockfile, which is deprecated and will be removed in the future.")
+ end
+ end
+
+ context "with a global path source" do
+ before do
+ build_lib "foo"
+
+ install_gemfile <<-G, raise_on_error: false
+ path "#{lib_path("foo-1.0")}"
+ gem 'foo'
+ G
+ end
+
+ it "shows an error" do
+ expect(err).to include("You can no longer specify a path source by itself")
+ end
+ end
+
context "when Bundler.setup is run in a ruby script" do
- it "should print a single deprecation warning" do
- create_file "gems.rb"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack", :group => :test
+ before do
+ create_file "gems.rb", "source 'https://gem.repo1'"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
G
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
- require 'bundler/vendored_thor'
- Bundler.ui = Bundler::UI::Shell.new
Bundler.setup
Bundler.setup
RUBY
+ end
- expect(warnings_without_version_messages).to have_major_deprecation("gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock.")
+ it "should print a single deprecation warning" do
+ expect(warnings).to include(
+ "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
+ )
end
end
context "when `bundler/deployment` is required in a ruby script" do
- it "should print a capistrano deprecation warning" do
- ruby(<<-RUBY)
+ before do
+ ruby <<-RUBY, raise_on_error: false
require 'bundler/deployment'
RUBY
+ end
- expect(warnings).to have_major_deprecation("Bundler no longer integrates " \
+ it "should print a capistrano deprecation warning" do
+ expect(err).to include("Bundler no longer integrates " \
"with Capistrano, but Capistrano provides " \
"its own integration with Bundler via the " \
"capistrano-bundler gem. Use it instead.")
end
end
- describe Bundler::Dsl do
+ context "when `bundler/capistrano` is required in a ruby script" do
before do
- @rubygems = double("rubygems")
- allow(Bundler::Source::Rubygems).to receive(:new) { @rubygems }
+ ruby <<-RUBY, raise_on_error: false
+ require 'bundler/capistrano'
+ RUBY
end
- context "with github gems" do
- it "warns about the https change" do
- msg = <<-EOS
-The :github git source is deprecated, and will be removed in Bundler 2.0. Change any "reponame" :github sources to "username/reponame". Add this code to the top of your Gemfile to ensure it continues to work:
+ it "fails with a helpful error" do
+ expect(err).to include("[REMOVED] The Bundler task for Capistrano. Please use https://github.com/capistrano/bundler")
+ end
+ end
- git_source(:github) {|repo_name| "https://github.com/\#{repo_name}.git" }
+ context "when `bundler/vlad` is required in a ruby script" do
+ before do
+ ruby <<-RUBY, raise_on_error: false
+ require 'bundler/vlad'
+ RUBY
+ end
- EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
- subject.gem("sparks", :github => "indirect/sparks")
+ it "fails with a helpful error" do
+ expect(err).to include("[REMOVED] The Bundler task for Vlad")
+ end
+ end
+
+ context "bundle show" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ context "with --outdated flag" do
+ before do
+ bundle "show --outdated", raise_on_error: false
end
- it "upgrades to https on request" do
- Bundler.settings.temporary "github.https" => true
- msg = <<-EOS
-The :github git source is deprecated, and will be removed in Bundler 2.0. Change any "reponame" :github sources to "username/reponame". Add this code to the top of your Gemfile to ensure it continues to work:
+ it "fails with a helpful message" do
+ expect(err).to include("the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`")
+ end
+ end
+ end
- git_source(:github) {|repo_name| "https://github.com/\#{repo_name}.git" }
+ context "bundle remove" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ context "with --install" do
+ it "fails with a helpful message" do
+ bundle "remove myrack --install", raise_on_error: false
- EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, "The `github.https` setting will be removed")
- subject.gem("sparks", :github => "indirect/sparks")
- github_uri = "https://github.com/indirect/sparks.git"
- expect(subject.dependencies.first.source.uri).to eq(github_uri)
+ expect(err).to include "The `--install` flag has been removed. `bundle install` is triggered by default."
end
end
+ end
- context "with bitbucket gems" do
- it "warns about removal" do
- allow(Bundler.ui).to receive(:deprecate)
- msg = <<-EOS
-The :bitbucket git source is deprecated, and will be removed in Bundler 2.0. Add this code to the top of your Gemfile to ensure it continues to work:
+ context "bundle viz" do
+ before do
+ bundle "viz", raise_on_error: false
+ end
- git_source(:bitbucket) do |repo_name|
- user_name, repo_name = repo_name.split("/")
- repo_name ||= user_name
- "https://\#{user_name}@bitbucket.org/\#{user_name}/\#{repo_name}.git"
+ it "fails with a helpful message" do
+ expect(err).to include "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
end
+ end
- EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
- subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
- end
+ context "bundle inject" do
+ before do
+ bundle "inject", raise_on_error: false
end
- context "with gist gems" do
- it "warns about removal" do
- allow(Bundler.ui).to receive(:deprecate)
- msg = "The :gist git source is deprecated, and will be removed " \
- "in Bundler 2.0. Add this code to the top of your Gemfile to ensure it " \
- "continues to work:\n\n git_source(:gist) {|repo_name| " \
- "\"https://gist.github.com/\#{repo_name}.git\" }\n\n"
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
- subject.gem("not-really-a-gem", :gist => "1234")
+ it "fails with a helpful message" do
+ expect(err).to include "The `inject` command has been replaced by the `add` command"
+ end
+ end
+
+ context "bundle plugin install --local_git" do
+ before do
+ build_git "foo" do |s|
+ s.write "plugins.rb"
end
end
+
+ it "fails with a helpful message" do
+ bundle "plugin install foo --local_git #{lib_path("foo-1.0")}", raise_on_error: false
+
+ expect(err).to include "--local_git has been removed, use --git"
+ end
end
- context "bundle show" do
- it "prints a deprecation warning" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
+ describe "removing rubocop" do
+ before do
+ bundle_config_global "gem.mit false"
+ bundle_config_global "gem.test false"
+ bundle_config_global "gem.coc false"
+ bundle_config_global "gem.ci false"
+ bundle_config_global "gem.changelog false"
+ end
+
+ context "bundle gem --rubocop" do
+ before do
+ bundle "gem my_new_gem --rubocop", raise_on_error: false
+ end
- bundle! :show
+ it "prints an error" do
+ expect(err).to include \
+ "--rubocop has been removed, use --linter=rubocop"
+ end
+ end
- warnings.gsub!(/gems included.*?\[DEPRECATED/im, "[DEPRECATED")
+ context "bundle gem --no-rubocop" do
+ before do
+ bundle "gem my_new_gem --no-rubocop", raise_on_error: false
+ end
- expect(warnings).to have_major_deprecation a_string_including("use `bundle list` instead of `bundle show`")
+ it "prints an error" do
+ expect(err).to include \
+ "--no-rubocop has been removed, use --no-linter"
+ end
end
end
- context "bundle console" do
- it "prints a deprecation warning" do
- bundle "console"
+ context " bundle gem --ext parameter with no value" do
+ it "prints error when used before gem name" do
+ bundle "gem --ext foo", raise_on_error: false
+ expect(err).to include "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
+ end
- expect(warnings).to have_major_deprecation \
- a_string_including("bundle console will be replaced by `bin/console` generated by `bundle gem <name>`")
+ it "prints error when used after gem name" do
+ bundle "gem foo --ext", raise_on_error: false
+ expect(err).to include "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
end
end
end
diff --git a/spec/bundler/other/platform_spec.rb b/spec/bundler/other/platform_spec.rb
deleted file mode 100644
index 6c59fd893c..0000000000
--- a/spec/bundler/other/platform_spec.rb
+++ /dev/null
@@ -1,1312 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle platform" do
- context "without flags" do
- let(:bundle_platform_platforms_string) do
- platforms = [rb]
- platforms.unshift(specific_local_platform) if Bundler.feature_flag.bundler_3_mode?
- platforms.map {|pl| "* #{pl}" }.join("\n")
- end
-
- it "returns all the output" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- #{ruby_version_correct}
-
- gem "foo"
- G
-
- bundle "platform"
- expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
-
-Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
-
-Your Gemfile specifies a Ruby version requirement:
-* ruby #{RUBY_VERSION}
-
-Your current platform satisfies the Ruby version requirement.
-G
- end
-
- it "returns all the output including the patchlevel" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- #{ruby_version_correct_patchlevel}
-
- gem "foo"
- G
-
- bundle "platform"
- expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
-
-Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
-
-Your Gemfile specifies a Ruby version requirement:
-* ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
-
-Your current platform satisfies the Ruby version requirement.
-G
- end
-
- it "doesn't print ruby version requirement if it isn't specified" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- gem "foo"
- G
-
- bundle "platform"
- expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
-
-Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
-
-Your Gemfile does not specify a Ruby version requirement.
-G
- end
-
- it "doesn't match the ruby version requirement" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- #{ruby_version_incorrect}
-
- gem "foo"
- G
-
- bundle "platform"
- expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
-
-Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
-
-Your Gemfile specifies a Ruby version requirement:
-* ruby #{not_local_ruby_version}
-
-Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}
-G
- end
- end
-
- context "--ruby" do
- it "returns ruby version when explicit" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("ruby 1.9.3")
- end
-
- it "defaults to MRI" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.9.3"
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("ruby 1.9.3")
- end
-
- it "handles jruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5'
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("ruby 1.8.7 (jruby 1.6.5)")
- end
-
- it "handles rbx" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("ruby 1.8.7 (rbx 1.2.4)")
- end
-
- it "handles truffleruby", :rubygems => ">= 2.1.0" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "2.5.1", :engine => 'truffleruby', :engine_version => '1.0.0-rc6'
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("ruby 2.5.1 (truffleruby 1.0.0-rc6)")
- end
-
- it "raises an error if engine is used but engine version is not" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'rbx'
-
- gem "foo"
- G
-
- bundle "platform"
-
- expect(exitstatus).not_to eq(0) if exitstatus
- end
-
- it "raises an error if engine_version is used but engine is not" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle "platform"
-
- expect(exitstatus).not_to eq(0) if exitstatus
- end
-
- it "raises an error if engine version doesn't match ruby version for MRI" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4'
-
- gem "foo"
- G
-
- bundle "platform"
-
- expect(exitstatus).not_to eq(0) if exitstatus
- end
-
- it "should print if no ruby version is specified" do
- gemfile <<-G
- source "file://#{gem_repo1}"
-
- gem "foo"
- G
-
- bundle "platform --ruby"
-
- expect(out).to eq("No ruby version specified")
- end
-
- it "handles when there is a locked requirement" do
- gemfile <<-G
- ruby "< 1.8.7"
- G
-
- lockfile <<-L
- GEM
- specs:
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
-
- RUBY VERSION
- ruby 1.0.0p127
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- bundle! "platform --ruby"
- expect(out).to eq("ruby 1.0.0p127")
- end
-
- it "handles when there is a requirement in the gemfile" do
- gemfile <<-G
- ruby ">= 1.8.7"
- G
-
- bundle! "platform --ruby"
- expect(out).to eq("ruby 1.8.7")
- end
-
- it "handles when there are multiple requirements in the gemfile" do
- gemfile <<-G
- ruby ">= 1.8.7", "< 2.0.0"
- G
-
- bundle! "platform --ruby"
- expect(out).to eq("ruby 1.8.7")
- end
- end
-
- let(:ruby_version_correct) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{local_engine_version}\"" }
- let(:ruby_version_correct_engineless) { "ruby \"#{RUBY_VERSION}\"" }
- let(:ruby_version_correct_patchlevel) { "#{ruby_version_correct}, :patchlevel => '#{RUBY_PATCHLEVEL}'" }
- let(:ruby_version_incorrect) { "ruby \"#{not_local_ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_ruby_version}\"" }
- let(:engine_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{not_local_tag}\", :engine_version => \"#{RUBY_VERSION}\"" }
- let(:engine_version_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_engine_version}\"" }
- let(:patchlevel_incorrect) { "#{ruby_version_correct}, :patchlevel => '#{not_local_patchlevel}'" }
- let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" }
-
- def should_be_ruby_version_incorrect
- expect(exitstatus).to eq(18) if exitstatus
- expect(out).to be_include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}")
- end
-
- def should_be_engine_incorrect
- expect(exitstatus).to eq(18) if exitstatus
- expect(out).to be_include("Your Ruby engine is #{local_ruby_engine}, but your Gemfile specified #{not_local_tag}")
- end
-
- def should_be_engine_version_incorrect
- expect(exitstatus).to eq(18) if exitstatus
- expect(out).to be_include("Your #{local_ruby_engine} version is #{local_engine_version}, but your Gemfile specified #{local_ruby_engine} #{not_local_engine_version}")
- end
-
- def should_be_patchlevel_incorrect
- expect(exitstatus).to eq(18) if exitstatus
- expect(out).to be_include("Your Ruby patchlevel is #{RUBY_PATCHLEVEL}, but your Gemfile specified #{not_local_patchlevel}")
- end
-
- def should_be_patchlevel_fixnum
- expect(exitstatus).to eq(18) if exitstatus
- expect(out).to be_include("The Ruby patchlevel in your Gemfile must be a string")
- end
-
- context "bundle install" do
- it "installs fine when the ruby version matches" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_correct}
- G
-
- expect(bundled_app("Gemfile.lock")).to exist
- end
-
- it "installs fine with any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_correct_engineless}
- G
-
- expect(bundled_app("Gemfile.lock")).to exist
- end
- end
-
- it "installs fine when the patchlevel matches" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_correct_patchlevel}
- G
-
- expect(bundled_app("Gemfile.lock")).to exist
- end
-
- it "doesn't install when the ruby version doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_incorrect}
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_ruby_version_incorrect
- end
-
- it "doesn't install when engine doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{engine_incorrect}
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_incorrect
- end
-
- it "doesn't install when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{engine_version_incorrect}
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_version_incorrect
- end
- end
-
- it "doesn't install when patchlevel doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle check" do
- it "checks fine when the ruby version matches" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_correct}
- G
-
- bundle :check
- expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
- end
-
- it "checks fine with any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_correct_engineless}
- G
-
- bundle :check
- expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
- end
- end
-
- it "fails when ruby version doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{ruby_version_incorrect}
- G
-
- bundle :check
- should_be_ruby_version_incorrect
- end
-
- it "fails when engine doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{engine_incorrect}
- G
-
- bundle :check
- should_be_engine_incorrect
- end
-
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "ruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{engine_version_incorrect}
- G
-
- bundle :check
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- bundle :check
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle update" do
- before do
- build_repo2
-
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
- G
- end
-
- it "updates successfully when the ruby version matches" do
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
-
- #{ruby_version_correct}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle "update", :all => bundle_update_requires_all?
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
- end
-
- it "updates fine with any engine" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
-
- #{ruby_version_correct_engineless}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle "update", :all => bundle_update_requires_all?
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
- end
- end
-
- it "fails when ruby version doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
-
- #{ruby_version_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle :update, :all => bundle_update_requires_all?
- should_be_ruby_version_incorrect
- end
-
- it "fails when ruby engine doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
-
- #{engine_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle :update, :all => bundle_update_requires_all?
- should_be_engine_incorrect
- end
-
- it "fails when ruby engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport"
- gem "rack-obama"
-
- #{engine_version_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle :update, :all => bundle_update_requires_all?
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle :update, :all => bundle_update_requires_all?
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle info" do
- before do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
- G
- end
-
- it "prints path if ruby version is correct" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rails"
-
- #{ruby_version_correct}
- G
-
- bundle "info rails --path"
- expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
- end
-
- it "prints path if ruby version is correct for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rails"
-
- #{ruby_version_correct_engineless}
- G
-
- bundle "info rails --path"
- expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
- end
- end
-
- it "fails if ruby version doesn't match", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
-
- #{ruby_version_incorrect}
- G
-
- bundle "show rails"
- should_be_ruby_version_incorrect
- end
-
- it "fails if engine doesn't match", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
-
- #{engine_incorrect}
- G
-
- bundle "show rails"
- should_be_engine_incorrect
- end
-
- it "fails if engine version doesn't match", :bundler => "< 3" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rails"
-
- #{engine_version_incorrect}
- G
-
- bundle "show rails"
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle "show rails"
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle cache" do
- before do
- install_gemfile <<-G
- source "file:#{gem_repo1}"
- gem 'rack'
- G
- end
-
- it "copies the .gem file to vendor/cache when ruby version matches" do
- gemfile <<-G
- gem 'rack'
-
- #{ruby_version_correct}
- G
-
- bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
-
- it "copies the .gem file to vendor/cache when ruby version matches for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem 'rack'
-
- #{ruby_version_correct_engineless}
- G
-
- bundle! :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
- end
-
- it "fails if the ruby version doesn't match" do
- gemfile <<-G
- gem 'rack'
-
- #{ruby_version_incorrect}
- G
-
- bundle :cache
- should_be_ruby_version_incorrect
- end
-
- it "fails if the engine doesn't match" do
- gemfile <<-G
- gem 'rack'
-
- #{engine_incorrect}
- G
-
- bundle :cache
- should_be_engine_incorrect
- end
-
- it "fails if the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- gem 'rack'
-
- #{engine_version_incorrect}
- G
-
- bundle :cache
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- bundle :cache
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle pack" do
- before do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem 'rack'
- G
- end
-
- it "copies the .gem file to vendor/cache when ruby version matches" do
- gemfile <<-G
- gem 'rack'
-
- #{ruby_version_correct}
- G
-
- bundle :pack
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
-
- it "copies the .gem file to vendor/cache when ruby version matches any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem 'rack'
-
- #{ruby_version_correct_engineless}
- G
-
- bundle :pack
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
- end
-
- it "fails if the ruby version doesn't match" do
- gemfile <<-G
- gem 'rack'
-
- #{ruby_version_incorrect}
- G
-
- bundle :pack
- should_be_ruby_version_incorrect
- end
-
- it "fails if the engine doesn't match" do
- gemfile <<-G
- gem 'rack'
-
- #{engine_incorrect}
- G
-
- bundle :pack
- should_be_engine_incorrect
- end
-
- it "fails if the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- gem 'rack'
-
- #{engine_version_incorrect}
- G
-
- bundle :pack
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- bundle :pack
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle exec" do
- before do
- ENV["BUNDLER_FORCE_TTY"] = "true"
- system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path
- end
-
- it "activates the correct gem when ruby version matches" do
- gemfile <<-G
- gem "rack", "0.9.1"
-
- #{ruby_version_correct}
- G
-
- bundle "exec rackup"
- expect(out).to eq("0.9.1")
- end
-
- it "activates the correct gem when ruby version matches any engine" do
- simulate_ruby_engine "jruby" do
- system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path
- gemfile <<-G
- gem "rack", "0.9.1"
-
- #{ruby_version_correct_engineless}
- G
-
- bundle "exec rackup"
- expect(out).to eq("0.9.1")
- end
- end
-
- it "fails when the ruby version doesn't match" do
- gemfile <<-G
- gem "rack", "0.9.1"
-
- #{ruby_version_incorrect}
- G
-
- bundle "exec rackup"
- should_be_ruby_version_incorrect
- end
-
- it "fails when the engine doesn't match" do
- gemfile <<-G
- gem "rack", "0.9.1"
-
- #{engine_incorrect}
- G
-
- bundle "exec rackup"
- should_be_engine_incorrect
- end
-
- # it "fails when the engine version doesn't match" do
- # simulate_ruby_engine "jruby" do
- # gemfile <<-G
- # gem "rack", "0.9.1"
- #
- # #{engine_version_incorrect}
- # G
- #
- # bundle "exec rackup"
- # should_be_engine_version_incorrect
- # end
- # end
-
- it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- bundle "exec rackup"
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle console", :bundler => "< 3" do
- before do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
- G
- end
-
- it "starts IRB with the default group loaded when ruby version matches" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{ruby_version_correct}
- G
-
- bundle "console" do |input, _, _|
- input.puts("puts RACK")
- input.puts("exit")
- end
- expect(out).to include("0.9.1")
- end
-
- it "starts IRB with the default group loaded when ruby version matches any engine" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{ruby_version_correct_engineless}
- G
-
- bundle "console" do |input, _, _|
- input.puts("puts RACK")
- input.puts("exit")
- end
- expect(out).to include("0.9.1")
- end
- end
-
- it "fails when ruby version doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{ruby_version_incorrect}
- G
-
- bundle "console"
- should_be_ruby_version_incorrect
- end
-
- it "fails when engine doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{engine_incorrect}
- G
-
- bundle "console"
- should_be_engine_incorrect
- end
-
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{engine_version_incorrect}
- G
-
- bundle "console"
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{patchlevel_incorrect}
- G
-
- bundle "console"
- should_be_patchlevel_incorrect
- end
- end
-
- context "Bundler.setup" do
- before do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack", :group => :test
- G
-
- ENV["BUNDLER_FORCE_TTY"] = "true"
- end
-
- it "makes a Gemfile.lock if setup succeeds" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{ruby_version_correct}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- run "1"
- expect(bundled_app("Gemfile.lock")).to exist
- end
-
- it "makes a Gemfile.lock if setup succeeds for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{ruby_version_correct_engineless}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- run "1"
- expect(bundled_app("Gemfile.lock")).to exist
- end
- end
-
- it "fails when ruby version doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{ruby_version_incorrect}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- ruby <<-R
- require 'rubygems'
- require 'bundler/setup'
- R
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_ruby_version_incorrect
- end
-
- it "fails when engine doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{engine_incorrect}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- ruby <<-R
- require 'rubygems'
- require 'bundler/setup'
- R
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_incorrect
- end
-
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{engine_version_incorrect}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- ruby <<-R
- require 'rubygems'
- require 'bundler/setup'
- R
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when patchlevel doesn't match" do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "yard"
- gem "rack"
-
- #{patchlevel_incorrect}
- G
-
- FileUtils.rm(bundled_app("Gemfile.lock"))
-
- ruby <<-R
- require 'rubygems'
- require 'bundler/setup'
- R
-
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_patchlevel_incorrect
- end
- end
-
- context "bundle outdated" do
- before do
- build_repo2 do
- build_git "foo", :path => lib_path("foo")
- end
-
- install_gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
- G
- end
-
- it "returns list of outdated gems when the ruby version matches" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{ruby_version_correct}
- G
-
- bundle "outdated"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5")
- expect(out).to include("foo (newest 1.0")
- end
-
- it "returns list of outdated gems when the ruby version matches for any engine" do
- simulate_ruby_engine "jruby" do
- bundle! :install
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{ruby_version_correct_engineless}
- G
-
- bundle "outdated"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("foo (newest 1.0")
- end
- end
-
- it "fails when the ruby version doesn't match" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{ruby_version_incorrect}
- G
-
- bundle "outdated"
- should_be_ruby_version_incorrect
- end
-
- it "fails when the engine doesn't match" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{engine_incorrect}
- G
-
- bundle "outdated"
- should_be_engine_incorrect
- end
-
- it "fails when the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{engine_version_incorrect}
- G
-
- bundle "outdated"
- should_be_engine_version_incorrect
- end
- end
-
- it "fails when the patchlevel doesn't match" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{patchlevel_incorrect}
- G
-
- bundle "outdated"
- should_be_patchlevel_incorrect
- end
- end
-
- it "fails when the patchlevel is a fixnum" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
-
- gemfile <<-G
- source "file://#{gem_repo2}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
-
- #{patchlevel_fixnum}
- G
-
- bundle "outdated"
- should_be_patchlevel_fixnum
- end
- end
- end
-end
diff --git a/spec/bundler/other/ssl_cert_spec.rb b/spec/bundler/other/ssl_cert_spec.rb
deleted file mode 100644
index 6d957276fc..0000000000
--- a/spec/bundler/other/ssl_cert_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/ssl_certs/certificate_manager"
-
-RSpec.describe "SSL Certificates", :rubygems_master do
- hosts = %w[
- rubygems.org
- index.rubygems.org
- rubygems.global.ssl.fastly.net
- staging.rubygems.org
- ]
-
- hosts.each do |host|
- it "can securely connect to #{host}", :realworld do
- Bundler::SSLCerts::CertificateManager.new.connect_to(host)
- end
- end
-end
diff --git a/spec/bundler/plugins/command_spec.rb b/spec/bundler/plugins/command_spec.rb
index 999d8b722b..05d535a70c 100644
--- a/spec/bundler/plugins/command_spec.rb
+++ b/spec/bundler/plugins/command_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install command-mah --source file://#{gem_repo2}"
+ bundle "plugin install command-mah --source https://gem.repo2"
end
it "executes without arguments" do
@@ -29,7 +29,7 @@ RSpec.describe "command plugins" do
end
it "accepts the arguments" do
- build_repo2 do
+ update_repo2 do
build_plugin "the-echoer" do |s|
s.write "plugins.rb", <<-RUBY
module Resonance
@@ -46,15 +46,49 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install the-echoer --source file://#{gem_repo2}"
+ bundle "plugin install the-echoer --source https://gem.repo2"
expect(out).to include("Installed plugin the-echoer")
bundle "echo tacos tofu lasange"
expect(out).to eq("You gave me tacos, tofu, lasange")
end
+ it "passes help flag to plugin" do
+ update_repo2 do
+ build_plugin "helpful" do |s|
+ s.write "plugins.rb", <<-RUBY
+ module Helpful
+ class Command
+ Bundler::Plugin::API.command "greet", self
+
+ def exec(command, args)
+ if args.include?("--help") || args.include?("-h")
+ puts "Usage: bundle greet [NAME]"
+ else
+ puts "Hello"
+ end
+ end
+ end
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install helpful --source https://gem.repo2"
+ expect(out).to include("Installed plugin helpful")
+
+ bundle "greet --help"
+ expect(out).to eq("Usage: bundle greet [NAME]")
+
+ bundle "greet -h"
+ expect(out).to eq("Usage: bundle greet [NAME]")
+
+ bundle "help greet"
+ expect(out).to eq("Usage: bundle greet [NAME]")
+ end
+
it "raises error on redeclaration of command" do
- build_repo2 do
+ update_repo2 do
build_plugin "copycat" do |s|
s.write "plugins.rb", <<-RUBY
module CopyCat
@@ -69,12 +103,10 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install copycat --source file://#{gem_repo2}"
+ bundle "plugin install copycat --source https://gem.repo2", raise_on_error: false
expect(out).not_to include("Installed plugin copycat")
- expect(out).to include("Failed to install plugin")
-
- expect(out).to include("Command(s) `mahcommand` declared by copycat are already registered.")
+ expect(err).to include("Failed to install plugin `copycat`, due to Bundler::Plugin::Index::CommandConflict (Command(s) `mahcommand` declared by copycat are already registered.)")
end
end
diff --git a/spec/bundler/plugins/hook_spec.rb b/spec/bundler/plugins/hook_spec.rb
index 53062095e2..ad8a4daeff 100644
--- a/spec/bundler/plugins/hook_spec.rb
+++ b/spec/bundler/plugins/hook_spec.rb
@@ -13,17 +13,17 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-install-all-plugin --source file://#{gem_repo2}"
+ bundle "plugin install before-install-all-plugin --source https://gem.repo2"
end
it "runs before all rubygems are installed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
- expect(out).to include "gems to be installed rake, rack"
+ expect(out).to include "gems to be installed rake, myrack"
end
end
@@ -39,18 +39,18 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-install-plugin --source file://#{gem_repo2}"
+ bundle "plugin install before-install-plugin --source https://gem.repo2"
end
it "runs before each rubygem is installed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
expect(out).to include "installing gem rake"
- expect(out).to include "installing gem rack"
+ expect(out).to include "installing gem myrack"
end
end
@@ -66,17 +66,17 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-install-all-plugin --source file://#{gem_repo2}"
+ bundle "plugin install after-install-all-plugin --source https://gem.repo2"
end
- it "runs after each rubygem is installed" do
+ it "runs after each all rubygems are installed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
- expect(out).to include "installed gems rake, rack"
+ expect(out).to include "installed gems rake, myrack"
end
end
@@ -92,18 +92,240 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-install-plugin --source file://#{gem_repo2}"
+ bundle "plugin install after-install-plugin --source https://gem.repo2"
end
it "runs after each rubygem is installed" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
expect(out).to include "installed gem rake : installed"
- expect(out).to include "installed gem rack : installed"
+ expect(out).to include "installed gem myrack : installed"
+ end
+ end
+
+ context "before-require-all hook" do
+ before do
+ build_repo2 do
+ build_plugin "before-require-all-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_REQUIRE_ALL do |deps|
+ puts "gems to be required \#{deps.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install before-require-all-plugin --source https://gem.repo2"
+ end
+
+ it "runs before all rubygems are required" do
+ install_gemfile_and_bundler_require
+ expect(out).to include "gems to be required rake, myrack"
+ end
+ end
+
+ context "before-require hook" do
+ before do
+ build_repo2 do
+ build_plugin "before-require-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_REQUIRE do |dep|
+ puts "requiring gem \#{dep.name}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install before-require-plugin --source https://gem.repo2"
+ end
+
+ it "runs before each rubygem is required" do
+ install_gemfile_and_bundler_require
+ expect(out).to include "requiring gem rake"
+ expect(out).to include "requiring gem myrack"
end
end
+
+ context "after-require-all hook" do
+ before do
+ build_repo2 do
+ build_plugin "after-require-all-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_REQUIRE_ALL do |deps|
+ puts "required gems \#{deps.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install after-require-all-plugin --source https://gem.repo2"
+ end
+
+ it "runs after all rubygems are required" do
+ install_gemfile_and_bundler_require
+ expect(out).to include "required gems rake, myrack"
+ end
+ end
+
+ context "after-require hook" do
+ before do
+ build_repo2 do
+ build_plugin "after-require-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_REQUIRE do |dep|
+ puts "required gem \#{dep.name}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install after-require-plugin --source https://gem.repo2"
+ end
+
+ it "runs after each rubygem is required" do
+ install_gemfile_and_bundler_require
+ expect(out).to include "required gem rake"
+ expect(out).to include "required gem myrack"
+ end
+ end
+
+ context "before-eval hook" do
+ before do
+ build_repo2 do
+ build_plugin "before-eval-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_EVAL do |gemfile, lockfile|
+ puts "hooked eval start of \#{File.basename(gemfile)} to \#{File.basename(lockfile)}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install before-eval-plugin --source https://gem.repo2"
+ end
+
+ it "runs before the Gemfile is evaluated" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rake"
+ G
+
+ expect(out).to include "hooked eval start of Gemfile to Gemfile.lock"
+ end
+ end
+
+ context "after-eval hook" do
+ before do
+ build_repo2 do
+ build_plugin "after-eval-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_EVAL do |defn|
+ puts "hooked eval after with gems \#{defn.dependencies.map(&:name).join(", ")}"
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install after-eval-plugin --source https://gem.repo2"
+ end
+
+ it "runs after the Gemfile is evaluated" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "rake"
+ G
+
+ expect(out).to include "hooked eval after with gems myrack, rake"
+ end
+ end
+
+ context "before-fetch and after-fetch hooks" do
+ before do
+ build_repo2 do
+ build_plugin "fetch-timing-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ @timing_start = nil
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_BEFORE_FETCH do |spec|
+ @timing_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ puts "gem \#{spec.name} started fetch at \#{@timing_start}"
+ end
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GEM_AFTER_FETCH do |spec|
+ timing_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ puts "gem \#{spec.name} took \#{timing_end - @timing_start} to fetch"
+ @timing_start = nil
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install fetch-timing-plugin --source https://gem.repo2"
+ end
+
+ it "runs around each gem download" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rake"
+ gem "myrack"
+ G
+
+ expect(out).to include "gem rake started fetch at"
+ expect(out).to match(/gem rake took \d+\.\d+ to fetch/)
+ expect(out).to include "gem myrack started fetch at"
+ expect(out).to match(/gem myrack took \d+\.\d+ to fetch/)
+ end
+ end
+
+ context "before-git-fetch and after-git-fetch hooks" do
+ before do
+ build_repo2 do
+ build_plugin "git-fetch-timing-plugin" do |s|
+ s.write "plugins.rb", <<-RUBY
+ @timing_start = nil
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GIT_BEFORE_FETCH do |source|
+ @timing_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ puts "git source \#{source.name} started fetch at \#{@timing_start}"
+ end
+ Bundler::Plugin::API.hook Bundler::Plugin::Events::GIT_AFTER_FETCH do |source|
+ timing_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ puts "git source \#{source.name} took \#{timing_end - @timing_start} to fetch"
+ @timing_start = nil
+ end
+ RUBY
+ end
+ end
+
+ bundle "plugin install git-fetch-timing-plugin --source https://gem.repo2"
+ end
+
+ it "runs around each git source fetch" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ relative_path = lib_path("foo").relative_path_from(bundled_app)
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{relative_path}"
+ G
+
+ expect(out).to include "git source foo started fetch at"
+ expect(out).to match(/git source foo took \d+\.\d+ to fetch/)
+ end
+ end
+
+ def install_gemfile_and_bundler_require
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rake"
+ gem "myrack"
+ G
+
+ ruby <<-RUBY
+ require "bundler"
+ Bundler.require
+ RUBY
+ end
end
diff --git a/spec/bundler/plugins/install_spec.rb b/spec/bundler/plugins/install_spec.rb
index 9304d78062..dcacf764be 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -9,21 +9,54 @@ RSpec.describe "bundler plugin install" do
end
it "shows proper message when gem in not found in the source" do
- bundle "plugin install no-foo --source file://#{gem_repo1}"
+ bundle "plugin install no-foo --source https://gem.repo1", raise_on_error: false
- expect(out).to include("Could not find")
+ expect(err).to include("Could not find")
plugin_should_not_be_installed("no-foo")
end
it "installs from rubygems source" do
- bundle "plugin install foo --source file://#{gem_repo2}"
+ bundle "plugin install foo --source https://gem.repo2"
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
end
+ it "installs from rubygems source in frozen mode" do
+ bundle "plugin install foo --source https://gem.repo2", env: { "BUNDLE_DEPLOYMENT" => "true" }
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
+ it "installs from sources configured as Gem.sources without any flags" do
+ bundle "plugin install foo", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_SOURCES" => "https://gem.repo2" }
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
+ it "shows help when --help flag is given" do
+ bundle "plugin install --help"
+
+ # The help message defined in ../../lib/bundler/man/bundle-plugin.1.ronn will be output.
+ expect(out).to include("You can install, uninstall, and list plugin(s)")
+ end
+
+ context "plugin is already installed" do
+ before do
+ bundle "plugin install foo --source https://gem.repo2"
+ end
+
+ it "doesn't install plugin again" do
+ bundle "plugin install foo --source https://gem.repo2"
+ expect(out).not_to include("Installing plugin foo")
+ expect(out).not_to include("Installed plugin foo")
+ end
+ end
+
it "installs multiple plugins" do
- bundle "plugin install foo kung-foo --source file://#{gem_repo2}"
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
expect(out).to include("Installed plugin foo")
expect(out).to include("Installed plugin kung-foo")
@@ -37,13 +70,50 @@ RSpec.describe "bundler plugin install" do
build_plugin "kung-foo", "1.1"
end
- bundle "plugin install foo kung-foo --version '1.0' --source file://#{gem_repo2}"
+ bundle "plugin install foo kung-foo --version '1.0' --source https://gem.repo2"
expect(out).to include("Installing foo 1.0")
expect(out).to include("Installing kung-foo 1.0")
plugin_should_be_installed("foo", "kung-foo")
end
+ it "installs the latest version if not installed" do
+ update_repo2 do
+ build_plugin "foo", "1.1"
+ end
+
+ bundle "plugin install foo --version 1.0 --source https://gem.repo2 --verbose"
+ expect(out).to include("Installing foo 1.0")
+
+ bundle "plugin install foo --source https://gem.repo2 --verbose"
+ expect(out).to include("Installing foo 1.1")
+
+ bundle "plugin install foo --source https://gem.repo2 --verbose"
+ expect(out).to include("Using foo 1.1")
+ end
+
+ it "raises an error when when --branch specified" do
+ bundle "plugin install foo --branch main --source https://gem.repo2", raise_on_error: false
+
+ expect(out).not_to include("Installed plugin foo")
+
+ expect(err).to include("--branch can only be used with git sources")
+ end
+
+ it "raises an error when --ref specified" do
+ bundle "plugin install foo --ref v1.2.3 --source https://gem.repo2", raise_on_error: false
+
+ expect(err).to include("--ref can only be used with git sources")
+ end
+
+ it "raises error when both --branch and --ref options are specified" do
+ bundle "plugin install foo --source https://gem.repo2 --branch main --ref v1.2.3", raise_on_error: false
+
+ expect(out).not_to include("Installed plugin foo")
+
+ expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.")
+ end
+
it "works with different load paths" do
build_repo2 do
build_plugin "testing" do |s|
@@ -61,7 +131,7 @@ RSpec.describe "bundler plugin install" do
s.write("src/fubar.rb")
end
end
- bundle "plugin install testing --source file://#{gem_repo2}"
+ bundle "plugin install testing --source https://gem.repo2"
bundle "check2", "no-color" => false
expect(out).to eq("mate")
@@ -74,19 +144,19 @@ RSpec.describe "bundler plugin install" do
build_plugin "kung-foo", "1.1"
end
- bundle "plugin install foo kung-foo --version '1.0' --source file://#{gem_repo2}"
+ bundle "plugin install foo kung-foo --version '1.0' --source https://gem.repo2"
expect(out).to include("Installing foo 1.0")
expect(out).to include("Installing kung-foo 1.0")
plugin_should_be_installed("foo", "kung-foo")
- build_repo2 do
+ update_repo2 do
build_gem "charlie"
end
- bundle "plugin install charlie --source file://#{gem_repo2}"
+ bundle "plugin install charlie --source https://gem.repo2", raise_on_error: false
- expect(out).to include("plugins.rb was not found")
+ expect(err).to include("Failed to install plugin `charlie`, due to Bundler::Plugin::MalformattedPlugin (plugins.rb was not found in the plugin.)")
expect(global_plugin_gem("charlie-1.0")).not_to be_directory
@@ -98,12 +168,12 @@ RSpec.describe "bundler plugin install" do
build_repo2 do
build_plugin "chaplin" do |s|
s.write "plugins.rb", <<-RUBY
- raise "I got you man"
+ raise RuntimeError, "threw exception on load"
RUBY
end
end
- bundle "plugin install chaplin --source file://#{gem_repo2}"
+ bundle "plugin install chaplin --source https://gem.repo2", raise_on_error: false
expect(global_plugin_gem("chaplin-1.0")).not_to be_directory
@@ -117,19 +187,72 @@ RSpec.describe "bundler plugin install" do
s.write "plugins.rb"
end
- bundle "plugin install foo --git file://#{lib_path("foo-1.0")}"
+ bundle "plugin install foo --git #{lib_path("foo-1.0")}"
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
+ it "installs form a local git source" do
+ build_git "foo" do |s|
+ s.write "plugins.rb"
+ end
+
+ bundle "plugin install foo --git #{lib_path("foo-1.0")}"
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
end
end
+ context "path plugins" do
+ it "installs from a path source" do
+ build_lib "path_plugin" do |s|
+ s.write "plugins.rb"
+ end
+ bundle "plugin install path_plugin --path #{lib_path("path_plugin-1.0")}"
+
+ expect(out).to include("Installed plugin path_plugin")
+ plugin_should_be_installed("path_plugin")
+ end
+
+ it "installs from a relative path source" do
+ build_lib "path_plugin" do |s|
+ s.write "plugins.rb"
+ end
+ path = lib_path("path_plugin-1.0").relative_path_from(bundled_app)
+ bundle "plugin install path_plugin --path #{path}"
+
+ expect(out).to include("Installed plugin path_plugin")
+ plugin_should_be_installed("path_plugin")
+ end
+
+ it "installs from a relative path source when inside an app" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ gemfile ""
+
+ build_lib "ga-plugin" do |s|
+ s.write "plugins.rb"
+ end
+
+ path = lib_path("ga-plugin-1.0").relative_path_from(bundled_app)
+ bundle "plugin install ga-plugin --path #{path}"
+
+ plugin_should_be_installed("ga-plugin")
+ expect(local_plugin_gem("foo-1.0")).not_to be_directory
+ end
+ end
+
context "Gemfile eval" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
+
it "installs plugins listed in gemfile" do
gemfile <<-G
- source 'file://#{gem_repo2}'
+ source 'https://gem.repo2'
plugin 'foo'
- gem 'rack', "1.0.0"
+ gem 'myrack', "1.0.0"
G
bundle "install"
@@ -138,17 +261,54 @@ RSpec.describe "bundler plugin install" do
expect(out).to include("Bundle complete!")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
plugin_should_be_installed("foo")
end
+ it "overrides the index with the new plugin version" do
+ gemfile <<-G
+ source 'https://gem.repo2'
+ plugin 'foo', "1.0"
+ gem 'myrack', "1.0.0"
+ G
+
+ bundle "install"
+
+ update_repo2 do
+ build_plugin "foo", "2.0.0"
+ end
+
+ gemfile <<-G
+ source 'https://gem.repo2'
+ plugin 'foo', "2.0"
+ gem 'myrack', "1.0.0"
+ G
+
+ bundle "install"
+
+ expected = local_plugin_gem("foo-2.0.0", "lib").to_s
+ expect(Bundler::Plugin.index.load_paths("foo")).to eq([expected])
+ end
+
+ it "respects bundler groups" do
+ gemfile <<-G
+ source 'https://gem.repo2'
+ plugin 'foo'
+ gem 'myrack', "1.0.0"
+ G
+
+ bundle "install", env: { "BUNDLE_WITHOUT" => "default" }
+
+ expect(out).to include("Bundle complete! 1 Gemfile dependency, 0 gems now installed.")
+ end
+
it "accepts plugin version" do
update_repo2 do
build_plugin "foo", "1.1.0"
end
- install_gemfile <<-G
- source 'file://#{gem_repo2}'
+ gemfile <<-G
+ source 'https://gem.repo2'
plugin 'foo', "1.0"
G
@@ -167,12 +327,65 @@ RSpec.describe "bundler plugin install" do
end
install_gemfile <<-G
+ source "https://gem.repo1"
plugin 'ga-plugin', :git => "#{lib_path("ga-plugin-1.0")}"
G
expect(out).to include("Installed plugin ga-plugin")
plugin_should_be_installed("ga-plugin")
end
+
+ it "accepts path sources" do
+ build_lib "ga-plugin" do |s|
+ s.write "plugins.rb"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ plugin 'ga-plugin', :path => "#{lib_path("ga-plugin-1.0")}"
+ G
+
+ expect(out).to include("Installed plugin ga-plugin")
+ plugin_should_be_installed("ga-plugin")
+ end
+
+ it "accepts relative path sources" do
+ build_lib "ga-plugin" do |s|
+ s.write "plugins.rb"
+ end
+
+ path = lib_path("ga-plugin-1.0").relative_path_from(bundled_app)
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ plugin 'ga-plugin', :path => "#{path}"
+ G
+
+ expect(out).to include("Installed plugin ga-plugin")
+ plugin_should_be_installed("ga-plugin")
+ end
+
+ context "in deployment mode" do
+ it "installs plugins" do
+ install_gemfile <<-G
+ source 'https://gem.repo2'
+ gem 'myrack', "1.0.0"
+ G
+
+ bundle_config "deployment true"
+ install_gemfile <<-G
+ source 'https://gem.repo2'
+ plugin 'foo'
+ gem 'myrack', "1.0.0"
+ G
+
+ expect(out).to include("Installed plugin foo")
+
+ expect(out).to include("Bundle complete!")
+
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ plugin_should_be_installed("foo")
+ end
+ end
end
context "inline gemfiles" do
@@ -181,20 +394,21 @@ RSpec.describe "bundler plugin install" do
require "bundler/inline"
gemfile do
- source 'file://#{gem_repo2}'
+ source 'https://gem.repo2'
plugin 'foo'
end
RUBY
- ruby code
+ ruby code, artifice: "compact_index", env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(local_plugin_gem("foo-1.0", "plugins.rb")).to exist
end
end
describe "local plugin" do
it "is installed when inside an app" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
gemfile ""
- bundle "plugin install foo --source file://#{gem_repo2}"
+ bundle "plugin install foo --source https://gem.repo2"
plugin_should_be_installed("foo")
expect(local_plugin_gem("foo-1.0")).to be_directory
@@ -217,7 +431,7 @@ RSpec.describe "bundler plugin install" do
end
# inside the app
- gemfile "source 'file://#{gem_repo2}'\nplugin 'fubar'"
+ gemfile "source 'https://gem.repo2'\nplugin 'fubar'"
bundle "install"
update_repo2 do
@@ -235,21 +449,16 @@ RSpec.describe "bundler plugin install" do
end
# outside the app
- Dir.chdir tmp
- bundle "plugin install fubar --source file://#{gem_repo2}"
+ bundle "plugin install fubar --source https://gem.repo2", dir: tmp
end
it "inside the app takes precedence over global plugin" do
- Dir.chdir bundled_app
-
bundle "shout"
expect(out).to eq("local_one")
end
it "outside the app global plugin is used" do
- Dir.chdir tmp
-
- bundle "shout"
+ bundle "shout", dir: tmp
expect(out).to eq("global_one")
end
end
diff --git a/spec/bundler/plugins/list_spec.rb b/spec/bundler/plugins/list_spec.rb
new file mode 100644
index 0000000000..30e3f82467
--- /dev/null
+++ b/spec/bundler/plugins/list_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundler plugin list" do
+ before do
+ build_repo2 do
+ build_plugin "foo" do |s|
+ s.write "plugins.rb", <<-RUBY
+ class Foo < Bundler::Plugin::API
+ command "shout"
+
+ def exec(command, args)
+ puts "Foo shout"
+ end
+ end
+ RUBY
+ end
+ build_plugin "bar" do |s|
+ s.write "plugins.rb", <<-RUBY
+ class Bar < Bundler::Plugin::API
+ command "scream"
+
+ def exec(command, args)
+ puts "Bar scream"
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ context "no plugins installed" do
+ it "shows proper no plugins installed message" do
+ bundle "plugin list"
+
+ expect(out).to include("No plugins installed")
+ end
+ end
+
+ context "single plugin installed" do
+ it "shows plugin name with commands list" do
+ bundle "plugin install foo --source https://gem.repo2"
+ plugin_should_be_installed("foo")
+ bundle "plugin list"
+
+ expected_output = "foo\n-----\n shout"
+ expect(out).to include(expected_output)
+ end
+ end
+
+ context "multiple plugins installed" do
+ it "shows plugin names with commands list" do
+ bundle "plugin install foo bar --source https://gem.repo2"
+ plugin_should_be_installed("foo", "bar")
+ bundle "plugin list"
+
+ expected_output = "foo\n-----\n shout\n\nbar\n-----\n scream"
+ expect(out).to include(expected_output)
+ end
+ end
+end
diff --git a/spec/bundler/plugins/source/example_spec.rb b/spec/bundler/plugins/source/example_spec.rb
index d9a3cd2b92..4cd4a1a931 100644
--- a/spec/bundler/plugins/source/example_spec.rb
+++ b/spec/bundler/plugins/source/example_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe "real source plugins" do
build_repo2 do
build_plugin "bundler-source-mpath" do |s|
s.write "plugins.rb", <<-RUBY
- require "bundler/vendored_fileutils"
require "bundler-source-mpath"
class MPath < Bundler::Plugin::API
@@ -34,6 +33,7 @@ RSpec.describe "real source plugins" do
def install(spec, opts)
mkdir_p(install_path.parent)
+ require 'fileutils'
FileUtils.cp_r(path, install_path)
spec_path = install_path.join("\#{spec.full_name}.gemspec")
@@ -52,7 +52,7 @@ RSpec.describe "real source plugins" do
build_lib "a-path-gem"
gemfile <<-G
- source "file://localhost#{gem_repo2}" # plugin source
+ source "https://gem.repo2" # plugin source
source "#{lib_path("a-path-gem-1.0")}", :type => :mpath do
gem "a-path-gem"
end
@@ -67,10 +67,14 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
- it "writes to lock file", :bundler => "< 3" do
+ it "writes to lockfile" do
bundle "install"
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "a-path-gem", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
PLUGIN SOURCE
remote: #{lib_path("a-path-gem-1.0")}
type: mpath
@@ -78,42 +82,17 @@ RSpec.describe "real source plugins" do
a-path-gem (1.0)
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- a-path-gem!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "writes to lock file", :bundler => "3" do
- bundle "install"
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
-
- PLUGIN SOURCE
- remote: #{lib_path("a-path-gem-1.0")}
- type: mpath
- specs:
- a-path-gem (1.0)
-
- PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
a-path-gem!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -126,14 +105,14 @@ RSpec.describe "real source plugins" do
end
it "installs the gem executables" do
- build_lib "gem-with-bin" do |s|
+ build_lib "gem_with_bin" do |s|
s.executables = ["foo"]
end
install_gemfile <<-G
- source "file://#{gem_repo2}" # plugin source
- source "#{lib_path("gem-with-bin-1.0")}", :type => :mpath do
- gem "gem-with-bin"
+ source "https://gem.repo2" # plugin source
+ source "#{lib_path("gem_with_bin-1.0")}", :type => :mpath do
+ gem "gem_with_bin"
end
G
@@ -145,33 +124,35 @@ RSpec.describe "real source plugins" do
let(:uri_hash) { Digest(:SHA1).hexdigest(lib_path("a-path-gem-1.0").to_s) }
it "copies repository to vendor cache and uses it" do
bundle "install"
- bundle :cache, forgotten_command_line_options([:all, :cache_all] => true)
+ bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.git")).not_to exist
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
- it "copies repository to vendor cache and uses it even when installed with bundle --path" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
- bundle! :cache, forgotten_command_line_options([:all, :cache_all] => true)
+ it "copies repository to vendor cache and uses it even when installed with `path` configured" do
+ bundle_config "path vendor/bundle"
+ bundle :install
+ bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
it "bundler package copies repository to vendor cache" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
- bundle! :package, forgotten_command_line_options([:all, :cache_all] => true)
+ bundle_config "path vendor/bundle"
+ bundle :install
+ bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
end
@@ -186,7 +167,7 @@ RSpec.describe "real source plugins" do
a-path-gem (1.0)
GEM
- remote: file:#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -196,12 +177,12 @@ RSpec.describe "real source plugins" do
a-path-gem!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "installs" do
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
@@ -213,6 +194,8 @@ RSpec.describe "real source plugins" do
build_repo2 do
build_plugin "bundler-source-gitp" do |s|
s.write "plugins.rb", <<-RUBY
+ require "open3"
+
class SPlugin < Bundler::Plugin::API
source "gitp"
@@ -221,7 +204,7 @@ RSpec.describe "real source plugins" do
def initialize(opts)
super
- @ref = options["ref"] || options["branch"] || options["tag"] || "master"
+ @ref = options["ref"] || options["branch"] || options["tag"] || "main"
@unlocked = false
end
@@ -252,9 +235,7 @@ RSpec.describe "real source plugins" do
mkdir_p(install_path.dirname)
rm_rf(install_path)
`git clone --no-checkout --quiet "\#{cache_path}" "\#{install_path}"`
- Dir.chdir install_path do
- `git reset --hard \#{revision}`
- end
+ Open3.capture2e("git reset --hard \#{revision}", :chdir => install_path)
spec_path = install_path.join("\#{spec.full_name}.gemspec")
spec_path.open("wb") {|f| f.write spec.to_ruby }
@@ -267,7 +248,7 @@ RSpec.describe "real source plugins" do
def options_to_lock
opts = {"revision" => revision}
- opts["ref"] = ref if ref != "master"
+ opts["ref"] = ref if ref != "main"
opts
end
@@ -308,9 +289,8 @@ RSpec.describe "real source plugins" do
cache_repo
end
- Dir.chdir cache_path do
- `git rev-parse --verify \#{@ref}`.strip
- end
+ output, _status = Open3.capture2e("git rev-parse --verify \#{@ref}", :chdir => cache_path)
+ output.strip
end
def base_name
@@ -325,13 +305,7 @@ RSpec.describe "real source plugins" do
@install_path ||= begin
git_scope = "\#{base_name}-\#{shortref_for_path(revision)}"
- path = gem_install_dir.join(git_scope)
-
- if !path.exist? && requires_sudo?
- user_bundle_path.join(ruby_scope).join(git_scope)
- else
- path
- end
+ gem_install_dir.join(git_scope)
end
end
@@ -346,8 +320,8 @@ RSpec.describe "real source plugins" do
build_git "ma-gitp-gem"
gemfile <<-G
- source "file://localhost#{gem_repo2}" # plugin source
- source "file://#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
+ source "https://gem.repo2" # plugin source
+ source "#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
gem "ma-gitp-gem"
end
G
@@ -359,57 +333,34 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
end
- it "writes to lock file", :bundler => "< 3" do
+ it "writes to lockfile" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
bundle "install"
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "ma-gitp-gem", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
PLUGIN SOURCE
- remote: file://#{lib_path("ma-gitp-gem-1.0")}
+ remote: #{lib_path("ma-gitp-gem-1.0")}
type: gitp
revision: #{revision}
specs:
ma-gitp-gem (1.0)
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- ma-gitp-gem!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "writes to lock file", :bundler => "3" do
- revision = revision_for(lib_path("ma-gitp-gem-1.0"))
- bundle "install"
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
-
- PLUGIN SOURCE
- remote: file://#{lib_path("ma-gitp-gem-1.0")}
- type: gitp
- revision: #{revision}
- specs:
- ma-gitp-gem (1.0)
-
- PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
ma-gitp-gem!
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -418,14 +369,14 @@ RSpec.describe "real source plugins" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
lockfile <<-G
PLUGIN SOURCE
- remote: file://#{lib_path("ma-gitp-gem-1.0")}
+ remote: #{lib_path("ma-gitp-gem-1.0")}
type: gitp
revision: #{revision}
specs:
ma-gitp-gem (1.0)
GEM
- remote: file:#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -435,7 +386,7 @@ RSpec.describe "real source plugins" do
ma-gitp-gem!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -449,7 +400,7 @@ RSpec.describe "real source plugins" do
bundle "install"
run <<-RUBY
- require 'ma-gitp-gem'
+ require 'ma/gitp/gem'
puts "WIN" unless defined?(MAGITPGEM_PREV_REF)
RUBY
expect(out).to eq("WIN")
@@ -460,17 +411,17 @@ RSpec.describe "real source plugins" do
bundle "update ma-gitp-gem"
run <<-RUBY
- require 'ma-gitp-gem'
+ require 'ma/gitp/gem'
puts "WIN" if defined?(MAGITPGEM_PREV_REF)
RUBY
expect(out).to eq("WIN")
end
it "updates the deps on change in gemfile" do
- update_git "ma-gitp-gem", "1.1", :path => lib_path("ma-gitp-gem-1.0"), :gemspec => true
+ update_git "ma-gitp-gem", "1.1", path: lib_path("ma-gitp-gem-1.0"), gemspec: true
gemfile <<-G
- source "file://#{gem_repo2}" # plugin source
- source "file://#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
+ source "https://gem.repo2" # plugin source
+ source "#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
gem "ma-gitp-gem", "1.1"
end
G
@@ -483,21 +434,21 @@ RSpec.describe "real source plugins" do
describe "bundle cache with gitp" do
it "copies repository to vendor cache and uses it" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "file://#{gem_repo2}" # plugin source
+ source "https://gem.repo2" # plugin source
source '#{lib_path("foo-1.0")}', :type => :gitp do
gem "foo"
end
G
- bundle :cache, forgotten_command_line_options([:all, :cache_all] => true)
+ bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("foo-1.0")
+ FileUtils.rm_r lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
end
diff --git a/spec/bundler/plugins/source_spec.rb b/spec/bundler/plugins/source_spec.rb
index 543e90eb60..995e50e653 100644
--- a/spec/bundler/plugins/source_spec.rb
+++ b/spec/bundler/plugins/source_spec.rb
@@ -16,11 +16,12 @@ RSpec.describe "bundler source plugin" do
it "installs bundler-source-* gem when no handler for source is present" do
install_gemfile <<-G
- source "file://#{gem_repo2}"
- source "file://#{lib_path("gitp")}", :type => :psource do
+ source "https://gem.repo2"
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("bundler-source-psource")
end
@@ -37,8 +38,8 @@ RSpec.describe "bundler source plugin" do
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
- source "file://#{lib_path("gitp")}", :type => :psource do
+ source "https://gem.repo2"
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
@@ -61,11 +62,11 @@ RSpec.describe "bundler source plugin" do
context "explicit presence in gemfile" do
before do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
plugin "another-psource"
- source "file://#{lib_path("gitp")}", :type => :psource do
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
end
@@ -75,6 +76,7 @@ RSpec.describe "bundler source plugin" do
end
it "installs the explicit one" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("another-psource")
end
@@ -86,11 +88,11 @@ RSpec.describe "bundler source plugin" do
context "explicit default source" do
before do
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
plugin "bundler-source-psource"
- source "file://#{lib_path("gitp")}", :type => :psource do
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
end
@@ -100,6 +102,7 @@ RSpec.describe "bundler source plugin" do
end
it "installs the default one" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("bundler-source-psource")
end
end
diff --git a/spec/bundler/plugins/uninstall_spec.rb b/spec/bundler/plugins/uninstall_spec.rb
new file mode 100644
index 0000000000..dedcc9f37c
--- /dev/null
+++ b/spec/bundler/plugins/uninstall_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundler plugin uninstall" do
+ before do
+ build_repo2 do
+ build_plugin "foo"
+ build_plugin "kung-foo"
+ end
+ end
+
+ it "shows proper error message when plugins are not specified" do
+ bundle "plugin uninstall"
+ expect(err).to include("No plugins to uninstall")
+ end
+
+ it "uninstalls specified plugins" do
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
+ plugin_should_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+
+ bundle "plugin uninstall foo"
+ expect(out).to include("Uninstalled plugin foo")
+ plugin_should_not_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+ end
+
+ it "shows proper message when plugin is not installed" do
+ bundle "plugin uninstall foo"
+ expect(err).to include("Plugin foo is not installed")
+ plugin_should_not_be_installed("foo")
+ end
+
+ it "doesn't wipe out path plugins" do
+ build_lib "path_plugin" do |s|
+ s.write "plugins.rb"
+ end
+ path = lib_path("path_plugin-1.0")
+ expect(path).to be_a_directory
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+
+ install_gemfile <<-G
+ source 'https://gem.repo2'
+ plugin 'path_plugin', :path => "#{path}"
+ gem 'myrack', '1.0.0'
+ G
+
+ plugin_should_be_installed("path_plugin")
+ expect(Bundler::Plugin.index.plugin_path("path_plugin")).to eq path
+
+ bundle "plugin uninstall path_plugin"
+ expect(out).to include("Uninstalled plugin path_plugin")
+ plugin_should_not_be_installed("path_plugin")
+ # the actual gem still exists though
+ expect(path).to be_a_directory
+ end
+
+ describe "with --all" do
+ it "uninstalls all installed plugins" do
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
+ plugin_should_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+
+ bundle "plugin uninstall --all"
+ plugin_should_not_be_installed("foo")
+ plugin_should_not_be_installed("kung-foo")
+ end
+
+ it "shows proper no plugins installed message when no plugins installed" do
+ bundle "plugin uninstall --all"
+ expect(out).to include("No plugins installed")
+ end
+ end
+end
diff --git a/spec/bundler/quality_es_spec.rb b/spec/bundler/quality_es_spec.rb
new file mode 100644
index 0000000000..e68674c030
--- /dev/null
+++ b/spec/bundler/quality_es_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+RSpec.describe "La biblioteca si misma" do
+ def check_for_expendable_words(filename)
+ failing_line_message = []
+ useless_words = %w[
+ básicamente
+ claramente
+ sólo
+ solamente
+ obvio
+ obviamente
+ fácil
+ fácilmente
+ sencillamente
+ simplemente
+ ]
+ pattern = /\b#{Regexp.union(useless_words)}\b/i
+
+ File.readlines(File.expand_path(filename, source_root)).each_with_index do |line, number|
+ next unless word_found = pattern.match(line)
+ failing_line_message << "#{filename}:#{number.succ} contiene '#{word_found}'. Esta palabra tiene un significado subjetivo y es mejor obviarla en textos técnicos."
+ end
+
+ failing_line_message unless failing_line_message.empty?
+ end
+
+ def check_for_specific_pronouns(filename)
+ failing_line_message = []
+ specific_pronouns = /\b(él|ella|ellos|ellas)\b/i
+
+ File.readlines(File.expand_path(filename, source_root)).each_with_index do |line, number|
+ next unless word_found = specific_pronouns.match(line)
+ failing_line_message << "#{filename}:#{number.succ} contiene '#{word_found}'. Use pronombres más genéricos en la documentación."
+ end
+
+ failing_line_message unless failing_line_message.empty?
+ end
+
+ it "mantiene la calidad de lenguaje de la documentación" do
+ included = /ronn/
+ error_messages = []
+ man_tracked_files.each do |filename|
+ next unless filename&.match?(included)
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
+ end
+ expect(error_messages.compact).to be_well_formed
+ end
+
+ it "mantiene la calidad de lenguaje de oraciones usadas en el código fuente" do
+ error_messages = []
+ exempt = /vendor/
+ lib_tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
+ end
+ expect(error_messages.compact).to be_well_formed
+ end
+end
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index 812acc344f..16b7f18788 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -1,30 +1,8 @@
# frozen_string_literal: true
-if defined?(Encoding) && Encoding.default_external.name != "UTF-8"
- # Poor man's ruby -E UTF-8, since it works on 1.8.7
- Encoding.default_external = Encoding.find("UTF-8")
-end
+require "set"
RSpec.describe "The library itself" do
- def check_for_debugging_mechanisms(filename)
- debugging_mechanisms_regex = /
- (binding\.pry)|
- (debugger)|
- (sleep\s*\(?\d+)|
- (fit\s*\(?("|\w))
- /x
-
- failing_lines = []
- File.readlines(filename).each_with_index do |line, number|
- if line =~ debugging_mechanisms_regex && !line.end_with?("# ignore quality_spec\n")
- failing_lines << number + 1
- end
- end
-
- return if failing_lines.empty?
- "#{filename} has debugging mechanisms (like binding.pry, sleep, debugger, rspec focusing, etc.) on lines #{failing_lines.join(", ")}"
- end
-
def check_for_git_merge_conflicts(filename)
merge_conflicts_regex = /
<<<<<<<|
@@ -33,8 +11,8 @@ RSpec.describe "The library itself" do
/x
failing_lines = []
- File.readlines(filename).each_with_index do |line, number|
- failing_lines << number + 1 if line =~ merge_conflicts_regex
+ each_line(filename) do |line, number|
+ failing_lines << number + 1 if line&.match?(merge_conflicts_regex)
end
return if failing_lines.empty?
@@ -42,9 +20,12 @@ RSpec.describe "The library itself" do
end
def check_for_tab_characters(filename)
+ # Because Go uses hard tabs
+ return if filename.end_with?(".go.tt")
+
failing_lines = []
- File.readlines(filename).each_with_index do |line, number|
- failing_lines << number + 1 if line =~ /\t/
+ each_line(filename) do |line, number|
+ failing_lines << number + 1 if line.include?("\t")
end
return if failing_lines.empty?
@@ -53,16 +34,25 @@ RSpec.describe "The library itself" do
def check_for_extra_spaces(filename)
failing_lines = []
- File.readlines(filename).each_with_index do |line, number|
- next if line =~ /^\s+#.*\s+\n$/
- next if %w[LICENCE.md].include?(line)
- failing_lines << number + 1 if line =~ /\s+\n$/
+ each_line(filename) do |line, number|
+ next if /^\s+#.*\s+\n$/.match?(line)
+ failing_lines << number + 1 if /\s+\n$/.match?(line)
end
return if failing_lines.empty?
"#{filename} has spaces on the EOL on lines #{failing_lines.join(", ")}"
end
+ def check_for_extraneous_quotes(filename)
+ failing_lines = []
+ each_line(filename) do |line, number|
+ failing_lines << number + 1 if /\u{2019}/.match?(line)
+ end
+
+ return if failing_lines.empty?
+ "#{filename} has an extraneous quote on lines #{failing_lines.join(", ")}"
+ end
+
def check_for_expendable_words(filename)
failing_line_message = []
useless_words = %w[
@@ -76,7 +66,7 @@ RSpec.describe "The library itself" do
]
pattern = /\b#{Regexp.union(useless_words)}\b/i
- File.readlines(filename).each_with_index do |line, number|
+ each_line(filename) do |line, number|
next unless word_found = pattern.match(line)
failing_line_message << "#{filename}:#{number.succ} has '#{word_found}'. Avoid using these kinds of weak modifiers."
end
@@ -88,7 +78,7 @@ RSpec.describe "The library itself" do
failing_line_message = []
specific_pronouns = /\b(he|she|his|hers|him|her|himself|herself)\b/i
- File.readlines(filename).each_with_index do |line, number|
+ each_line(filename) do |line, number|
next unless word_found = specific_pronouns.match(line)
failing_line_message << "#{filename}:#{number.succ} has '#{word_found}'. Use more generic pronouns in documentation."
end
@@ -96,95 +86,70 @@ RSpec.describe "The library itself" do
failing_line_message unless failing_line_message.empty?
end
- RSpec::Matchers.define :be_well_formed do
- match(&:empty?)
-
- failure_message do |actual|
- actual.join("\n")
- end
- end
-
it "has no malformed whitespace" do
- exempt = /\.gitmodules|\.marshal|fixtures|vendor|ssl_certs|LICENSE|vcr_cassettes/
+ exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|index\.txt$/
error_messages = []
- Dir.chdir(root) do
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler` : `git ls-files -z -- lib`
- lib_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_tab_characters(filename)
- error_messages << check_for_extra_spaces(filename)
- end
+ tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ error_messages << check_for_tab_characters(filename)
+ error_messages << check_for_extra_spaces(filename)
end
expect(error_messages.compact).to be_well_formed
end
- it "does not include any leftover debugging or development mechanisms" do
- exempt = %r{quality_spec.rb|support/helpers|vcr_cassettes|\.md|\.ronn}
+ it "has no extraneous quotes" do
+ exempt = /vendor|vcr_cassettes|LICENSE|rbreadline\.diff/
error_messages = []
- Dir.chdir(root) do
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler` : `git ls-files -z -- lib`
- lib_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_debugging_mechanisms(filename)
- end
+ tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ error_messages << check_for_extraneous_quotes(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "does not include any unresolved merge conflicts" do
error_messages = []
- exempt = %r{lock/lockfile_(bundler_1_)?spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser\.rb}
- Dir.chdir(root) do
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler` : `git ls-files -z -- lib`
- lib_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_git_merge_conflicts(filename)
- end
+ exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser}
+ tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ error_messages << check_for_git_merge_conflicts(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "maintains language quality of the documentation" do
- included = /ronn/
error_messages = []
- Dir.chdir(root) do
- `git ls-files -z -- man`.split("\x0").each do |filename|
- next unless filename =~ included
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ man_tracked_files.each do |filename|
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "maintains language quality of sentences used in source code" do
error_messages = []
- exempt = /vendor/
- Dir.chdir(root) do
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb` : `git ls-files -z -- lib`
- lib_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ exempt = /vendor|vcr_cassettes|CODE_OF_CONDUCT/
+ lib_tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "documents all used settings" do
exemptions = %w[
- auto_config_jobs
- cache_command_is_package
- console_command
- deployment_means_frozen
- forget_cli_options
+ gem.changelog
+ gem.ci
gem.coc
+ gem.linter
gem.mit
+ gem.bundle
+ gem.rubocop
+ gem.test
+ git.allow_insecure
inline
- lockfile_upgrade_warning
- lockfile_uses_separate_rubygems_sources
- use_gem_version_promoter_for_major_updates
- viz_command
+ trust-policy
]
all_settings = Hash.new {|h, k| h[k] = [] }
@@ -193,17 +158,16 @@ RSpec.describe "The library itself" do
Bundler::Settings::BOOL_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::BOOL_KEYS" }
Bundler::Settings::NUMBER_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::NUMBER_KEYS" }
Bundler::Settings::ARRAY_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::ARRAY_KEYS" }
+ Bundler::Settings::STRING_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::STRING_KEYS" }
- Dir.chdir(root) do
- key_pattern = /([a-z\._-]+)/i
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb` : `git ls-files -z -- lib`
- lib_files.split("\x0").each do |filename|
- File.readlines(filename).each_with_index do |line, number|
- line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" }
- end
+ key_pattern = /([a-z\._-]+)/i
+ lib_tracked_files.each do |filename|
+ each_line(filename) do |line, number|
+ line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" }
end
- documented_settings = File.read("man/bundle-config.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten
end
+ settings_section = File.read(source_root.join("lib/bundler/man/bundle-config.1.ronn")).split(/^## /).find {|section| section.start_with?("LIST OF AVAILABLE KEYS") }
+ documented_settings = settings_section.scan(/^\* `#{key_pattern}`/).flatten
documented_settings.each do |s|
all_settings.delete(s)
@@ -223,45 +187,75 @@ RSpec.describe "The library itself" do
end
it "can still be built" do
- Dir.chdir(root) do
- begin
- gem_command! :build, gemspec
- if Bundler.rubygems.provides?(">= 2.4")
- # there's no way aroudn this warning
- last_command.stderr.sub!(/^YAML safe loading.*/, "")
-
- # older rubygems have weird warnings, and we won't actually be using them
- # to build the gem for releases anyways
- expect(last_command.stderr).to be_empty, "bundler should build as a gem without warnings, but\n#{err}"
- end
- ensure
- # clean up the .gem generated
- path_prefix = ruby_core? ? "lib/" : "./"
- FileUtils.rm("#{path_prefix}bundler-#{Bundler::VERSION}.gem")
- end
+ with_built_bundler do |gem_path|
+ expect(File.exist?(gem_path)).to be true
end
end
+ it "ships the correct set of files" do
+ git_list = tracked_files.reject {|f| f.start_with?("spec/") }
+
+ gem_list = loaded_gemspec.files
+ gem_list.map! {|f| f.sub(%r{\Aexe/}, "libexec/") } if ruby_core?
+
+ expect(git_list).to match_array(gem_list)
+ end
+
it "does not contain any warnings" do
- Dir.chdir(root) do
- exclusions = %w[
- lib/bundler/capistrano.rb
- lib/bundler/deployment.rb
- lib/bundler/gem_tasks.rb
- lib/bundler/vlad.rb
- lib/bundler/templates/gems.rb
- ]
- lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb` : `git ls-files -z -- lib`
- lib_files = lib_files.split("\x0").grep(/\.rb$/) - exclusions
- lib_files.reject! {|f| f.start_with?("lib/bundler/vendor") }
- lib_files.map! {|f| f.chomp(".rb") }
- sys_exec!("ruby -w -Ilib") do |input, _, _|
- lib_files.each do |f|
- input.puts "require '#{f.sub(%r{\Alib/}, "")}'"
- end
+ exclusions = %w[
+ lib/bundler/capistrano.rb
+ lib/bundler/deployment.rb
+ lib/bundler/gem_tasks.rb
+ lib/bundler/vlad.rb
+ ]
+ files_to_require = lib_tracked_files.grep(/\.rb$/) - exclusions
+ files_to_require.reject! {|f| f.start_with?("lib/bundler/vendor") }
+ files_to_require.map! {|f| File.expand_path(f, source_root) }
+ files_to_require.sort!
+ sys_exec("ruby -w") do |input, _, _|
+ files_to_require.each do |f|
+ input.puts "require '#{f}'"
end
+ end
+
+ warnings = stdboth.split("\n")
+ # ignore warnings around deprecated Object#=~ method in RubyGems
+ warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} }
- expect(last_command.stdboth.split("\n")).to be_well_formed
+ expect(warnings).to be_well_formed
+ end
+
+ it "does not use require internally, but require_relative" do
+ exempt = %r{templates/|\.5|\.1|vendor/}
+ all_bad_requires = []
+ lib_tracked_files.each do |filename|
+ next if filename&.match?(exempt)
+ each_line(filename) do |line, number|
+ line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" }
+ end
end
+
+ expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}"
+ end
+
+ # We don't want our artifice code to activate bundler, but it needs to use the
+ # namespaced implementation of `Net::HTTP`. So we duplicate the file in
+ # bundler that loads that.
+ it "keeps vendored_net_http spec code in sync with the lib implementation" do
+ lib_implementation_path = File.join(source_lib_dir, "bundler", "vendored_net_http.rb")
+ expect(File.exist?(lib_implementation_path)).to be_truthy
+ lib_code = File.read(lib_implementation_path)
+
+ spec_implementation_path = File.join(spec_dir, "support", "vendored_net_http.rb")
+ expect(File.exist?(spec_implementation_path)).to be_truthy
+ spec_code = File.read(spec_implementation_path)
+
+ expect(lib_code).to eq(spec_code)
+ end
+
+ private
+
+ def each_line(filename, &block)
+ File.readlines(File.expand_path(filename, source_root), encoding: "UTF-8").each_with_index(&block)
end
end
diff --git a/spec/bundler/realworld/dependency_api_spec.rb b/spec/bundler/realworld/dependency_api_spec.rb
deleted file mode 100644
index 13527ce5d1..0000000000
--- a/spec/bundler/realworld/dependency_api_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "gemcutter's dependency API", :realworld => true do
- context "when Gemcutter API takes too long to respond" do
- before do
- require_rack
-
- port = find_unused_port
- @server_uri = "http://127.0.0.1:#{port}"
-
- require File.expand_path("../../support/artifice/endpoint_timeout", __FILE__)
- require "thread"
- @t = Thread.new do
- server = Rack::Server.start(:app => EndpointTimeout,
- :Host => "0.0.0.0",
- :Port => port,
- :server => "webrick",
- :AccessLog => [],
- :Logger => Spec::SilentLogger.new)
- server.start
- end
- @t.run
-
- wait_for_server("127.0.0.1", port)
- bundle! "config timeout 1"
- end
-
- after do
- Artifice.deactivate
- @t.kill
- @t.join
- end
-
- it "times out and falls back on the modern index" do
- install_gemfile! <<-G, :artifice => nil
- source "#{@server_uri}"
- gem "rack"
- G
-
- expect(out).to include("Fetching source index from #{@server_uri}/")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-end
diff --git a/spec/bundler/realworld/double_check_spec.rb b/spec/bundler/realworld/double_check_spec.rb
index 94ab49ba2a..0741560395 100644
--- a/spec/bundler/realworld/double_check_spec.rb
+++ b/spec/bundler/realworld/double_check_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-RSpec.describe "double checking sources", :realworld => true do
- it "finds already-installed gems", :ruby => ">= 2.2" do
+RSpec.describe "double checking sources", realworld: true do
+ it "finds already-installed gems" do
create_file("rails.gemspec", <<-RUBY)
Gem::Specification.new do |s|
s.name = "rails"
@@ -26,7 +26,7 @@ RSpec.describe "double checking sources", :realworld => true do
cmd = <<-RUBY
require "bundler"
- require #{File.expand_path("../../support/artifice/vcr.rb", __FILE__).dump}
+ require "#{spec_dir}/support/artifice/vcr"
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
@@ -34,7 +34,7 @@ RSpec.describe "double checking sources", :realworld => true do
end
RUBY
- ruby! cmd
- ruby! cmd
+ ruby cmd
+ ruby cmd
end
end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index bbfd0f68fd..391aa0cef6 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -1,85 +1,51 @@
# frozen_string_literal: true
-RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
+RSpec.describe "real world edgecases", realworld: true do
def rubygems_version(name, requirement)
- ruby! <<-RUBY
- require #{File.expand_path("../../support/artifice/vcr.rb", __FILE__).dump}
+ ruby <<-RUBY
+ require "#{spec_dir}/support/artifice/vcr"
require "bundler"
require "bundler/source/rubygems/remote"
require "bundler/fetcher"
- source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org"))
- fetcher = Bundler::Fetcher.new(source)
- index = fetcher.specs([#{name.dump}], nil)
- rubygem = index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last
+ rubygem = Bundler.ui.silence do
+ remote = Bundler::Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org"))
+ source = Bundler::Source::Rubygems.new
+ fetcher = Bundler::Fetcher.new(remote)
+ index = fetcher.specs([#{name.dump}], source)
+ requirement = Gem::Requirement.create(#{requirement.dump})
+ index.search(#{name.dump}).select {|spec| requirement.satisfied_by?(spec.version) }.last
+ end
if rubygem.nil?
- raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
+ raise ArgumentError, "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
"Found specs:\n\#{index.send(:specs).inspect}"
end
- "#{name} (\#{rubygem.version})"
+ puts "#{name} (\#{rubygem.version})"
RUBY
end
- # there is no rbx-relative-require gem that will install on 1.9
- it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do
- gemfile <<-G
- source "https://rubygems.org"
- gem "linecache", "0.46"
- G
- bundle :lock
- expect(err).to lack_errors
- expect(exitstatus).to eq(0) if exitstatus
- end
-
- # https://github.com/bundler/bundler/issues/1202
- it "bundle cache works with rubygems 1.3.7 and pre gems",
- :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do
- install_gemfile <<-G
- source "https://rubygems.org"
- gem "rack", "1.3.0.beta2"
- gem "will_paginate", "3.0.pre2"
- G
- bundle :cache
- expect(out).not_to include("Removing outdated .gem files from vendor/cache")
- end
-
- # https://github.com/bundler/bundler/issues/1486
- # this is a hash collision that only manifests on 1.8.7
- it "finds the correct child versions", :ruby => "~> 1.8.7" do
- gemfile <<-G
- source "https://rubygems.org"
-
- gem 'i18n', '~> 0.6.0'
- gem 'activesupport', '~> 3.0.5'
- gem 'activerecord', '~> 3.0.5'
- gem 'builder', '~> 2.1.2'
- G
- bundle :lock
- expect(lockfile).to include("activemodel (3.0.5)")
- end
-
- it "resolves dependencies correctly", :ruby => "<= 1.9.3" do
+ it "resolves dependencies correctly" do
gemfile <<-G
source "https://rubygems.org"
- gem 'rails', '~> 3.0'
+ gem 'rails', '~> 5.0'
gem 'capybara', '~> 2.2.0'
gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
G
- bundle! :lock
- expect(lockfile).to include(rubygems_version("rails", "~> 3.0"))
+ bundle :lock
+ expect(lockfile).to include(rubygems_version("rails", "~> 5.0"))
expect(lockfile).to include("capybara (2.2.1)")
end
- it "installs the latest version of gxapi_rails", :ruby => "<= 1.9.3" do
+ it "installs the latest version of gxapi_rails" do
gemfile <<-G
source "https://rubygems.org"
gem "sass-rails"
- gem "rails", "~> 3"
+ gem "rails", "~> 5"
gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written
gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
G
- bundle! :lock
+ bundle :lock
expect(lockfile).to include("gxapi_rails (0.0.6)")
end
@@ -92,291 +58,18 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
gem "activerecord", "~> 3.0"
gem "builder", "~> 2.1.2"
G
- bundle! :lock
+ bundle :lock
expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0"))
expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0"))
end
- it "is able to update a top-level dependency when there is a conflict on a shared transitive child", :ruby => "2.1" do
- # from https://github.com/bundler/bundler/issues/5031
-
- gemfile <<-G
- source "https://rubygems.org"
- gem 'rails', '~> 4.2.7.1'
- gem 'paperclip', '~> 5.1.0'
- G
-
- lockfile <<-L
- GEM
- remote: https://rubygems.org/
- specs:
- actionmailer (4.2.7.1)
- actionpack (= 4.2.7.1)
- actionview (= 4.2.7.1)
- activejob (= 4.2.7.1)
- mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.7.1)
- actionview (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- rack (~> 1.6)
- rack-test (~> 0.6.2)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.7.1)
- activesupport (= 4.2.7.1)
- builder (~> 3.1)
- erubis (~> 2.7.0)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- activejob (4.2.7.1)
- activesupport (= 4.2.7.1)
- globalid (>= 0.3.0)
- activemodel (4.2.7.1)
- activesupport (= 4.2.7.1)
- builder (~> 3.1)
- activerecord (4.2.7.1)
- activemodel (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- arel (~> 6.0)
- activesupport (4.2.7.1)
- i18n (~> 0.7)
- json (~> 1.7, >= 1.7.7)
- minitest (~> 5.1)
- thread_safe (~> 0.3, >= 0.3.4)
- tzinfo (~> 1.1)
- arel (6.0.3)
- builder (3.2.2)
- climate_control (0.0.3)
- activesupport (>= 3.0)
- cocaine (0.5.8)
- climate_control (>= 0.0.3, < 1.0)
- concurrent-ruby (1.0.2)
- erubis (2.7.0)
- globalid (0.3.7)
- activesupport (>= 4.1.0)
- i18n (0.7.0)
- json (1.8.3)
- loofah (2.0.3)
- nokogiri (>= 1.5.9)
- mail (2.6.4)
- mime-types (>= 1.16, < 4)
- mime-types (3.1)
- mime-types-data (~> 3.2015)
- mime-types-data (3.2016.0521)
- mimemagic (0.3.2)
- mini_portile2 (2.1.0)
- minitest (5.9.1)
- nokogiri (1.6.8)
- mini_portile2 (~> 2.1.0)
- pkg-config (~> 1.1.7)
- paperclip (5.1.0)
- activemodel (>= 4.2.0)
- activesupport (>= 4.2.0)
- cocaine (~> 0.5.5)
- mime-types
- mimemagic (~> 0.3.0)
- pkg-config (1.1.7)
- rack (1.6.4)
- rack-test (0.6.3)
- rack (>= 1.0)
- rails (4.2.7.1)
- actionmailer (= 4.2.7.1)
- actionpack (= 4.2.7.1)
- actionview (= 4.2.7.1)
- activejob (= 4.2.7.1)
- activemodel (= 4.2.7.1)
- activerecord (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.7.1)
- sprockets-rails
- rails-deprecated_sanitizer (1.0.3)
- activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.7)
- activesupport (>= 4.2.0.beta, < 5.0)
- nokogiri (~> 1.6.0)
- rails-deprecated_sanitizer (>= 1.0.1)
- rails-html-sanitizer (1.0.3)
- loofah (~> 2.0)
- railties (4.2.7.1)
- actionpack (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- rake (>= 0.8.7)
- thor (>= 0.18.1, < 2.0)
- rake (11.3.0)
- sprockets (3.7.0)
- concurrent-ruby (~> 1.0)
- rack (> 1, < 3)
- sprockets-rails (3.2.0)
- actionpack (>= 4.0)
- activesupport (>= 4.0)
- sprockets (>= 3.0.0)
- thor (0.19.1)
- thread_safe (0.3.5)
- tzinfo (1.2.2)
- thread_safe (~> 0.1)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- paperclip (~> 5.1.0)
- rails (~> 4.2.7.1)
- L
-
- bundle! "lock --update paperclip"
-
- expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
- end
-
- # https://github.com/bundler/bundler/issues/1500
- it "does not fail install because of gem plugins" do
- realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2")
- gemfile <<-G
- source "https://rubygems.org"
-
- gem 'rack', '1.0.1'
- G
-
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
- expect(err).not_to include("Could not find rake")
- expect(err).to lack_errors
- end
-
- it "checks out git repos when the lockfile is corrupted" do
- gemfile <<-G
- source "https://rubygems.org"
- git_source(:github) {|repo| "https://github.com/\#{repo}.git" }
-
- gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- G
-
- lockfile <<-L
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GEM
- remote: https://rubygems.org/
- specs:
- arel (3.0.2)
- builder (3.0.0)
- erubis (2.7.0)
- hike (1.2.1)
- i18n (0.6.0)
- journey (1.0.3)
- multi_json (1.1.0)
- rack (1.4.1)
- rack-cache (1.2)
- rack (>= 0.4)
- rack-test (0.6.1)
- rack (>= 1.0)
- sprockets (2.1.2)
- hike (~> 1.2)
- rack (~> 1.0)
- tilt (~> 1.1, != 1.3.0)
- tilt (1.3.3)
- tzinfo (0.3.32)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- actionpack!
- activerecord!
- activesupport!
- L
-
- bundle! :lock
- expect(last_command.stderr).to lack_errors
- end
-
- it "outputs a helpful error message when gems have invalid gemspecs" do
- install_gemfile <<-G, :standalone => true
+ it "outputs a helpful warning when gems have a gemspec with invalid `require_paths`" do
+ install_gemfile <<-G, standalone: true, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" }
source 'https://rubygems.org'
gem "resque-scheduler", "2.2.0"
+ gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0
+ gem "ruby2_keywords", "0.0.5"
G
- expect(out).to include("You have one or more invalid gemspecs that need to be fixed.")
- expect(out).to include("resque-scheduler 2.2.0 has an invalid gemspec")
+ expect(err).to include("resque-scheduler 2.2.0 includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this").once
end
end
diff --git a/spec/bundler/realworld/ffi_spec.rb b/spec/bundler/realworld/ffi_spec.rb
new file mode 100644
index 0000000000..bede372b41
--- /dev/null
+++ b/spec/bundler/realworld/ffi_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+RSpec.describe "loading dynamically linked library on a bundle exec context", realworld: true do
+ it "passes ENV right after argv in memory" do
+ create_file "foo.rb", <<~RUBY
+ require 'ffi'
+
+ module FOO
+ extend FFI::Library
+ ffi_lib './libfoo.so'
+
+ attach_function :Hello, [], :void
+ end
+
+ FOO.Hello()
+ RUBY
+
+ create_file "libfoo.c", <<~'C'
+ #include <stdio.h>
+
+ static int foo_init(int argc, char** argv, char** envp) {
+ if (argv[argc+1] == NULL) {
+ printf("FAIL\n");
+ } else {
+ printf("OK\n");
+ }
+
+ return 0;
+ }
+
+ #if defined(__APPLE__) && defined(__MACH__)
+ __attribute__((section("__DATA,__mod_init_func"), used, aligned(sizeof(void*))))
+ #else
+ __attribute__((section(".init_array")))
+ #endif
+ static void *ctr = &foo_init;
+
+ extern char** environ;
+
+ void Hello() {
+ return;
+ }
+ C
+
+ in_bundled_app "gcc -g -o libfoo.so -shared -fpic libfoo.c"
+
+ install_gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'ffi', force_ruby_platform: true
+ G
+
+ bundle "exec ruby foo.rb"
+
+ expect(out).to eq("OK")
+ end
+end
diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile b/spec/bundler/realworld/fixtures/tapioca/Gemfile
new file mode 100644
index 0000000000..447d715706
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "tapioca"
diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
new file mode 100644
index 0000000000..c2df2f9229
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
@@ -0,0 +1,49 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ erubi (1.13.1)
+ netrc (0.11.0)
+ parallel (1.26.3)
+ prism (1.3.0)
+ rbi (0.2.2)
+ prism (~> 1.0)
+ sorbet-runtime (>= 0.5.9204)
+ sorbet (0.5.11725)
+ sorbet-static (= 0.5.11725)
+ sorbet-runtime (0.5.11725)
+ sorbet-static (0.5.11725-aarch64-linux)
+ sorbet-static (0.5.11725-universal-darwin)
+ sorbet-static (0.5.11725-x86_64-linux)
+ sorbet-static-and-runtime (0.5.11725)
+ sorbet (= 0.5.11725)
+ sorbet-runtime (= 0.5.11725)
+ spoom (1.5.0)
+ erubi (>= 1.10.0)
+ prism (>= 0.28.0)
+ sorbet-static-and-runtime (>= 0.5.10187)
+ thor (>= 0.19.2)
+ tapioca (0.16.6)
+ bundler (>= 2.2.25)
+ netrc (>= 0.11.0)
+ parallel (>= 1.21.0)
+ rbi (~> 0.2)
+ sorbet-static-and-runtime (>= 0.5.11087)
+ spoom (>= 1.2.0)
+ thor (>= 1.2.0)
+ yard-sorbet
+ thor (1.4.0)
+ yard (0.9.42)
+ yard-sorbet (0.9.0)
+ sorbet-runtime
+ yard
+
+PLATFORMS
+ aarch64-linux
+ universal-darwin
+ x86_64-linux
+
+DEPENDENCIES
+ tapioca
+
+BUNDLED WITH
+ 4.1.0.dev
diff --git a/spec/bundler/realworld/fixtures/warbler/.gitignore b/spec/bundler/realworld/fixtures/warbler/.gitignore
new file mode 100644
index 0000000000..d392f0e82c
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/.gitignore
@@ -0,0 +1 @@
+*.jar
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile b/spec/bundler/realworld/fixtures/warbler/Gemfile
new file mode 100644
index 0000000000..5687bbd975
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "demo", path: "./demo"
+gem "jruby-jars", "~> 10.0"
+gem "warbler", "~> 2.1"
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
new file mode 100644
index 0000000000..05f3bc4e3f
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -0,0 +1,35 @@
+PATH
+ remote: demo
+ specs:
+ demo (1.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ jruby-jars (10.0.0.1)
+ jruby-rack (1.2.7)
+ ostruct (0.6.3)
+ rake (13.3.0)
+ rexml (3.4.2)
+ rubyzip (3.3.0)
+ warbler (2.1.0)
+ jruby-jars (>= 9.4, < 10.1)
+ jruby-rack (>= 1.2.3, < 1.3)
+ ostruct (~> 0.6.2)
+ rake (~> 13.0, >= 13.0.3)
+ rexml (~> 3.0)
+ rubyzip (>= 3.0.0)
+
+PLATFORMS
+ arm64-darwin
+ java
+ ruby
+ universal-java
+
+DEPENDENCIES
+ demo!
+ jruby-jars (~> 10.0)
+ warbler (~> 2.1)
+
+BUNDLED WITH
+ 4.1.0.dev
diff --git a/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb b/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb
new file mode 100644
index 0000000000..25f614ecc2
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+puts require "bundler/setup"
diff --git a/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec b/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec
new file mode 100644
index 0000000000..ed5a0dc080
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ spec.name = "demo"
+ spec.version = "1.0"
+ spec.author = "Somebody"
+ spec.summary = "A demo gem"
+ spec.license = "MIT"
+ spec.homepage = "https://example.org"
+end
diff --git a/spec/bundler/realworld/gemfile_source_header_spec.rb b/spec/bundler/realworld/gemfile_source_header_spec.rb
deleted file mode 100644
index 59c1916874..0000000000
--- a/spec/bundler/realworld/gemfile_source_header_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require "thread"
-
-RSpec.describe "fetching dependencies with a mirrored source", :realworld => true, :rubygems => ">= 2.0" do
- let(:mirror) { "https://server.example.org" }
- let(:original) { "http://127.0.0.1:#{@port}" }
-
- before do
- setup_server
- bundle "config --local mirror.#{mirror} #{original}"
- end
-
- after do
- Artifice.deactivate
- @t.kill
- @t.join
- end
-
- it "sets the 'X-Gemfile-Source' header and bundles successfully" do
- gemfile <<-G
- source "#{mirror}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
-
- private
-
- def setup_server
- require_rack
- @port = find_unused_port
- @server_uri = "http://127.0.0.1:#{@port}"
-
- require File.expand_path("../../support/artifice/endpoint_mirror_source", __FILE__)
-
- @t = Thread.new do
- Rack::Server.start(:app => EndpointMirrorSource,
- :Host => "0.0.0.0",
- :Port => @port,
- :server => "webrick",
- :AccessLog => [],
- :Logger => Spec::SilentLogger.new)
- end.run
-
- wait_for_server("127.0.0.1", @port)
- end
-end
diff --git a/spec/bundler/realworld/git_spec.rb b/spec/bundler/realworld/git_spec.rb
new file mode 100644
index 0000000000..9eff74f1c9
--- /dev/null
+++ b/spec/bundler/realworld/git_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.describe "github source", realworld: true do
+ it "properly fetches PRs" do
+ install_gemfile <<-G
+ source "https://rubygems.org"
+
+ gem "reline", github: "https://github.com/ruby/reline/pull/488"
+ G
+ end
+end
diff --git a/spec/bundler/realworld/mirror_probe_spec.rb b/spec/bundler/realworld/mirror_probe_spec.rb
deleted file mode 100644
index ab74886329..0000000000
--- a/spec/bundler/realworld/mirror_probe_spec.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# frozen_string_literal: true
-
-require "thread"
-
-RSpec.describe "fetching dependencies with a not available mirror", :realworld => true do
- let(:mirror) { @mirror_uri }
- let(:original) { @server_uri }
- let(:server_port) { @server_port }
- let(:host) { "127.0.0.1" }
-
- before do
- require_rack
- setup_server
- setup_mirror
- end
-
- after do
- Artifice.deactivate
- @server_thread.kill
- @server_thread.join
- end
-
- context "with a specific fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/__FALLBACK_TIMEOUT/" => "true",
- "BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
- end
-
- it "install a gem using the original uri when the mirror is not responding" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
- end
-
- context "with a global fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__ALL__FALLBACK_TIMEOUT/" => "1",
- "BUNDLE_MIRROR__ALL" => mirror)
- end
-
- it "install a gem using the original uri when the mirror is not responding" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
- end
-
- context "with a specific mirror without a fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
- end
-
- it "fails to install the gem with a timeout error" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(out).to include("Fetching source index from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Could not fetch specs from #{mirror}")
- end
-
- it "prints each error and warning on a new line" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(last_command.stdout).to include "Fetching source index from #{mirror}/"
- expect(last_command.bundler_err).to include <<-EOS.strip
-Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Could not fetch specs from #{mirror}/
- EOS
- end
- end
-
- context "with a global mirror without a fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__ALL" => mirror)
- end
-
- it "fails to install the gem with a timeout error" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil
-
- expect(out).to include("Fetching source index from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(out).to include("Could not fetch specs from #{mirror}")
- end
- end
-
- def setup_server
- @server_port = find_unused_port
- @server_uri = "http://#{host}:#{@server_port}"
-
- require File.expand_path("../../support/artifice/endpoint", __FILE__)
-
- @server_thread = Thread.new do
- Rack::Server.start(:app => Endpoint,
- :Host => host,
- :Port => @server_port,
- :server => "webrick",
- :AccessLog => [],
- :Logger => Spec::SilentLogger.new)
- end.run
-
- wait_for_server(host, @server_port)
- end
-
- def setup_mirror
- mirror_port = find_unused_port
- @mirror_uri = "http://#{host}:#{mirror_port}"
- end
-end
diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb
index ed4430c68b..b57fdfd0ee 100644
--- a/spec/bundler/realworld/parallel_spec.rb
+++ b/spec/bundler/realworld/parallel_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "parallel", :realworld => true, :sometimes => true do
+RSpec.describe "parallel", realworld: true do
it "installs" do
gemfile <<-G
source "https://rubygems.org"
@@ -9,13 +9,9 @@ RSpec.describe "parallel", :realworld => true, :sometimes => true do
gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
G
- bundle :install, :jobs => 4, :env => { "DEBUG" => "1" }
+ bundle :install, jobs: 4, env: { "DEBUG" => "1" }
- if Bundler.rubygems.provides?(">= 2.1.0")
- expect(out).to match(/[1-3]: /)
- else
- expect(out).to include("is not threadsafe")
- end
+ expect(out).to match(/[1-3]: /)
bundle "info activesupport --path"
expect(out).to match(/activesupport/)
@@ -38,13 +34,9 @@ RSpec.describe "parallel", :realworld => true, :sometimes => true do
gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
G
- bundle :update, :jobs => 4, :env => { "DEBUG" => "1" }, :all => bundle_update_requires_all?
+ bundle :update, jobs: 4, env: { "DEBUG" => "1" }, all: true
- if Bundler.rubygems.provides?(">= 2.1.0")
- expect(out).to match(/[1-3]: /)
- else
- expect(out).to include("is not threadsafe")
- end
+ expect(out).to match(/[1-3]: /)
bundle "info activesupport --path"
expect(out).to match(/activesupport-3\.2\.\d+/)
@@ -54,14 +46,14 @@ RSpec.describe "parallel", :realworld => true, :sometimes => true do
end
it "works with --standalone" do
- gemfile <<-G, :standalone => true
+ gemfile <<-G
source "https://rubygems.org"
gem "diff-lcs"
G
- bundle :install, :standalone => true, :jobs => 4
+ bundle :install, standalone: true, jobs: 4
- ruby <<-RUBY, :no_lib => true
+ ruby <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
new file mode 100644
index 0000000000..5d36ba7455
--- /dev/null
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "bundle install with complex dependencies", realworld: true do
+ it "resolves quickly" do
+ gemfile <<-G
+ source 'https://rubygems.org'
+
+ gem "actionmailer"
+ gem "mongoid", ">= 0.10.2"
+ G
+
+ bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
+ expect(out).to include("Solution found after 1 attempts")
+ end
+
+ it "resolves quickly (case 2)" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'metasploit-erd'
+ gem 'rails-erd'
+ gem 'yard'
+
+ gem 'coveralls'
+ gem 'rails'
+ gem 'simplecov'
+ gem 'rspec-rails'
+ G
+
+ bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
+ expect(out).to include("Solution found after 2 attempts")
+ end
+end
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb
index c023f5d7aa..185df1b1c7 100644
--- a/spec/bundler/resolver/basic_spec.rb
+++ b/spec/bundler/resolver/basic_spec.rb
@@ -6,15 +6,15 @@ RSpec.describe "Resolving" do
end
it "resolves a single gem" do
- dep "rack"
+ dep "myrack"
- should_resolve_as %w[rack-1.1]
+ should_resolve_as %w[myrack-1.1]
end
it "resolves a gem with dependencies" do
dep "actionpack"
- should_resolve_as %w[actionpack-2.3.5 activesupport-2.3.5 rack-1.0]
+ should_resolve_as %w[actionpack-2.3.5 activesupport-2.3.5 myrack-1.0]
end
it "resolves a conflicting index" do
@@ -35,7 +35,7 @@ RSpec.describe "Resolving" do
should_resolve_as %w[berkshelf-2.0.7 chef-10.26 chef_app-1.0.0 json-1.7.7]
end
- it "prefers expicitly requested dependencies when resolving an index which would otherwise be ambiguous" do
+ it "prefers explicitly requested dependencies when resolving an index which would otherwise be ambiguous" do
@index = an_ambiguous_index
dep "a"
dep "b"
@@ -84,7 +84,7 @@ RSpec.describe "Resolving" do
dep "activesupport", "= 3.0.0.beta"
dep "actionpack"
- should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta rack-1.1 rack-mount-0.6]
+ should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta myrack-1.1 myrack-mount-0.6]
end
it "prefers non-pre-releases when doing conservative updates" do
@@ -100,11 +100,20 @@ RSpec.describe "Resolving" do
end
it "raises an exception if a child dependency is not resolved" do
- @index = a_unresovable_child_index
+ @index = a_unresolvable_child_index
dep "chef_app_error"
expect do
resolve
- end.to raise_error(Bundler::VersionConflict)
+ end.to raise_error(Bundler::SolveFailure)
+ end
+
+ it "does not try to re-resolve including prereleases if gems involved don't have prereleases" do
+ @index = a_unresolvable_child_index
+ dep "chef_app_error"
+ expect(Bundler.ui).not_to receive(:debug).with("Retrying resolution...", any_args)
+ expect do
+ resolve
+ end.to raise_error(Bundler::SolveFailure)
end
it "raises an exception with the minimal set of conflicting dependencies" do
@@ -118,14 +127,15 @@ RSpec.describe "Resolving" do
dep "c"
expect do
resolve
- end.to raise_error(Bundler::VersionConflict, <<-E.strip)
-Bundler could not find compatible versions for gem "a":
- In Gemfile:
- b was resolved to 1.0, which depends on
- a (>= 2)
-
- c was resolved to 1.0, which depends on
- a (< 1)
+ end.to raise_error(Bundler::SolveFailure, <<~E.strip)
+ Could not find compatible versions
+
+ Because every version of c depends on a < 1
+ and every version of b depends on a >= 2,
+ every version of c is incompatible with b >= 0.
+ So, because Gemfile depends on b >= 0
+ and Gemfile depends on c >= 0,
+ version solving has failed.
E
end
@@ -134,7 +144,7 @@ Bundler could not find compatible versions for gem "a":
dep "circular_app"
expect do
- resolve
+ Bundler::SpecSet.new(resolve).sort
end.to raise_error(Bundler::CyclicDependencyError, /please remove either gem 'bar' or gem 'foo'/i)
end
@@ -169,17 +179,12 @@ Bundler could not find compatible versions for gem "a":
s.required_ruby_version = "~> 2.0.0"
end
- gem "ruby\0", "1.8.7"
+ gem "Ruby\0", "1.8.7"
end
dep "foo"
- dep "ruby\0", "1.8.7"
-
- deps = []
- @deps.each do |d|
- deps << Bundler::DepProxy.new(d, "ruby")
- end
+ dep "Ruby\0", "1.8.7"
- should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]]
+ should_resolve_and_include %w[foo-1.0.0 bar-1.0.0]
end
context "conservative" do
@@ -206,12 +211,12 @@ Bundler could not find compatible versions for gem "a":
it "resolves all gems to latest patch" do
# strict is not set, so bar goes up a minor version due to dependency from foo 1.4.5
- should_conservative_resolve_and_include :patch, [], %w[foo-1.4.5 bar-2.1.1]
+ should_conservative_resolve_and_include :patch, true, %w[foo-1.4.5 bar-2.1.1]
end
it "resolves all gems to latest patch strict" do
# strict is set, so foo can only go up to 1.4.4 to avoid bar going up a minor version, and bar can go up to 2.0.5
- should_conservative_resolve_and_include [:patch, :strict], [], %w[foo-1.4.4 bar-2.0.5]
+ should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.4 bar-2.0.5]
end
it "resolves foo only to latest patch - same dependency case" do
@@ -226,14 +231,14 @@ Bundler could not find compatible versions for gem "a":
# dependencies and since the dependency of the selected foo gem changes, the latest matching
# dependency of "bar", "~> 2.1" -- bar-2.1.1 -- is selected. This is not a bug and follows
# the long-standing documented Conservative Updating behavior of bundle install.
- # http://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING
+ # https://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING
should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.5 bar-2.1.1]
end
it "resolves foo only to latest patch - changing dependency declared case" do
# bar is locked AND a declared dependency in the Gemfile, so it will not move, and therefore
# foo can only move up to 1.4.4.
- @base << build_spec("bar", "2.0.3").first
+ @base = Bundler::SpecSet.new([Bundler::LazySpecification.new("bar", Gem::Version.new("2.0.3"), nil)])
should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.4 bar-2.0.3]
end
@@ -251,20 +256,20 @@ Bundler could not find compatible versions for gem "a":
it "resolves all gems to latest minor" do
# strict is not set, so bar goes up a major version due to dependency from foo 1.4.5
- should_conservative_resolve_and_include :minor, [], %w[foo-1.5.1 bar-3.0.0]
+ should_conservative_resolve_and_include :minor, true, %w[foo-1.5.1 bar-3.0.0]
end
it "resolves all gems to latest minor strict" do
# strict is set, so foo can only go up to 1.5.0 to avoid bar going up a major version
- should_conservative_resolve_and_include [:minor, :strict], [], %w[foo-1.5.0 bar-2.1.1]
+ should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.5.0 bar-2.1.1]
end
it "resolves all gems to latest major" do
- should_conservative_resolve_and_include :major, [], %w[foo-2.0.0 bar-3.0.0]
+ should_conservative_resolve_and_include :major, true, %w[foo-2.0.0 bar-3.0.0]
end
it "resolves all gems to latest major strict" do
- should_conservative_resolve_and_include [:major, :strict], [], %w[foo-2.0.0 bar-3.0.0]
+ should_conservative_resolve_and_include [:major, :strict], true, %w[foo-2.0.0 bar-3.0.0]
end
# Why would this happen in real life? If bar 2.2 has a bug that the author of foo wants to bypass
@@ -287,22 +292,131 @@ Bundler could not find compatible versions for gem "a":
end
it "could revert to a previous version level patch" do
- should_conservative_resolve_and_include :patch, [], %w[foo-1.4.4 bar-2.1.1]
+ should_conservative_resolve_and_include :patch, true, %w[foo-1.4.4 bar-2.1.1]
end
it "cannot revert to a previous version in strict mode level patch" do
# fall back to the locked resolution since strict means we can't regress either version
- should_conservative_resolve_and_include [:patch, :strict], [], %w[foo-1.4.3 bar-2.2.3]
+ should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.3 bar-2.2.3]
end
it "could revert to a previous version level minor" do
- should_conservative_resolve_and_include :minor, [], %w[foo-1.5.0 bar-2.0.5]
+ should_conservative_resolve_and_include :minor, true, %w[foo-1.5.0 bar-2.0.5]
end
it "cannot revert to a previous version in strict mode level minor" do
# fall back to the locked resolution since strict means we can't regress either version
- should_conservative_resolve_and_include [:minor, :strict], [], %w[foo-1.4.3 bar-2.2.3]
+ should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.4.3 bar-2.2.3]
+ end
+ end
+ end
+
+ it "handles versions that redundantly depend on themselves" do
+ @index = build_index do
+ gem "myrack", "3.0.0"
+
+ gem "standalone_migrations", "7.1.0" do
+ dep "myrack", "~> 2.0"
+ end
+
+ gem "standalone_migrations", "2.0.4" do
+ dep "standalone_migrations", ">= 0"
+ end
+
+ gem "standalone_migrations", "1.0.13" do
+ dep "myrack", ">= 0"
+ end
+ end
+
+ dep "myrack", "~> 3.0"
+ dep "standalone_migrations"
+
+ should_resolve_as %w[myrack-3.0.0 standalone_migrations-2.0.4]
+ end
+
+ it "ignores versions that incorrectly depend on themselves" do
+ @index = build_index do
+ gem "myrack", "3.0.0"
+
+ gem "standalone_migrations", "7.1.0" do
+ dep "myrack", "~> 2.0"
+ end
+
+ gem "standalone_migrations", "2.0.4" do
+ dep "standalone_migrations", ">= 2.0.5"
+ end
+
+ gem "standalone_migrations", "1.0.13" do
+ dep "myrack", ">= 0"
+ end
+ end
+
+ dep "myrack", "~> 3.0"
+ dep "standalone_migrations"
+
+ should_resolve_as %w[myrack-3.0.0 standalone_migrations-1.0.13]
+ end
+
+ it "does not ignore versions that incorrectly depend on themselves when dependency_api is not available" do
+ @index = build_index do
+ gem "myrack", "3.0.0"
+
+ gem "standalone_migrations", "7.1.0" do
+ dep "myrack", "~> 2.0"
+ end
+
+ gem "standalone_migrations", "2.0.4" do
+ dep "standalone_migrations", ">= 2.0.5"
+ end
+
+ gem "standalone_migrations", "1.0.13" do
+ dep "myrack", ">= 0"
+ end
+ end
+
+ dep "myrack", "~> 3.0"
+ dep "standalone_migrations"
+
+ should_resolve_without_dependency_api %w[myrack-3.0.0 standalone_migrations-2.0.4]
+ end
+
+ it "resolves fine cases that need joining unbounded disjoint ranges" do
+ @index = build_index do
+ gem "inspec", "5.22.3" do
+ dep "ruby", ">= 3.2.2"
+ dep "train-kubernetes", ">= 0.1.7"
+ end
+
+ gem "ruby", "3.2.2"
+
+ gem "train-kubernetes", "0.1.12" do
+ dep "k8s-ruby", ">= 0.14.0"
+ end
+
+ gem "train-kubernetes", "0.1.10" do
+ dep "k8s-ruby", "= 0.10.5"
+ end
+
+ gem "train-kubernetes", "0.1.7" do
+ dep "k8s-ruby", ">= 0.10.5"
+ end
+
+ gem "k8s-ruby", "0.10.5" do
+ dep "ruby","< 3.2.2"
+ end
+
+ gem "k8s-ruby", "0.11.0" do
+ dep "ruby", ">= 3.2.2"
+ end
+
+ gem "k8s-ruby", "0.14.0" do
+ dep "ruby", "< 3.2.2"
end
end
+
+ dep "inspec", "5.22.3"
+ dep "ruby", "3.2.2"
+
+ should_resolve_as %w[inspec-5.22.3 ruby-3.2.2 train-kubernetes-0.1.7 k8s-ruby-0.11.0]
end
end
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index fee0cf1f1c..a1d095d024 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -28,10 +28,321 @@ RSpec.describe "Resolving platform craziness" do
end
end
+ it "resolves multiplatform gems with redundant platforms correctly" do
+ @index = build_index do
+ gem "zookeeper", "1.4.11"
+ gem "zookeeper", "1.4.11", "java" do
+ dep "slyphon-log4j", "= 1.2.15"
+ dep "slyphon-zookeeper_jar", "= 3.3.5"
+ end
+ gem "slyphon-log4j", "1.2.15"
+ gem "slyphon-zookeeper_jar", "3.3.5", "java"
+ end
+
+ dep "zookeeper"
+ platforms "java", "ruby", "universal-java-11"
+
+ should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java]
+ end
+
+ it "takes the latest ruby gem, even if an older platform specific version is available" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
+ gem "foo", "1.1.0"
+ end
+ dep "foo"
+ platforms "x64-mingw-ucrt"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the ruby version if the platform version is incompatible" do
+ @index = build_index do
+ gem "bar", "1.0.0"
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt" do
+ dep "bar", "< 1"
+ end
+ end
+ dep "foo"
+ platforms "x64-mingw-ucrt"
+
+ should_resolve_as %w[foo-1.0.0]
+ end
+
+ it "prefers the platform specific gem to the ruby version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
+ end
+ dep "foo"
+ platforms "x64-mingw-ucrt"
+
+ should_resolve_as %w[foo-1.0.0-x64-mingw-ucrt]
+ end
+
+ describe "on a linux platform" do
+ # Ruby's platform is *-linux => platform's libc is glibc, so not musl
+ # Ruby's platform is *-linux-musl => platform's libc is musl, so not glibc
+ # Gem's platform is *-linux => gem is glibc + maybe musl compatible
+ # Gem's platform is *-linux-musl => gem is musl compatible but not glibc
+
+ it "favors the platform version-specific gem on a version-specifying linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux-musl]
+ end
+
+ it "favors the version-less gem over the version-specific gem on a gnu linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+
+ it "ignores the platform version-specific gem on a gnu linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_not_resolve
+ end
+
+ it "falls back to the platform version-less gem on a linux platform with a version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ end
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+
+ it "falls back to the ruby platform gem on a gnu linux platform when only a version-specifying gem is available" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_resolve_as %w[foo-1.0.0]
+ end
+
+ it "falls back to the platform version-less gem on a version-specifying linux platform and no ruby platform gem is available" do
+ @index = build_index do
+ gem "foo", "1.0.0", "x86_64-linux"
+ end
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+ end
+
+ context "when the platform specific gem doesn't match the required_ruby_version" do
+ before do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
+ gem "foo", "1.1.0"
+ gem "foo", "1.1.0", "x64-mingw-ucrt" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "Ruby\0", "2.5.1"
+ platforms "x64-mingw-ucrt"
+ end
+
+ it "takes the latest ruby gem" do
+ dep "foo"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the latest ruby gem, even if requirement does not match previous versions with the same ruby requirement" do
+ dep "foo", "1.1.0"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+ end
+
+ it "takes the latest ruby gem with required_ruby_version if the platform specific gem doesn't match the required_ruby_version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
+ gem "foo", "1.1.0" do |s|
+ s.required_ruby_version = [">= 2.0"]
+ end
+ gem "foo", "1.1.0", "x64-mingw-ucrt" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "foo"
+ dep "Ruby\0", "2.5.1"
+ platforms "x64-mingw-ucrt"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version with multiple platforms" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
+ gem "foo", "1.1.0" do |s|
+ s.required_ruby_version = [">= 2.0"]
+ end
+ gem "foo", "1.1.0", "x64-mingw-ucrt" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "foo"
+ dep "Ruby\0", "2.5.1"
+ platforms "x86_64-linux", "x64-mingw-ucrt"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "includes gems needed for at least one platform" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "extra2", ">= 0"
+ end
+
+ gem "extra2", "1.0.0" do
+ dep "extra3", ">= 0"
+ end
+
+ gem "extra3", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "properly adds platforms when platform requirements come from different dependencies" do
+ @index = build_index do
+ gem "ffi", "1.9.14"
+ gem "ffi", "1.9.14", "universal-mingw32"
+
+ gem "gssapi", "0.1"
+ gem "gssapi", "0.2"
+ gem "gssapi", "0.3"
+ gem "gssapi", "1.2.0" do
+ dep "ffi", ">= 1.0.1"
+ end
+
+ gem "mixlib-shellout", "2.2.6"
+ gem "mixlib-shellout", "2.2.6", "universal-mingw32" do
+ dep "win32-process", "~> 0.8.2"
+ end
+
+ # we need all these versions to get the sorting the same as it would be
+ # pulling from rubygems.org
+ %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v|
+ gem "win32-process", v do
+ dep "ffi", ">= 1.0.0"
+ end
+ end
+ end
+
+ dep "mixlib-shellout"
+ dep "gssapi"
+
+ platforms "universal-mingw32", "ruby"
+
+ should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3]
+ end
+
describe "with mingw32" do
before :each do
@index = build_index do
- platforms "mingw32 mswin32 x64-mingw32" do |platform|
+ platforms "mingw32 mswin32 x64-mingw-ucrt" do |platform|
gem "thin", "1.2.7", platform
end
gem "win32-api", "1.5.1", "universal-mingw32"
@@ -52,10 +363,10 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[thin-1.2.7-mingw32]
end
- it "finds x64-mingw gems" do
- platforms "x64-mingw32"
+ it "finds x64-mingw-ucrt gems" do
+ platforms "x64-mingw-ucrt"
dep "thin"
- should_resolve_as %w[thin-1.2.7-x64-mingw32]
+ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
end
it "finds universal-mingw gems on x86-mingw" do
@@ -65,7 +376,19 @@ RSpec.describe "Resolving platform craziness" do
end
it "finds universal-mingw gems on x64-mingw" do
- platform "x64-mingw32"
+ platform "x64-mingw-ucrt"
+ dep "win32-api"
+ should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
+ end
+
+ it "finds x64-mingw-ucrt gems" do
+ platforms "x64-mingw-ucrt"
+ dep "thin"
+ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
+ end
+
+ it "finds universal-mingw gems on x64-mingw-ucrt" do
+ platform "x64-mingw-ucrt"
dep "win32-api"
should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
end
@@ -90,11 +413,11 @@ RSpec.describe "Resolving platform craziness" do
end
end
- it "reports on the conflict" do
+ it "takes the ruby version as fallback" do
platforms "ruby", "java"
dep "foo"
- should_conflict_on "baz"
+ should_resolve_as %w[bar-1.0.0 baz-1.0.0 foo-1.0.0]
end
end
end
diff --git a/spec/bundler/runtime/env_helpers_spec.rb b/spec/bundler/runtime/env_helpers_spec.rb
new file mode 100644
index 0000000000..c4ebdd1fd2
--- /dev/null
+++ b/spec/bundler/runtime/env_helpers_spec.rb
@@ -0,0 +1,236 @@
+# frozen_string_literal: true
+
+RSpec.describe "env helpers" do
+ def bundle_exec_ruby(args, options = {})
+ build_bundler_context options.dup
+ bundle "exec '#{Gem.ruby}' #{args}", options
+ end
+
+ def build_bundler_context(options = {})
+ bundle "config set path vendor/bundle", options.dup
+ gemfile "source 'https://gem.repo1'"
+ bundle "install", options
+ end
+
+ def run_bundler_script(env, script)
+ system(env, "ruby", "-I#{lib_dir}", "-rbundler", script.to_s)
+ end
+
+ describe "Bundler.original_env" do
+ it "should return the PATH present before bundle was activated" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.original_env["PATH"]
+ RUBY
+ path = `getconf PATH`.strip + "#{File::PATH_SEPARATOR}/foo"
+ with_path_as(path) do
+ bundle_exec_ruby(bundled_app("source.rb").to_s)
+ expect(stdboth).to eq(path)
+ end
+ end
+
+ it "should return the GEM_PATH present before bundle was activated" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.original_env['GEM_PATH']
+ RUBY
+ gem_path = ENV["GEM_PATH"] + "#{File::PATH_SEPARATOR}/foo"
+ with_gem_path_as(gem_path) do
+ bundle_exec_ruby(bundled_app("source.rb").to_s)
+ expect(stdboth).to eq(gem_path)
+ end
+ end
+
+ it "works with nested bundle exec invocations", :ruby_repo do
+ create_file("exe.rb", <<-'RUBY')
+ count = ARGV.first.to_i
+ exit if count < 0
+ STDERR.puts "#{count} #{ENV["PATH"].end_with?("#{File::PATH_SEPARATOR}/foo")}"
+ if count == 2
+ ENV["PATH"] = "#{ENV["PATH"]}#{File::PATH_SEPARATOR}/foo"
+ end
+ exec(Gem.ruby, __FILE__, (count - 1).to_s)
+ RUBY
+ path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby)
+ with_path_as(path) do
+ build_bundler_context
+ bundle_exec_ruby("#{bundled_app("exe.rb")} 2")
+ end
+ expect(err).to eq <<-EOS.strip
+2 false
+1 true
+0 true
+ EOS
+ end
+
+ it "removes variables that bundler added", :ruby_repo do
+ original = ruby('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")', artifice: "fail")
+ create_file("source.rb", <<-RUBY)
+ puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n")
+ RUBY
+ bundle_exec_ruby bundled_app("source.rb"), artifice: "fail"
+ expect(out).to eq original
+ end
+ end
+
+ describe "Bundler.unbundled_env" do
+ it "should delete BUNDLE_PATH" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env.has_key?('BUNDLE_PATH')
+ RUBY
+ ENV["BUNDLE_PATH"] = "./foo"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include "false"
+ end
+
+ it "should remove absolute path to 'bundler/setup' from RUBYOPT even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env['RUBYOPT']
+ RUBY
+ setup_require = "-r#{lib_dir}/bundler/setup"
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 #{setup_require} #{ENV["RUBYOPT"]}"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).not_to include(setup_require)
+ end
+
+ it "should remove relative path to 'bundler/setup' from RUBYOPT even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env['RUBYOPT']
+ RUBY
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).not_to include("-rbundler/setup")
+ end
+
+ it "should delete BUNDLER_SETUP even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env.has_key?('BUNDLER_SETUP')
+ RUBY
+ ENV["BUNDLER_ORIG_BUNDLER_SETUP"] = system_gem_path("gems/bundler-#{Bundler::VERSION}/lib/bundler/setup").to_s
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include "false"
+ end
+
+ it "should restore RUBYLIB", :ruby_repo do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env['RUBYLIB']
+ RUBY
+ ENV["RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo"
+ ENV["BUNDLER_ORIG_RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo-original"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include("/foo-original")
+ end
+
+ it "should restore the original MANPATH" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env['MANPATH']
+ RUBY
+ ENV["MANPATH"] = "/foo"
+ ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include("/foo-original")
+ end
+ end
+
+ describe "Bundler.with_original_env" do
+ it "should set ENV to original_env in the block" do
+ expected = Bundler.original_env
+ actual = Bundler.with_original_env { ENV.to_hash }
+ expect(actual).to eq(expected)
+ end
+
+ it "should restore the environment after execution" do
+ Bundler.with_original_env do
+ ENV["FOO"] = "hello"
+ end
+
+ expect(ENV).not_to have_key("FOO")
+ end
+ end
+
+ describe "Bundler.with_unbundled_env" do
+ it "should set ENV to unbundled_env in the block" do
+ expected = Bundler.unbundled_env
+ actual = Bundler.with_unbundled_env { ENV.to_hash }
+ expect(actual).to eq(expected)
+ end
+
+ it "should restore the environment after execution" do
+ Bundler.with_unbundled_env do
+ ENV["FOO"] = "hello"
+ end
+
+ expect(ENV).not_to have_key("FOO")
+ end
+ end
+
+ describe "Bundler.original_system" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Bundler.original_system("ruby", "-e", "exit(42) if ENV['BUNDLE_FOO'] == 'bar'")
+
+ exit $?.exitstatus
+ RUBY
+ end
+
+ it "runs system inside with_original_env" do
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(42)
+ end
+ end
+
+ describe "Bundler.unbundled_system" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Bundler.unbundled_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'")
+
+ exit $?.exitstatus
+ RUBY
+ end
+
+ it "runs system inside with_unbundled_env" do
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(42)
+ end
+ end
+
+ describe "Bundler.original_exec" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Process.fork do
+ exit Bundler.original_exec(%(test "\$BUNDLE_FOO" = "bar"))
+ end
+
+ _, status = Process.wait2
+
+ exit(status.exitstatus)
+ RUBY
+ end
+
+ it "runs exec inside with_original_env" do
+ skip "Fork not implemented" if Gem.win_platform?
+
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(0)
+ end
+ end
+
+ describe "Bundler.unbundled_exec" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Process.fork do
+ exit Bundler.unbundled_exec(%(test "\$BUNDLE_FOO" = "bar"))
+ end
+
+ _, status = Process.wait2
+
+ exit(status.exitstatus)
+ RUBY
+ end
+
+ it "runs exec inside with_unbundled_env" do
+ skip "Fork not implemented" if Gem.win_platform?
+
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(1)
+ end
+ end
+end
diff --git a/spec/bundler/runtime/executable_spec.rb b/spec/bundler/runtime/executable_spec.rb
index 7ba510a509..89cee21b00 100644
--- a/spec/bundler/runtime/executable_spec.rb
+++ b/spec/bundler/runtime/executable_spec.rb
@@ -2,181 +2,133 @@
RSpec.describe "Running bin/* commands" do
before :each do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
end
it "runs the bundled command when in the bundle" do
- bundle! "binstubs rack"
+ bundle "binstubs myrack"
- build_gem "rack", "2.0", :to_system => true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- gembin "rackup"
+ gembin "myrackup"
expect(out).to eq("1.0.0")
end
- it "allows the location of the gem stubs to be specified" do
- bundle! "binstubs rack", :path => "gbin"
+ it "allows the location of the gem stubs to be configured" do
+ bundle_config "bin gbin"
+ bundle "binstubs myrack"
expect(bundled_app("bin")).not_to exist
- expect(bundled_app("gbin/rackup")).to exist
+ expect(bundled_app("gbin/myrackup")).to exist
- gembin bundled_app("gbin/rackup")
+ gembin bundled_app("gbin/myrackup")
expect(out).to eq("1.0.0")
end
it "allows absolute paths as a specification of where to install bin stubs" do
- bundle! "binstubs rack", :path => tmp("bin")
+ bundle_config "bin #{tmp("bin")}"
+ bundle "binstubs myrack"
- gembin tmp("bin/rackup")
+ gembin tmp("bin/myrackup")
expect(out).to eq("1.0.0")
end
it "uses the default ruby install name when shebang is not specified" do
- bundle! "binstubs rack"
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n")
+ bundle "binstubs myrack"
+ expect(File.readlines(bundled_app("bin/myrackup")).first).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n")
end
it "allows the name of the shebang executable to be specified" do
- bundle! "binstubs rack", :shebang => "ruby-foo"
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env ruby-foo\n")
+ bundle "binstubs myrack", shebang: "ruby-foo"
+ expect(File.readlines(bundled_app("bin/myrackup")).first).to eq("#!/usr/bin/env ruby-foo\n")
end
it "runs the bundled command when out of the bundle" do
- bundle! "binstubs rack"
+ bundle "binstubs myrack"
- build_gem "rack", "2.0", :to_system => true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- Dir.chdir(tmp) do
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
+ gembin "myrackup", dir: tmp
+ expect(out).to eq("1.0.0")
end
it "works with gems in path" do
- build_lib "rack", :path => lib_path("rack") do |s|
- s.executables = "rackup"
+ build_lib "myrack", path: lib_path("myrack") do |s|
+ s.executables = "myrackup"
end
gemfile <<-G
- gem "rack", :path => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :path => "#{lib_path("myrack")}"
G
- bundle! "binstubs rack"
+ bundle "binstubs myrack"
- build_gem "rack", "2.0", :to_system => true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- gembin "rackup"
+ gembin "myrackup"
expect(out).to eq("1.0")
end
- it "creates a bundle binstub" do
- build_gem "bundler", Bundler::VERSION, :to_system => true do |s|
- s.executables = "bundle"
- end
-
+ it "does not create a bundle binstub" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "bundler"
G
- bundle! "binstubs bundler"
+ bundle "binstubs bundler"
- expect(bundled_app("bin/bundle")).to exist
- end
-
- it "does not generate bin stubs if the option was not specified" do
- bundle! "install"
+ expect(bundled_app("bin/bundle")).not_to exist
- expect(bundled_app("bin/rackup")).not_to exist
+ expect(err).to include("Bundler itself does not use binstubs because its version is selected by RubyGems")
end
- it "allows you to stop installing binstubs", :bundler => "< 3" do
- bundle! "install --binstubs bin/"
- bundled_app("bin/rackup").rmtree
- bundle! "install --binstubs \"\""
-
- expect(bundled_app("bin/rackup")).not_to exist
-
- bundle! "config bin"
- expect(out).to include("You have not configured a value for `bin`")
- end
-
- it "remembers that the option was specified", :bundler => "< 3" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
- G
-
- bundle! :install, forgotten_command_line_options([:binstubs, :bin] => "bin")
-
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
- gem "rack"
- G
-
- bundle "install"
-
- expect(bundled_app("bin/rackup")).to exist
- end
-
- it "rewrites bins on --binstubs (to maintain backwards compatibility)", :bundler => "< 2" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
- bundle! :install, forgotten_command_line_options([:binstubs, :bin] => "bin")
-
- File.open(bundled_app("bin/rackup"), "wb") do |file|
- file.print "OMG"
- end
-
+ it "does not generate bin stubs if the option was not specified" do
bundle "install"
- expect(bundled_app("bin/rackup").read).to_not eq("OMG")
+ expect(bundled_app("bin/myrackup")).not_to exist
end
- it "rewrites bins on binstubs (to maintain backwards compatibility)" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ it "rewrites bins on binstubs with --force option" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- create_file("bin/rackup", "OMG")
+ create_file("bin/myrackup", "OMG")
- bundle! "binstubs rack"
+ bundle "binstubs myrack", { force: true }
- expect(bundled_app("bin/rackup").read).to_not eq("OMG")
+ expect(bundled_app("bin/myrackup").read.strip).to_not eq("OMG")
end
it "use BUNDLE_GEMFILE gemfile for binstub" do
- # context with bin/bunlder w/ default Gemfile
- bundle! "binstubs bundler"
+ # context with bin/bundler w/ default Gemfile
+ bundle "binstubs bundler"
# generate other Gemfile with executable gem
build_repo2 do
build_gem("bindir") {|s| s.executables = "foo" }
end
- create_file("OtherGemfile", <<-G)
- source "file://#{gem_repo2}"
+ gemfile("OtherGemfile", <<-G)
+ source "https://gem.repo2"
gem 'bindir'
G
# generate binstub for executable from non default Gemfile (other then bin/bundler version)
ENV["BUNDLE_GEMFILE"] = "OtherGemfile"
bundle "install"
- bundle! "binstubs bindir"
+ bundle "binstubs bindir"
# remove user settings
ENV["BUNDLE_GEMFILE"] = nil
@@ -184,7 +136,6 @@ RSpec.describe "Running bin/* commands" do
# run binstub for non default Gemfile
gembin "foo"
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("1.0")
end
end
diff --git a/spec/bundler/runtime/gem_tasks_spec.rb b/spec/bundler/runtime/gem_tasks_spec.rb
index de72869dc3..b855142e60 100644
--- a/spec/bundler/runtime/gem_tasks_spec.rb
+++ b/spec/bundler/runtime/gem_tasks_spec.rb
@@ -1,28 +1,74 @@
# frozen_string_literal: true
-RSpec.describe "require 'bundler/gem_tasks'", :ruby_repo do
- before :each do
+RSpec.describe "require 'bundler/gem_tasks'" do
+ let(:define_local_gem_using_gem_tasks) do
bundled_app("foo.gemspec").open("w") do |f|
f.write <<-GEMSPEC
Gem::Specification.new do |s|
s.name = "foo"
+ s.version = "1.0"
+ s.summary = "dummy"
+ s.author = "Perry Mason"
end
GEMSPEC
end
+
bundled_app("Rakefile").open("w") do |f|
f.write <<-RAKEFILE
- $:.unshift("#{bundler_path}")
require "bundler/gem_tasks"
RAKEFILE
end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "rake"
+ G
end
- it "includes the relevant tasks" do
- with_gem_path_as(Spec::Path.base_system_gems.to_s) do
- sys_exec "#{rake} -T"
+ let(:define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl) do
+ bundled_app("foo.gemspec").open("w") do |f|
+ f.write <<-GEMSPEC
+ Gem::Specification.new do |s|
+ s.name = "foo"
+ s.version = "1.0"
+ s.summary = "dummy"
+ s.author = "Perry Mason"
+ s.extensions = "ext/extconf.rb"
+ end
+ GEMSPEC
+ end
+
+ bundled_app("Rakefile").open("w") do |f|
+ f.write <<-RAKEFILE
+ require "bundler/gem_tasks"
+ RAKEFILE
+ end
+
+ Dir.mkdir bundled_app("ext")
+
+ bundled_app("ext/extconf.rb").open("w") do |f|
+ f.write <<-EXTCONF
+ require "mkmf"
+ File.write("Makefile", dummy_makefile($srcdir).join)
+ EXTCONF
end
- expect(err).to eq("")
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gemspec
+
+ gem "rake"
+ G
+ end
+
+ it "includes the relevant tasks" do
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app "rake -T"
+
+ expect(err).to be_empty
expected_tasks = [
"rake build",
"rake clean",
@@ -32,13 +78,81 @@ RSpec.describe "require 'bundler/gem_tasks'", :ruby_repo do
]
tasks = out.lines.to_a.map {|s| s.split("#").first.strip }
expect(tasks & expected_tasks).to eq(expected_tasks)
- expect(exitstatus).to eq(0) if exitstatus
end
- it "adds 'pkg' to rake/clean's CLOBBER" do
- with_gem_path_as(Spec::Path.base_system_gems.to_s) do
- sys_exec! %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect')
+ it "defines a working `rake install` task", :ruby_repo do
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app "rake install"
+
+ expect(err).to be_empty
+
+ bundle "exec rake install"
+
+ expect(err).to be_empty
+ end
+
+ it "defines a working `rake install` task for local gems with extensions", :ruby_repo do
+ define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl
+
+ bundle "exec rake install"
+
+ expect(err).to be_empty
+ end
+
+ context "rake build when path has spaces", :ruby_repo do
+ before do
+ define_local_gem_using_gem_tasks
+
+ spaced_bundled_app = tmp("bundled app")
+ FileUtils.cp_r bundled_app, spaced_bundled_app
+ bundle "exec rake build", dir: spaced_bundled_app
+ end
+
+ it "still runs successfully" do
+ expect(err).to be_empty
+ end
+ end
+
+ context "rake build when path has brackets", :ruby_repo do
+ before do
+ define_local_gem_using_gem_tasks
+
+ bracketed_bundled_app = tmp("bundled[app")
+ FileUtils.cp_r bundled_app, bracketed_bundled_app
+ bundle "exec rake build", dir: bracketed_bundled_app
+ end
+
+ it "still runs successfully" do
+ expect(err).to be_empty
+ end
+ end
+
+ context "bundle path configured locally" do
+ before do
+ define_local_gem_using_gem_tasks
+
+ bundle_config "path vendor/bundle"
end
- expect(last_command.stdout).to eq '["pkg"]'
+
+ it "works", :ruby_repo do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "rake"
+ G
+
+ bundle "exec rake -T"
+
+ expect(err).to be_empty
+ end
+ end
+
+ it "adds 'pkg' to rake/clean's CLOBBER" do
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app %(rake -e 'load "Rakefile"; puts CLOBBER.inspect')
+
+ expect(out).to eq '["pkg"]'
end
end
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index 18ca246199..c6f9bbdbd7 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -2,10 +2,9 @@
RSpec.describe "bundler/inline#gemfile" do
def script(code, options = {})
- requires = ["bundler/inline"]
- requires.unshift File.expand_path("../../support/artifice/" + options.delete(:artifice) + ".rb", __FILE__) if options.key?(:artifice)
- requires = requires.map {|r| "require '#{r}'" }.join("\n")
- @out = ruby("#{requires}\n\n" + code, options)
+ options[:artifice] ||= "compact_index"
+ options[:env] ||= { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ ruby("require 'bundler/inline'\n\n" + code, options)
end
before :each do
@@ -28,7 +27,7 @@ RSpec.describe "bundler/inline#gemfile" do
s.write "lib/four.rb", "puts 'four'"
end
- build_lib "five", "1.0.0", :no_default => true do |s|
+ build_lib "five", "1.0.0", no_default: true do |s|
s.write "lib/mofive.rb", "puts 'five'"
end
@@ -48,6 +47,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "requires the gems" do
script <<-RUBY
gemfile do
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
end
@@ -55,10 +55,10 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to eq("two")
- expect(exitstatus).to be_zero if exitstatus
- script <<-RUBY
+ script <<-RUBY, raise_on_error: false
gemfile do
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "eleven"
end
@@ -72,48 +72,60 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile(true) do
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
RUBY
- expect(out).to include("Rack's post install message")
- expect(exitstatus).to be_zero if exitstatus
+ expect(out).to include("Myrack's post install message")
- script <<-RUBY, :artifice => "endpoint"
+ script <<-RUBY, artifice: "endpoint"
gemfile(true) do
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "activesupport", :require => true
end
RUBY
expect(out).to include("Installing activesupport")
- err.gsub! %r{.*lib/sinatra/base\.rb:\d+: warning: constant ::Fixnum is deprecated$}, ""
- err.strip!
- expect(err).to lack_errors
- expect(exitstatus).to be_zero if exitstatus
+ err_lines = err.split("\n")
+ err_lines.reject! {|line| line =~ /\.rb:\d+: warning: / }
+ expect(err_lines).to be_empty
end
it "lets me use my own ui object" do
- script <<-RUBY, :artifice => "endpoint"
+ script <<-RUBY, artifice: "endpoint"
require 'bundler'
- class MyBundlerUI < Bundler::UI::Silent
+ class MyBundlerUI < Bundler::UI::Shell
def confirm(msg, newline = nil)
puts "CONFIRMED!"
end
end
- gemfile(true, :ui => MyBundlerUI.new) do
- source "https://notaserver.com"
+ my_ui = MyBundlerUI.new
+ my_ui.level = "confirm"
+ gemfile(true, :ui => my_ui) do
+ source "https://notaserver.test"
gem "activesupport", :require => true
end
RUBY
expect(out).to eq("CONFIRMED!\nCONFIRMED!")
- expect(exitstatus).to be_zero if exitstatus
+ end
+
+ it "has an option for quiet installation" do
+ script <<-RUBY, artifice: "endpoint"
+ require 'bundler/inline'
+
+ gemfile(true, :quiet => true) do
+ source "https://notaserver.test"
+ gem "activesupport", :require => true
+ end
+ RUBY
+
+ expect(out).to be_empty
end
it "raises an exception if passed unknown arguments" do
- script <<-RUBY
+ script <<-RUBY, raise_on_error: false
gemfile(true, :arglebargle => true) do
path "#{lib_path}"
gem "two"
@@ -130,6 +142,7 @@ RSpec.describe "bundler/inline#gemfile" do
require 'bundler'
options = { :ui => Bundler::UI::Shell.new }
gemfile(false, options) do
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
end
@@ -138,22 +151,68 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to match("OKAY")
- expect(exitstatus).to be_zero if exitstatus
end
it "installs quietly if necessary when the install option is not set" do
script <<-RUBY
gemfile do
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ puts MYRACK
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+
+ it "installs subdependencies quietly if necessary when the install option is not set" do
+ build_repo4 do
+ build_gem "myrack" do |s|
+ s.add_dependency "myrackdep"
+ end
+
+ build_gem "myrackdep", "1.0.0"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ gemfile do
+ source "https://gem.repo4"
+ gem "myrack"
+ end
+
+ require "myrackdep"
+ puts MYRACKDEP
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+
+ it "installs subdependencies quietly if necessary when the install option is not set, and multiple sources used" do
+ build_repo4 do
+ build_gem "myrack" do |s|
+ s.add_dependency "myrackdep"
+ end
+
+ build_gem "myrackdep", "1.0.0"
+ end
+
+ script <<-RUBY, artifice: "compact_index_extra_api"
+ gemfile do
+ source "https://test.repo"
+ source "https://test.repo/extra" do
+ gem "myrack"
+ end
end
- puts RACK
+ require "myrackdep"
+ puts MYRACKDEP
RUBY
expect(out).to eq("1.0.0")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs quietly from git if necessary when the install option is not set" do
@@ -161,6 +220,7 @@ RSpec.describe "bundler/inline#gemfile" do
baz_ref = build_git("baz", "2.0.0").ref_for("HEAD")
script <<-RUBY
gemfile do
+ source "https://gem.repo1"
gem "foo", :git => #{lib_path("foo-1.0.0").to_s.dump}
gem "baz", :git => #{lib_path("baz-2.0.0").to_s.dump}, :ref => #{baz_ref.dump}
end
@@ -171,19 +231,20 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to eq("1.0.0\n2.0.0")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "allows calling gemfile twice" do
script <<-RUBY
gemfile do
path "#{lib_path}" do
+ source "https://gem.repo1"
gem "two"
end
end
gemfile do
path "#{lib_path}" do
+ source "https://gem.repo1"
gem "four"
end
end
@@ -191,12 +252,118 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to eq("two\nfour")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
+ end
+
+ it "doesn't reinstall already installed gems" do
+ system_gems "myrack-1.0.0"
+
+ script <<-RUBY
+ require 'bundler'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "activesupport"
+ gem "myrack"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing myrack")
+ expect(err).to be_empty
+ end
+
+ it "installs gems in later gemfile calls" do
+ system_gems "myrack-1.0.0"
+
+ script <<-RUBY
+ require 'bundler'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "activesupport"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing myrack")
+ expect(err).to be_empty
+ end
+
+ it "doesn't reinstall already installed gems in later gemfile calls" do
+ system_gems "myrack-1.0.0"
+
+ script <<-RUBY
+ require 'bundler'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "activesupport"
+ end
+
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing myrack")
+ expect(err).to be_empty
+ end
+
+ it "installs gems with native extensions in later gemfile calls" do
+ system_gems "myrack-1.0.0"
+
+ build_git "foo" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/foo.rb", "w") do |f|
+ f.puts "FOO = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ script <<-RUBY
+ require 'bundler'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ gemfile(true, ui: ui) do
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ end
+
+ require 'foo'
+ puts FOO
+ puts $:.grep(/ext/)
+ RUBY
+
+ expect(out).to include("YES")
+ expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
+ expect(err).to be_empty
end
it "installs inline gems when a Gemfile.lock is present" do
gemfile <<-G
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "rake"
G
@@ -213,40 +380,94 @@ RSpec.describe "bundler/inline#gemfile" do
rake
BUNDLED WITH
- 1.13.6
+ #{Bundler::VERSION}
G
- in_app_root do
- script <<-RUBY
- gemfile do
- source "file://#{gem_repo1}"
- gem "rack"
- end
+ script <<-RUBY
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
- puts RACK
- RUBY
- end
+ puts MYRACK
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "does not leak Gemfile.lock versions to the installation output" do
+ gemfile <<-G
+ source "https://notaserver.test"
+ gem "rake"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (11.3.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ script <<-RUBY
+ gemfile(true) do
+ source "https://gem.repo1"
+ gem "rake", "#{rake_version}"
+ end
+ RUBY
+ expect(out).to include("Installing rake #{rake_version}")
+ expect(out).not_to include("was 11.3.0")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
+ end
+
+ it "installs inline gems when frozen is set" do
+ script <<-RUBY, env: { "BUNDLE_FROZEN" => "true", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ puts MYRACK
+ RUBY
+
+ expect(last_command.stderr).to be_empty
+ end
+
+ it "installs inline gems when deployment is set" do
+ script <<-RUBY, env: { "BUNDLE_DEPLOYMENT" => "true", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ puts MYRACK
+ RUBY
+
+ expect(last_command.stderr).to be_empty
end
it "installs inline gems when BUNDLE_GEMFILE is set to an empty string" do
ENV["BUNDLE_GEMFILE"] = ""
- in_app_root do
- script <<-RUBY
- gemfile do
- source "file://#{gem_repo1}"
- gem "rack"
- end
+ script <<-RUBY
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
- puts RACK
- RUBY
- end
+ puts MYRACK
+ RUBY
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs inline gems when BUNDLE_BIN is set" do
@@ -254,13 +475,277 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile do
- source "file://#{gem_repo1}"
- gem "rack" # has the rackup executable
+ source "https://gem.repo1"
+ gem "myrack" # has the myrackup executable
end
- puts RACK
+ puts MYRACK
RUBY
expect(last_command).to be_success
- expect(last_command.stdout).to eq "1.0.0"
+ expect(out).to eq "1.0.0"
+ end
+
+ context "when BUNDLE_PATH is set" do
+ it "installs inline gems to the system path regardless" do
+ script <<-RUBY, env: { "BUNDLE_PATH" => "./vendor/inline", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile(true) do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+ RUBY
+ expect(last_command).to be_success
+ expect(system_gem_path("gems/myrack-1.0.0")).to exist
+ end
+ end
+
+ it "skips platform warnings" do
+ bundle_config "force_ruby_platform true"
+
+ script <<-RUBY
+ gemfile(true) do
+ source "https://gem.repo1"
+ gem "myrack", platform: :jruby
+ end
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "still installs if the application has `bundle package` no_install config set" do
+ bundle_config "no_install true"
+
+ script <<-RUBY
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+ RUBY
+
+ expect(last_command).to be_success
+ expect(system_gem_path("gems/myrack-1.0.0")).to exist
+ end
+
+ it "preserves previous BUNDLE_GEMFILE value" do
+ ENV["BUNDLE_GEMFILE"] = ""
+ script <<-RUBY
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ puts "BUNDLE_GEMFILE is empty" if ENV["BUNDLE_GEMFILE"].empty?
+ system("#{Gem.ruby} -w -e '42'") # this should see original value of BUNDLE_GEMFILE
+ exit $?.exitstatus
+ RUBY
+
+ expect(last_command).to be_success
+ expect(out).to include("BUNDLE_GEMFILE is empty")
+ end
+
+ it "resets BUNDLE_GEMFILE to the empty string if it wasn't set previously" do
+ ENV["BUNDLE_GEMFILE"] = nil
+ script <<-RUBY
+ gemfile do
+ source "https://gem.repo1"
+ gem "myrack"
+ end
+
+ puts "BUNDLE_GEMFILE is empty" if ENV["BUNDLE_GEMFILE"].empty?
+ system("#{Gem.ruby} -w -e '42'") # this should see original value of BUNDLE_GEMFILE
+ exit $?.exitstatus
+ RUBY
+
+ expect(last_command).to be_success
+ expect(out).to include("BUNDLE_GEMFILE is empty")
+ end
+
+ it "does not error out if library requires optional dependencies" do
+ Dir.mkdir tmp("path_without_gemfile")
+
+ foo_code = <<~RUBY
+ begin
+ gem "bar"
+ rescue LoadError
+ end
+
+ puts "WIN"
+ RUBY
+
+ build_lib "foo", "1.0.0" do |s|
+ s.write "lib/foo.rb", foo_code
+ end
+
+ script <<-RUBY, dir: tmp("path_without_gemfile"), env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ gemfile do
+ source "https://gem.repo2"
+ path "#{lib_path}" do
+ gem "foo", require: false
+ end
+ end
+
+ require "foo"
+ RUBY
+
+ expect(out).to eq("WIN")
+ expect(err).to be_empty
+ end
+
+ it "does not load default timeout", rubygems: ">= 3.5.0" do
+ default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false
+ skip "timeout isn't a default gem" if default_timeout_version.empty?
+
+ build_repo4 do
+ build_gem "timeout", "999"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "https://gem.repo4"
+
+ gem "timeout"
+ end
+ RUBY
+
+ expect(out).to include("Installing timeout 999")
+ end
+
+ it "does not upcase ENV" do
+ script <<-RUBY
+ require 'bundler/inline'
+
+ ENV['Test_Variable'] = 'value string'
+ puts("before: \#{ENV.each_key.select { |key| key.match?(/test_variable/i) }}")
+
+ gemfile do
+ source "https://gem.repo1"
+ end
+
+ puts("after: \#{ENV.each_key.select { |key| key.match?(/test_variable/i) }}")
+ RUBY
+
+ expect(out).to include("before: [\"Test_Variable\"]")
+ expect(out).to include("after: [\"Test_Variable\"]")
+ end
+
+ it "does not create a lockfile" do
+ script <<-RUBY
+ require 'bundler/inline'
+
+ gemfile do
+ source "https://gem.repo1"
+ end
+
+ puts Dir.glob("Gemfile.lock")
+ RUBY
+
+ expect(out).to be_empty
+ end
+
+ it "does not reset ENV" do
+ script <<-RUBY
+ require 'bundler/inline'
+
+ gemfile do
+ source "https://gem.repo1"
+
+ ENV['FOO'] = 'bar'
+ end
+
+ puts ENV['FOO']
+ RUBY
+
+ expect(out).to eq("bar")
+ end
+
+ it "does not load specified version of psych and stringio", :ruby_repo do
+ build_repo4 do
+ build_gem "psych", "999"
+ build_gem "stringio", "999"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "https://gem.repo4"
+
+ gem "psych"
+ gem "stringio"
+ end
+ RUBY
+
+ expect(out).to include("Installing psych 999")
+ expect(out).to include("Installing stringio 999")
+ if Gem.respond_to?(:use_psych?) && Gem.use_psych?
+ expect(out).to include("The psych gem was resolved to 999")
+ expect(out).to include("The stringio gem was resolved to 999")
+ end
+ end
+
+ it "installs a conflicting default gem and non-default gems together" do
+ build_repo4 do
+ build_gem "securerandom", "999"
+ build_gem "myrack", "1.0.0"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ gemfile(true) do
+ source "https://gem.repo4"
+ gem "securerandom"
+ gem "myrack"
+ end
+
+ puts MYRACK
+ RUBY
+
+ expect(out).to include("Installing securerandom 999")
+ expect(out).to include("Installing myrack 1.0.0")
+ expect(out).to include("1.0.0")
+ expect(err).to be_empty
+ end
+
+ it "installs a conflicting default gem alongside git sources" do
+ build_repo4 do
+ build_gem "securerandom", "999"
+ end
+
+ build_git "foo", "1.0.0"
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ gemfile(true) do
+ source "https://gem.repo4"
+ gem "securerandom"
+ gem "foo", :git => #{lib_path("foo-1.0.0").to_s.dump}
+ end
+
+ puts FOO
+ RUBY
+
+ expect(out).to include("Installing securerandom 999")
+ expect(out).to include("1.0.0")
+ expect(err).to be_empty
+ end
+
+ it "leaves a lockfile in the same directory as the inline script alone" do
+ install_gemfile <<~G
+ source "https://gem.repo1"
+ gem "foo"
+ G
+
+ original_lockfile = lockfile
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "https://gem.repo1"
+
+ gem "myrack"
+ end
+ RUBY
+
+ expect(lockfile).to eq(original_lockfile)
end
end
diff --git a/spec/bundler/runtime/load_spec.rb b/spec/bundler/runtime/load_spec.rb
index b74dbde3f6..472cde87c5 100644
--- a/spec/bundler/runtime/load_spec.rb
+++ b/spec/bundler/runtime/load_spec.rb
@@ -3,18 +3,19 @@
RSpec.describe "Bundler.load" do
describe "with a gemfile" do
before(:each) do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
- expect(Bundler.load.dependencies).to have_dep("rack", ">= 0")
+ expect(Bundler.load.dependencies).to have_dep("myrack", ">= 0")
end
it "provides a list of the resolved gems" do
- expect(Bundler.load.gems).to have_gem("rack-1.0.0", "bundler-#{Bundler::VERSION}")
+ expect(Bundler.load.gems).to have_gem("myrack-1.0.0", "bundler-#{Bundler::VERSION}")
end
it "ignores blank BUNDLE_GEMFILEs" do
@@ -27,19 +28,20 @@ RSpec.describe "Bundler.load" do
describe "with a gems.rb file" do
before(:each) do
- create_file "gems.rb", <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ gemfile "gems.rb", <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle! :install
+ bundle :install
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
- expect(Bundler.load.dependencies).to have_dep("rack", ">= 0")
+ expect(Bundler.load.dependencies).to have_dep("myrack", ">= 0")
end
it "provides a list of the resolved gems" do
- expect(Bundler.load.gems).to have_gem("rack-1.0.0", "bundler-#{Bundler::VERSION}")
+ expect(Bundler.load.gems).to have_gem("myrack-1.0.0", "bundler-#{Bundler::VERSION}")
end
end
@@ -58,7 +60,7 @@ RSpec.describe "Bundler.load" do
end
it "does not find a Gemfile above the testing directory" do
- bundler_gemfile = tmp.join("../Gemfile")
+ bundler_gemfile = Pathname.new(__dir__).join("../../Gemfile")
unless File.exist?(bundler_gemfile)
FileUtils.touch(bundler_gemfile)
@remove_bundler_gemfile = true
@@ -66,24 +68,24 @@ RSpec.describe "Bundler.load" do
begin
expect { Bundler.load }.to raise_error(Bundler::GemfileNotFound)
ensure
- bundler_gemfile.rmtree if @remove_bundler_gemfile
+ FileUtils.rm_rf bundler_gemfile if @remove_bundler_gemfile
end
end
end
describe "when called twice" do
it "doesn't try to load the runtime twice" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
gem "activesupport", :group => :test
G
- ruby! <<-RUBY
+ ruby <<-RUBY
require "bundler"
Bundler.setup :default
Bundler.require :default
- puts RACK
+ puts MYRACK
begin
require "activesupport"
rescue LoadError
@@ -97,11 +99,11 @@ RSpec.describe "Bundler.load" do
describe "not hurting brittle rubygems" do
it "does not inject #source into the generated YAML of the gem specs" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "activerecord"
G
-
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
Bundler.load.specs.each do |spec|
expect(spec.to_yaml).not_to match(/^\s+source:/)
expect(spec.to_yaml).not_to match(/^\s+groups:/)
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index eecf162427..6d96758956 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -3,27 +3,27 @@
RSpec.describe "Bundler.setup with multi platform stuff" do
it "raises a friendly error when gems are missing locally" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{local_tag}
DEPENDENCIES
- rack
+ myrack
G
ruby <<-R
begin
require 'bundler'
- Bundler.setup
+ Bundler.ui.silence { Bundler.setup }
rescue Bundler::GemNotFound => e
puts "WIN"
end
@@ -35,7 +35,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
it "will resolve correctly on the current platform when the lockfile was targeted for a different one" do
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
nokogiri (1.4.2-java)
weakling (= 0.0.3)
@@ -48,19 +48,147 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
G
- simulate_platform "x86-darwin-10"
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ simulate_platform "x86-darwin-10" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri"
+ G
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2"
+ end
+ end
+
+ it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "mini_portile2", "~> 2.5.0"
+ s.add_dependency "racca", "~> 1.5.2"
+ end
+
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ s.add_dependency "racca", "~> 1.4"
+ end
+
+ build_gem "mini_portile2", "2.5.0"
+ build_gem "racca", "1.5.2"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "mini_portile2", "2.5.0"
+ c.checksum gem_repo4, "nokogiri", "1.11.1"
+ c.checksum gem_repo4, "nokogiri", "1.11.1", Bundler.local_platform
+ c.checksum gem_repo4, "racca", "1.5.2"
+ end
+
+ good_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mini_portile2 (2.5.0)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racca (~> 1.5.2)
+ nokogiri (1.11.1-#{Bundler.local_platform})
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ nokogiri (~> 1.11)
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "nokogiri", "~> 1.11"
+ G
+
+ lockfile good_lockfile
+
+ bundle "update nokogiri"
+
+ expect(lockfile).to eq(good_lockfile)
+ end
+
+ it "will not try to install platform specific gems when they don't match the current ruby if locked only to ruby" do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1"
+
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.11.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(out).to include("Fetching nokogiri 1.11.1")
+ expect(the_bundle).to include_gems "nokogiri 1.11.1"
+ expect(the_bundle).not_to include_gems "nokogiri 1.11.1 #{Bundler.local_platform}"
+ end
+
+ it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby_only do
+ gemfile <<-G
+ source "https://gem.repo1"
gem "nokogiri"
G
- expect(the_bundle).to include_gems "nokogiri 1.4.2"
+ lockfile <<-G
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ nokogiri (1.4.2)
+ nokogiri (1.4.2-java)
+ weakling (>= 0.0.3)
+ weakling (0.0.3)
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ bundle "install"
+
+ expect(out).to include("Fetching nokogiri 1.4.2 (java)")
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 java"
end
it "will add the resolve for the current platform" do
lockfile <<-G
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
nokogiri (1.4.2-java)
weakling (= 0.0.3)
@@ -73,46 +201,207 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
G
- simulate_platform "x86-darwin-100"
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
+ end
+ end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ it "allows specifying only-ruby-platform on jruby", :jruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "nokogiri"
gem "platform_specific"
G
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
+ bundle_config "force_ruby_platform true"
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 ruby"
end
it "allows specifying only-ruby-platform" do
- simulate_platform "java"
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
+
+ bundle_config "force_ruby_platform true"
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 ruby"
+ end
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ it "allows specifying only-ruby-platform even if the lockfile is locked to a specific compatible platform" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "nokogiri"
gem "platform_specific"
G
- bundle! "config force_ruby_platform true"
+ bundle_config "force_ruby_platform true"
- bundle! "install"
+ bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 ruby"
+ end
+
+ it "doesn't pull platform specific gems on truffleruby", :truffleruby_only do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
+
+ it "doesn't pull platform specific gems on truffleruby (except when whitelisted) even if lockfile was generated with an older version that declared ruby as platform", :truffleruby_only do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "libv8"
+
+ build_gem "libv8" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "libv8"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "libv8 1.0 x86_64-linux"
+ end
+ end
+
+ it "doesn't pull platform specific gems on truffleruby, even if lockfile only includes those", :truffleruby_only do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ platform_specific (1.0-x86-darwin-100)
+
+ PLATFORMS
+ x86-darwin-100
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
+
+ it "pulls platform specific gems correctly on musl" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = "aarch64-linux"
+ end
+ end
+
+ simulate_platform "aarch64-linux-musl" do
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo4"
+ gem "nokogiri"
+ G
+ end
+
+ expect(out).to include("Fetching nokogiri 1.13.8 (aarch64-linux)")
end
it "allows specifying only-ruby-platform on windows with dependency platforms" do
- simulate_windows do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "nokogiri", :platforms => [:mingw, :mswin, :x64_mingw, :jruby]
+ simulate_platform "x86-mswin32" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri", :platforms => [:windows, :jruby]
gem "platform_specific"
G
- bundle! "config force_ruby_platform true"
+ bundle_config "force_ruby_platform true"
- bundle! "install"
+ bundle "install"
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ expect(the_bundle).to not_include_gems "nokogiri"
+ end
+ end
+
+ it "allows specifying only-ruby-platform on windows with gemspec dependency" do
+ build_lib("foo", "1.0", path: bundled_app) do |s|
+ s.add_dependency "myrack"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gemspec
+ G
+ bundle :lock
+
+ simulate_platform "x86-mswin32" do
+ bundle_config "force_ruby_platform true"
+ bundle "install"
+
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -122,29 +411,58 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
s.add_dependency "platform_specific"
end
end
- simulate_windows x64_mingw do
+ simulate_platform "x64-mingw-ucrt" do
lockfile <<-L
GEM
- remote: file:#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0-x86-mingw32)
requires_platform_specific (1.0)
platform_specific
PLATFORMS
- x64-mingw32
+ x64-mingw-ucrt
x86-mingw32
DEPENDENCIES
requires_platform_specific
L
- install_gemfile! <<-G, :verbose => true
- source "file://#{gem_repo2}"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo2"
gem "requires_platform_specific"
G
- expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw32"
+ expect(out).to include("lockfile does not have all gems needed for the current platform")
+ expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw-ucrt"
+ end
+ end
+
+ %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw-ucrt aarch64-mingw-ucrt].each do |platform|
+ it "allows specifying platform windows on #{platform} platform" do
+ simulate_platform platform do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ platform_specific (1.0-#{platform})
+ requires_platform_specific (1.0)
+ platform_specific
+
+ PLATFORMS
+ #{platform}
+
+ DEPENDENCIES
+ requires_platform_specific
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific", :platforms => [:windows]
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{platform}"
+ end
end
end
end
diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb
index 0484e38845..46613286d2 100644
--- a/spec/bundler/runtime/require_spec.rb
+++ b/spec/bundler/runtime/require_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "Bundler.require" do
s.write "lib/four.rb", "puts 'four'"
end
- build_lib "five", "1.0.0", :no_default => true do |s|
+ build_lib "five", "1.0.0", no_default: true do |s|
s.write "lib/mofive.rb", "puts 'five'"
end
@@ -46,6 +46,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "one", :group => :bar, :require => %w[baz qux]
gem "two"
@@ -112,16 +113,15 @@ RSpec.describe "Bundler.require" do
it "raises an exception if a require is specified but the file does not exist" do
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two", :require => 'fail'
end
G
- load_error_run <<-R, "fail"
- Bundler.require
- R
+ run "Bundler.require", raise_on_error: false
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to include("cannot load such file -- fail")
end
it "displays a helpful message if the required gem throws an error" do
@@ -130,12 +130,13 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "faulty"
end
G
- run "Bundler.require"
+ run "Bundler.require", raise_on_error: false
expect(err).to match("error while trying to load the gem 'faulty'")
expect(err).to match("Gem Internal Error Message")
end
@@ -146,21 +147,15 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "loadfuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR: \#{e.message}"
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err).to eq_err("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err_without_deprecations).to include("cannot load such file -- load-bar")
end
describe "with namespaced gems" do
@@ -168,11 +163,11 @@ RSpec.describe "Bundler.require" do
build_lib "jquery-rails", "1.0.0" do |s|
s.write "lib/jquery/rails.rb", "puts 'jquery/rails'"
end
- lib_path("jquery-rails-1.0.0/lib/jquery-rails.rb").rmtree
end
it "requires gem names that are namespaced" do
gemfile <<-G
+ source "https://gem.repo1"
path '#{lib_path}' do
gem 'jquery-rails'
end
@@ -183,10 +178,12 @@ RSpec.describe "Bundler.require" do
end
it "silently passes if the require fails" do
- build_lib "bcrypt-ruby", "1.0.0", :no_default => true do |s|
+ build_lib "bcrypt-ruby", "1.0.0", no_default: true do |s|
s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'"
end
gemfile <<-G
+ source "https://gem.repo1"
+
path "#{lib_path}" do
gem "bcrypt-ruby"
end
@@ -198,20 +195,20 @@ RSpec.describe "Bundler.require" do
RUBY
ruby(cmd)
- expect(err).to lack_errors
+ expect(err).to be_empty
end
it "does not mangle explicitly given requires" do
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem 'jquery-rails', :require => 'jquery-rails'
end
G
- load_error_run <<-R, "jquery-rails"
- Bundler.require
- R
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ run "Bundler.require", raise_on_error: false
+
+ expect(err_without_deprecations).to include("cannot load such file -- jquery-rails")
end
it "handles the case where regex fails" do
@@ -220,57 +217,44 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "load-fuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'")
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to include("libfuuu-1.0").and include("cannot open shared object file")
end
it "doesn't swallow the error when the library has an unrelated error" do
build_lib "load-fuuu", "1.0.0" do |s|
s.write "lib/load/fuuu.rb", "raise LoadError.new(\"cannot load such file -- load-bar\")"
end
- lib_path("load-fuuu-1.0.0/lib/load-fuuu.rb").rmtree
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "load-fuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR: \#{e.message}"
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err).to eq_err("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err_without_deprecations).to include("cannot load such file -- load-bar")
end
end
describe "using bundle exec" do
it "requires the locked gems" do
- bundle "exec ruby -e 'Bundler.require'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle "exec ruby -e 'Bundler.require'"
expect(out).to eq("two")
- bundle "exec ruby -e 'Bundler.require(:bar)'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle "exec ruby -e 'Bundler.require(:bar)'"
expect(out).to eq("baz\nqux")
- bundle "exec ruby -e 'Bundler.require(:default, :bar)'", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle "exec ruby -e 'Bundler.require(:default, :bar)'"
expect(out).to eq("baz\nqux\ntwo")
end
end
@@ -302,6 +286,7 @@ RSpec.describe "Bundler.require" do
it "works when the gems are in the Gemfile in the correct order" do
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
gem "one"
@@ -314,12 +299,13 @@ RSpec.describe "Bundler.require" do
describe "a gem with different requires for different envs" do
before(:each) do
- build_gem "multi_gem", :to_bundle => true do |s|
+ build_gem "multi_gem", to_bundle: true do |s|
s.write "lib/one.rb", "puts 'ONE'"
s.write "lib/two.rb", "puts 'TWO'"
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "multi_gem", :require => "one", :group => :one
gem "multi_gem", :require => "two", :group => :two
G
@@ -343,6 +329,7 @@ RSpec.describe "Bundler.require" do
it "fails when the gems are in the Gemfile in the wrong order" do
gemfile <<-G
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "one"
gem "two"
@@ -355,30 +342,30 @@ RSpec.describe "Bundler.require" do
describe "with busted gems" do
it "should be busted" do
- build_gem "busted_require", :to_bundle => true do |s|
+ build_gem "busted_require", to_bundle: true do |s|
s.write "lib/busted_require.rb", "require 'no_such_file_omg'"
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "busted_require"
G
- load_error_run <<-R, "no_such_file_omg"
- Bundler.require
- R
- expect(err).to eq_err("ZOMG LOAD ERROR")
+ run "Bundler.require", raise_on_error: false
+
+ expect(err_without_deprecations).to include("cannot load such file -- no_such_file_omg")
end
end
end
- it "does not load rubygems gemspecs that are used", :rubygems => ">= 2.5.2" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ it "does not load rubygems gemspecs that are used" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- run! <<-R
- path = File.join(Gem.dir, "specifications", "rack-1.0.0.gemspec")
+ run <<-R
+ path = File.join(Gem.dir, "specifications", "myrack-1.0.0.gemspec")
contents = File.read(path)
contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join
File.open(path, "w") do |f|
@@ -386,7 +373,7 @@ RSpec.describe "Bundler.require" do
end
R
- run! <<-R
+ run <<-R
Bundler.require
puts "WIN"
R
@@ -394,14 +381,15 @@ RSpec.describe "Bundler.require" do
expect(out).to eq("WIN")
end
- it "does not load git gemspecs that are used", :rubygems => ">= 2.5.2" do
+ it "does not load git gemspecs that are used" do
build_git "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
path = Gem.loaded_specs["foo"].loaded_from
contents = File.read(path)
contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join
@@ -410,7 +398,47 @@ RSpec.describe "Bundler.require" do
end
R
- run! <<-R
+ run <<-R
+ Bundler.require
+ puts "WIN"
+ R
+
+ expect(out).to eq("WIN")
+ end
+
+ it "does not load plugins" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ create_file "plugins/rubygems_plugin.rb", "puts 'FAIL'"
+
+ run <<~R, env: { "RUBYLIB" => rubylib.unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) }
+ Bundler.require
+ puts "WIN"
+ R
+
+ expect(out).to eq("WIN")
+ end
+
+ it "does not extract gemspecs from application cache packages" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle :cache
+
+ path = cached_gem("myrack-1.0.0")
+
+ run <<-R
+ File.open("#{path}", "w") do |f|
+ f.write "broken package"
+ end
+ R
+
+ run <<-R
Bundler.require
puts "WIN"
R
@@ -422,31 +450,31 @@ end
RSpec.describe "Bundler.require with platform specific dependencies" do
it "does not require the gems that are pinned to other platforms" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
platforms :#{not_local_tag} do
- gem "fail", :require => "omgomg"
+ gem "platform_specific", :require => "omgomg"
end
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
run "Bundler.require"
- expect(err).to lack_errors
+ expect(err).to be_empty
end
it "requires gems pinned to multiple platforms, including the current one" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
platforms :#{not_local_tag}, :#{local_tag} do
- gem "rack", :require => "rack"
+ gem "myrack", :require => "myrack"
end
G
- run "Bundler.require; puts RACK"
+ run "Bundler.require; puts MYRACK"
expect(out).to eq("1.0.0")
- expect(err).to lack_errors
+ expect(err).to be_empty
end
end
diff --git a/spec/bundler/runtime/requiring_spec.rb b/spec/bundler/runtime/requiring_spec.rb
new file mode 100644
index 0000000000..f0e0aeacaf
--- /dev/null
+++ b/spec/bundler/runtime/requiring_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+RSpec.describe "Requiring bundler" do
+ it "takes care of requiring rubygems when entrypoint is bundler/setup" do
+ sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", env: { "RUBYOPT" => "--disable=gems" })
+
+ expect(stdboth).to eq("true")
+ end
+
+ it "takes care of requiring rubygems when requiring just bundler" do
+ sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler -e'puts true'", env: { "RUBYOPT" => "--disable=gems" })
+
+ expect(stdboth).to eq("true")
+ end
+end
diff --git a/spec/bundler/runtime/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb
new file mode 100644
index 0000000000..176c2a3121
--- /dev/null
+++ b/spec/bundler/runtime/self_management_spec.rb
@@ -0,0 +1,279 @@
+# frozen_string_literal: true
+
+RSpec.describe "Self management" do
+ describe "auto switching" do
+ let(:previous_minor) do
+ "9.3.0"
+ end
+
+ let(:current_version) do
+ "9.4.0"
+ end
+
+ before do
+ build_repo4 do
+ build_bundler previous_minor
+
+ build_bundler current_version
+
+ build_gem "myrack", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "myrack"
+ G
+
+ pristine_system_gems "bundler-#{current_version}"
+ end
+
+ it "installs locked version when using system path and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle_config "path.system true"
+ bundle "install"
+ expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+
+ # It uninstalls the older system bundler
+ bundle "clean --force", artifice: nil
+ expect(out).to eq("Removing bundler (#{current_version})")
+
+ # App now uses locked version
+ bundle "-v", artifice: nil
+ expect(out).to eq(previous_minor)
+
+ # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff
+ unless ruby_core?
+ # App now uses locked version, even when not using the CLI directly
+ file = bundled_app("bin/bundle_version.rb")
+ create_file file, <<-RUBY
+ #!#{Gem.ruby}
+ require 'bundler/setup'
+ puts '#{previous_minor}'
+ RUBY
+ file.chmod(0o777)
+ cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb"
+ in_bundled_app cmd
+ expect(out).to eq(previous_minor)
+ end
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose", artifice: nil
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "installs locked version when using local path and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle_config "path vendor/bundle"
+ bundle "install"
+ expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist
+
+ # It does not uninstall the locked bundler
+ bundle "clean"
+ expect(out).to be_empty
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to eq(previous_minor)
+
+ # Preserves original gem home when auto-switching
+ bundle "exec ruby -e 'puts Bundler.original_env[\"GEM_HOME\"]'"
+ expect(out).to eq(ENV["GEM_HOME"])
+
+ # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff
+ unless ruby_core?
+ # App now uses locked version, even when not using the CLI directly
+ file = bundled_app("bin/bundle_version.rb")
+ create_file file, <<-RUBY
+ #!#{Gem.ruby}
+ require 'bundler/setup'
+ puts '#{previous_minor}'
+ RUBY
+ file.chmod(0o777)
+ cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb"
+ in_bundled_app cmd
+ expect(out).to eq(previous_minor)
+ end
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "installs locked version when using deployment option and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle_config "deployment true"
+ bundle "install"
+ expect(out).to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist
+
+ # It does not uninstall the locked bundler
+ bundle "clean"
+ expect(out).to be_empty
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to eq(previous_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{current_version} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "does not try to install a development version" do
+ lockfile_bundled_with("#{previous_minor}.dev")
+
+ bundle "install --verbose"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
+ end
+
+ it "does not try to install when --local is passed" do
+ lockfile_bundled_with(previous_minor)
+ system_gems "myrack-1.0.0", path: local_gem_path
+
+ bundle "install --local"
+ expect(out).not_to match(/Installing Bundler/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
+ end
+
+ it "shows a discrete message if locked bundler does not exist" do
+ missing_minor = "#{current_version[0]}.999.999"
+
+ lockfile_bundled_with(missing_minor)
+
+ bundle "install"
+ expect(err).to eq("Your lockfile is locked to a version of bundler (#{missing_minor}) that doesn't exist at https://rubygems.org/. Going on using #{current_version}")
+
+ bundle "-v"
+ expect(out).to eq(current_version)
+ end
+
+ it "installs BUNDLE_VERSION version when using bundle config version x.y.z" do
+ lockfile_bundled_with(current_version)
+
+ bundle_config "version #{previous_minor}"
+ bundle "install"
+ expect(out).to include("Bundler #{current_version} is running, but your configuration was #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+
+ bundle "-v"
+ expect(out).to eq(previous_minor)
+ end
+
+ it "requires the right bundler version from the config and run bundle CLI without re-exec" do
+ unless Bundler.rubygems.provides?(">= 4.1.0.dev")
+ skip "This spec can only run when Gem::BundlerVersionFinder.bundler_versions reads bundler configs"
+ end
+
+ lockfile_bundled_with(current_version)
+
+ bundle_config "version #{previous_minor}"
+ bundle_config "path.system true"
+ bundle "install"
+
+ script = bundled_app("script.rb")
+ create_file(script, "p 'executed once'")
+
+ bundle "-v", env: { "RUBYOPT" => "-r#{script}" }
+ expect(out).to eq(%("executed once"\n9.3.0))
+ end
+
+ it "does not try to install when using bundle config version global" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle_config "version system"
+ bundle "install"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
+ end
+
+ it "does not try to install when using bundle config version <dev-version>" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle_config "version #{previous_minor}.dev"
+ bundle "install"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
+ end
+
+ it "ignores malformed lockfile version" do
+ lockfile_bundled_with("2.3.")
+
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{current_version}")
+ end
+
+ it "uses the right original script when re-execing, if `$0` has been changed to something that's not a script", :ruby_repo do
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ test = bundled_app("test.rb")
+
+ create_file test, <<~RUBY
+ $0 = "this is the program name"
+ require "bundler/setup"
+ RUBY
+
+ lockfile_bundled_with("9.9.9")
+
+ in_bundled_app "#{Gem.ruby} #{test}", raise_on_error: false
+ expect(err).to include("Could not find myrack-1.0.0")
+ expect(err).not_to include("this is the program name")
+ end
+
+ it "uses modified $0 when re-execing, if `$0` has been changed to a script", :ruby_repo do
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ runner = bundled_app("runner.rb")
+
+ create_file runner, <<~RUBY
+ $0 = ARGV.shift
+ load $0
+ RUBY
+
+ script = bundled_app("script.rb")
+ create_file script, <<~RUBY
+ require "bundler/setup"
+ RUBY
+
+ lockfile_bundled_with("9.9.9")
+
+ in_bundled_app "#{Gem.ruby} #{runner} #{script}", raise_on_error: false
+ expect(err).to include("Could not find myrack-1.0.0")
+ end
+
+ private
+
+ def lockfile_bundled_with(version)
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{version}
+ L
+ end
+ end
+end
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index 15dd1fe190..ceb6fcf66a 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -1,22 +1,23 @@
# frozen_string_literal: true
+require "tmpdir"
+
RSpec.describe "Bundler.setup" do
describe "with no arguments" do
it "makes all groups available" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :group => :test
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
G
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to eq("1.0.0")
end
end
@@ -24,58 +25,54 @@ RSpec.describe "Bundler.setup" do
describe "when called with groups" do
before(:each) do
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack", :group => :test
+ gem "myrack", :group => :test
G
end
it "doesn't make all groups available" do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup(:default)
begin
- require 'rack'
+ require 'myrack'
rescue LoadError
puts "WIN"
end
RUBY
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to eq("WIN")
end
it "accepts string for group name" do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup(:default, 'test')
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to eq("1.0.0")
end
it "leaves all groups available if they were already" do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup
Bundler.setup(:default)
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to eq("1.0.0")
end
it "leaves :default available if setup is called twice" do
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup(:default)
Bundler.setup(:default, :test)
@@ -87,21 +84,21 @@ RSpec.describe "Bundler.setup" do
puts "FAIL"
end
RUBY
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to match("WIN")
end
it "handles multiple non-additive invocations" do
- ruby <<-RUBY
+ ruby <<-RUBY, raise_on_error: false
require 'bundler'
Bundler.setup(:default, :test)
Bundler.setup(:default)
- require 'rack'
+ require 'myrack'
puts "FAIL"
RUBY
- expect(err).to match("rack")
+ expect(err).to match("myrack")
expect(err).to match("LoadError")
expect(out).not_to match("FAIL")
end
@@ -109,60 +106,51 @@ RSpec.describe "Bundler.setup" do
context "load order" do
def clean_load_path(lp)
- without_bundler_load_path = ruby!("puts $LOAD_PATH").split("\n")
- lp = lp - [
- bundler_path.to_s,
- bundler_path.join("gems/bundler-#{Bundler::VERSION}/lib").to_s,
- tmp("rubygems/lib").to_s,
- root.join("../lib").expand_path.to_s,
- ] - without_bundler_load_path
- lp.map! {|p| p.sub(/^#{Regexp.union system_gem_path.to_s, default_bundle_path.to_s}/i, "") }
+ without_bundler_load_path = ruby("puts $LOAD_PATH").split("\n")
+ lp -= [*without_bundler_load_path, lib_dir.to_s]
+ lp.map! {|p| p.sub(system_gem_path.to_s, "") }
end
it "puts loaded gems after -I and RUBYLIB", :ruby_repo do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- ENV["RUBYOPT"] = "-Idash_i_dir"
+ ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -Idash_i_dir"
ENV["RUBYLIB"] = "rubylib_dir"
ruby <<-RUBY
- require 'rubygems'
require 'bundler'
Bundler.setup
puts $LOAD_PATH
RUBY
load_path = out.split("\n")
- rack_load_order = load_path.index {|path| path.include?("rack") }
+ myrack_load_order = load_path.index {|path| path.include?("myrack") }
- expect(err).to eq("")
- expect(load_path[1]).to include "dash_i_dir"
- expect(load_path[2]).to include "rubylib_dir"
- expect(rack_load_order).to be > 0
+ expect(err).to be_empty
+ expect(load_path).to include(a_string_ending_with("dash_i_dir"), "rubylib_dir")
+ expect(myrack_load_order).to be > 0
end
it "orders the load path correctly when there are dependencies" do
+ bundle_config "path.system true"
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "rails"
G
- ruby! <<-RUBY
- require 'rubygems'
+ ruby <<-RUBY
require 'bundler'
+ gem "bundler", "#{Bundler::VERSION}" if #{ruby_core?}
Bundler.setup
puts $LOAD_PATH
RUBY
load_path = clean_load_path(out.split("\n"))
- unless Bundler.load.specs["bundler"].empty?
- load_path.delete_if {|path| path =~ /bundler/ }
- end
-
expect(load_path).to start_with(
"/gems/rails-2.3.2/lib",
"/gems/activeresource-2.3.2/lib",
@@ -170,20 +158,21 @@ RSpec.describe "Bundler.setup" do
"/gems/actionpack-2.3.2/lib",
"/gems/actionmailer-2.3.2/lib",
"/gems/activesupport-2.3.2/lib",
- "/gems/rake-10.0.2/lib"
+ "/gems/rake-#{rake_version}/lib"
)
end
it "falls back to order the load path alphabetically for backwards compatibility" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
+ bundle_config "path.system true"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "weakling"
gem "duradura"
gem "terranova"
G
- ruby! <<-RUBY
- require 'rubygems'
+ ruby <<-RUBY
require 'bundler/setup'
puts $LOAD_PATH
RUBY
@@ -200,12 +189,11 @@ RSpec.describe "Bundler.setup" do
it "raises if the Gemfile was not yet installed" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ruby <<-R
- require 'rubygems'
require 'bundler'
begin
@@ -221,68 +209,66 @@ RSpec.describe "Bundler.setup" do
it "doesn't create a Gemfile.lock if the setup fails" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- ruby <<-R
- require 'rubygems'
+ ruby <<-R, raise_on_error: false
require 'bundler'
Bundler.setup
R
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
end
it "doesn't change the Gemfile.lock if the setup fails" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- lockfile = File.read(bundled_app("Gemfile.lock"))
+ lockfile = File.read(bundled_app_lock)
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "nosuchgem", "10.0"
G
- ruby <<-R
- require 'rubygems'
+ ruby <<-R, raise_on_error: false
require 'bundler'
Bundler.setup
R
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
+ expect(File.read(bundled_app_lock)).to eq(lockfile)
end
it "makes a Gemfile.lock if setup succeeds" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- File.read(bundled_app("Gemfile.lock"))
+ File.read(bundled_app_lock)
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
run "1"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
describe "$BUNDLE_GEMFILE" do
context "user provides an absolute path" do
it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile bundled_app("4realz"), <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
@@ -294,17 +280,16 @@ RSpec.describe "Bundler.setup" do
end
context "an absolute path is not provided" do
- it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
+ it "uses BUNDLE_GEMFILE to locate the gemfile if present and doesn't fail in deployment mode" do
gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
bundle "install"
- bundle "install --deployment"
+ bundle_config "deployment true"
ENV["BUNDLE_GEMFILE"] = "Gemfile"
ruby <<-R
- require 'rubygems'
require 'bundler'
begin
@@ -318,28 +303,54 @@ RSpec.describe "Bundler.setup" do
expect(out).to eq("WIN")
end
end
+
+ context "user sets it via `config set --local gemfile`" do
+ it "uses the value in the config" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ gemfile bundled_app("CustomGemfile"), <<-G
+ source "https://gem.repo1"
+ gem "activesupport", "2.3.5"
+ G
+
+ bundle_config "gemfile #{bundled_app("CustomGemfile")}"
+ bundle "install"
+
+ ruby <<-R
+ require 'bundler'
+ Bundler.setup
+ require 'activesupport'
+ puts ACTIVESUPPORT
+ R
+
+ expect(out).to eq("2.3.5")
+ end
+ end
end
it "prioritizes gems in BUNDLE_PATH over gems in GEM_HOME" do
ENV["BUNDLE_PATH"] = bundled_app(".bundle").to_s
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
- build_gem "rack", "1.0", :to_system => true do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
describe "integrate with rubygems" do
describe "by replacing #gem" do
before :each do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
end
@@ -356,23 +367,10 @@ RSpec.describe "Bundler.setup" do
expect(out).to eq("WIN")
end
- it "version_requirement is now deprecated in rubygems 1.4.0+ when gem is missing" do
- run <<-R
- begin
- gem "activesupport"
- puts "FAIL"
- rescue LoadError
- puts "WIN"
- end
- R
-
- expect(err).to lack_errors
- end
-
it "replaces #gem but raises when the version is wrong" do
run <<-R
begin
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
puts "FAIL"
rescue LoadError
puts "WIN"
@@ -381,39 +379,27 @@ RSpec.describe "Bundler.setup" do
expect(out).to eq("WIN")
end
-
- it "version_requirement is now deprecated in rubygems 1.4.0+ when the version is wrong" do
- run <<-R
- begin
- gem "rack", "1.0.0"
- puts "FAIL"
- rescue LoadError
- puts "WIN"
- end
- R
-
- expect(err).to lack_errors
- end
end
describe "by hiding system gems" do
before :each do
system_gems "activesupport-2.3.5"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "yard"
G
end
it "removes system gems from Gem.source_index" do
run "require 'yard'"
- expect(out).to eq("bundler-#{Bundler::VERSION}\nyard-1.0")
+ expect(out).to include("bundler-#{Bundler::VERSION}").and include("yard-1.0")
+ expect(out).not_to include("activesupport-2.3.5")
end
context "when the ruby stdlib is a substring of Gem.path" do
it "does not reject the stdlib from $LOAD_PATH" do
- substring = "/" + $LOAD_PATH.find {|p| p =~ /vendor_ruby/ }.split("/")[2]
- run "puts 'worked!'", :env => { "GEM_PATH" => substring }
+ substring = "/" + $LOAD_PATH.find {|p| p.include?("vendor_ruby") }.split("/")[2]
+ run "puts 'worked!'", env: { "GEM_PATH" => substring }
expect(out).to eq("worked!")
end
end
@@ -422,36 +408,37 @@ RSpec.describe "Bundler.setup" do
describe "with paths" do
it "activates the gems in the path source" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "puts 'WIN'"
+ build_lib "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "puts 'WIN'"
end
gemfile <<-G
- source "file://#{gem_repo1}"
- path "#{lib_path("rack-1.0.0")}" do
- gem "rack"
+ source "https://gem.repo1"
+ path "#{lib_path("myrack-1.0.0")}" do
+ gem "myrack"
end
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN")
end
end
describe "with git" do
before do
- build_git "rack", "1.0.0"
+ build_git "myrack", "1.0.0"
gemfile <<-G
- gem "rack", :git => "#{lib_path("rack-1.0.0")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-1.0.0")}"
G
end
it "provides a useful exception when the git repo is not checked out yet" do
- run "1"
- expect(err).to match(/the git source #{lib_path('rack-1.0.0')} is not yet checked out. Please run `bundle install`/i)
+ run "1", raise_on_error: false
+ expect(err).to match(/the git source #{lib_path("myrack-1.0.0")} is not yet checked out. Please run `bundle install`/i)
end
it "does not hit the git binary if the lockfile is available and up to date" do
@@ -460,7 +447,6 @@ RSpec.describe "Bundler.setup" do
break_git!
ruby <<-R
- require 'rubygems'
require 'bundler'
begin
@@ -477,12 +463,11 @@ RSpec.describe "Bundler.setup" do
it "provides a good exception if the lockfile is unavailable" do
bundle "install"
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
break_git!
ruby <<-R
- require "rubygems"
require "bundler"
begin
@@ -493,122 +478,125 @@ RSpec.describe "Bundler.setup" do
end
R
- run "puts 'FAIL'"
+ run "puts 'FAIL'", raise_on_error: false
expect(err).not_to include "This is not the git you are looking for"
end
it "works even when the cache directory has been deleted" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
- FileUtils.rm_rf vendored_gems("cache")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle :install
+ FileUtils.rm_r default_cache_path
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle_config "path vendor/bundle"
+ bundle :install
- with_read_only("**/*") do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ with_read_only("#{bundled_app}/**/*") do
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
it "finds git gem when default bundle path becomes read only" do
+ bundle_config "path .bundle"
bundle "install"
- with_read_only("#{Bundler.bundle_path}/**/*") do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ with_read_only("#{bundled_app(".bundle")}/**/*") do
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
describe "when specifying local override" do
it "explodes if given path does not exist on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install
- FileUtils.rm_rf(lib_path("local-rack"))
- run "require 'rack'"
- expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
+ FileUtils.rm_r(lib_path("local-myrack"))
+ run "require 'myrack'", raise_on_error: false
+ expect(err).to match(/Cannot use local override for myrack-0.8 because #{Regexp.escape(lib_path("local-myrack").to_s)} does not exist/)
end
it "explodes if branch is not given on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- run "require 'rack'"
+ run "require 'myrack'", raise_on_error: false
expect(err).to match(/because :branch is not specified in Gemfile/)
end
it "explodes on different branches on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle :install
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "changed"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "changed"
G
- run "require 'rack'"
- expect(err).to match(/is using branch master but Gemfile specifies changed/)
+ run "require 'myrack'", raise_on_error: false
+ expect(err).to match(/is using branch main but Gemfile specifies changed/)
end
it "explodes on refs with different branches on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :ref => "main", :branch => "main"
G
gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "nonexistant"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :ref => "main", :branch => "nonexistent"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- run "require 'rack'"
- expect(err).to match(/is using branch master but Gemfile specifies nonexistant/)
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'", raise_on_error: false
+ expect(err).to match(/is using branch main but Gemfile specifies nonexistent/)
end
end
describe "when excluding groups" do
it "doesn't change the resolve if --without is used" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
- source "file://#{gem_repo1}"
+ bundle_config "without rails"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "activesupport"
group :rails do
@@ -616,14 +604,15 @@ RSpec.describe "Bundler.setup" do
end
G
- install_gems "activesupport-2.3.5"
+ system_gems "activesupport-2.3.5"
- expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => :default
+ expect(the_bundle).to include_gems "activesupport 2.3.2", groups: :default
end
it "remembers --without and does not bail on bare Bundler.setup" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
- source "file://#{gem_repo1}"
+ bundle_config "without rails"
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "activesupport"
group :rails do
@@ -631,94 +620,105 @@ RSpec.describe "Bundler.setup" do
end
G
- install_gems "activesupport-2.3.5"
+ system_gems "activesupport-2.3.5"
expect(the_bundle).to include_gems "activesupport 2.3.2"
end
- it "remembers --without and does not include groups passed to Bundler.setup" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
- source "file://#{gem_repo1}"
- gem "activesupport"
+ it "remembers --without and does not bail on bare Bundler.setup, even in the case of path gems no longer available" do
+ bundle_config "without development"
- group :rack do
- gem "rack"
- end
+ path = bundled_app(File.join("vendor", "foo"))
+ build_lib "foo", path: path
- group :rails do
- gem "rails", "2.3.2"
- end
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "activesupport", "2.3.2"
+ gem 'foo', :path => 'vendor/foo', :group => :development
G
- expect(the_bundle).not_to include_gems "activesupport 2.3.2", :groups => :rack
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => :rack
+ FileUtils.rm_r(path)
+
+ ruby "require 'bundler'; Bundler.setup", env: { "DEBUG" => "1" }
+ expect(out).to include("Assuming that source at `vendor/foo` has not changed since fetching its specs errored")
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ expect(err).to be_empty
end
- end
- # Unfortunately, gem_prelude does not record the information about
- # activated gems, so this test cannot work on 1.9 :(
- if RUBY_VERSION < "1.9"
- describe "preactivated gems" do
- it "raises an exception if a pre activated gem conflicts with the bundle" do
- system_gems "thin-1.0", "rack-1.0.0"
- build_gem "thin", "1.1", :to_system => true do |s|
- s.add_dependency "rack"
+ it "doesn't re-resolve when a pre-release bundler is used and a dependency includes a dependency on bundler" do
+ system_gems "bundler-9.99.9.beta1"
+
+ build_repo4 do
+ build_gem "depends_on_bundler", "1.0" do |s|
+ s.add_dependency "bundler", ">= 1.5.0"
end
+ end
- gemfile <<-G
- gem "thin", "1.0"
- G
+ install_gemfile <<~G
+ source "https://gem.repo4"
+ gem "depends_on_bundler"
+ G
- ruby <<-R
- require 'rubygems'
- gem "thin"
- require 'bundler'
- begin
- Bundler.setup
- puts "FAIL"
- rescue Gem::LoadError => e
- puts e.message
- end
- R
+ ruby "require '#{system_gem_path("gems/bundler-9.99.9.beta1/lib/bundler.rb")}'; Bundler.setup", env: { "DEBUG" => "1" }
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ expect(out).not_to include("lockfile does not have all gems needed for the current platform")
+ expect(err).to be_empty
+ end
- expect(out).to eq("You have already activated thin 1.1, but your Gemfile requires thin 1.0. Prepending `bundle exec` to your command may solve this.")
- end
+ it "doesn't fail in frozen mode when bundler is a Gemfile dependency" do
+ install_gemfile <<~G
+ source "https://gem.repo4"
+ gem "bundler"
+ G
- it "version_requirement is now deprecated in rubygems 1.4.0+" do
- system_gems "thin-1.0", "rack-1.0.0"
- build_gem "thin", "1.1", :to_system => true do |s|
- s.add_dependency "rack"
- end
+ bundle "install --verbose", env: { "BUNDLE_FROZEN" => "true" }
+ expect(err).to be_empty
+ end
- gemfile <<-G
- gem "thin", "1.0"
- G
+ it "doesn't re-resolve when deleting dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "actionpack"
+ G
- ruby <<-R
- require 'rubygems'
- gem "thin"
- require 'bundler'
- begin
- Bundler.setup
- puts "FAIL"
- rescue Gem::LoadError => e
- puts e.message
- end
- R
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "myrack"
+ G
- expect(err).to lack_errors
- end
+ expect(out).to include("Some dependencies were deleted, using a subset of the resolution from the lockfile")
+ expect(err).to be_empty
+ end
+
+ it "remembers --without and does not include groups passed to Bundler.setup" do
+ bundle_config "without rails"
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "activesupport"
+
+ group :myrack do
+ gem "myrack"
+ end
+
+ group :rails do
+ gem "rails", "2.3.2"
+ end
+ G
+
+ expect(the_bundle).not_to include_gems "activesupport 2.3.2", groups: :myrack
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: :myrack
end
end
# RubyGems returns loaded_from as a string
it "has loaded_from as a string on all specs" do
build_git "foo"
- build_git "no-gemspec", :gemspec => false
+ build_git "no-gemspec", gemspec: false
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "foo", :git => "#{lib_path("foo-1.0")}"
gem "no-gemspec", "1.0", :git => "#{lib_path("no-gemspec-1.0")}"
G
@@ -732,81 +732,162 @@ RSpec.describe "Bundler.setup" do
expect(out).to be_empty
end
- it "does not load all gemspecs", :rubygems => ">= 2.3" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ it "has gem_dir pointing to local repo" do
+ build_lib "foo", "1.0", path: bundled_app
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec
+ G
+
+ run <<-R
+ puts Gem.loaded_specs['foo'].gem_dir
+ R
+
+ expect(out).to eq(bundled_app.to_s)
+ end
+
+ it "does not load all gemspecs" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- run! <<-R
- File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f|
+ run <<-R
+ File.open(File.join(Gem.dir, "specifications", "invalid.gemspec"), "w") do |f|
+ f.write <<-RUBY
+# -*- encoding: utf-8 -*-
+# stub: invalid 1.0.0 ruby lib
+
+Gem::Specification.new do |s|
+ s.name = "invalid"
+ s.version = "1.0.0"
+ s.authors = ["Invalid Author"]
+ s.files = ["lib/invalid.rb"]
+ s.add_dependency "nonexistent-gem", "~> 999.999.999"
+ s.validate!
+end
+ RUBY
+ end
+ R
+
+ run <<-R
+ File.open(File.join(Gem.dir, "specifications", "invalid-ext.gemspec"), "w") do |f|
f.write <<-RUBY
# -*- encoding: utf-8 -*-
-# stub: broken 1.0.0 ruby lib
+# stub: invalid-ext 1.0.0 ruby lib
+# stub: a.ext\\0b.ext
Gem::Specification.new do |s|
- s.name = "broken"
+ s.name = "invalid-ext"
s.version = "1.0.0"
- raise "BROKEN GEMSPEC"
+ s.authors = ["Invalid Author"]
+ s.files = ["lib/invalid.rb"]
+ s.required_ruby_version = "~> 0.8.0"
+ s.validate!
end
RUBY
end
+ # Need to write the gem.build_complete file,
+ # otherwise the full spec is loaded to check the installed_by_version
+ extensions_dir = Gem.default_ext_dir_for(Gem.dir) || File.join(Gem.dir, "extensions", Gem::Platform.local.to_s, Gem.extension_api_version)
+ Bundler::FileUtils.mkdir_p(File.join(extensions_dir, "invalid-ext-1.0.0"))
+ File.open(File.join(extensions_dir, "invalid-ext-1.0.0", "gem.build_complete"), "w") {}
R
- run! <<-R
- puts "WIN"
+ run <<-R
+ puts "Success"
R
- expect(out).to eq("WIN")
+ expect(out).to eq("Success")
end
it "ignores empty gem paths" do
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ENV["GEM_HOME"] = ""
- bundle %(exec ruby -e "require 'set'"), :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
+ bundle %(exec ruby -e "require 'set'")
- expect(err).to lack_errors
+ expect(err).to be_empty
end
- describe "$MANPATH" do
- before do
+ it "can require rubygems without warnings, when using a local cache", :truffleruby do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "package"
+ bundle %(exec ruby -w -e "require 'rubygems'")
+
+ expect(err).to be_empty
+ end
+
+ context "when the user has `MANPATH` set", :man do
+ before { ENV["MANPATH"] = "/foo#{File::PATH_SEPARATOR}" }
+
+ it "adds the gem's man dir to the MANPATH" do
build_repo4 do
build_gem "with_man" do |s|
s.write("man/man1/page.1", "MANPAGE")
end
end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "with_man"
+ G
+
+ run "puts ENV['MANPATH']"
+ expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}/foo")
end
+ end
- context "when the user has one set" do
- before { ENV["MANPATH"] = "/foo:" }
+ context "when the user does not have `MANPATH` set", :man do
+ before { ENV.delete("MANPATH") }
- it "adds the gem's man dir to the MANPATH" do
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- gem "with_man"
- G
+ it "adds the gem's man dir to the MANPATH, leaving : in the end so that system man pages still work" do
+ build_repo4 do
+ build_gem "with_man" do |s|
+ s.write("man/man1/page.1", "MANPAGE")
+ end
- run! "puts ENV['MANPATH']"
- expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}:/foo")
+ build_gem "with_man_overriding_system_man" do |s|
+ s.write("man/man1/ls.1", "LS MANPAGE")
+ end
end
- end
- context "when the user does not have one set" do
- before { ENV.delete("MANPATH") }
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "with_man"
+ G
- it "adds the gem's man dir to the MANPATH" do
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- gem "with_man"
- G
+ run <<~RUBY
+ puts ENV['MANPATH']
+ require "open3"
+ puts Open3.capture2e("man", "ls")[1].success?
+ RUBY
- run! "puts ENV['MANPATH']"
- expect(out).to eq(default_bundle_path("gems/with_man-1.0/man").to_s)
- end
+ expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}\ntrue")
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "with_man_overriding_system_man"
+ G
+
+ run <<~RUBY
+ puts ENV['MANPATH']
+ require "open3"
+ puts Open3.capture2e({ "LC_ALL" => "C" }, "man", "ls")[0]
+ RUBY
+
+ lines = out.split("\n")
+
+ expect(lines).to include("#{default_bundle_path("gems/with_man_overriding_system_man-1.0/man")}#{File::PATH_SEPARATOR}")
+ expect(lines).to include("LS MANPAGE")
end
end
@@ -820,7 +901,7 @@ end
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
gem "requirepaths", :require => nil
G
@@ -828,26 +909,17 @@ end
expect(out).to eq("yay")
end
- it "should clean $LOAD_PATH properly", :ruby_repo do
+ it "should clean $LOAD_PATH properly" do
gem_name = "very_simple_binary"
full_gem_name = gem_name + "-1.0"
- ext_dir = File.join(tmp "extenstions", full_gem_name)
- install_gem full_gem_name
+ system_gems full_gem_name
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
G
ruby <<-R
- if Gem::Specification.method_defined? :extension_dir
- s = Gem::Specification.find_by_name '#{gem_name}'
- s.extension_dir = '#{ext_dir}'
-
- # Don't build extensions.
- s.class.send(:define_method, :build_extensions) { nil }
- end
-
require 'bundler'
gem '#{gem_name}'
@@ -863,126 +935,126 @@ end
context "with bundler is located in symlinked GEM_HOME" do
let(:gem_home) { Dir.mktmpdir }
- let(:symlinked_gem_home) { Tempfile.new("gem_home") }
- let(:bundler_dir) { ruby_core? ? File.expand_path("../../../..", __FILE__) : File.expand_path("../../..", __FILE__) }
- let(:bundler_lib) { File.join(bundler_dir, "lib") }
+ let(:symlinked_gem_home) { tmp("gem_home-symlink").to_s }
+ let(:full_name) { "bundler-#{Bundler::VERSION}" }
before do
- FileUtils.ln_sf(gem_home, symlinked_gem_home.path)
+ File.symlink(gem_home, symlinked_gem_home)
gems_dir = File.join(gem_home, "gems")
specifications_dir = File.join(gem_home, "specifications")
Dir.mkdir(gems_dir)
Dir.mkdir(specifications_dir)
- FileUtils.ln_s(bundler_dir, File.join(gems_dir, "bundler-#{Bundler::VERSION}"))
+ File.symlink(source_root, File.join(gems_dir, full_name))
- gemspec_file = ruby_core? ? "#{bundler_dir}/lib/bundler.gemspec" : "#{bundler_dir}/bundler.gemspec"
- gemspec = File.read(gemspec_file).
- sub("Bundler::VERSION", %("#{Bundler::VERSION}"))
- gemspec = gemspec.lines.reject {|line| line =~ %r{lib/bundler/version} }.join
+ gemspec_content = File.binread(gemspec).
+ sub("Bundler::VERSION", %("#{Bundler::VERSION}")).
+ lines.reject {|line| line.include?("lib/bundler/version") }.join
- File.open(File.join(specifications_dir, "bundler.gemspec"), "wb") do |f|
- f.write(gemspec)
+ File.open(File.join(specifications_dir, "#{full_name}.gemspec"), "wb") do |f|
+ f.write(gemspec_content)
end
end
- it "should succesfully require 'bundler/setup'", :ruby_repo do
- install_gemfile ""
-
- ENV["GEM_PATH"] = symlinked_gem_home.path
+ it "should not remove itself from the LOAD_PATH and require a different copy of 'bundler/setup'" do
+ install_gemfile "source 'https://gem.repo1'"
- ruby <<-R
- if $LOAD_PATH.include?("#{bundler_lib}")
- # We should use bundler from GEM_PATH for this test, so we should
- # remove path to the bundler source tree
- $LOAD_PATH.delete("#{bundler_lib}")
- else
- raise "We don't have #{bundler_lib} in $LOAD_PATH"
+ ruby <<-R, env: { "GEM_PATH" => symlinked_gem_home }
+ TracePoint.trace(:class) do |tp|
+ if tp.path.include?("bundler") && !tp.path.start_with?("#{source_root}")
+ puts "OMG. Defining a class from another bundler at \#{tp.path}:\#{tp.lineno}"
+ end
end
- puts (require 'bundler/setup')
+ gem 'bundler', '#{Bundler::VERSION}'
+ require 'bundler/setup'
R
- expect(out).to eql("true")
+ expect(out).to be_empty
end
end
- it "stubs out Gem.refresh so it does not reveal system gems" do
- system_gems "rack-1.0.0"
+ it "does not reveal system gems even when Gem.refresh is called" do
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport"
G
run <<-R
- puts Bundler.rubygems.find_name("rack").inspect
+ puts Bundler.rubygems.installed_specs.map(&:name)
Gem.refresh
- puts Bundler.rubygems.find_name("rack").inspect
+ puts Bundler.rubygems.installed_specs.map(&:name)
R
- expect(out).to eq("[]\n[]")
+ expect(out).to eq("activesupport\nbundler\nactivesupport\nbundler")
end
describe "when a vendored gem specification uses the :path option" do
+ let(:filesystem_root) do
+ current = Pathname.new(Dir.pwd)
+ current = current.parent until current == current.parent
+ current
+ end
+
it "should resolve paths relative to the Gemfile" do
path = bundled_app(File.join("vendor", "foo"))
- build_lib "foo", :path => path
+ build_lib "foo", path: path
# If the .gemspec exists, then Bundler handles the path differently.
# See Source::Path.load_spec_files for details.
FileUtils.rm(File.join(path, "foo.gemspec"))
install_gemfile <<-G
+ source "https://gem.repo1"
gem 'foo', '1.2.3', :path => 'vendor/foo'
G
- Dir.chdir(bundled_app.parent) do
- run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile") }
- require 'foo'
- R
- end
- expect(err).to lack_errors
+ run <<-R, env: { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, dir: bundled_app.parent
+ require 'foo'
+ R
+ expect(err).to be_empty
end
it "should make sure the Bundler.root is really included in the path relative to the Gemfile" do
- relative_path = File.join("vendor", Dir.pwd[1..-1], "foo")
+ relative_path = File.join("vendor", Dir.pwd.gsub(/^#{filesystem_root}/, ""))
absolute_path = bundled_app(relative_path)
FileUtils.mkdir_p(absolute_path)
- build_lib "foo", :path => absolute_path
+ build_lib "foo", path: absolute_path
# If the .gemspec exists, then Bundler handles the path differently.
# See Source::Path.load_spec_files for details.
FileUtils.rm(File.join(absolute_path, "foo.gemspec"))
gemfile <<-G
+ source "https://gem.repo1"
gem 'foo', '1.2.3', :path => '#{relative_path}'
G
bundle :install
- Dir.chdir(bundled_app.parent) do
- run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile") }
- require 'foo'
- R
- end
+ run <<-R, env: { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, dir: bundled_app.parent
+ require 'foo'
+ R
- expect(err).to lack_errors
+ expect(err).to be_empty
end
end
describe "with git gems that don't have gemspecs" do
before :each do
- build_git "no-gemspec", :gemspec => false
+ build_git "no_gemspec", gemspec: false
install_gemfile <<-G
- gem "no-gemspec", "1.0", :git => "#{lib_path("no-gemspec-1.0")}"
+ source "https://gem.repo1"
+ gem "no_gemspec", "1.0", :git => "#{lib_path("no_gemspec-1.0")}"
G
end
it "loads the library via a virtual spec" do
run <<-R
- require 'no-gemspec'
- puts NOGEMSPEC
+ require 'no_gemspec'
+ puts NO_GEMSPEC
R
expect(out).to eq("1.0")
@@ -991,10 +1063,10 @@ end
describe "with bundled and system gems" do
before :each do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "file://#{gem_repo1}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
@@ -1002,10 +1074,8 @@ end
it "does not pull in system gems" do
run <<-R
- require 'rubygems'
-
begin;
- require 'rack'
+ require 'myrack'
rescue LoadError
puts 'WIN'
end
@@ -1027,13 +1097,13 @@ end
it "raises an exception if gem is used to invoke a system gem not in the bundle" do
run <<-R
begin
- gem 'rack'
+ gem 'myrack'
rescue LoadError => e
puts e.message
end
R
- expect(out).to eq("rack is not part of the bundle. Add it to your Gemfile.")
+ expect(out).to eq("myrack is not part of the bundle. Add it to your Gemfile.")
end
it "sets GEM_HOME appropriately" do
@@ -1044,12 +1114,12 @@ end
describe "with system gems in the bundle" do
before :each do
- bundle! "config path.system true"
- system_gems "rack-1.0.0"
+ bundle_config "path.system true"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
gem "activesupport", "2.3.5"
G
end
@@ -1063,12 +1133,10 @@ end
describe "with a gemspec that requires other files" do
before :each do
- build_git "bar", :gemspec => false do |s|
+ build_git "bar", gemspec: false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
- lib = File.expand_path('../lib/', __FILE__)
- $:.unshift lib unless $:.include?(lib)
- require 'bar/version'
+ require_relative 'lib/bar/version'
Gem::Specification.new do |s|
s.name = 'bar'
@@ -1081,6 +1149,7 @@ end
end
gemfile <<-G
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
@@ -1092,14 +1161,15 @@ end
end
it "error intelligently if the gemspec has a LoadError" do
- ref = update_git "bar", :gemspec => false do |s|
+ skip "whitespace issue?" if Gem.win_platform?
+
+ ref = update_git "bar", gemspec: false do |s|
s.write "bar.gemspec", "require 'foobarbaz'"
end.ref_for("HEAD")
- bundle :install
+ bundle :install, raise_on_error: false
- expect(out.lines.map(&:chomp)).to include(
+ expect(err.lines.map(&:chomp)).to include(
a_string_starting_with("[!] There was an error while loading `bar.gemspec`:"),
- RUBY_VERSION >= "1.9" ? a_string_starting_with("Does it try to require a relative path? That's been removed in Ruby 1.9.") : "",
" # from #{default_bundle_path "bundler", "gems", "bar-1.0-#{ref[0, 12]}", "bar.gemspec"}:1",
" > require 'foobarbaz'"
)
@@ -1110,54 +1180,59 @@ end
ruby <<-RUBY
require 'bundler'
+ bundler_module = class << Bundler; self; end
+ bundler_module.send(:remove_method, :require)
def Bundler.require(path)
- raise "LOSE"
+ raise StandardError, "didn't use binding from top level"
end
Bundler.load
RUBY
- expect(err).to lack_errors
- expect(out).to eq("")
+ expect(err).to be_empty
+ expect(out).to be_empty
end
end
describe "when Bundler is bundled" do
it "doesn't blow up" do
install_gemfile <<-G
- gem "bundler", :path => "#{File.expand_path("..", lib)}"
+ source "https://gem.repo1"
+ gem "bundler", :path => "#{root}"
G
- bundle %(exec ruby -e "require 'bundler'; Bundler.setup"), :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
- expect(err).to lack_errors
+ bundle %(exec ruby -e "require 'bundler'; Bundler.setup")
+ expect(err).to be_empty
end
end
describe "when BUNDLED WITH" do
def lock_with(bundler_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
- remote: file:#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
L
if bundler_version
- lock += "\n BUNDLED WITH\n #{bundler_version}\n"
+ lock += "\nBUNDLED WITH\n #{bundler_version}\n"
end
lock
end
before do
+ bundle_config "path.system true"
+
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -1165,7 +1240,7 @@ end
it "does not change the lock" do
lockfile lock_with(nil)
ruby "require 'bundler/setup'"
- lockfile_should_be lock_with(nil)
+ expect(lockfile).to eq lock_with(nil)
end
end
@@ -1173,17 +1248,18 @@ end
it "does not change the lock or warn" do
lockfile lock_with(Bundler::VERSION.succ)
ruby "require 'bundler/setup'"
- expect(out).to eq("")
- expect(err).to eq("")
- lockfile_should_be lock_with(Bundler::VERSION.succ)
+ expect(out).to be_empty
+ expect(err).to be_empty
+ expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
context "is older" do
it "does not change the lock" do
+ system_gems "bundler-1.10.1"
lockfile lock_with("1.10.1")
ruby "require 'bundler/setup'"
- lockfile_should_be lock_with("1.10.1")
+ expect(lockfile).to eq lock_with("1.10.1")
end
end
end
@@ -1192,67 +1268,110 @@ end
let(:ruby_version) { nil }
def lock_with(ruby_version = nil)
- lock = <<-L
+ checksums = checksums_section do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
+ lock = <<~L
GEM
- remote: file://localhost#{gem_repo1}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
+ #{checksums}
L
if ruby_version
- lock += "\n RUBY VERSION\n ruby #{ruby_version}\n"
+ lock += "\nRUBY VERSION\n ruby #{ruby_version}\n"
end
- lock += <<-L
+ lock += <<~L
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- normalize_uri_file(lock)
+ lock
end
before do
install_gemfile <<-G
ruby ">= 0"
- source "file://localhost#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
lockfile lock_with(ruby_version)
end
context "is not present" do
- it "does not change the lock" do
- expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
+ # Skipped on ruby-core because `ruby "require 'bundler/setup'"` does not
+ # activate bundler as a gem there, so Source::Metadata falls back to a
+ # synthetic spec whose cache_file does not exist on disk and
+ # LockfileGenerator#bundler_checksum drops the bundler checksum, while
+ # the on-disk lockfile still has it.
+ it "does not change the lock", :ruby_repo do
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
end
end
context "is newer" do
let(:ruby_version) { "5.5.5" }
it "does not change the lock or warn" do
- expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
- expect(out).to eq("")
- expect(err).to eq("")
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
+ expect(out).to be_empty
+ expect(err).to be_empty
end
end
context "is older" do
let(:ruby_version) { "1.0.0" }
it "does not change the lock" do
- expect { ruby! "require 'bundler/setup'" }.not_to change { lockfile }
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
end
end
end
describe "with gemified standard libraries" do
- it "does not load Psych", :ruby => "~> 2.2" do
- gemfile ""
+ it "does not load Digest", :ruby_repo do
+ build_git "bar", gemspec: false do |s|
+ s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
+ s.write "bar.gemspec", <<-G
+ require_relative 'lib/bar/version'
+
+ Gem::Specification.new do |s|
+ s.name = 'bar'
+ s.version = BAR_VERSION
+ s.summary = 'Bar'
+ s.files = Dir["lib/**/*.rb"]
+ s.author = 'no one'
+
+ s.add_dependency 'digest'
+ end
+ G
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "bar", :git => "#{lib_path("bar-1.0")}"
+ G
+
+ bundle :install, env: { "BUNDLE_LOCKFILE_CHECKSUMS" => "false" }
+
+ ruby <<-RUBY, artifice: nil
+ require 'bundler/setup'
+ puts defined?(::Digest) ? "Digest defined" : "Digest undefined"
+ require 'digest'
+ RUBY
+ expect(out).to eq("Digest undefined")
+ end
+
+ it "does not load Psych" do
+ gemfile "source 'https://gem.repo1'"
ruby <<-RUBY
require 'bundler/setup'
puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined"
@@ -1265,8 +1384,8 @@ end
end
it "does not load openssl" do
- install_gemfile! ""
- ruby! <<-RUBY
+ install_gemfile "source 'https://gem.repo1'"
+ ruby <<-RUBY, artifice: nil
require "bundler/setup"
puts defined?(OpenSSL) || "undefined"
require "openssl"
@@ -1275,30 +1394,73 @@ end
expect(out).to eq("undefined\nconstant")
end
+ it "does not load uri while reading gemspecs", rubygems: ">= 3.6.0.dev" do
+ Dir.mkdir bundled_app("test")
+
+ create_file(bundled_app("test/test.gemspec"), <<-G)
+ Gem::Specification.new do |s|
+ s.name = "test"
+ s.version = "1.0.0"
+ s.summary = "test"
+ s.authors = ['John Doe']
+ s.homepage = 'https://example.com'
+ end
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "test", path: "#{bundled_app("test")}"
+ G
+
+ ruby <<-RUBY, artifice: nil
+ require "bundler/setup"
+ puts defined?(URI) || "undefined"
+ require "uri"
+ puts defined?(URI) || "undefined"
+ RUBY
+ expect(out).to eq("undefined\nconstant")
+ end
+
+ it "activates default gems when they are part of the bundle, but not installed explicitly", :ruby_repo do
+ default_delegate_version = ruby "gem 'delegate'; require 'delegate'; puts Delegator::VERSION"
+
+ build_repo2 do
+ build_gem "delegate", default_delegate_version
+ end
+
+ gemfile "source \"https://gem.repo2\"; gem 'delegate'"
+
+ ruby <<-RUBY
+ require "bundler/setup"
+ require "delegate"
+ puts defined?(::Delegator) ? "Delegator defined" : "Delegator undefined"
+ RUBY
+
+ expect(out).to eq("Delegator defined")
+ expect(err).to be_empty
+ end
+
describe "default gem activation" do
let(:exemptions) do
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7") || ENV["RGV"] == "master"
- []
- else
- %w[io-console openssl]
- end << "bundler"
+ exempts = %w[did_you_mean bundler uri pathname]
+ exempts << "error_highlight" # added in Ruby 3.1 as a default gem
+ exempts << "ruby2_keywords" # added in Ruby 3.1 as a default gem
+ exempts << "syntax_suggest" # added in Ruby 3.2 as a default gem
+ exempts
end
- let(:activation_warning_hack) { strip_whitespace(<<-RUBY) }
+ let(:activation_warning_hack) { <<~RUBY }
require #{spec_dir.join("support/hax").to_s.dump}
- require "rubygems"
-
- if Gem::Specification.instance_methods.map(&:to_sym).include?(:activate)
- Gem::Specification.send(:alias_method, :bundler_spec_activate, :activate)
- Gem::Specification.send(:define_method, :activate) do
- unless #{exemptions.inspect}.include?(name)
- warn '-' * 80
- warn "activating \#{full_name}"
- warn *caller
- warn '*' * 80
- end
- bundler_spec_activate
+
+ Gem::Specification.send(:alias_method, :bundler_spec_activate, :activate)
+ Gem::Specification.send(:define_method, :activate) do
+ unless #{exemptions.inspect}.include?(name)
+ warn '-' * 80
+ warn "activating \#{full_name}"
+ warn(*caller)
+ warn '*' * 80
end
+ bundler_spec_activate
end
RUBY
@@ -1307,8 +1469,7 @@ end
"-r#{bundled_app("activation_warning_hack.rb")} #{ENV["RUBYOPT"]}"
end
- let(:code) { strip_whitespace(<<-RUBY) }
- require "bundler/setup"
+ let(:code) { <<~RUBY }
require "pp"
loaded_specs = Gem.loaded_specs.dup
#{exemptions.inspect}.each {|s| loaded_specs.delete(s) }
@@ -1322,124 +1483,228 @@ end
RUBY
it "activates no gems with -rbundler/setup" do
- install_gemfile! ""
- ruby! code, :env => { :RUBYOPT => activation_warning_hack_rubyopt }
- expect(last_command.stdout).to eq("{}")
+ install_gemfile "source 'https://gem.repo1'"
+ ruby code, env: { "RUBYOPT" => activation_warning_hack_rubyopt + " -rbundler/setup" }, artifice: nil
+ expect(out).to eq("{}")
end
it "activates no gems with bundle exec" do
- install_gemfile! ""
- # ensure we clean out the default gems, bceause bundler's allowed to be activated
+ install_gemfile "source 'https://gem.repo1'"
create_file("script.rb", code)
- bundle! "exec ruby ./script.rb", :env => { :RUBYOPT => activation_warning_hack_rubyopt + " -rbundler/setup" }
- expect(last_command.stdout).to eq("{}")
+ bundle "exec ruby ./script.rb", env: { "RUBYOPT" => activation_warning_hack_rubyopt }
+ expect(out).to eq("{}")
end
it "activates no gems with bundle exec that is loaded" do
- # TODO: remove once https://github.com/erikhuda/thor/pull/539 is released
- exemptions << "io-console"
+ skip "not executable" if Gem.win_platform?
- install_gemfile! ""
+ install_gemfile "source 'https://gem.repo1'"
create_file("script.rb", "#!/usr/bin/env ruby\n\n#{code}")
FileUtils.chmod(0o777, bundled_app("script.rb"))
- bundle! "exec ./script.rb", :artifice => nil, :env => { :RUBYOPT => activation_warning_hack_rubyopt }
- expect(last_command.stdout).to eq("{}")
- end
-
- let(:default_gems) do
- ruby!(<<-RUBY).split("\n")
- if Gem::Specification.is_a?(Enumerable)
- puts Gem::Specification.select(&:default_gem?).map(&:name)
- end
- RUBY
+ bundle "exec ./script.rb", env: { "RUBYOPT" => activation_warning_hack_rubyopt }
+ expect(out).to eq("{}")
end
- it "activates newer versions of default gems" do
+ it "does not load net-http-pipeline too early" do
build_repo4 do
- default_gems.each do |g|
- build_gem g, "999999"
- end
+ build_gem "net-http-pipeline", "1.0.1"
end
- default_gems.reject! {|g| exemptions.include?(g) }
+ system_gems "net-http-pipeline-1.0.1", gem_repo: gem_repo4
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- #{default_gems}.each do |g|
- gem g, "999999"
- end
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "net-http-pipeline", "1.0.1"
G
- expect(the_bundle).to include_gems(*default_gems.map {|g| "#{g} 999999" })
+ bundle_config "path vendor/bundle"
+
+ bundle :install
+
+ bundle :check
+
+ expect(out).to eq("The Gemfile's dependencies are satisfied")
end
- it "activates older versions of default gems" do
- build_repo4 do
- default_gems.each do |g|
- build_gem g, "0.0.0.a"
+ Gem::Specification.select(&:default_gem?).map(&:name).each do |g|
+ it "activates newer versions of #{g}", :ruby_repo do
+ skip if exemptions.include?(g)
+
+ build_repo4 do
+ build_gem g, "999999"
end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "#{g}", "999999"
+ G
+
+ expect(the_bundle).to include_gem("#{g} 999999", env: { "RUBYOPT" => activation_warning_hack_rubyopt }, artifice: nil)
end
- default_gems.reject! {|g| exemptions.include?(g) }
+ it "activates older versions of #{g}", :ruby_repo do
+ skip if exemptions.include?(g)
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
- #{default_gems}.each do |g|
- gem g, "0.0.0.a"
+ build_repo4 do
+ build_gem g, "0.0.0.a"
end
- G
- expect(the_bundle).to include_gems(*default_gems.map {|g| "#{g} 0.0.0.a" })
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "#{g}", "0.0.0.a"
+ G
+
+ expect(the_bundle).to include_gem("#{g} 0.0.0.a", env: { "RUBYOPT" => activation_warning_hack_rubyopt }, artifice: nil)
+ end
end
end
end
describe "after setup" do
- it "allows calling #gem on random objects", :bundler => "< 3" do
+ it "keeps Kernel#gem private" do
install_gemfile <<-G
- source "file:#{gem_repo1}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- ruby! <<-RUBY
+ ruby <<-RUBY, raise_on_error: false
require "bundler/setup"
- Object.new.gem "rack"
- puts Gem.loaded_specs["rack"].full_name
+ Object.new.gem "myrack"
+ puts "FAIL"
RUBY
- expect(out).to eq("rack-1.0.0")
+ expect(stdboth).not_to include "FAIL"
+ expect(err).to match(/private method [`']gem'/)
end
- it "keeps Kernel#gem private", :bundler => "3" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem "rack"
+ it "keeps Kernel#require private" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- ruby <<-RUBY
+ ruby <<-RUBY, raise_on_error: false
require "bundler/setup"
- Object.new.gem "rack"
+ Object.new.require "myrack"
puts "FAIL"
RUBY
- expect(last_command.stdboth).not_to include "FAIL"
- expect(last_command.stderr).to include "private method `gem'"
+ expect(stdboth).not_to include "FAIL"
+ expect(err).to match(/private method [`']require'/)
end
- it "keeps Kernel#require private" do
- install_gemfile! <<-G
- source "file:#{gem_repo1}"
- gem "rack"
+ it "memoizes initial set of specs when requiring bundler/setup, so that even if further code mutates dependencies, Bundler.definition.specs is not affected" do
+ install_gemfile <<~G
+ source "https://gem.repo1"
+ gem "yard"
+ gem "myrack", :group => :test
G
+ ruby <<-RUBY, raise_on_error: false
+ require "bundler/setup"
+ Bundler.require(:test).select! {|d| (d.groups & [:test]).any? }
+ puts Bundler.definition.specs.map(&:name).join(", ")
+ RUBY
+
+ expect(out).to include("myrack, yard")
+ end
+
+ it "does not cause double loads when higher versions of default gems are activated before bundler" do
+ build_repo2 do
+ build_gem "json", "999.999.999" do |s|
+ s.write "lib/json.rb", <<~RUBY
+ module JSON
+ VERSION = "999.999.999"
+ end
+ RUBY
+ end
+ end
+
+ system_gems "json-999.999.999", gem_repo: gem_repo2
+
+ install_gemfile "source 'https://gem.repo1'"
ruby <<-RUBY
+ require "json"
require "bundler/setup"
- Object.new.require "rack"
- puts "FAIL"
+ require "json"
RUBY
- expect(last_command.stdboth).not_to include "FAIL"
- expect(last_command.stderr).to include "private method `require'"
+ expect(err).to be_empty
+ end
+ end
+
+ it "does not undo the Kernel.require decorations", rubygems: ">= 3.4.6" do
+ install_gemfile "source 'https://gem.repo1'"
+ script = bundled_app("bin/script")
+ create_file(script, <<~RUBY)
+ module Kernel
+ module_function
+
+ alias_method :require_before_extra_monkeypatches, :require
+
+ def require(path)
+ puts "requiring \#{path} used the monkeypatch"
+
+ require_before_extra_monkeypatches(path)
+ end
+ end
+
+ require "bundler/setup"
+
+ require "foo"
+ RUBY
+
+ sys_exec "#{Gem.ruby} #{script}", raise_on_error: false
+ expect(out).to include("requiring foo used the monkeypatch")
+ end
+
+ it "performs an automatic bundle install" do
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
+ G
+
+ bundle_config "auto_install 1"
+
+ ruby <<-RUBY, artifice: "compact_index"
+ require 'bundler/setup'
+ RUBY
+ expect(err).to be_empty
+ expect(out).to include("Installing myrack 1.0.0")
+ end
+
+ context "in a read-only filesystem" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo4"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "should fail loudly if the lockfile platforms don't include the current platform" do
+ simulate_platform "x86_64-linux" do
+ ruby <<-RUBY, raise_on_error: false, env: { "BUNDLER_SPEC_READ_ONLY" => "true", "BUNDLER_FORCE_TTY" => "true" }
+ require "bundler/setup"
+ RUBY
+ end
+
+ expect(err).to include("Your lockfile is missing the current platform, but can't be updated because file system is read-only")
end
end
end
diff --git a/spec/bundler/runtime/with_clean_env_spec.rb b/spec/bundler/runtime/with_clean_env_spec.rb
deleted file mode 100644
index da8e37b45d..0000000000
--- a/spec/bundler/runtime/with_clean_env_spec.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "Bundler.with_env helpers" do
- def bundle_exec_ruby!(code, *args)
- opts = args.last.is_a?(Hash) ? args.pop : {}
- env = opts[:env] ||= {}
- env[:RUBYOPT] ||= "-r#{spec_dir.join("support/hax")}"
- args.push opts
- bundle! "exec '#{Gem.ruby}' -e #{code}", *args
- end
-
- describe "Bundler.original_env" do
- before do
- bundle "config path vendor/bundle"
- gemfile ""
- bundle "install"
- end
-
- it "should return the PATH present before bundle was activated" do
- code = "print Bundler.original_env['PATH']"
- path = `getconf PATH`.strip + "#{File::PATH_SEPARATOR}/foo"
- with_path_as(path) do
- bundle_exec_ruby!(code.dump)
- expect(last_command.stdboth).to eq(path)
- end
- end
-
- it "should return the GEM_PATH present before bundle was activated" do
- code = "print Bundler.original_env['GEM_PATH']"
- gem_path = ENV["GEM_PATH"] + ":/foo"
- with_gem_path_as(gem_path) do
- bundle_exec_ruby!(code.dump)
- expect(last_command.stdboth).to eq(gem_path)
- end
- end
-
- it "works with nested bundle exec invocations", :ruby_repo do
- create_file("exe.rb", <<-'RB')
- count = ARGV.first.to_i
- exit if count < 0
- STDERR.puts "#{count} #{ENV["PATH"].end_with?(":/foo")}"
- if count == 2
- ENV["PATH"] = "#{ENV["PATH"]}:/foo"
- end
- exec(Gem.ruby, __FILE__, (count - 1).to_s)
- RB
- path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby)
- with_path_as(path) do
- bundle! "exec '#{Gem.ruby}' #{bundled_app("exe.rb")} 2", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
- end
- expect(err).to eq <<-EOS.strip
-2 false
-1 true
-0 true
- EOS
- end
-
- it "removes variables that bundler added", :ruby_repo do
- original = ruby!('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")', :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" })
- code = 'puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n")'
- bundle! "exec '#{Gem.ruby}' -e #{code.dump}", :env => { :RUBYOPT => "-r#{spec_dir.join("support/hax")}" }
- expect(out).to eq original
- end
- end
-
- describe "Bundler.clean_env", :bundler => "< 3" do
- before do
- bundle "config path vendor/bundle"
- gemfile ""
- bundle "install"
- end
-
- it "should delete BUNDLE_PATH" do
- code = "print Bundler.clean_env.has_key?('BUNDLE_PATH')"
- ENV["BUNDLE_PATH"] = "./foo"
- bundle_exec_ruby! code.dump
- expect(last_command.stdboth).to eq "false"
- end
-
- it "should remove '-rbundler/setup' from RUBYOPT" do
- code = "print Bundler.clean_env['RUBYOPT']"
- ENV["RUBYOPT"] = "-W2 -rbundler/setup"
- bundle_exec_ruby! code.dump
- expect(last_command.stdboth).not_to include("-rbundler/setup")
- end
-
- it "should clean up RUBYLIB", :ruby_repo do
- code = "print Bundler.clean_env['RUBYLIB']"
- ENV["RUBYLIB"] = root.join("lib").to_s + File::PATH_SEPARATOR + "/foo"
- bundle_exec_ruby! code.dump
- expect(last_command.stdboth).to eq("/foo")
- end
-
- it "should restore the original MANPATH" do
- code = "print Bundler.clean_env['MANPATH']"
- ENV["MANPATH"] = "/foo"
- ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original"
- bundle_exec_ruby! code.dump
- expect(last_command.stdboth).to eq("/foo-original")
- end
- end
-
- describe "Bundler.with_original_env" do
- it "should set ENV to original_env in the block" do
- expected = Bundler.original_env
- actual = Bundler.with_original_env { ENV.to_hash }
- expect(actual).to eq(expected)
- end
-
- it "should restore the environment after execution" do
- Bundler.with_original_env do
- ENV["FOO"] = "hello"
- end
-
- expect(ENV).not_to have_key("FOO")
- end
- end
-
- describe "Bundler.with_clean_env", :bundler => "< 3" do
- it "should set ENV to clean_env in the block" do
- expected = Bundler.clean_env
- actual = Bundler.with_clean_env { ENV.to_hash }
- expect(actual).to eq(expected)
- end
-
- it "should restore the environment after execution" do
- Bundler.with_clean_env do
- ENV["FOO"] = "hello"
- end
-
- expect(ENV).not_to have_key("FOO")
- end
- end
-
- describe "Bundler.clean_system", :ruby => ">= 1.9", :bundler => "< 3" do
- it "runs system inside with_clean_env" do
- Bundler.clean_system(%(echo 'if [ "$BUNDLE_PATH" = "" ]; then exit 42; else exit 1; fi' | /bin/sh))
- expect($?.exitstatus).to eq(42)
- end
- end
-
- describe "Bundler.clean_exec", :ruby => ">= 1.9", :bundler => "< 3" do
- it "runs exec inside with_clean_env" do
- pid = Kernel.fork do
- Bundler.clean_exec(%(echo 'if [ "$BUNDLE_PATH" = "" ]; then exit 42; else exit 1; fi' | /bin/sh))
- end
- Process.wait(pid)
- expect($?.exitstatus).to eq(42)
- end
- end
-end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index ff009e773f..27ddc6a771 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -1,68 +1,77 @@
# frozen_string_literal: true
-$:.unshift File.expand_path("..", __FILE__)
-$:.unshift File.expand_path("../../lib", __FILE__)
-
-require "rubygems"
-module Gem
- if defined?(@path_to_default_spec_map)
- @path_to_default_spec_map.delete_if do |_path, spec|
- spec.name == "bundler"
- end
- end
-end
-
-begin
- require File.expand_path("../support/path.rb", __FILE__)
- spec = Gem::Specification.load(Spec::Path.gemspec.to_s)
- rspec = spec.dependencies.find {|d| d.name == "rspec" }
- gem "rspec", rspec.requirement.to_s
- require "rspec"
- require "diff/lcs"
-rescue LoadError
- abort "Run rake spec:deps to install development dependencies"
-end
-
-require "bundler/psyched_yaml"
+require "psych"
require "bundler/vendored_fileutils"
-require "uri"
+require "bundler/vendored_uri"
require "digest"
-# Delete the default copy of Bundler that RVM installs for us when running in CI
-require "fileutils"
-if ENV.select {|k, _v| k =~ /TRAVIS/ }.any? && Gem::Version.new(Gem::VERSION) > Gem::Version.new("2.0")
- Dir.glob(File.join(Gem::Specification.default_specifications_dir, "bundler*.gemspec")).each do |file|
- FileUtils.rm_rf(file)
- end
-
- Dir.glob(File.join(RbConfig::CONFIG["sitelibdir"], "bundler*")).each do |file|
- FileUtils.rm_rf(file)
- end
-end
-
if File.expand_path(__FILE__) =~ %r{([^\w/\.:\-])}
abort "The bundler specs cannot be run from a path that contains special characters (particularly #{$1.inspect})"
end
+# Bundler CLI will have different help text depending on whether any of these
+# variables is set, since the `-e` flag `bundle gem` with require an explicit
+# value if they are not set, but will use their value by default if set. So make
+# sure they are `nil` before loading bundler to get a consistent help text,
+# since some tests rely on that.
+ENV["EDITOR"] = nil
+ENV["VISUAL"] = nil
+ENV["BUNDLER_EDITOR"] = nil
require "bundler"
-Dir["#{File.expand_path("../support", __FILE__)}/*.rb"].each do |file|
- file = file.gsub(%r{\A#{Regexp.escape File.expand_path("..", __FILE__)}/}, "")
- require file unless file.end_with?("hax.rb")
-end
-
-$debug = false
+# If we use shared GEM_HOME and install multiple versions, it may cause
+# unexpected test failures.
+gem "diff-lcs", "< 2.0"
+
+require "rspec/core"
+require "rspec/expectations"
+require "rspec/mocks"
+require "rspec/support/differ"
+gem "rubygems-generate_index"
+require "rubygems/indexer"
+
+require_relative "support/builders"
+require_relative "support/checksums"
+require_relative "support/filters"
+require_relative "support/helpers"
+require_relative "support/indexes"
+require_relative "support/matchers"
+require_relative "support/permissions"
+require_relative "support/platforms"
+require_relative "support/shards"
-Spec::Manpages.setup
-Spec::Rubygems.setup
-FileUtils.rm_rf(Spec::Path.gem_repo1)
-ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -r#{Spec::Path.spec_dir}/support/hax.rb"
-ENV["BUNDLE_SPEC_RUN"] = "true"
+begin
+ raise LoadError if File.exist?(File.expand_path("../../lib/bundler/bundler.gemspec", __dir__))
+
+ gem "simplecov_json_formatter"
+ require "simplecov"
+
+ SimpleCov.start do
+ command_name "bundler:#{Process.pid}"
+ root File.expand_path("../bundler", __dir__)
+ coverage_dir File.expand_path("../coverage", __dir__)
+
+ add_filter "/spec/"
+ add_filter "/test/"
+ add_filter "/lib/rubygems/"
+ add_filter "/lib/bundler/vendor/"
+ add_filter "/tool/"
+ add_filter "/tmp/"
+ add_filter ".gemspec"
+ end
-# Don't wrap output in tests
-ENV["THOR_COLUMNS"] = "10000"
+ SimpleCov.print_error_status = false
+ SimpleCov.at_exit do
+ $stdout = File.open(File::NULL, "w")
+ SimpleCov.result.format!
+ ensure
+ $stdout = STDOUT
+ end
+rescue LoadError
+ # SimpleCov is not installed
+end
-Spec::CodeClimate.setup
+$debug = false
module Gem
def self.ruby=(ruby)
@@ -72,18 +81,23 @@ end
RSpec.configure do |config|
config.include Spec::Builders
+ config.include Spec::Checksums
config.include Spec::Helpers
config.include Spec::Indexes
config.include Spec::Matchers
config.include Spec::Path
- config.include Spec::Rubygems
config.include Spec::Platforms
- config.include Spec::Sudo
config.include Spec::Permissions
+ config.include Spec::Shards
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"
+ config.silence_filter_announcements = !ENV["TEST_ENV_NUMBER"].nil?
+
+ config.backtrace_exclusion_patterns <<
+ %r{./spec/(spec_helper\.rb|support/.+)}
+
config.disable_monkey_patching!
# Since failures cause us to keep a bunch of long strings in memory, stop
@@ -92,67 +106,87 @@ RSpec.configure do |config|
# forever due to memory constraints
config.fail_fast ||= 25 if ENV["CI"]
- if ENV["BUNDLER_SUDO_TESTS"] && Spec::Sudo.present?
- config.filter_run :sudo => true
- else
- config.filter_run_excluding :sudo => true
+ config.bisect_runner = :shell
+
+ config.expect_with :rspec do |c|
+ c.syntax = :expect
+
+ c.max_formatted_output_length = 1000
end
- if ENV["BUNDLER_REALWORLD_TESTS"]
- config.filter_run :realworld => true
- else
- config.filter_run_excluding :realworld => true
+ config.mock_with :rspec do |mocks|
+ mocks.allow_message_expectations_on_nil = false
end
- git_version = Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
+ config.before :suite do
+ Gem.ruby = ENV["RUBY"] if ENV["RUBY"]
+
+ require_relative "support/rubygems_ext"
+ Spec::Rubygems.test_setup
+
+ # Disable retry delays in tests to speed them up
+ Bundler::Retry.default_base_delay = 0
+
+ # Simulate bundler has not yet been loaded
+ ENV.replace(ENV.to_hash.delete_if {|k, _v| k.start_with?(Bundler::EnvironmentPreserver::BUNDLER_PREFIX) })
+
+ ENV["BUNDLER_SPEC_RUN"] = "true"
+ ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil
+ ENV["BUNDLE_APP_CONFIG"] = nil
+ ENV["BUNDLE_SILENCE_ROOT_WARNING"] = nil
+ ENV["RUBYGEMS_GEMDEPS"] = nil
+ ENV["XDG_CONFIG_HOME"] = nil
+ ENV["XDG_CACHE_HOME"] = nil
+ ENV["GEMRC"] = nil
+
+ # Prevent tests from modifying the user's global git config.
+ # GIT_CONFIG_GLOBAL and GIT_CONFIG_NOSYSTEM are available since Git 2.32.
+ git_version = `git --version`[/(\d+\.\d+\.\d+)/, 1]
+ if Gem::Version.new(git_version) >= Gem::Version.new("2.32")
+ ENV["GIT_CONFIG_GLOBAL"] = File.join(ENV["HOME"], ".gitconfig")
+ ENV["GIT_CONFIG_NOSYSTEM"] = "1"
+ end
- config.filter_run_excluding :ruby => LessThanProc.with(RUBY_VERSION)
- config.filter_run_excluding :rubygems => LessThanProc.with(Gem::VERSION)
- config.filter_run_excluding :git => LessThanProc.with(git_version)
- config.filter_run_excluding :rubygems_master => (ENV["RGV"] != "master")
- config.filter_run_excluding :bundler => LessThanProc.with(Bundler::VERSION.split(".")[0, 2].join("."))
- config.filter_run_excluding :ruby_repo => !(ENV["BUNDLE_RUBY"] && ENV["BUNDLE_GEM"]).nil?
+ # Don't wrap output in tests
+ ENV["THOR_COLUMNS"] = "10000"
- config.filter_run_when_matching :focus unless ENV["CI"]
+ extend(Spec::Builders)
- original_wd = Dir.pwd
- original_env = ENV.to_hash.delete_if {|k, _v| k.start_with?(Bundler::EnvironmentPreserver::BUNDLER_PREFIX) }
+ build_repo1
- config.expect_with :rspec do |c|
- c.syntax = :expect
+ reset!
end
config.around :each do |example|
- if ENV["BUNDLE_RUBY"]
- orig_ruby = Gem.ruby
- Gem.ruby = ENV["BUNDLE_RUBY"]
- end
- example.run
- Gem.ruby = orig_ruby if ENV["BUNDLE_RUBY"]
- end
+ default_system_gems
- config.before :all do
- build_repo1
- end
+ with_gem_path_as(system_gem_path) do
+ Bundler.ui.silence { example.run }
- config.before :each do
+ all_output = all_commands_output
+ if example.exception && !all_output.empty?
+ message = all_output + "\n" + example.exception.message
+ (class << example.exception; self; end).send(:define_method, :message) do
+ message
+ end
+ end
+ end
+ ensure
reset!
- system_gems []
- in_app_root
- @command_executions = []
end
- config.after :each do |example|
- all_output = @command_executions.map(&:to_s_verbose).join("\n\n")
- if example.exception && !all_output.empty?
- warn all_output unless config.formatters.grep(RSpec::Core::Formatters::DocumentationFormatter).empty?
- message = example.exception.message + "\n\nCommands:\n#{all_output}"
- (class << example.exception; self; end).send(:define_method, :message) do
- message
- end
- end
+ Spec::Shards::EXAMPLE_MAPPINGS.each do |tag, file_paths|
+ file_pattern = Regexp.union(file_paths.map {|path| Regexp.new(Regexp.escape(path) + "$") })
- Dir.chdir(original_wd)
- ENV.replace(original_env)
+ config.define_derived_metadata(file_path: file_pattern) do |metadata|
+ metadata[tag] = true
+ end
end
+
+ config.before(:context) do |example|
+ metadata = example.class.metadata
+ if metadata[:type] != :aruba && !metadata[:realworld] && metadata.keys.none? {|k| Spec::Shards::EXAMPLE_MAPPINGS.keys.include?(k) }
+ warn "#{metadata[:file_path]} is not assigned to any shard. see spec/support/shards.rb for details."
+ end
+ end unless Spec::Path.ruby_core?
end
diff --git a/spec/bundler/support/activate.rb b/spec/bundler/support/activate.rb
new file mode 100644
index 0000000000..143b77833d
--- /dev/null
+++ b/spec/bundler/support/activate.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require "rubygems"
+Gem.instance_variable_set(:@ruby, ENV["RUBY"]) if ENV["RUBY"]
+
+require_relative "path"
+bundler_gemspec = Spec::Path.loaded_gemspec
+bundler_gemspec.instance_variable_set(:@full_gem_path, Spec::Path.source_root.to_s)
+bundler_gemspec.activate if bundler_gemspec.respond_to?(:activate)
diff --git a/spec/bundler/support/artifice/compact_index.rb b/spec/bundler/support/artifice/compact_index.rb
index 01e8eb7837..ebc4d0ae5b 100644
--- a/spec/bundler/support/artifice/compact_index.rb
+++ b/spec/bundler/support/artifice/compact_index.rb
@@ -1,122 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-$LOAD_PATH.unshift Dir[base_system_gems.join("gems/compact_index*/lib")].first.to_s
-require "compact_index"
-
-class CompactIndexAPI < Endpoint
- helpers do
- def load_spec(name, version, platform, gem_repo)
- full_name = "#{name}-#{version}"
- full_name += "-#{platform}" if platform != "ruby"
- Marshal.load(Bundler.rubygems.inflate(File.open(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz")).read))
- end
-
- def etag_response
- response_body = yield
- checksum = Digest(:MD5).hexdigest(response_body)
- return if not_modified?(checksum)
- headers "ETag" => quote(checksum)
- headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
- content_type "text/plain"
- requested_range_for(response_body)
- rescue => e
- puts e
- puts e.backtrace
- raise
- end
-
- def not_modified?(checksum)
- etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
-
- return unless etags.include?(checksum)
- headers "ETag" => quote(checksum)
- status 304
- body ""
- end
-
- def requested_range_for(response_body)
- ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
-
- if ranges
- status 206
- body ranges.map! {|range| slice_body(response_body, range) }.join
- else
- status 200
- body response_body
- end
- end
-
- def quote(string)
- %("#{string}")
- end
-
- def parse_etags(value)
- value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
- end
-
- def slice_body(body, range)
- if body.respond_to?(:byteslice)
- body.byteslice(range)
- else # pre-1.9.3
- body.unpack("@#{range.first}a#{range.end + 1}").first
- end
- end
-
- def gems(gem_repo = GEM_REPO)
- @gems ||= {}
- @gems[gem_repo] ||= begin
- specs = Bundler::Deprecate.skip_during do
- %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
- load_spec(name, version, platform, gem_repo)
- end
- end.flatten
- end
-
- specs.group_by(&:name).map do |name, versions|
- gem_versions = versions.map do |spec|
- deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
- reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
- CompactIndex::Dependency.new(d.name, reqs)
- end
- checksum = begin
- Digest::SHA256.file("#{GEM_REPO}/gems/#{spec.original_name}.gem").base64digest
- rescue
- nil
- end
- CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil,
- deps, spec.required_ruby_version, spec.required_rubygems_version)
- end
- CompactIndex::Gem.new(name, gem_versions)
- end
- end
- end
- end
-
- get "/names" do
- etag_response do
- CompactIndex.names(gems.map(&:name))
- end
- end
-
- get "/versions" do
- etag_response do
- file = tmp("versions.list")
- file.delete if file.file?
- file = CompactIndex::VersionsFile.new(file.to_s)
- file.create(gems)
- file.contents
- end
- end
-
- get "/info/:name" do
- etag_response do
- gem = gems.find {|g| g.name == params[:name] }
- CompactIndex.info(gem ? gem.versions : [])
- end
- end
-end
+require_relative "helpers/compact_index"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexAPI)
diff --git a/spec/bundler/support/artifice/compact_index_api_missing.rb b/spec/bundler/support/artifice/compact_index_api_missing.rb
index d4e68c38e8..f771f7d1f0 100644
--- a/spec/bundler/support/artifice/compact_index_api_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_api_missing.rb
@@ -1,18 +1,13 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexApiMissing < CompactIndexAPI
get "/fetch/actual/gem/:id" do
- $stderr.puts params[:id]
- if params[:id] == "rack-1.0.gemspec.rz"
- halt 404
- else
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
+ halt 404
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexApiMissing)
diff --git a/spec/bundler/support/artifice/compact_index_basic_authentication.rb b/spec/bundler/support/artifice/compact_index_basic_authentication.rb
index 97aa6cbd84..b9115cdd86 100644
--- a/spec/bundler/support/artifice/compact_index_basic_authentication.rb
+++ b/spec/bundler/support/artifice/compact_index_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexBasicAuthentication < CompactIndexAPI
before do
@@ -12,4 +10,6 @@ class CompactIndexBasicAuthentication < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexBasicAuthentication)
diff --git a/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb b/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
index 62feb9f164..83b147d2ae 100644
--- a/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
+++ b/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexChecksumMismatch < CompactIndexAPI
get "/versions" do
- headers "ETag" => quote("123")
+ headers "Repr-Digest" => "sha-256=:ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=:"
headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
content_type "text/plain"
- body ""
+ body "content does not match the checksum"
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexChecksumMismatch)
diff --git a/spec/bundler/support/artifice/compact_index_concurrent_download.rb b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
index 972ecb88b7..5d55b8a72b 100644
--- a/spec/bundler/support/artifice/compact_index_concurrent_download.rb
+++ b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
@@ -1,19 +1,18 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexConcurrentDownload < CompactIndexAPI
get "/versions" do
versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
- # Verify the original (empty) content hasn't been deleted, e.g. on a retry
- File.read(versions) == "" || raise("Original file should be present and empty")
+ # Verify the original content hasn't been deleted, e.g. on a retry
+ data = File.binread(versions)
+ data == "created_at" || raise("Original file should be present with expected content")
# Verify this is only requested once for a partial download
- env["HTTP_RANGE"] || raise("Missing Range header for expected partial download")
+ env["HTTP_RANGE"] == "bytes=#{data.bytesize - 1}-" || raise("Missing Range header for expected partial download")
# Overwrite the file in parallel, which should be then overwritten
# after a successful download to prevent corruption
@@ -21,7 +20,7 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
file.contents
@@ -29,4 +28,6 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexConcurrentDownload)
diff --git a/spec/bundler/support/artifice/compact_index_cooldown.rb b/spec/bundler/support/artifice/compact_index_cooldown.rb
new file mode 100644
index 0000000000..85e3173c98
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_cooldown.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index_cooldown"
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexCooldownAPI)
diff --git a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
index 0d349bcc1e..282e9c8961 100644
--- a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexCredsDiffHost < CompactIndexAPI
helpers do
@@ -26,14 +24,16 @@ class CompactIndexCredsDiffHost < CompactIndexAPI
end
get "/gems/:id" do
- redirect "http://diffhost.com/no/creds/#{params[:id]}"
+ redirect "http://diffhost.test/no/creds/#{params[:id]}"
end
get "/no/creds/:id" do
if request.host.include?("diffhost") && !auth.provided?
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexCredsDiffHost)
diff --git a/spec/bundler/support/artifice/compact_index_etag_match.rb b/spec/bundler/support/artifice/compact_index_etag_match.rb
new file mode 100644
index 0000000000..6c62166051
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_etag_match.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexEtagMatch < CompactIndexAPI
+ get "/versions" do
+ raise ArgumentError, "ETag header should be present" unless env["HTTP_IF_NONE_MATCH"]
+ headers "ETag" => env["HTTP_IF_NONE_MATCH"]
+ status 304
+ body ""
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexEtagMatch)
diff --git a/spec/bundler/support/artifice/compact_index_extra.rb b/spec/bundler/support/artifice/compact_index_extra.rb
index 84d1859235..cd41b3ecca 100644
--- a/spec/bundler/support/artifice/compact_index_extra.rb
+++ b/spec/bundler/support/artifice/compact_index_extra.rb
@@ -1,37 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
-
-class CompactIndexExtra < CompactIndexAPI
- get "/extra/versions" do
- halt 404
- end
-
- get "/extra/api/v1/dependencies" do
- halt 404
- end
-
- get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo2}/specs.4.8.gz")
- end
-
- get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo2}/prerelease_specs.4.8.gz")
- end
-
- get "/extra/quick/Marshal.4.8/:id" do
- redirect "/extra/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/extra/gems/:id" do
- File.read("#{gem_repo2}/gems/#{params[:id]}")
- end
-end
+require_relative "helpers/compact_index_extra"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexExtra)
diff --git a/spec/bundler/support/artifice/compact_index_extra_api.rb b/spec/bundler/support/artifice/compact_index_extra_api.rb
index 903aa900fb..8b9d304ab4 100644
--- a/spec/bundler/support/artifice/compact_index_extra_api.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_api.rb
@@ -1,52 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
-
-class CompactIndexExtraApi < CompactIndexAPI
- get "/extra/names" do
- etag_response do
- CompactIndex.names(gems(gem_repo4).map(&:name))
- end
- end
-
- get "/extra/versions" do
- etag_response do
- file = tmp("versions.list")
- file.delete if file.file?
- file = CompactIndex::VersionsFile.new(file.to_s)
- file.create(gems(gem_repo4))
- file.contents
- end
- end
-
- get "/extra/info/:name" do
- etag_response do
- gem = gems(gem_repo4).find {|g| g.name == params[:name] }
- CompactIndex.info(gem ? gem.versions : [])
- end
- end
-
- get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo4}/specs.4.8.gz")
- end
-
- get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo4}/prerelease_specs.4.8.gz")
- end
-
- get "/extra/quick/Marshal.4.8/:id" do
- redirect "/extra/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/extra/gems/:id" do
- File.read("#{gem_repo4}/gems/#{params[:id]}")
- end
-end
+require_relative "helpers/compact_index_extra_api"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexExtraApi)
diff --git a/spec/bundler/support/artifice/compact_index_extra_api_missing.rb b/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
index e72040f604..df6ede584c 100644
--- a/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index_extra_api", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index_extra_api"
class CompactIndexExtraAPIMissing < CompactIndexExtraApi
get "/extra/fetch/actual/gem/:id" do
if params[:id] == "missing-1.0.gemspec.rz"
halt 404
else
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexExtraAPIMissing)
diff --git a/spec/bundler/support/artifice/compact_index_extra_missing.rb b/spec/bundler/support/artifice/compact_index_extra_missing.rb
index 67a9d23691..255c89afdb 100644
--- a/spec/bundler/support/artifice/compact_index_extra_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_missing.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index_extra", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index_extra"
class CompactIndexExtraMissing < CompactIndexExtra
get "/extra/fetch/actual/gem/:id" do
if params[:id] == "missing-1.0.gemspec.rz"
halt 404
else
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexExtraMissing)
diff --git a/spec/bundler/support/artifice/compact_index_forbidden.rb b/spec/bundler/support/artifice/compact_index_forbidden.rb
index 0a4dfdb2e8..18c30ed9a2 100644
--- a/spec/bundler/support/artifice/compact_index_forbidden.rb
+++ b/spec/bundler/support/artifice/compact_index_forbidden.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexForbidden < CompactIndexAPI
get "/versions" do
@@ -10,4 +8,6 @@ class CompactIndexForbidden < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexForbidden)
diff --git a/spec/bundler/support/artifice/compact_index_host_redirect.rb b/spec/bundler/support/artifice/compact_index_host_redirect.rb
index ab371117de..4f82bf3812 100644
--- a/spec/bundler/support/artifice/compact_index_host_redirect.rb
+++ b/spec/bundler/support/artifice/compact_index_host_redirect.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexHostRedirect < CompactIndexAPI
- get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
+ get "/fetch/actual/gem/:id", host_name: "localgemserver.test" do
redirect "http://bundler.localgemserver.test#{request.path_info}"
end
@@ -18,4 +16,6 @@ class CompactIndexHostRedirect < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexHostRedirect)
diff --git a/spec/bundler/support/artifice/compact_index_mirror_down.rb b/spec/bundler/support/artifice/compact_index_mirror_down.rb
new file mode 100644
index 0000000000..88983c715d
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_mirror_down.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+require_relative "helpers/artifice"
+require_relative "helpers/rack_request"
+
+module Artifice
+ module Net
+ class HTTPMirrorDown < HTTP
+ def connect
+ raise SocketError if address == "gem.mirror"
+
+ super
+ end
+ end
+
+ HTTP.endpoint = CompactIndexAPI
+ end
+
+ replace_net_http(Net::HTTPMirrorDown)
+end
diff --git a/spec/bundler/support/artifice/compact_index_no_checksums.rb b/spec/bundler/support/artifice/compact_index_no_checksums.rb
new file mode 100644
index 0000000000..ecb7fc7d7c
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_no_checksums.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexNoChecksums < CompactIndexAPI
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ gem.versions.map(&:number).join("\n")
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexNoChecksums)
diff --git a/spec/bundler/support/artifice/compact_index_no_gem.rb b/spec/bundler/support/artifice/compact_index_no_gem.rb
index 01c5be1b3d..71f6629688 100644
--- a/spec/bundler/support/artifice/compact_index_no_gem.rb
+++ b/spec/bundler/support/artifice/compact_index_no_gem.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexNoGem < CompactIndexAPI
get "/gems/:id" do
@@ -10,4 +8,6 @@ class CompactIndexNoGem < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexNoGem)
diff --git a/spec/bundler/support/artifice/compact_index_partial_update.rb b/spec/bundler/support/artifice/compact_index_partial_update.rb
index eaedff5105..f111d91ef9 100644
--- a/spec/bundler/support/artifice/compact_index_partial_update.rb
+++ b/spec/bundler/support/artifice/compact_index_partial_update.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexPartialUpdate < CompactIndexAPI
# Stub the server to never return 304s. This simulates the behaviour of
@@ -18,21 +16,23 @@ class CompactIndexPartialUpdate < CompactIndexAPI
)
# Verify a cached copy of the versions file exists
- unless File.read(cached_versions_path).start_with?("created_at: ")
+ unless File.binread(cached_versions_path).start_with?("created_at: ")
raise("Cached versions file should be present and have content")
end
# Verify that a partial request is made, starting from the index of the
# final byte of the cached file.
- unless env["HTTP_RANGE"] == "bytes=#{File.read(cached_versions_path).bytesize - 1}-"
- raise("Range header should be present, and start from the index of the final byte of the cache.")
+ unless env["HTTP_RANGE"] == "bytes=#{File.binread(cached_versions_path).bytesize - 1}-"
+ raise("Range header should be present, and start from the index of the final byte of the cache. #{env["HTTP_RANGE"].inspect}")
end
etag_response do
# Return the exact contents of the cache.
- File.read(cached_versions_path)
+ File.binread(cached_versions_path)
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexPartialUpdate)
diff --git a/spec/bundler/support/artifice/compact_index_partial_update_bad_digest.rb b/spec/bundler/support/artifice/compact_index_partial_update_bad_digest.rb
new file mode 100644
index 0000000000..ac04336636
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_partial_update_bad_digest.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+# The purpose of this Artifice is to test that an incremental response is invalidated
+# and a second request is issued for the full content.
+class CompactIndexPartialUpdateBadDigest < CompactIndexAPI
+ def partial_update_bad_digest
+ response_body = yield
+ if request.env["HTTP_RANGE"]
+ headers "Repr-Digest" => "sha-256=:#{Digest::SHA256.base64digest("wrong digest on ranged request")}:"
+ else
+ headers "Repr-Digest" => "sha-256=:#{Digest::SHA256.base64digest(response_body)}:"
+ end
+ headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
+ content_type "text/plain"
+ requested_range_for(response_body)
+ end
+
+ get "/versions" do
+ partial_update_bad_digest do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ file.contents([], calculate_info_checksums: true)
+ end
+ end
+
+ get "/info/:name" do
+ partial_update_bad_digest do
+ gem = gems.find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexPartialUpdateBadDigest)
diff --git a/spec/bundler/support/artifice/compact_index_partial_update_no_digest_not_incremental.rb b/spec/bundler/support/artifice/compact_index_partial_update_no_digest_not_incremental.rb
new file mode 100644
index 0000000000..99bae039f0
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_partial_update_no_digest_not_incremental.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+# The purpose of this Artifice is to test that an incremental response is ignored
+# when the digest is not present to verify that the partial response is valid.
+class CompactIndexPartialUpdateNoDigestNotIncremental < CompactIndexAPI
+ def partial_update_no_digest
+ response_body = yield
+ headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
+ content_type "text/plain"
+ requested_range_for(response_body)
+ end
+
+ get "/versions" do
+ partial_update_no_digest do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ lines = file.contents([], calculate_info_checksums: true).split("\n")
+ name, versions, checksum = lines.last.split(" ")
+
+ # shuffle versions so new versions are not appended to the end
+ [*lines[0..-2], [name, versions.split(",").reverse.join(","), checksum].join(" ")].join("\n")
+ end
+ end
+
+ get "/info/:name" do
+ partial_update_no_digest do
+ gem = gems.find {|g| g.name == params[:name] }
+ lines = CompactIndex.info(gem ? gem.versions : []).split("\n")
+
+ # shuffle versions so new versions are not appended to the end
+ [lines.first, lines.last, *lines[1..-2]].join("\n")
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexPartialUpdateNoDigestNotIncremental)
diff --git a/spec/bundler/support/artifice/compact_index_precompiled_before.rb b/spec/bundler/support/artifice/compact_index_precompiled_before.rb
new file mode 100644
index 0000000000..b5f72f546a
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_precompiled_before.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexPrecompiledBefore < CompactIndexAPI
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ move_ruby_variant_to_the_end(CompactIndex.info(gem ? gem.versions : []))
+ end
+ end
+
+ private
+
+ def move_ruby_variant_to_the_end(response)
+ lines = response.split("\n")
+ ruby = lines.find {|line| /\A\d+\.\d+\.\d* \|/.match(line) }
+ lines.delete(ruby)
+ lines.push(ruby).join("\n")
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexPrecompiledBefore)
diff --git a/spec/bundler/support/artifice/compact_index_range_ignored.rb b/spec/bundler/support/artifice/compact_index_range_ignored.rb
new file mode 100644
index 0000000000..2303682c1f
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_range_ignored.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexRangeIgnored < CompactIndexAPI
+ # Stub the server to not return 304 so that we don't bypass all the logic
+ def not_modified?(_checksum)
+ false
+ end
+
+ get "/versions" do
+ cached_versions_path = File.join(
+ Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
+ )
+
+ # Verify a cached copy of the versions file exists
+ unless File.binread(cached_versions_path).size > 0
+ raise("Cached versions file should be present and have content")
+ end
+
+ # Verify that a partial request is made, starting from the index of the
+ # final byte of the cached file.
+ unless env.delete("HTTP_RANGE")
+ raise("Expected client to write the full response on the first try")
+ end
+
+ etag_response do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ file.contents
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexRangeIgnored)
diff --git a/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb b/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
index 487be4771a..8a7c4b79b0 100644
--- a/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
+++ b/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexRangeNotSatisfiable < CompactIndexAPI
get "/versions" do
@@ -11,7 +9,7 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI
else
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
file.contents
@@ -31,4 +29,6 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexRangeNotSatisfiable)
diff --git a/spec/bundler/support/artifice/compact_index_rate_limited.rb b/spec/bundler/support/artifice/compact_index_rate_limited.rb
new file mode 100644
index 0000000000..4495491635
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_rate_limited.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexRateLimited < CompactIndexAPI
+ class RequestCounter
+ def self.queue
+ @queue ||= Thread::Queue.new
+ end
+
+ def self.size
+ @queue.size
+ end
+
+ def self.enq(name)
+ @queue.enq(name)
+ end
+
+ def self.deq
+ @queue.deq
+ end
+ end
+
+ configure do
+ RequestCounter.queue
+ end
+
+ get "/info/:name" do
+ RequestCounter.enq(params[:name])
+
+ begin
+ if RequestCounter.size == 1
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ else
+ status 429
+ end
+ ensure
+ RequestCounter.deq
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexRateLimited)
diff --git a/spec/bundler/support/artifice/compact_index_redirects.rb b/spec/bundler/support/artifice/compact_index_redirects.rb
index e83451b5b6..f7ba393239 100644
--- a/spec/bundler/support/artifice/compact_index_redirects.rb
+++ b/spec/bundler/support/artifice/compact_index_redirects.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexRedirect < CompactIndexAPI
get "/fetch/actual/gem/:id" do
@@ -18,4 +16,6 @@ class CompactIndexRedirect < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexRedirect)
diff --git a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
index abbf3258e7..96259385e7 100644
--- a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
+++ b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexStrictBasicAuthentication < CompactIndexAPI
before do
@@ -12,9 +10,11 @@ class CompactIndexStrictBasicAuthentication < CompactIndexAPI
# Only accepts password == "password"
unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz"
- halt 403, "Authentication failed"
+ halt 401, "Authentication failed"
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexStrictBasicAuthentication)
diff --git a/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb b/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
index 7e1d3686e2..15850599b6 100644
--- a/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
+++ b/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexWrongDependencies < CompactIndexAPI
get "/info/:name" do
@@ -14,4 +12,6 @@ class CompactIndexWrongDependencies < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexWrongDependencies)
diff --git a/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb b/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
index db4d8e3974..9bd2ca0a9d 100644
--- a/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
+++ b/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
-require File.expand_path("../compact_index", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexWrongGemChecksum < CompactIndexAPI
get "/info/:name" do
etag_response do
name = params[:name]
gem = gems.find {|g| g.name == name }
- checksum = ENV.fetch("BUNDLER_SPEC_#{name.upcase}_CHECKSUM") { "ab" * 22 }
+ # This generates the hexdigest "2222222222222222222222222222222222222222222222222222222222222222"
+ checksum = ENV.fetch("BUNDLER_SPEC_#{name.upcase}_CHECKSUM") { "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI=" }
versions = gem ? gem.versions : []
versions.each {|v| v.checksum = checksum }
CompactIndex.info(versions)
@@ -17,4 +16,6 @@ class CompactIndexWrongGemChecksum < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexWrongGemChecksum)
diff --git a/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb b/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb
deleted file mode 100644
index 12a6fa153f..0000000000
--- a/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require File.expand_path("../endpoint_marshal_fail", __FILE__)
-
-Artifice.deactivate
-
-class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
- before do
- unless env["HTTP_AUTHORIZATION"]
- halt 401, "Authentication info not supplied"
- end
- end
-end
-
-Artifice.activate_with(EndpointMarshalFailBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint.rb b/spec/bundler/support/artifice/endpoint.rb
index 9a0cfae8a2..15242a7942 100644
--- a/spec/bundler/support/artifice/endpoint.rb
+++ b/spec/bundler/support/artifice/endpoint.rb
@@ -1,100 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../../path.rb", __FILE__)
-require Spec::Path.root.join("lib/bundler/deprecate")
-include Spec::Path
-
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,rack,tilt,sinatra}-*/lib")].map(&:to_s))
-require "artifice"
-require "sinatra/base"
-
-ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
-ALL_REQUESTS_MUTEX = Mutex.new
-
-at_exit do
- if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
- expected = expected.split("\n").sort
- actual = ALL_REQUESTS.sort
-
- unless expected == actual
- raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
- end
- end
-end
-
-class Endpoint < Sinatra::Base
- def self.all_requests
- @all_requests ||= []
- end
-
- GEM_REPO = Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
- set :raise_errors, true
- set :show_exceptions, false
-
- def call!(*)
- super.tap do
- ALL_REQUESTS_MUTEX.synchronize do
- ALL_REQUESTS << @request.url
- end
- end
- end
-
- helpers do
- def dependencies_for(gem_names, gem_repo = GEM_REPO)
- return [] if gem_names.nil? || gem_names.empty?
-
- require "rubygems"
- require "bundler"
- Bundler::Deprecate.skip_during do
- all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read)
- end.inject(:+)
-
- all_specs.map do |name, version, platform|
- spec = load_spec(name, version, platform, gem_repo)
- next unless gem_names.include?(spec.name)
- {
- :name => spec.name,
- :number => spec.version.version,
- :platform => spec.platform.to_s,
- :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
- [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
- end
- }
- end.compact
- end
- end
-
- def load_spec(name, version, platform, gem_repo)
- full_name = "#{name}-#{version}"
- full_name += "-#{platform}" if platform != "ruby"
- Marshal.load(Bundler.rubygems.inflate(File.open(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz")).read))
- end
- end
-
- get "/quick/Marshal.4.8/:id" do
- redirect "/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/fetch/actual/gem/:id" do
- File.read("#{GEM_REPO}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/gems/:id" do
- File.read("#{GEM_REPO}/gems/#{params[:id]}")
- end
-
- get "/api/v1/dependencies" do
- Marshal.dump(dependencies_for(params[:gems]))
- end
-
- get "/specs.4.8.gz" do
- File.read("#{GEM_REPO}/specs.4.8.gz")
- end
-
- get "/prerelease_specs.4.8.gz" do
- File.read("#{GEM_REPO}/prerelease_specs.4.8.gz")
- end
-end
+require_relative "helpers/endpoint"
+require_relative "helpers/artifice"
Artifice.activate_with(Endpoint)
diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb
index 202ccfc829..9dd373bbf6 100644
--- a/spec/bundler/support/artifice/endpoint_500.rb
+++ b/spec/bundler/support/artifice/endpoint_500.rb
@@ -1,19 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../../path.rb", __FILE__)
-include Spec::Path
+require_relative "../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,rack,tilt,sinatra}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
-require "artifice"
require "sinatra/base"
-Artifice.deactivate
-
class Endpoint500 < Sinatra::Base
before do
halt 500
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(Endpoint500)
diff --git a/spec/bundler/support/artifice/endpoint_api_forbidden.rb b/spec/bundler/support/artifice/endpoint_api_forbidden.rb
index bb89747adc..6bdc5896d6 100644
--- a/spec/bundler/support/artifice/endpoint_api_forbidden.rb
+++ b/spec/bundler/support/artifice/endpoint_api_forbidden.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointApiForbidden < Endpoint
get "/api/v1/dependencies" do
@@ -10,4 +8,6 @@ class EndpointApiForbidden < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointApiForbidden)
diff --git a/spec/bundler/support/artifice/endpoint_api_missing.rb b/spec/bundler/support/artifice/endpoint_api_missing.rb
deleted file mode 100644
index 95db8e2a7e..0000000000
--- a/spec/bundler/support/artifice/endpoint_api_missing.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
-
-class EndpointApiMissing < Endpoint
- get "/fetch/actual/gem/:id" do
- $stderr.puts params[:id]
- if params[:id] == "rack-1.0.gemspec.rz"
- halt 404
- else
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
- end
-end
-
-Artifice.activate_with(EndpointApiMissing)
diff --git a/spec/bundler/support/artifice/endpoint_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_basic_authentication.rb
index 223671bc29..e8e3569e63 100644
--- a/spec/bundler/support/artifice/endpoint_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointBasicAuthentication < Endpoint
before do
@@ -12,4 +10,6 @@ class EndpointBasicAuthentication < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
index 925954b12d..9cbb4de61a 100644
--- a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointCredsDiffHost < Endpoint
helpers do
@@ -26,14 +24,16 @@ class EndpointCredsDiffHost < Endpoint
end
get "/gems/:id" do
- redirect "http://diffhost.com/no/creds/#{params[:id]}"
+ redirect "http://diffhost.test/no/creds/#{params[:id]}"
end
get "/no/creds/:id" do
if request.host.include?("diffhost") && !auth.provided?
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointCredsDiffHost)
diff --git a/spec/bundler/support/artifice/endpoint_extra.rb b/spec/bundler/support/artifice/endpoint_extra.rb
index 422f65401b..021fd435fe 100644
--- a/spec/bundler/support/artifice/endpoint_extra.rb
+++ b/spec/bundler/support/artifice/endpoint_extra.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointExtra < Endpoint
get "/extra/api/v1/dependencies" do
@@ -10,11 +8,11 @@ class EndpointExtra < Endpoint
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo2}/specs.4.8.gz")
+ File.binread("#{gem_repo2}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo2}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -22,12 +20,14 @@ class EndpointExtra < Endpoint
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo2}/gems/#{params[:id]}")
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtra)
diff --git a/spec/bundler/support/artifice/endpoint_extra_api.rb b/spec/bundler/support/artifice/endpoint_extra_api.rb
index 62e2c2bb93..a965af6e73 100644
--- a/spec/bundler/support/artifice/endpoint_extra_api.rb
+++ b/spec/bundler/support/artifice/endpoint_extra_api.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointExtraApi < Endpoint
get "/extra/api/v1/dependencies" do
@@ -11,11 +9,11 @@ class EndpointExtraApi < Endpoint
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo4}/specs.4.8.gz")
+ File.binread("#{gem_repo4}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo4}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -23,12 +21,14 @@ class EndpointExtraApi < Endpoint
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo4}/gems/#{params[:id]}")
+ File.binread("#{gem_repo4}/gems/#{params[:id]}")
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtraApi)
diff --git a/spec/bundler/support/artifice/endpoint_extra_missing.rb b/spec/bundler/support/artifice/endpoint_extra_missing.rb
index 038a12610a..73e2defb32 100644
--- a/spec/bundler/support/artifice/endpoint_extra_missing.rb
+++ b/spec/bundler/support/artifice/endpoint_extra_missing.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint_extra", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint_extra"
class EndpointExtraMissing < EndpointExtra
get "/extra/fetch/actual/gem/:id" do
if params[:id] == "missing-1.0.gemspec.rz"
halt 404
else
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtraMissing)
diff --git a/spec/bundler/support/artifice/endpoint_fallback.rb b/spec/bundler/support/artifice/endpoint_fallback.rb
index 554c08f0a2..742e563f07 100644
--- a/spec/bundler/support/artifice/endpoint_fallback.rb
+++ b/spec/bundler/support/artifice/endpoint_fallback.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointFallback < Endpoint
DEPENDENCY_LIMIT = 60
@@ -16,4 +14,6 @@ class EndpointFallback < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointFallback)
diff --git a/spec/bundler/support/artifice/endpoint_host_redirect.rb b/spec/bundler/support/artifice/endpoint_host_redirect.rb
index cda5664be2..6ce51bed93 100644
--- a/spec/bundler/support/artifice/endpoint_host_redirect.rb
+++ b/spec/bundler/support/artifice/endpoint_host_redirect.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointHostRedirect < Endpoint
- get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
+ get "/fetch/actual/gem/:id", host_name: "localgemserver.test" do
redirect "http://bundler.localgemserver.test#{request.path_info}"
end
@@ -14,4 +12,6 @@ class EndpointHostRedirect < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointHostRedirect)
diff --git a/spec/bundler/support/artifice/endpoint_marshal_fail.rb b/spec/bundler/support/artifice/endpoint_marshal_fail.rb
index 2a5dcdc2fd..74ce321de6 100644
--- a/spec/bundler/support/artifice/endpoint_marshal_fail.rb
+++ b/spec/bundler/support/artifice/endpoint_marshal_fail.rb
@@ -1,13 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint_fallback", __FILE__)
-
-Artifice.deactivate
-
-class EndpointMarshalFail < EndpointFallback
- get "/api/v1/dependencies" do
- "f0283y01hasf"
- end
-end
+require_relative "helpers/endpoint_marshal_fail"
+require_relative "helpers/artifice"
Artifice.activate_with(EndpointMarshalFail)
diff --git a/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
new file mode 100644
index 0000000000..ea4cfbe965
--- /dev/null
+++ b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require_relative "helpers/endpoint_marshal_fail"
+
+class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
+ before do
+ unless env["HTTP_AUTHORIZATION"]
+ halt 401, "Authentication info not supplied"
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(EndpointMarshalFailBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_mirror_source.rb b/spec/bundler/support/artifice/endpoint_mirror_source.rb
index 64452f198d..fed7a746b9 100644
--- a/spec/bundler/support/artifice/endpoint_mirror_source.rb
+++ b/spec/bundler/support/artifice/endpoint_mirror_source.rb
@@ -1,15 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
+require_relative "helpers/endpoint"
class EndpointMirrorSource < Endpoint
get "/gems/:id" do
- if request.env["HTTP_X_GEMFILE_SOURCE"] == "https://server.example.org/"
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ if request.env["HTTP_X_GEMFILE_SOURCE"] == "https://server.example.org/" && request.env["HTTP_USER_AGENT"].start_with?("bundler")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
else
halt 500
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointMirrorSource)
diff --git a/spec/bundler/support/artifice/endpoint_redirect.rb b/spec/bundler/support/artifice/endpoint_redirect.rb
index ebf01458ba..84f546ba9d 100644
--- a/spec/bundler/support/artifice/endpoint_redirect.rb
+++ b/spec/bundler/support/artifice/endpoint_redirect.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointRedirect < Endpoint
get "/fetch/actual/gem/:id" do
@@ -14,4 +12,6 @@ class EndpointRedirect < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointRedirect)
diff --git a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
index 905a519f3f..dff360c5c5 100644
--- a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointStrictBasicAuthentication < Endpoint
before do
@@ -12,9 +10,11 @@ class EndpointStrictBasicAuthentication < Endpoint
# Only accepts password == "password"
unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz"
- halt 403, "Authentication failed"
+ halt 401, "Authentication failed"
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointStrictBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_timeout.rb b/spec/bundler/support/artifice/endpoint_timeout.rb
index 3f60471c90..86b793e499 100644
--- a/spec/bundler/support/artifice/endpoint_timeout.rb
+++ b/spec/bundler/support/artifice/endpoint_timeout.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require File.expand_path("../endpoint_fallback", __FILE__)
-
-Artifice.deactivate
+require_relative "helpers/endpoint_fallback"
class EndpointTimeout < EndpointFallback
SLEEP_TIMEOUT = 3
@@ -12,4 +10,6 @@ class EndpointTimeout < EndpointFallback
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointTimeout)
diff --git a/spec/bundler/support/artifice/fail.rb b/spec/bundler/support/artifice/fail.rb
index 1059c6df4e..5ddbc4e590 100644
--- a/spec/bundler/support/artifice/fail.rb
+++ b/spec/bundler/support/artifice/fail.rb
@@ -1,20 +1,11 @@
# frozen_string_literal: true
-require "net/http"
-begin
- require "net/https"
-rescue LoadError
- nil # net/https or openssl
-end
-
-# We can't use artifice here because it uses rack
-
-module Artifice; end # for < 2.0, Net::HTTP::Persistent::SSLReuse
+require_relative "../vendored_net_http"
-class Fail < Net::HTTP
- # Net::HTTP uses a @newimpl instance variable to decide whether
+class Fail < Gem::Net::HTTP
+ # Gem::Net::HTTP uses a @newimpl instance variable to decide whether
# to use a legacy implementation. Since we are subclassing
- # Net::HTTP, we must set it
+ # Gem::Net::HTTP, we must set it
@newimpl = true
def request(req, body = nil, &block)
@@ -26,14 +17,11 @@ class Fail < Net::HTTP
end
def exception(req)
- name = ENV.fetch("BUNDLER_SPEC_EXCEPTION") { "Errno::ENETUNREACH" }
- const = name.split("::").reduce(Object) {|mod, sym| mod.const_get(sym) }
- const.new("host down: Bundler spec artifice fail! #{req["PATH_INFO"]}")
+ Errno::ENETUNREACH.new("host down: Bundler spec artifice fail! #{req["PATH_INFO"]}")
end
end
-# Replace Net::HTTP with our failing subclass
-::Net.class_eval do
- remove_const(:HTTP)
- const_set(:HTTP, ::Fail)
-end
+require_relative "helpers/artifice"
+
+# Replace Gem::Net::HTTP with our failing subclass
+Artifice.replace_net_http(::Fail)
diff --git a/spec/bundler/support/artifice/helpers/artifice.rb b/spec/bundler/support/artifice/helpers/artifice.rb
new file mode 100644
index 0000000000..788268295c
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/artifice.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+# This module was initially borrowed from https://github.com/wycats/artifice
+module Artifice
+ # Activate Artifice with a particular Rack endpoint.
+ #
+ # Calling this method will replace the Gem::Net::HTTP system
+ # with a replacement that routes all requests to the
+ # Rack endpoint.
+ #
+ # @param [#call] endpoint A valid Rack endpoint
+ def self.activate_with(endpoint)
+ require_relative "rack_request"
+
+ Net::HTTP.endpoint = endpoint
+ replace_net_http(Artifice::Net::HTTP)
+ end
+
+ # Deactivate the Artifice replacement.
+ def self.deactivate
+ replace_net_http(::Gem::Net::HTTP)
+ end
+
+ def self.replace_net_http(value)
+ ::Gem::Net.class_eval do
+ remove_const(:HTTP)
+ const_set(:HTTP, value)
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index.rb b/spec/bundler/support/artifice/helpers/compact_index.rb
new file mode 100644
index 0000000000..e684aa8628
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+$LOAD_PATH.unshift Spec::Path.tmp_root.join("compact_index/lib").to_s
+require "compact_index"
+require "digest"
+
+class CompactIndexAPI < Endpoint
+ helpers do
+ include Spec::Path
+
+ def load_spec(name, version, platform, gem_repo)
+ full_name = "#{name}-#{version}"
+ full_name += "-#{platform}" if platform != "ruby"
+ Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
+ end
+
+ def etag_response
+ response_body = yield
+ etag = Digest::MD5.hexdigest(response_body)
+ headers "ETag" => quote(etag)
+ return if not_modified?(etag)
+ headers "Repr-Digest" => "sha-256=:#{Digest::SHA256.base64digest(response_body)}:"
+ headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
+ content_type "text/plain"
+ requested_range_for(response_body)
+ rescue StandardError => e
+ puts e
+ puts e.backtrace
+ raise
+ end
+
+ def not_modified?(etag)
+ etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
+
+ return unless etags.include?(etag)
+ status 304
+ body ""
+ end
+
+ def requested_range_for(response_body)
+ ranges = Rack::Utils.get_byte_ranges(env["HTTP_RANGE"], response_body.bytesize)
+
+ if ranges
+ status 206
+ body ranges.map! {|range| slice_body(response_body, range) }.join
+ else
+ status 200
+ body response_body
+ end
+ end
+
+ def quote(string)
+ %("#{string}")
+ end
+
+ def parse_etags(value)
+ value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
+ end
+
+ def slice_body(body, range)
+ body.byteslice(range)
+ end
+
+ def gems(gem_repo = default_gem_repo)
+ @gems ||= {}
+ @gems[gem_repo] ||= begin
+ specs = Bundler::Deprecate.skip_during do
+ %w[specs.4.8 prerelease_specs.4.8].flat_map do |filename|
+ spec_index = gem_repo.join(filename)
+ next [] unless File.exist?(spec_index)
+
+ Marshal.load(File.binread(spec_index)).map do |name, version, platform|
+ load_spec(name, version, platform, gem_repo)
+ end
+ end
+ end
+
+ specs.group_by(&:name).map do |name, versions|
+ gem_versions = versions.map do |spec|
+ deps = spec.runtime_dependencies.map do |d|
+ reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
+ CompactIndex::Dependency.new(d.name, reqs)
+ end
+ begin
+ checksum = ENV.fetch("BUNDLER_SPEC_#{name.upcase}_CHECKSUM") do
+ Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").hexdigest
+ end
+ rescue StandardError
+ checksum = nil
+ end
+ build_gem_version(spec, deps, checksum)
+ end
+ CompactIndex::Gem.new(name, gem_versions)
+ end
+ end
+ end
+
+ def build_gem_version(spec, deps, checksum)
+ CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil,
+ deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s)
+ end
+ end
+
+ get "/names" do
+ etag_response do
+ CompactIndex.names(gems.map(&:name))
+ end
+ end
+
+ get "/versions" do
+ etag_response do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ file.contents
+ end
+ end
+
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index_cooldown.rb b/spec/bundler/support/artifice/helpers/compact_index_cooldown.rb
new file mode 100644
index 0000000000..9920fd2c95
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index_cooldown.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+class CompactIndexCooldownAPI < CompactIndexAPI
+ helpers do
+ def build_gem_version(spec, deps, checksum)
+ created_at = spec.date&.utc&.iso8601
+ CompactIndex::GemVersionV2.new(spec.version.version, spec.platform.to_s, checksum, nil,
+ deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s, created_at)
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index_extra.rb b/spec/bundler/support/artifice/helpers/compact_index_extra.rb
new file mode 100644
index 0000000000..9e742630dd
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index_extra.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+class CompactIndexExtra < CompactIndexAPI
+ get "/extra/versions" do
+ halt 404
+ end
+
+ get "/extra/api/v1/dependencies" do
+ halt 404
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo2}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb b/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb
new file mode 100644
index 0000000000..d9a7d83d23
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+class CompactIndexExtraApi < CompactIndexAPI
+ get "/extra/names" do
+ etag_response do
+ CompactIndex.names(gems(gem_repo4).map(&:name))
+ end
+ end
+
+ get "/extra/versions" do
+ etag_response do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems(gem_repo4))
+ file.contents
+ end
+ end
+
+ get "/extra/info/:name" do
+ etag_response do
+ gem = gems(gem_repo4).find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo4}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo4}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint.rb b/spec/bundler/support/artifice/helpers/endpoint.rb
new file mode 100644
index 0000000000..9590611dfe
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require_relative "../../path"
+
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
+
+require "sinatra/base"
+
+ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
+ALL_REQUESTS_MUTEX = Thread::Mutex.new
+
+at_exit do
+ if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
+ expected = expected.split("\n").sort
+ actual = ALL_REQUESTS.sort
+
+ unless expected == actual
+ raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
+ end
+ end
+end
+
+class Endpoint < Sinatra::Base
+ def self.all_requests
+ @all_requests ||= []
+ end
+
+ set :raise_errors, true
+ set :show_exceptions, false
+ set :host_authorization, permitted_hosts: [".example.org", ".local", ".mirror", ".repo", ".repo1", ".repo2", ".repo3", ".repo4", ".rubygems.org", ".security", ".source", ".test", "127.0.0.1"]
+
+ def call!(*)
+ super.tap do
+ ALL_REQUESTS_MUTEX.synchronize do
+ ALL_REQUESTS << @request.url
+ end
+ end
+ end
+
+ helpers do
+ include Spec::Path
+
+ def default_gem_repo
+ if ENV["BUNDLER_SPEC_GEM_REPO"]
+ Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"])
+ else
+ case request.host
+ when "gem.repo1"
+ Spec::Path.gem_repo1
+ when "gem.repo2"
+ Spec::Path.gem_repo2
+ when "gem.repo3"
+ Spec::Path.gem_repo3
+ when "gem.repo4"
+ Spec::Path.gem_repo4
+ else
+ Spec::Path.gem_repo1
+ end
+ end
+ end
+
+ def dependencies_for(gem_names, gem_repo = default_gem_repo)
+ return [] if gem_names.nil? || gem_names.empty?
+
+ all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
+ Marshal.load(File.binread(gem_repo.join(filename)))
+ end.inject(:+)
+
+ all_specs.filter_map do |name, version, platform|
+ spec = load_spec(name, version, platform, gem_repo)
+ next unless gem_names.include?(spec.name)
+ {
+ name: spec.name,
+ number: spec.version.version,
+ platform: spec.platform.to_s,
+ dependencies: spec.runtime_dependencies.map do |dep|
+ [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
+ end,
+ }
+ end
+ end
+
+ def load_spec(name, version, platform, gem_repo)
+ full_name = "#{name}-#{version}"
+ full_name += "-#{platform}" if platform != "ruby"
+ Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
+ end
+ end
+
+ get "/quick/Marshal.4.8/:id" do
+ redirect "/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/fetch/actual/gem/:id" do
+ File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/gems/:id" do
+ File.binread("#{default_gem_repo}/gems/#{params[:id]}")
+ end
+
+ get "/api/v1/dependencies" do
+ Marshal.dump(dependencies_for(params[:gems]))
+ end
+
+ get "/specs.4.8.gz" do
+ File.binread("#{default_gem_repo}/specs.4.8.gz")
+ end
+
+ get "/prerelease_specs.4.8.gz" do
+ File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_extra.rb b/spec/bundler/support/artifice/helpers/endpoint_extra.rb
new file mode 100644
index 0000000000..ad08495b50
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_extra.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+class EndpointExtra < Endpoint
+ get "/extra/api/v1/dependencies" do
+ halt 404
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo2}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_fallback.rb b/spec/bundler/support/artifice/helpers/endpoint_fallback.rb
new file mode 100644
index 0000000000..a232930b67
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_fallback.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+class EndpointFallback < Endpoint
+ DEPENDENCY_LIMIT = 60
+
+ get "/api/v1/dependencies" do
+ if params[:gems] && params[:gems].size <= DEPENDENCY_LIMIT
+ Marshal.dump(dependencies_for(params[:gems]))
+ else
+ halt 413, "Too many gems to resolve, please request less than #{DEPENDENCY_LIMIT} gems"
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb b/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb
new file mode 100644
index 0000000000..c409d39d99
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative "endpoint_fallback"
+
+class EndpointMarshalFail < EndpointFallback
+ get "/api/v1/dependencies" do
+ "f0283y01hasf"
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/rack_request.rb b/spec/bundler/support/artifice/helpers/rack_request.rb
new file mode 100644
index 0000000000..05ff034463
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/rack_request.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require "rack/test"
+require_relative "../../vendored_net_http"
+
+module Artifice
+ module Net
+ # This is an internal object that can receive Rack requests
+ # to the application using the Rack::Test API
+ class RackRequest
+ include Rack::Test::Methods
+ attr_reader :app
+
+ def initialize(app)
+ @app = app
+ end
+ end
+
+ class HTTP < ::Gem::Net::HTTP
+ class << self
+ attr_accessor :endpoint
+ end
+
+ # Gem::Net::HTTP uses a @newimpl instance variable to decide whether
+ # to use a legacy implementation. Since we are subclassing
+ # Gem::Net::HTTP, we must set it
+ @newimpl = true
+
+ # We don't need to connect, so blank out this method
+ def connect
+ end
+
+ # Replace the Gem::Net::HTTP request method with a method
+ # that converts the request into a Rack request and
+ # dispatches it to the Rack endpoint.
+ #
+ # @param [Net::HTTPRequest] req A Gem::Net::HTTPRequest
+ # object, or one if its subclasses
+ # @param [optional, String, #read] body This should
+ # be sent as "rack.input". If it's a String, it will
+ # be converted to a StringIO.
+ # @return [Net::HTTPResponse]
+ #
+ # @yield [Net::HTTPResponse] If a block is provided,
+ # this method will yield the Gem::Net::HTTPResponse to
+ # it after the body is read.
+ def request(req, body = nil, &block)
+ rack_request = RackRequest.new(self.class.endpoint)
+
+ req.each_header do |header, value|
+ rack_request.header(header, value)
+ end
+
+ scheme = use_ssl? ? "https" : "http"
+ prefix = "#{scheme}://#{addr_port}"
+ body_stream_contents = req.body_stream.read if req.body_stream
+
+ response = rack_request.request("#{prefix}#{req.path}",
+ { method: req.method, input: body || req.body || body_stream_contents })
+
+ make_net_http_response(response, &block)
+ end
+
+ private
+
+ # This method takes a Rack response and creates a Gem::Net::HTTPResponse
+ # Instead of trying to mock HTTPResponse directly, we just convert
+ # the Rack response into a String that looks like a normal HTTP
+ # response and call Gem::Net::HTTPResponse.read_new
+ #
+ # @param [Array(#to_i, Hash, #each)] response a Rack response
+ # @return [Net::HTTPResponse]
+ # @yield [Net::HTTPResponse] If a block is provided, yield the
+ # response to it after the body is read
+ def make_net_http_response(response)
+ status = response.status
+ headers = response.headers
+ body = response.body
+
+ response_string = []
+ response_string << "HTTP/1.1 #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
+
+ headers.each do |header, value|
+ response_string << "#{header}: #{value}"
+ end
+
+ response_string << "" << body
+
+ response_io = ::Gem::Net::BufferedIO.new(StringIO.new(response_string.join("\n")))
+ res = ::Gem::Net::HTTPResponse.read_new(response_io)
+
+ res.reading_body(response_io, true) do
+ yield res if block_given?
+ end
+
+ res
+ end
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb
index edd2f49a91..0bf5ade8f6 100644
--- a/spec/bundler/support/artifice/vcr.rb
+++ b/spec/bundler/support/artifice/vcr.rb
@@ -1,18 +1,13 @@
# frozen_string_literal: true
-require "net/http"
-if RUBY_VERSION < "1.9"
- begin
- require "net/https"
- rescue LoadError
- nil # net/https or openssl
- end
-end # but only for 1.8
+require_relative "../vendored_net_http"
+require_relative "../path"
-CASSETTE_PATH = File.expand_path("../vcr_cassettes", __FILE__)
+CASSETTE_PATH = "#{Spec::Path.spec_dir}/support/artifice/vcr_cassettes".freeze
+USED_CASSETTES_PATH = "#{Spec::Path.spec_dir}/support/artifice/used_cassettes.txt".freeze
CASSETTE_NAME = ENV.fetch("BUNDLER_SPEC_VCR_CASSETTE_NAME") { "realworld" }
-class BundlerVCRHTTP < Net::HTTP
+class BundlerVCRHTTP < Gem::Net::HTTP
class RequestHandler
attr_reader :http, :request, :body, :response_block
def initialize(http, request, body = nil, &response_block)
@@ -28,6 +23,10 @@ class BundlerVCRHTTP < Net::HTTP
@__vcr_request_handler = handler
end
+ File.open(USED_CASSETTES_PATH, "a+") do |f|
+ f.puts request_pair_paths.map {|path| Pathname.new(path).relative_path_from(Spec::Path.git_root).to_s }.join("\n")
+ end
+
if recorded_response?
recorded_response
else
@@ -37,19 +36,18 @@ class BundlerVCRHTTP < Net::HTTP
def recorded_response?
return true if ENV["BUNDLER_SPEC_PRE_RECORDED"]
- return false if ENV["BUNDLER_SPEC_FORCE_RECORD"]
request_pair_paths.all? {|f| File.exist?(f) }
end
def recorded_response
File.open(request_pair_paths.last, "rb:ASCII-8BIT") do |response_file|
- response_io = ::Net::BufferedIO.new(response_file)
- ::Net::HTTPResponse.read_new(response_io).tap do |response|
+ response_io = ::Gem::Net::BufferedIO.new(response_file)
+ ::Gem::Net::HTTPResponse.read_new(response_io).tap do |response|
response.decode_content = request.decode_content if request.respond_to?(:decode_content)
- response.uri = request.uri if request.respond_to?(:uri)
+ response.uri = request.uri
response.reading_body(response_io, request.response_body_permitted?) do
- response_block.call(response) if response_block
+ response_block&.call(response)
end
end
end
@@ -63,6 +61,7 @@ class BundlerVCRHTTP < Net::HTTP
response = http.request_without_vcr(request, body, &response_block)
@recording = false
unless @recording
+ require "fileutils"
FileUtils.mkdir_p(File.dirname(request_path))
binwrite(request_path, request_to_string(request))
binwrite(response_path, response_to_string(response))
@@ -75,30 +74,13 @@ class BundlerVCRHTTP < Net::HTTP
end
def file_name_for_key(key)
- key.join("/").gsub(/[\:*?"<>|]/, "-")
+ File.join(*key).gsub(/[\:*?"<>|]/, "-")
end
def request_pair_paths
%w[request response].map do |kind|
- File.join(CASSETTE_PATH, CASSETTE_NAME, file_name_for_key(key + [kind]))
- end
- end
-
- def read_stored_request(path)
- contents = File.read(path)
- headers = {}
- method = nil
- path = nil
- contents.lines.grep(/^> /).each do |line|
- if line =~ /^> (GET|HEAD|POST|PATCH|PUT|DELETE) (.*)/
- method = $1
- path = $2.strip
- elsif line =~ /^> (.*?): (.*)/
- headers[$1] = $2
- end
+ File.join(CASSETTE_PATH, CASSETTE_NAME, file_name_for_key(key), kind)
end
- body = contents =~ /^([^>].*)/m && $1
- Net::HTTP.const_get(method.capitalize).new(path, headers).tap {|r| r.body = body if body }
end
def request_to_string(request)
@@ -139,6 +121,19 @@ class BundlerVCRHTTP < Net::HTTP
end
end
+ def start_with_vcr
+ if ENV["BUNDLER_SPEC_PRE_RECORDED"]
+ raise IOError, "HTTP session already opened" if @started
+ @socket = nil
+ @started = true
+ else
+ start_without_vcr
+ end
+ end
+
+ alias_method :start_without_vcr, :start
+ alias_method :start, :start_with_vcr
+
def request_with_vcr(request, *args, &block)
handler = request.instance_eval do
remove_instance_variable(:@__vcr_request_handler) if defined?(@__vcr_request_handler)
@@ -151,8 +146,7 @@ class BundlerVCRHTTP < Net::HTTP
alias_method :request, :request_with_vcr
end
-# Replace Net::HTTP with our VCR subclass
-::Net.class_eval do
- remove_const(:HTTP)
- const_set(:HTTP, BundlerVCRHTTP)
-end
+require_relative "helpers/artifice"
+
+# Replace Gem::Net::HTTP with our VCR subclass
+Artifice.replace_net_http(BundlerVCRHTTP)
diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb
index f39b2c6d53..3056540beb 100644
--- a/spec/bundler/support/artifice/windows.rb
+++ b/spec/bundler/support/artifice/windows.rb
@@ -1,23 +1,17 @@
# frozen_string_literal: true
-require File.expand_path("../../path.rb", __FILE__)
-include Spec::Path
-
-$LOAD_PATH.unshift Dir[base_system_gems.join("gems/artifice*/lib")].first.to_s
-$LOAD_PATH.unshift(*Dir[base_system_gems.join("gems/rack-*/lib")])
-$LOAD_PATH.unshift Dir[base_system_gems.join("gems/tilt*/lib")].first.to_s
-$LOAD_PATH.unshift Dir[base_system_gems.join("gems/sinatra*/lib")].first.to_s
-require "artifice"
-require "sinatra/base"
+require_relative "../path"
+
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
-Artifice.deactivate
+require "sinatra/base"
class Windows < Sinatra::Base
set :raise_errors, true
set :show_exceptions, false
helpers do
- def gem_repo
+ def default_gem_repo
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
end
end
@@ -29,7 +23,7 @@ class Windows < Sinatra::Base
files.each do |file|
get "/#{file}" do
- File.read gem_repo.join(file)
+ File.binread default_gem_repo.join(file)
end
end
@@ -46,4 +40,6 @@ class Windows < Sinatra::Base
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(Windows)
diff --git a/spec/bundler/support/build_metadata.rb b/spec/bundler/support/build_metadata.rb
new file mode 100644
index 0000000000..2eade4137b
--- /dev/null
+++ b/spec/bundler/support/build_metadata.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require_relative "path"
+require_relative "helpers"
+
+module Spec
+ module BuildMetadata
+ include Spec::Path
+ include Spec::Helpers
+
+ def write_build_metadata(dir: source_root, version: Bundler::VERSION)
+ build_metadata = {
+ git_commit_sha: git_commit_sha,
+ built_at: release_date_for(version, dir: dir),
+ }
+
+ replace_build_metadata(build_metadata, dir: dir)
+ end
+
+ def reset_build_metadata(dir: source_root)
+ build_metadata = {
+ built_at: nil,
+ }
+
+ replace_build_metadata(build_metadata, dir: dir)
+ end
+
+ private
+
+ def replace_build_metadata(build_metadata, dir:)
+ build_metadata_file = File.expand_path("lib/bundler/build_metadata.rb", dir)
+
+ ivars = build_metadata.sort.map do |k, v|
+ " @#{k} = #{loaded_gemspec.send(:ruby_code, v)}"
+ end.join("\n")
+
+ contents = File.read(build_metadata_file)
+ contents.sub!(/^(\s+# begin ivars).+(^\s+# end ivars)/m, "\\1\n#{ivars}\n\\2")
+ File.open(build_metadata_file, "w") {|f| f << contents }
+ end
+
+ def git_commit_sha
+ ruby_core_tarball? ? "unknown" : git("rev-parse --short HEAD", source_root).strip
+ end
+
+ def release_date_for(version, dir:)
+ changelog = File.expand_path("CHANGELOG.md", dir)
+ File.readlines(changelog)[2].scan(/^## #{Regexp.escape(version)} \((.*)\)/).first&.first if File.exist?(changelog)
+ end
+
+ extend self
+ end
+end
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index 97134a045a..43ab7e053d 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -2,9 +2,18 @@
require "bundler/shared_helpers"
require "shellwords"
+require "fileutils"
+require "rubygems/package"
+
+require_relative "build_metadata"
module Spec
module Builders
+ def self.extended(mod)
+ mod.extend Path
+ mod.extend Helpers
+ end
+
def self.constantize(name)
name.delete("-").upcase
end
@@ -19,28 +28,35 @@ module Spec
def build_repo1
build_repo gem_repo1 do
- build_gem "rack", %w[0.9.1 1.0.0] do |s|
- s.executables = "rackup"
- s.post_install_message = "Rack's post install message"
+ FileUtils.cp rake_path, "#{gem_repo1}/gems/"
+
+ build_gem "coffee-script-source"
+ build_gem "git"
+ build_gem "puma"
+ build_gem "minitest"
+
+ build_gem "myrack", %w[0.9.1 1.0.0] do |s|
+ s.executables = "myrackup"
+ s.post_install_message = "Myrack's post install message"
end
build_gem "thin" do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
s.post_install_message = "Thin's post install message"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
- s.post_install_message = "Rack-obama's post install message"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
+ s.post_install_message = "Myrack-obama's post install message"
end
- build_gem "rack_middleware", "1.0" do |s|
- s.add_dependency "rack", "0.9.1"
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "0.9.1"
end
build_gem "rails", "2.3.2" do |s|
s.executables = "rails"
- s.add_dependency "rake", "10.0.2"
+ s.add_dependency "rake", rake_version
s.add_dependency "actionpack", "2.3.2"
s.add_dependency "activerecord", "2.3.2"
s.add_dependency "actionmailer", "2.3.2"
@@ -64,40 +80,28 @@ module Spec
s.add_dependency "activesupport", ">= 2.0.0"
end
- build_gem "rails_fail" do |s|
- s.add_dependency "activesupport", "= 1.2.3"
- end
-
- build_gem "missing_dep" do |s|
- s.add_dependency "not_here"
- end
-
- build_gem "rspec", "1.2.7", :no_default => true do |s|
+ build_gem "rspec", "1.2.7", no_default: true do |s|
s.write "lib/spec.rb", "SPEC = '1.2.7'"
end
- build_gem "rack-test", :no_default => true do |s|
- s.write "lib/rack/test.rb", "RACK_TEST = '1.0'"
- end
-
- build_gem "platform_specific" do |s|
- s.platform = Bundler.local_platform
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ build_gem "myrack-test", no_default: true do |s|
+ s.write "lib/myrack/test.rb", "MYRACK_TEST = '1.0'"
end
build_gem "platform_specific" do |s|
s.platform = "java"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 JAVA'"
end
build_gem "platform_specific" do |s|
s.platform = "ruby"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
end
build_gem "platform_specific" do |s|
s.platform = "x86-mswin32"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 MSWIN'"
+ end
+
+ build_gem "platform_specific" do |s|
+ s.platform = "x64-mswin64"
end
build_gem "platform_specific" do |s|
@@ -105,39 +109,37 @@ module Spec
end
build_gem "platform_specific" do |s|
- s.platform = "x64-mingw32"
+ s.platform = "x64-mingw-ucrt"
+ end
+
+ build_gem "platform_specific" do |s|
+ s.platform = "aarch64-mingw-ucrt"
end
build_gem "platform_specific" do |s|
s.platform = "x86-darwin-100"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 x86-darwin-100'"
end
build_gem "only_java", "1.0" do |s|
s.platform = "java"
- s.write "lib/only_java.rb", "ONLY_JAVA = '1.0.0 JAVA'"
end
build_gem "only_java", "1.1" do |s|
s.platform = "java"
- s.write "lib/only_java.rb", "ONLY_JAVA = '1.1.0 JAVA'"
end
build_gem "nokogiri", "1.4.2"
build_gem "nokogiri", "1.4.2" do |s|
s.platform = "java"
- s.write "lib/nokogiri.rb", "NOKOGIRI = '1.4.2 JAVA'"
s.add_dependency "weakling", ">= 0.0.3"
end
build_gem "laduradura", "5.15.2"
build_gem "laduradura", "5.15.2" do |s|
s.platform = "java"
- s.write "lib/laduradura.rb", "LADURADURA = '5.15.2 JAVA'"
end
build_gem "laduradura", "5.15.3" do |s|
s.platform = "java"
- s.write "lib/laduradura.rb", "LADURADURA = '5.15.2 JAVA'"
end
build_gem "weakling", "0.0.3"
@@ -146,55 +148,12 @@ module Spec
build_gem "duradura", "7.0"
- build_gem "multiple_versioned_deps" do |s|
- s.add_dependency "weakling", ">= 0.0.1", "< 0.1"
- end
-
- build_gem "not_released", "1.0.pre"
-
- build_gem "has_prerelease", "1.0"
- build_gem "has_prerelease", "1.1.pre"
-
- build_gem "with_development_dependency" do |s|
- s.add_development_dependency "activesupport", "= 2.3.5"
- end
-
- build_gem "with_license" do |s|
- s.license = "MIT"
- end
-
- build_gem "with_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
- f.puts "IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
- build_gem "another_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
- f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
build_gem "very_simple_binary", &:add_c_extension
build_gem "simple_binary", &:add_c_extension
build_gem "bundler", "0.9" do |s|
s.executables = "bundle"
- s.write "bin/bundle", "puts 'FAIL'"
+ s.write "bin/bundle", "#!/usr/bin/env ruby\nputs 'FAIL'"
end
# The bundler 0.8 gem has a rubygems plugin that always loads :(
@@ -203,149 +162,63 @@ module Spec
s.write "lib/rubygems_plugin.rb", "require 'bundler/omg' ; puts 'FAIL'"
end
- build_gem "bundler_dep" do |s|
- s.add_dependency "bundler"
- end
-
# The yard gem iterates over Gem.source_index looking for plugins
build_gem "yard" do |s|
s.write "lib/yard.rb", <<-Y
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.8.10")
- specs = Gem::Specification
- else
- specs = Gem.source_index.find_name('')
- end
- specs.sort_by(&:name).each do |gem|
+ Gem::Specification.sort_by(&:name).each do |gem|
puts gem.full_name
end
Y
end
- # The rcov gem is platform mswin32, but has no arch
- build_gem "rcov" do |s|
- s.platform = Gem::Platform.new([nil, "mswin32", nil])
- s.write "lib/rcov.rb", "RCOV = '1.0.0'"
- end
-
build_gem "net-ssh"
build_gem "net-sftp", "1.1.1" do |s|
s.add_dependency "net-ssh", ">= 1.0.0", "< 1.99.0"
end
- # Test complicated gem dependencies for install
- build_gem "net_a" do |s|
- s.add_dependency "net_b"
- s.add_dependency "net_build_extensions"
- end
-
- build_gem "net_b"
-
- build_gem "net_build_extensions" do |s|
- s.add_dependency "rake"
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/net_build_extensions.rb", "w") do |f|
- f.puts "NET_BUILD_EXTENSIONS = 'YES'"
- end
- end
- RUBY
- end
-
- build_gem "net_c" do |s|
- s.add_dependency "net_a"
- s.add_dependency "net_d"
- end
-
- build_gem "net_d"
-
- build_gem "net_e" do |s|
- s.add_dependency "net_d"
- end
-
- # Capistrano did this (at least until version 2.5.10)
- # RubyGems 2.2 doesn't allow the specifying of a dependency twice
- # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f
- build_gem "double_deps", "1.0", :skip_validation => true do |s|
- s.add_dependency "net-ssh", ">= 1.0.0"
- s.add_dependency "net-ssh"
- end
-
build_gem "foo"
-
- # A minimal fake pry console
- build_gem "pry" do |s|
- s.write "lib/pry.rb", <<-RUBY
- class Pry
- class << self
- def toplevel_binding
- unless defined?(@toplevel_binding) && @toplevel_binding
- TOPLEVEL_BINDING.eval %{
- def self.__pry__; binding; end
- Pry.instance_variable_set(:@toplevel_binding, __pry__)
- class << self; undef __pry__; end
- }
- end
- @toplevel_binding.eval('private')
- @toplevel_binding
- end
-
- def __pry__
- while line = gets
- begin
- puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1')
- rescue Exception => e
- puts "\#{e.class}: \#{e.message}"
- puts e.backtrace.first
- end
- end
- end
- alias start __pry__
- end
- end
- RUBY
- end
end
end
- def build_repo2(&blk)
- FileUtils.rm_rf gem_repo2
- FileUtils.cp_r gem_repo1, gem_repo2
- update_repo2(&blk) if block_given?
+ def build_repo2(**kwargs, &blk)
+ FileUtils.cp_r gem_repo1, gem_repo2, remove_destination: true
+ update_repo2(**kwargs, &blk) if block_given?
end
- def build_repo3
- build_repo gem_repo3 do
- build_gem "rack"
+ # A repo that has no pre-installed gems included. (The caller completely
+ # determines the contents with the block.)
+ #
+ # If the repo already exists, `#update_repo` will be called.
+ def build_repo3(**kwargs, &blk)
+ if File.exist?(gem_repo3)
+ update_repo(gem_repo3, &blk)
+ else
+ build_repo gem_repo3, **kwargs, &blk
end
- FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
end
- # A repo that has no pre-installed gems included. (The caller completely
- # determines the contents with the block.)
- def build_repo4(&blk)
- FileUtils.rm_rf gem_repo4
- build_repo(gem_repo4, &blk)
+ # Like build_repo3, this is a repo that has no pre-installed gems included.
+ #
+ # If the repo already exists, `#udpate_repo` will be called
+ def build_repo4(**kwargs, &blk)
+ if File.exist?(gem_repo4)
+ update_repo gem_repo4, &blk
+ else
+ build_repo gem_repo4, **kwargs, &blk
+ end
end
- def update_repo4(&blk)
- update_repo(gem_repo4, &blk)
+ def update_repo2(**kwargs, &blk)
+ update_repo(gem_repo2, **kwargs, &blk)
end
- def update_repo2
- update_repo gem_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
- end
- yield if block_given?
- end
+ def update_repo3(&blk)
+ update_repo(gem_repo3, &blk)
end
def build_security_repo
build_repo security_repo do
- build_gem "rack"
+ build_gem "myrack"
build_gem "signed_gem" do |s|
cert = "signing-cert.pem"
@@ -358,37 +231,60 @@ module Spec
end
end
- def build_repo(path, &blk)
- return if File.directory?(path)
- rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
+ # A minimal fake irb console
+ def build_dummy_irb(version = "9.9.9")
+ build_gem "irb", version do |s|
+ s.write "lib/irb.rb", <<-RUBY
+ class IRB
+ class << self
+ def toplevel_binding
+ unless defined?(@toplevel_binding) && @toplevel_binding
+ TOPLEVEL_BINDING.eval %{
+ def self.__irb__; binding; end
+ IRB.instance_variable_set(:@toplevel_binding, __irb__)
+ class << self; undef __irb__; end
+ }
+ end
+ @toplevel_binding.eval('private')
+ @toplevel_binding
+ end
- if rake_path.nil?
- Spec::Path.base_system_gems.rmtree
- Spec::Rubygems.setup
- rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
+ def __irb__
+ while line = gets
+ begin
+ puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1')
+ rescue Exception => e
+ puts "\#{e.class}: \#{e.message}"
+ puts e.backtrace.first
+ end
+ end
+ end
+ alias start __irb__
+ end
+ end
+ RUBY
end
+ end
- if rake_path
- FileUtils.mkdir_p("#{path}/gems")
- FileUtils.cp rake_path, "#{path}/gems/"
- else
- abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again."
- end
+ def build_repo(path, **kwargs, &blk)
+ return if File.directory?(path)
+
+ FileUtils.mkdir_p("#{path}/gems")
- update_repo(path, &blk)
+ update_repo(path,**kwargs, &blk)
end
- def update_repo(path)
- if path == gem_repo1 && caller.first.split(" ").last == "`build_repo`"
+ def update_repo(path, build_compact_index: true)
+ exempted_caller = Gem.ruby_version >= Gem::Version.new("3.4.0.dev") && RUBY_ENGINE != "jruby" ? "#{Module.nesting.first}#build_repo" : "build_repo"
+ if path == gem_repo1 && caller_locations(1, 1).first.label != exempted_caller
raise "Updating gem_repo1 is unsupported -- use gem_repo2 instead"
end
return unless block_given?
@_build_path = "#{path}/gems"
@_build_repo = File.basename(path)
yield
- with_gem_path_as Path.base_system_gems do
- Dir.chdir(path) { gem_command! :generate_index }
- end
+ options = { build_compact: build_compact_index }
+ Gem::Indexer.new(path, options).generate_index
ensure
@_build_path = nil
@_build_repo = nil
@@ -413,14 +309,14 @@ module Spec
end
end
- def build_dep(name, requirements = Gem::Requirement.default, type = :runtime)
- Bundler::Dependency.new(name, :version => requirements)
- end
-
def build_lib(name, *args, &blk)
build_with(LibBuilder, name, args, &blk)
end
+ def build_bundler(*args, &blk)
+ build_with(BundlerBuilder, "bundler", args, &blk)
+ end
+
def build_gem(name, *args, &blk)
build_with(GemBuilder, name, args, &blk)
end
@@ -429,20 +325,20 @@ module Spec
opts = args.last.is_a?(Hash) ? args.last : {}
builder = opts[:bare] ? GitBareBuilder : GitBuilder
spec = build_with(builder, name, args, &block)
- GitReader.new(opts[:path] || lib_path(spec.full_name))
+ GitReader.new(self, opts[:path] || lib_path(spec.full_name))
end
def update_git(name, *args, &block)
opts = args.last.is_a?(Hash) ? args.last : {}
spec = build_with(GitUpdater, name, args, &block)
- GitReader.new(opts[:path] || lib_path(spec.full_name))
+ GitReader.new(self, opts[:path] || lib_path(spec.full_name))
end
def build_plugin(name, *args, &blk)
build_with(PluginBuilder, name, args, &blk)
end
- private
+ private
def build_with(builder, name, args, &blk)
@_build_path ||= nil
@@ -456,7 +352,6 @@ module Spec
Array(versions).each do |version|
spec = builder.new(self, name, version)
- spec.authors = ["no one"] if !spec.authors || spec.authors.empty?
yield spec if block_given?
spec._build(options)
end
@@ -527,6 +422,58 @@ module Spec
alias_method :dep, :runtime
end
+ class BundlerBuilder
+ def initialize(context, name, version)
+ @context = context
+ @spec = Spec::Path.loaded_gemspec.dup
+ @spec.version = version || Bundler::VERSION
+ end
+
+ def required_ruby_version
+ @spec.required_ruby_version
+ end
+
+ def required_ruby_version=(x)
+ @spec.required_ruby_version = x
+ end
+
+ def _build(options = {})
+ full_name = "bundler-#{@spec.version}"
+ build_path = (options[:build_path] || @context.tmp) + full_name
+ bundler_path = build_path + "#{full_name}.gem"
+
+ FileUtils.mkdir_p build_path
+
+ @context.shipped_files.each do |shipped_file|
+ target_shipped_file = shipped_file
+ target_shipped_file = shipped_file.sub(/\Alibexec/, "exe") if @context.ruby_core?
+ target_shipped_file = build_path + target_shipped_file
+ target_shipped_dir = File.dirname(target_shipped_file)
+ FileUtils.mkdir_p target_shipped_dir unless File.directory?(target_shipped_dir)
+ FileUtils.cp File.expand_path(shipped_file, @context.source_root), target_shipped_file, preserve: true
+ end
+
+ @context.replace_version_file(@spec.version, dir: build_path)
+ @context.replace_changelog(@spec.version, dir: build_path) if options[:released]
+
+ Spec::BuildMetadata.write_build_metadata(dir: build_path, version: @spec.version.to_s)
+
+ Dir.chdir build_path do
+ Gem::DefaultUserInteraction.use_ui(Gem::SilentUI.new) do
+ Gem::Package.build(@spec)
+ end
+ end
+
+ if block_given?
+ yield(bundler_path)
+ else
+ FileUtils.mv bundler_path, options[:path]
+ end
+ ensure
+ FileUtils.rm_rf build_path
+ end
+ end
+
class LibBuilder
def initialize(context, name, version)
@context = context
@@ -540,6 +487,7 @@ module Spec
s.email = "foo@bar.baz"
s.homepage = "http://example.com"
s.license = "MIT"
+ s.required_ruby_version = ">= 3.0"
end
@files = {}
end
@@ -556,25 +504,17 @@ module Spec
@spec.executables = Array(val)
@spec.executables.each do |file|
executable = "#{@spec.bindir}/#{file}"
- shebang = if Bundler.current_ruby.jruby?
- "#!/usr/bin/env jruby\n"
- else
- "#!/usr/bin/env ruby\n"
- end
+ shebang = "#!/usr/bin/env ruby\n"
@spec.files << executable
- write executable, "#{shebang}require '#{@name}' ; puts #{Builders.constantize(@name)}"
+ write executable, "#{shebang}require_relative '../lib/#{@name}' ; puts #{Builders.constantize(@name)}"
end
end
def add_c_extension
- require_paths << "ext"
extensions << "ext/extconf.rb"
write "ext/extconf.rb", <<-RUBY
require "mkmf"
-
- # exit 1 unless with_config("simple")
-
extension_name = "#{name}_c"
if extra_lib_dir = with_config("ext-lib")
# add extra libpath if --with-ext-lib is
@@ -588,7 +528,7 @@ module Spec
write "ext/#{name}.c", <<-C
#include "ruby.h"
- void Init_#{name}_c() {
+ void Init_#{name}_c(void) {
rb_define_module("#{Builders.constantize(name)}_IN_C");
}
C
@@ -599,11 +539,20 @@ module Spec
if options[:rubygems_version]
@spec.rubygems_version = options[:rubygems_version]
- def @spec.mark_version; end
def @spec.validate(*); end
end
+ unless options[:no_default]
+ gem_source = options[:source] || "path@#{path}"
+ @files = _default_files.
+ merge("lib/#{entrypoint}/source.rb" => "#{Builders.constantize(name)}_SOURCE = #{gem_source.to_s.dump}").
+ merge(@files)
+ end
+
+ @spec.authors = ["no one"]
+ @spec.files += @files.keys
+
case options[:gemspec]
when false
# do nothing
@@ -613,140 +562,118 @@ module Spec
@files["#{name}.gemspec"] = @spec.to_ruby
end
- unless options[:no_default]
- gem_source = options[:source] || "path@#{path}"
- @files = _default_files.
- merge("lib/#{name}/source.rb" => "#{Builders.constantize(name)}_SOURCE = #{gem_source.to_s.dump}").
- merge(@files)
- end
-
- @spec.authors = ["no one"]
-
@files.each do |file, source|
- file = Pathname.new(path).join(file)
- FileUtils.mkdir_p(file.dirname)
- File.open(file, "w") {|f| f.puts source }
+ full_path = Pathname.new(path).join(file)
+ FileUtils.mkdir_p(full_path.dirname)
+ File.open(full_path, "w") {|f| f.puts source }
+ FileUtils.chmod("+x", full_path) if @spec.executables.map {|exe| "#{@spec.bindir}/#{exe}" }.include?(file)
end
- @spec.files = @files.keys
path
end
def _default_files
- @_default_files ||= begin
- platform_string = " #{@spec.platform}" unless @spec.platform == Gem::Platform::RUBY
- { "lib/#{name}.rb" => "#{Builders.constantize(name)} = '#{version}#{platform_string}'" }
- end
+ @_default_files ||= { "lib/#{entrypoint}.rb" => "#{Builders.constantize(name)} = '#{version}#{platform_string}'" }
+ end
+
+ def entrypoint
+ name.tr("-", "/")
end
def _default_path
@context.tmp("libs", @spec.full_name)
end
+
+ def platform_string
+ " #{@spec.platform}" unless @spec.platform == Gem::Platform::RUBY
+ end
end
class GitBuilder < LibBuilder
def _build(options)
+ default_branch = options[:default_branch] || "main"
path = options[:path] || _default_path
source = options[:source] || "git@#{path}"
- super(options.merge(:path => path, :source => source))
- Dir.chdir(path) do
- `git init`
- `git add *`
- `git config user.email "lol@wut.com"`
- `git config user.name "lolwut"`
- `git commit -m 'OMG INITIAL COMMIT'`
- end
+ super(options.merge(path: path, source: source))
+ @context.git("config --global init.defaultBranch #{default_branch}", path)
+ @context.git("init", path)
+ @context.git("add *", path)
+ @context.git("config user.email lol@wut.com", path)
+ @context.git("config user.name lolwut", path)
+ @context.git("config commit.gpgsign false", path)
+ @context.git("commit -m OMG_INITIAL_COMMIT", path)
end
end
class GitBareBuilder < LibBuilder
def _build(options)
path = options[:path] || _default_path
- super(options.merge(:path => path))
- Dir.chdir(path) do
- `git init --bare`
- end
+ super(options.merge(path: path))
+ @context.git("init --bare", path)
end
end
class GitUpdater < LibBuilder
- def silently(str)
- `#{str} 2>#{Bundler::NULL}`
- end
-
def _build(options)
libpath = options[:path] || _default_path
update_gemspec = options[:gemspec] || false
source = options[:source] || "git@#{libpath}"
- Dir.chdir(libpath) do
- silently "git checkout master"
-
- if branch = options[:branch]
- raise "You can't specify `master` as the branch" if branch == "master"
- escaped_branch = Shellwords.shellescape(branch)
-
- if `git branch | grep #{escaped_branch}`.empty?
- silently("git branch #{escaped_branch}")
- end
-
- silently("git checkout #{escaped_branch}")
- elsif tag = options[:tag]
- `git tag #{Shellwords.shellescape(tag)}`
- elsif options[:remote]
- silently("git remote add origin file://#{options[:remote]}")
- elsif options[:push]
- silently("git push origin #{options[:push]}")
- end
+ if branch = options[:branch]
+ @context.git("checkout -b #{Shellwords.shellescape(branch)}", libpath)
+ elsif tag = options[:tag]
+ @context.git("tag #{Shellwords.shellescape(tag)}", libpath)
+ elsif options[:remote]
+ @context.git("remote add origin #{options[:remote]}", libpath)
+ elsif options[:push]
+ @context.git("push origin #{options[:push]}", libpath)
+ end
- current_ref = `git rev-parse HEAD`.strip
- _default_files.keys.each do |path|
- _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'"
- end
- super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source))
- `git add *`
- `git commit -m "BUMP"`
+ current_ref = @context.git("rev-parse HEAD", libpath).strip
+ _default_files.keys.each do |path|
+ _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'"
end
+ super(options.merge(path: libpath, gemspec: update_gemspec, source: source))
+ @context.git("commit -am BUMP", libpath)
end
end
class GitReader
- attr_reader :path
+ attr_reader :context, :path
- def initialize(path)
+ def initialize(context, path)
+ @context = context
@path = path
end
def ref_for(ref, len = nil)
- ref = git "rev-parse #{ref}"
+ ref = context.git "rev-parse #{ref}", path
ref = ref[0..len] if len
ref
end
-
- private
-
- def git(cmd)
- Bundler::SharedHelpers.with_clean_git_env do
- Dir.chdir(@path) { `git #{cmd}`.strip }
- end
- end
end
class GemBuilder < LibBuilder
def _build(opts)
- lib_path = super(opts.merge(:path => @context.tmp(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default]))
+ lib_path = opts[:lib_path] || @context.tmp(".tmp/#{@spec.full_name}")
+ lib_path = super(opts.merge(path: lib_path, no_default: opts[:no_default]))
destination = opts[:path] || _default_path
- Dir.chdir(lib_path) do
- FileUtils.mkdir_p(destination)
+ FileUtils.mkdir_p(lib_path.join(destination))
- @spec.authors = ["that guy"] if !@spec.authors || @spec.authors.empty?
-
- Bundler.rubygems.build(@spec, opts[:skip_validation])
+ if [:yaml, false].include?(opts[:gemspec])
+ Dir.chdir(lib_path) do
+ Bundler.rubygems.build(@spec, opts[:skip_validation])
+ end
+ elsif opts[:skip_validation]
+ Dir.chdir(lib_path) { Gem::Package.build(@spec, true) }
+ else
+ Dir.chdir(lib_path) { Gem::Package.build(@spec) }
end
+
gem_path = File.expand_path("#{@spec.full_name}.gem", lib_path)
if opts[:to_system]
- @context.system_gems gem_path, :keep_path => true
+ @context.system_gems gem_path, default: opts[:default]
elsif opts[:to_bundle]
- @context.system_gems gem_path, :path => :bundle_path, :keep_path => true
+ @context.system_gems gem_path, path: @context.default_bundle_path
else
FileUtils.mv(gem_path, destination)
end
@@ -759,60 +686,63 @@ module Spec
class PluginBuilder < GemBuilder
def _default_files
- @_default_files ||= super.merge("plugins.rb" => "")
+ @_default_files ||= {
+ "lib/#{name}.rb" => "#{Builders.constantize(name)} = '#{version}#{platform_string}'",
+ "plugins.rb" => "",
+ }
end
end
- TEST_CERT = <<-CERT.gsub(/^\s*/, "")
+ TEST_CERT = <<~CERT
-----BEGIN CERTIFICATE-----
- MIIDMjCCAhqgAwIBAgIBATANBgkqhkiG9w0BAQUFADAnMQwwCgYDVQQDDAN5b3Ux
+ MIIDNTCCAh2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAnMQwwCgYDVQQDDAN5b3Ux
FzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTE1MDIwODAwMTIyM1oXDTQyMDYy
NTAwMTIyM1owJzEMMAoGA1UEAwwDeW91MRcwFQYKCZImiZPyLGQBGRYHZXhhbXBs
- ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANlvFdpN43c4DMS9Jo06
- m0a7k3bQ3HWQ1yrYhZMi77F1F73NpBknYHIzDktQpGn6hs/4QFJT4m4zNEBF47UL
- jHU5nTK5rjkS3niGYUjvh3ZEzVeo9zHUlD/UwflDo4ALl3TSo2KY/KdPS/UTdLXL
- ajkQvaVJtEDgBPE3DPhlj5whp+Ik3mDHej7qpV6F502leAwYaFyOtlEG/ZGNG+nZ
- L0clH0j77HpP42AylHDi+vakEM3xcjo9BeWQ6Vkboic93c9RTt6CWBWxMQP7Nol1
- MOebz9XOSQclxpxWteXNfPRtMdAhmRl76SMI8ywzThNPpa4EH/yz34ftebVOgKyM
- nd0CAwEAAaNpMGcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFA7D
- n9qo0np23qi3aOYuAAPn/5IdMBYGA1UdEQQPMA2BC3lvdUBleGFtcGxlMBYGA1Ud
- EgQPMA2BC3lvdUBleGFtcGxlMA0GCSqGSIb3DQEBBQUAA4IBAQA7Gyk62sWOUX/N
- vk4tJrgKESph6Ns8+E36A7n3jt8zCep8ldzMvwTWquf9iqhsC68FilEoaDnUlWw7
- d6oNuaFkv7zfrWGLlvqQJC+cu2X5EpcCksg5oRp8VNbwJysJ6JgwosxzROII8eXc
- R+j1j6mDvQYqig2QOnzf480pjaqbP+tspfDFZbhKPrgM3Blrb3ZYuFpv4zkqI7aB
- 6fuk2DUhNO1CuwrJA84TqC+jGo73bDKaT5hrIDiaJRrN5+zcWja2uEWrj5jSbep4
- oXdEdyH73hOHMBP40uds3PqnUsxEJhzjB2sCCe1geV24kw9J4m7EQXPVkUKDgKrt
- LlpDmOoo
+ ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkupYkg3Nd1oXM3fo0d
+ mVJBWNrni88lKDuIIQXwcKe6XCgiloZG708ecLTOws9+o9MkTl9Wtpf/WGXT98NK
+ EPUYakd2Fv1SuD1jWYlP7iDR6hB3RkWBm5ziujYftVJ4ZrPD42PLjDASvlh75Tvr
+ MeM7yq/qkcgNsd9dQyUvMNPks3tla9je7Dt7Auli2IN3CNXys7gIOfwJH0Bb/M6t
+ y7oUfpoUKAfLzwe61abztgDu1lSNgdFBM1kcxYflyh/FkX5TlAcWeAXzLrnxAXGR
+ UxXrxW4oPC+kZi/pDRBd7X4zQDx7bCmr1+FsS3M05i3w5E08Tt9iKRk4V8nCmE4i
+ k6UCAwEAAaNsMGowCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYE
+ FOOOFw5TNAqt/TcRRZEU3Dg/58XuMBYGA1UdEQQPMA2BC3lvdUBleGFtcGxlMBYG
+ A1UdEgQPMA2BC3lvdUBleGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQAy3xnmobxU
+ 1SyhHvoIXTJmG0wt1DQ/Dqwjy362LpEf1UHt29wtg1Mph58eVtl93z5Vd2t4/O77
+ E2BHpSu9ujc6/Br4+2uA/Qk/xRyLBtZAwty6J4uFvOOg985HonN+RCUZbKSUTmtA
+ TZvNtIDAZFQ8Tu75K4gIBxDcz7biGi4i1VJ3F3GNCNeossr9IQwKvb+UWFq14U5R
+ IzUnGgMIzcjUG2kKQvddRD1CjS+egtcLvShbOfm5bs4w4rfQ2FPF+Aaf9v7fxa/c
+ Jrf3K+cB19eAy7O4nlPG1xurvnZd0QpqRk++werrBuKe1Pgga7YBLePfJhzwqcZv
+ wVOSsB870yeO
-----END CERTIFICATE-----
CERT
- TEST_PKEY = <<-PKEY.gsub(/^\s*/, "")
+ TEST_PKEY = <<~PKEY
-----BEGIN RSA PRIVATE KEY-----
- MIIEowIBAAKCAQEA2W8V2k3jdzgMxL0mjTqbRruTdtDcdZDXKtiFkyLvsXUXvc2k
- GSdgcjMOS1CkafqGz/hAUlPibjM0QEXjtQuMdTmdMrmuORLeeIZhSO+HdkTNV6j3
- MdSUP9TB+UOjgAuXdNKjYpj8p09L9RN0tctqORC9pUm0QOAE8TcM+GWPnCGn4iTe
- YMd6PuqlXoXnTaV4DBhoXI62UQb9kY0b6dkvRyUfSPvsek/jYDKUcOL69qQQzfFy
- Oj0F5ZDpWRuiJz3dz1FO3oJYFbExA/s2iXUw55vP1c5JByXGnFa15c189G0x0CGZ
- GXvpIwjzLDNOE0+lrgQf/LPfh+15tU6ArIyd3QIDAQABAoIBACbDqz20TS1gDMa2
- gj0DidNedbflHKjJHdNBru7Ad8NHgOgR1YO2hXdWquG6itVqGMbTF4SV9/R1pIcg
- 7qvEV1I+50u31tvOBWOvcYCzU48+TO2n7gowQA3xPHPYHzog1uu48fAOHl0lwgD7
- av9OOK3b0jO5pC08wyTOD73pPWU0NrkTh2+N364leIi1pNuI1z4V+nEuIIm7XpVd
- 5V4sXidMTiEMJwE6baEDfTjHKaoRndXrrPo3ryIXmcX7Ag1SwAQwF5fBCRToCgIx
- dszEZB1bJD5gA6r+eGnJLB/F60nK607az5o3EdguoB2LKa6q6krpaRCmZU5svvoF
- J7xgBPECgYEA8RIzHAQ3zbaibKdnllBLIgsqGdSzebTLKheFuigRotEV3Or/z5Lg
- k/nVnThWVkTOSRqXTNpJAME6a4KTdcVSxYP+SdZVO1esazHrGb7xPVb7MWSE1cqp
- WEk3Yy8OUOPoPQMc4dyGzd30Mi8IBB6gnFIYOTrpUo0XtkBv8rGGhfsCgYEA5uYn
- 6QgL4NqNT84IXylmMb5ia3iBt6lhxI/A28CDtQvfScl4eYK0IjBwdfG6E1vJgyzg
- nJzv3xEVo9bz+Kq7CcThWpK5JQaPnsV0Q74Wjk0ShHet15txOdJuKImnh5F6lylC
- GTLR9gnptytfMH/uuw4ws0Q2kcg4l5NHKOWOnAcCgYEAvAwIVkhsB0n59Wu4gCZu
- FUZENxYWUk/XUyQ6KnZrG2ih90xQ8+iMyqFOIm/52R2fFKNrdoWoALC6E3ct8+ZS
- pMRLrelFXx8K3it4SwMJR2H8XBEfFW4bH0UtsW7Zafv+AunUs9LETP5gKG1LgXsq
- qgXX43yy2LQ61O365YPZfdUCgYBVbTvA3MhARbvYldrFEnUL3GtfZbNgdxuD9Mee
- xig0eJMBIrgfBLuOlqtVB70XYnM4xAbKCso4loKSHnofO1N99siFkRlM2JOUY2tz
- kMWZmmxKdFjuF0WZ5f/5oYxI/QsFGC+rUQEbbWl56mMKd5qkvEhKWudxoklF0yiV
- ufC8SwKBgDWb8iWqWN5a/kfvKoxFcDM74UHk/SeKMGAL+ujKLf58F+CbweM5pX9C
- EUsxeoUEraVWTiyFVNqD81rCdceus9TdBj0ZIK1vUttaRZyrMAwF0uQSfjtxsOpd
- l69BkyvzjgDPkmOHVGiSZDLi3YDvypbUpo6LOy4v5rVg5U2F/A0v
+ MIIEowIBAAKCAQEAyS6liSDc13Whczd+jR2ZUkFY2ueLzyUoO4ghBfBwp7pcKCKW
+ hkbvTx5wtM7Cz36j0yROX1a2l/9YZdP3w0oQ9RhqR3YW/VK4PWNZiU/uINHqEHdG
+ RYGbnOK6Nh+1Unhms8PjY8uMMBK+WHvlO+sx4zvKr+qRyA2x311DJS8w0+Sze2Vr
+ 2N7sO3sC6WLYg3cI1fKzuAg5/AkfQFv8zq3LuhR+mhQoB8vPB7rVpvO2AO7WVI2B
+ 0UEzWRzFh+XKH8WRflOUBxZ4BfMuufEBcZFTFevFbig8L6RmL+kNEF3tfjNAPHts
+ KavX4WxLczTmLfDkTTxO32IpGThXycKYTiKTpQIDAQABAoIBABpyrHEWRed5X7aN
+ kXCBzKSN/LLChT8VNnB6bppLnV501yVbmV2hDlg2EJZkfCMvwIptwnPcKs2uqZ4G
+ u2gMC6X9Bgkg/YK4u4nZJBiIzoMNYEUL48wYGYS1dcokaapO3nQ8M1+XjyAexrFL
+ 5btL1IIisScRTQWiGe6FtzcN43sSNkBISyDF5zG4Kodynqi0ekITmMl2q5XLWcsM
+ KBnmZcRFEmFae2YYczVy8SXNApkZEvN69znvAX1iDNnZ3sJFchXo1nRPt4stOOKw
+ mydgIYqaNQ22aF3OkblvoA4Y4m+X2Qt1sfkryKa5xTT7DSE81GmmazNI64EWqtES
+ 6Xde6P0CgYEA+V1vuSnE5fWX188abWMbVwNMC71WfHbntFmI+qwWYPEpickm+RGX
+ DDfXs5unlVX4KUmjfplgavO29op1GZTuD9TlRnUAV0+0aJnNq4DY6XsHfD84qsBr
+ gQGEHeJ1cMGNDnZR/EV3eudMalj9Qjpx9NoXNzMykb0/SUYZQemiqwcCgYEAzokC
+ s0GoHVJqan4dfU0h0G5QPncrajW9DGG1ySxK/A2eqbVB8W2ZQx39OS26/Gydb31p
+ cR7zm8PZpNbzLqlIMEbD4F6q22xxvYVtDx/HHPjxHMi87yxwQ9uLDUHoMa/LciTO
+ djv3D1xTDDGxbpjmsdmINetunAs3htxku7JY5PMCgYBs3/TVvXzwgmhHm28Ib4sS
+ VKgxP/uw4CGORsFd4SDsNp9SP3c6rAltFjyheMaUlzKApFwz/DdyuvIZdp5mCvZe
+ BzALsS3y8SPtv6lixiDu3/6GqvvM4bKOYuESQzvPfVJfDB4DrTjben2MuUnqTqZO
+ p6IXQc1EgIJPNcH1W1LgpQKBgAKZlPAevngIBpDqn4JpSyititMOevxuSr/yJvCu
+ Xw9HOJ0YTAk3APvoT7y9h6IP1/eEU6R56EUotP+vOQZ4WRFKgsK7TllOxyvElzfe
+ hYom1BoxqLc2Dv+7rsdu8fZWKTB5qCOy44xM9DquEXa79AN/IojTOuQ5++v1sErw
+ ls/jAoGBANneGe9ogN51mYkrLyg1fhU1i24gFRq+sPGEvsCUoE6Vjw/lawQQ80T8
+ v45TFqvhoGpgznqy3qxDJyguquZg6HN2yW6HE2Dvk7uk3XogcjdXgNDmWqb2j0eE
+ z9pKzHCqfwNVPuYf44Znyo2YeyZ2kHn42MU73oXuFshUs3QHcH+P
-----END RSA PRIVATE KEY-----
PKEY
end
diff --git a/spec/bundler/support/bundle b/spec/bundler/support/bundle
new file mode 100755
index 0000000000..8f8b535295
--- /dev/null
+++ b/spec/bundler/support/bundle
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/activate"
+
+load File.expand_path("bundle", Spec::Path.exedir)
diff --git a/spec/bundler/support/bundle.rb b/spec/bundler/support/bundle.rb
new file mode 100644
index 0000000000..aa7b121706
--- /dev/null
+++ b/spec/bundler/support/bundle.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require_relative "path"
+
+warn "#{__FILE__} is deprecated. Please use #{Spec::Path.dev_binstub} instead"
+
+load Spec::Path.dev_binstub
diff --git a/spec/bundler/support/checksums.rb b/spec/bundler/support/checksums.rb
new file mode 100644
index 0000000000..7b69bba668
--- /dev/null
+++ b/spec/bundler/support/checksums.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+module Spec
+ module Checksums
+ class ChecksumsBuilder
+ attr_reader :bundler_registered
+
+ def initialize(enabled = true, &block)
+ @enabled = enabled
+ @checksums = {}
+ yield self if block_given?
+ end
+
+ def initialize_copy(original)
+ super
+ @checksums = @checksums.dup
+ end
+
+ def checksum(repo, name, version, platform = Gem::Platform::RUBY, folder = "gems")
+ @bundler_registered = true if name == "bundler"
+
+ name_tuple = Gem::NameTuple.new(name, version, platform)
+ gem_file = File.join(repo, folder, "#{name_tuple.full_name}.gem")
+ File.open(gem_file, "rb") do |f|
+ register(name_tuple, Bundler::Checksum.from_gem(f, "#{gem_file} (via ChecksumsBuilder#checksum)"))
+ end
+ end
+
+ def no_checksum(name, version, platform = Gem::Platform::RUBY)
+ name_tuple = Gem::NameTuple.new(name, version, platform)
+ register(name_tuple, nil)
+ end
+
+ def delete(name, platform = nil)
+ @checksums.reject! {|k, _| k.name == name && (platform.nil? || k.platform == platform) }
+ end
+
+ def to_s
+ return "" unless @enabled
+
+ locked_checksums = @checksums.map do |name_tuple, checksum|
+ checksum &&= " #{checksum.to_lock}"
+ " #{name_tuple.lock_name}#{checksum}\n"
+ end
+
+ "\nCHECKSUMS\n#{locked_checksums.sort.join}"
+ end
+
+ private
+
+ def register(name_tuple, checksum)
+ delete(name_tuple.name, name_tuple.platform)
+ @checksums[name_tuple] = checksum
+ end
+ end
+
+ def checksums_section(enabled = true, bundler_checksum: true, &block)
+ ChecksumsBuilder.new(enabled, &block).tap do |builder|
+ next if builder.bundler_registered || !bundler_checksum
+
+ next if Bundler::VERSION.to_s.end_with?(".dev")
+ builder.checksum(system_gem_path, "bundler", Bundler::VERSION, Gem::Platform::RUBY, "cache")
+ end
+ end
+
+ def checksums_section_when_enabled(target_lockfile = nil, &block)
+ begin
+ enabled = (target_lockfile || lockfile).match?(/^CHECKSUMS$/)
+ rescue Errno::ENOENT
+ enabled = true
+ end
+ checksums_section(enabled, &block)
+ end
+
+ def checksum_to_lock(*args)
+ checksums_section(true, bundler_checksum: false) do |c|
+ c.checksum(*args)
+ end.to_s.sub(/^CHECKSUMS\n/, "").strip
+ end
+
+ def checksum_digest(*args)
+ checksum_to_lock(*args).split(Bundler::Checksum::ALGO_SEPARATOR, 2).last
+ end
+
+ # if prefixes is given, removes all checksums where the line
+ # has any of the prefixes on the line before the checksum
+ # otherwise, removes all checksums from the lockfile
+ def remove_checksums_from_lockfile(lockfile, *prefixes)
+ head, remaining = lockfile.split(/^CHECKSUMS$/, 2)
+ return lockfile unless remaining
+ checksums, tail = remaining.split("\n\n", 2)
+
+ prefixes =
+ if prefixes.empty?
+ nil
+ else
+ /(#{prefixes.map {|p| Regexp.escape(p) }.join("|")})/
+ end
+
+ checksums = checksums.each_line.map do |line|
+ if prefixes.nil? || line.match?(prefixes)
+ line.gsub(/ sha256=[a-f0-9]{64}/i, "")
+ else
+ line
+ end
+ end
+
+ head.concat(
+ "CHECKSUMS",
+ checksums.join,
+ "\n\n",
+ tail
+ )
+ end
+
+ def remove_checksums_section_from_lockfile(lockfile)
+ head, remaining = lockfile.split(/^CHECKSUMS$/, 2)
+ return lockfile unless remaining
+ _checksums, tail = remaining.split("\n\n", 2)
+ head.concat(tail)
+ end
+
+ def checksum_from_package(gem_file, name, version)
+ name_tuple = Gem::NameTuple.new(name, version)
+
+ checksum = nil
+
+ File.open(gem_file, "rb") do |f|
+ checksum = Bundler::Checksum.from_gem(f, gemfile)
+ end
+
+ "#{name_tuple.lock_name} #{checksum.to_lock}"
+ end
+ end
+end
diff --git a/spec/bundler/support/code_climate.rb b/spec/bundler/support/code_climate.rb
deleted file mode 100644
index a15442cabe..0000000000
--- a/spec/bundler/support/code_climate.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module CodeClimate
- def self.setup
- require "codeclimate-test-reporter"
- ::CodeClimate::TestReporter.start
- configure_exclusions
- rescue LoadError
- # it's fine if CodeClimate isn't set up
- nil
- end
-
- def self.configure_exclusions
- SimpleCov.start do
- add_filter "/bin/"
- add_filter "/lib/bundler/man/"
- add_filter "/lib/bundler/vendor/"
- add_filter "/man/"
- add_filter "/pkg/"
- add_filter "/spec/"
- add_filter "/tmp/"
- end
- end
- end
-end
diff --git a/spec/bundler/support/command_execution.rb b/spec/bundler/support/command_execution.rb
index 556285ac52..e2915b996d 100644
--- a/spec/bundler/support/command_execution.rb
+++ b/spec/bundler/support/command_execution.rb
@@ -1,25 +1,38 @@
# frozen_string_literal: true
-require "support/helpers"
-require "support/path"
-
module Spec
- CommandExecution = Struct.new(:command, :working_directory, :exitstatus, :stdout, :stderr) do
- include RSpec::Matchers::Composable
+ class CommandExecution
+ def initialize(command, timeout:)
+ @command = command
+ @timeout = timeout
+ @original_stdout = String.new
+ @original_stderr = String.new
+ end
- def to_s
- c = Shellwords.shellsplit(command.strip).map {|s| s.include?("\n") ? " \\\n <<EOS\n#{s.gsub(/^/, " ").chomp}\nEOS" : Shellwords.shellescape(s) }
- c = c.reduce("") do |acc, elem|
- concat = acc + " " + elem
-
- last_line = concat.match(/.*\z/)[0]
- if last_line.size >= 100
- acc + " \\\n " + elem
- else
- concat
- end
+ attr_accessor :exitstatus, :command, :original_stdout, :original_stderr
+ attr_reader :timeout
+ attr_writer :failure_reason
+
+ def raise_error!
+ return unless failure?
+
+ error_header = if failure_reason == :timeout
+ "Invoking `#{command}` was aborted after #{timeout} seconds with output:"
+ else
+ "Invoking `#{command}` failed with output:"
end
- "$ #{c.strip}"
+
+ raise <<~ERROR
+ #{error_header}
+
+ ----------------------------------------------------------------------
+ #{stdboth}
+ ----------------------------------------------------------------------
+ ERROR
+ end
+
+ def to_s
+ "$ #{command}"
end
alias_method :inspect, :to_s
@@ -27,12 +40,12 @@ module Spec
@stdboth ||= [stderr, stdout].join("\n").strip
end
- def bundler_err
- if Bundler::VERSION.start_with?("1.")
- stdout
- else
- stderr
- end
+ def stdout
+ normalize(original_stdout)
+ end
+
+ def stderr
+ normalize(original_stderr)
end
def to_s_verbose
@@ -53,5 +66,13 @@ module Spec
return true unless exitstatus
exitstatus > 0
end
+
+ private
+
+ attr_reader :failure_reason
+
+ def normalize(string)
+ string.dup.force_encoding(Encoding::UTF_8).scrub.strip.gsub("\r\n", "\n")
+ end
end
end
diff --git a/spec/bundler/support/env.rb b/spec/bundler/support/env.rb
new file mode 100644
index 0000000000..0899bd82a3
--- /dev/null
+++ b/spec/bundler/support/env.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Spec
+ module Env
+ def ruby_core?
+ File.exist?(File.expand_path("../../../lib/bundler/bundler.gemspec", __dir__))
+ end
+
+ def rubylib
+ ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR)
+ end
+ end
+end
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
new file mode 100644
index 0000000000..2be25b4a78
--- /dev/null
+++ b/spec/bundler/support/filters.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class RequirementChecker < Proc
+ def self.against(provided)
+ new do |required|
+ requirement = Gem::Requirement.new(required)
+
+ !requirement.satisfied_by?(provided)
+ end.tap do |checker|
+ checker.provided = provided
+ end
+ end
+
+ attr_accessor :provided
+
+ def inspect
+ "\"#{provided}\""
+ end
+end
+
+git_version = Gem::Version.new(`git --version`[/(\d+\.\d+\.\d+)/, 1])
+
+RSpec.configure do |config|
+ config.filter_run_excluding realworld: true
+
+ config.filter_run_excluding rubygems: RequirementChecker.against(Gem.rubygems_version)
+ config.filter_run_excluding git: RequirementChecker.against(git_version)
+ config.filter_run_excluding ruby_repo: !ENV["GEM_COMMAND"].nil?
+ config.filter_run_excluding no_color_tty: Gem.win_platform? || !ENV["GITHUB_ACTION"].nil?
+ config.filter_run_excluding permissions: Gem.win_platform?
+ config.filter_run_excluding readline: Gem.win_platform?
+ config.filter_run_excluding jruby_only: RUBY_ENGINE != "jruby"
+ config.filter_run_excluding truffleruby_only: RUBY_ENGINE != "truffleruby"
+ config.filter_run_excluding man: Gem.win_platform?
+ config.filter_run_excluding mri_only: RUBY_ENGINE != "ruby"
+
+ config.filter_run_when_matching :focus unless ENV["CI"]
+
+ config.before(:each, :bundler) do |example|
+ bundle_config "simulate_version #{example.metadata[:bundler]}"
+ end
+end
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index b14e4a5943..46718f5fa4 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -1,67 +1,74 @@
# frozen_string_literal: true
-require "rubygems"
+if ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+ Object.send(:remove_const, :RUBY_PLATFORM)
+ RUBY_PLATFORM = ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+end
module Gem
- if version = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"]
- remove_const(:VERSION) if const_defined?(:VERSION)
- VERSION = version
+ def self.ruby=(ruby)
+ @ruby = ruby
end
- class Platform
- @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) if ENV["BUNDLER_SPEC_PLATFORM"]
+ if ENV["RUBY"]
+ Gem.ruby = ENV["RUBY"]
end
- @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
- if defined?(@path_to_default_spec_map) && !ENV["BUNDLER_SPEC_KEEP_DEFAULT_BUNDLER_GEM"]
- @path_to_default_spec_map.delete_if do |_path, spec|
- spec.name == "bundler"
- end
+ if ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_specifications_dir = nil
end
-end
-if ENV["BUNDLER_SPEC_VERSION"]
- module Bundler
- remove_const(:VERSION) if const_defined?(:VERSION)
- VERSION = ENV["BUNDLER_SPEC_VERSION"].dup
- end
-end
+ spec_platform = ENV["BUNDLER_SPEC_PLATFORM"]
+ if spec_platform
+ if /mingw|mswin/.match?(spec_platform)
+ @@win_platform = nil # rubocop:disable Style/ClassVars
+ RbConfig::CONFIG["host_os"] = spec_platform.gsub(/^[^-]+-/, "").tr("-", "_")
+ end
-if ENV["BUNDLER_SPEC_WINDOWS"] == "true"
- require "bundler/constants"
+ RbConfig::CONFIG["arch"] = spec_platform
- module Bundler
- remove_const :WINDOWS if defined?(WINDOWS)
- WINDOWS = true
+ class Platform
+ @local = nil
+ end
+ @platforms = []
+ end
+
+ if ENV["BUNDLER_SPEC_GEM_SOURCES"]
+ self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
end
-end
-class Object
- if ENV["BUNDLER_SPEC_RUBY_ENGINE"]
- if defined?(RUBY_ENGINE) && RUBY_ENGINE != "jruby" && ENV["BUNDLER_SPEC_RUBY_ENGINE"] == "jruby"
- begin
- # this has to be done up front because psych will try to load a .jar
- # if it thinks its on jruby
- require "psych"
- rescue LoadError
- nil
+ if ENV["BUNDLER_SPEC_READ_ONLY"]
+ module ReadOnly
+ def open(file, mode)
+ if file != IO::NULL && mode == "wb"
+ raise Errno::EROFS
+ else
+ super
+ end
end
end
- remove_const :RUBY_ENGINE if defined?(RUBY_ENGINE)
- RUBY_ENGINE = ENV["BUNDLER_SPEC_RUBY_ENGINE"]
+ File.singleton_class.prepend ReadOnly
+ end
- if RUBY_ENGINE == "jruby"
- remove_const :JRUBY_VERSION if defined?(JRUBY_VERSION)
- JRUBY_VERSION = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
+ if ENV["BUNDLER_SPEC_FAKE_RESOLVE"]
+ module FakeResolv
+ def getaddrinfo(host, port)
+ if host == ENV["BUNDLER_SPEC_FAKE_RESOLVE"]
+ [["AF_INET", port, "127.0.0.1", "127.0.0.1", 2, 2, 17]]
+ else
+ super
+ end
+ end
end
+
+ Socket.singleton_class.prepend FakeResolv
end
end
-if ENV["BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD"]
- $LOADED_FEATURES << File.expand_path("../../../bundler/compatibility_guard.rb", __FILE__)
- $LOADED_FEATURES << File.expand_path("../../../bundler/compatibility_guard", __FILE__)
- $LOADED_FEATURES << "bundler/compatibility_guard.rb"
- $LOADED_FEATURES << "bundler/compatibility_guard"
- require "bundler/compatibility_guard"
+# mise installed rubygems_plugin.rb to system wide `site_ruby` directory.
+# This empty module avoid to call `mise` command.
+module ReshimInstaller
+ def self.reshim; end
end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index 181dac3220..b0d4b5008b 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -1,87 +1,61 @@
# frozen_string_literal: true
-require "open3"
+require_relative "the_bundle"
+require_relative "path"
+require_relative "options"
+require_relative "subprocess"
module Spec
module Helpers
+ include Spec::Path
+ include Spec::Options
+ include Spec::Subprocess
+
+ def self.extended(mod)
+ mod.extend Spec::Path
+ mod.extend Spec::Options
+ mod.extend Spec::Subprocess
+ end
+
def reset!
Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir|
- next if %w[base remote1 gems rubygems . ..].include?(File.basename(dir))
- if ENV["BUNDLER_SUDO_TESTS"]
- `sudo rm -rf "#{dir}"`
- else
- FileUtils.rm_rf(dir)
- end
+ next if %w[base base_system remote1 rubocop standard gems rubygems . ..].include?(File.basename(dir))
+ FileUtils.rm_r(dir)
end
FileUtils.mkdir_p(home)
FileUtils.mkdir_p(tmpdir)
Bundler.reset!
- Bundler.ui = nil
- Bundler.ui # force it to initialize
- end
-
- def self.bang(method)
- define_method("#{method}!") do |*args, &blk|
- send(method, *args, &blk).tap do
- unless last_command.success?
- raise RuntimeError,
- "Invoking #{method}!(#{args.map(&:inspect).join(", ")}) failed:\n#{last_command.stdboth}",
- caller.drop_while {|bt| bt.start_with?(__FILE__) }
- end
- end
- end
- end
-
- def the_bundle(*args)
- TheBundle.new(*args)
- end
-
- def last_command
- @command_executions.last || raise("There is no last command")
- end
-
- def out
- last_command.stdboth
- end
-
- def err
- last_command.stderr
- end
-
- def exitstatus
- last_command.exitstatus
+ Bundler::Source::Git::GitProxy.reset
+ Gem.clear_paths
end
- def bundle_update_requires_all?
- Bundler::VERSION.start_with?("2.") ? nil : true
+ def the_bundle
+ TheBundle.new
end
- def in_app_root(&blk)
- Dir.chdir(bundled_app, &blk)
- end
+ MAJOR_DEPRECATION = /^\[DEPRECATED\]\s*/
- def in_app_root2(&blk)
- Dir.chdir(bundled_app2, &blk)
+ def err_without_deprecations
+ err.gsub(/#{MAJOR_DEPRECATION}.+[\n]?/, "")
end
- def in_app_root_custom(root, &blk)
- Dir.chdir(root, &blk)
+ def deprecations
+ err.split("\n").filter_map {|l| l.sub(MAJOR_DEPRECATION, "") if l.match?(MAJOR_DEPRECATION) }
end
def run(cmd, *args)
opts = args.last.is_a?(Hash) ? args.pop : {}
groups = args.map(&:inspect).join(", ")
- setup = "require 'rubygems' ; require 'bundler' ; Bundler.setup(#{groups})\n"
- ruby(setup + cmd, opts)
+ setup = "require 'bundler' ; Bundler.ui.silence { Bundler.setup(#{groups}) }"
+ ruby([setup, cmd].join(" ; "), opts)
end
- bang :run
def load_error_run(ruby, name, *args)
cmd = <<-RUBY
begin
#{ruby}
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
+ warn e.message if e.message.include?("-- #{name}")
end
RUBY
opts = args.last.is_a?(Hash) ? args.pop : {}
@@ -89,54 +63,35 @@ module Spec
run(cmd, *args)
end
- def lib
- root.join("lib")
+ def in_bundled_app(cmd, options = {})
+ sys_exec(cmd, dir: bundled_app, raise_on_error: options[:raise_on_error])
end
- def spec
- spec_dir.to_s
- end
-
- def bundle(cmd, options = {})
- with_sudo = options.delete(:sudo)
- sudo = with_sudo == :preserve_env ? "sudo -E" : "sudo" if with_sudo
-
- bundle_bin = options.delete("bundle_bin") || bindir.join("bundle")
-
- if system_bundler = options.delete(:system_bundler)
- bundle_bin = "-S bundle"
- end
+ def bundle(cmd, options = {}, &block)
+ bundle_bin = options.delete(:bundle_bin)
+ bundle_bin ||= installed_bindir.join("bundle")
env = options.delete(:env) || {}
- env["PATH"].gsub!("#{Path.root}/exe", "") if env["PATH"] && system_bundler
requires = options.delete(:requires) || []
- requires << "support/hax"
-
- artifice = options.delete(:artifice) do
- if RSpec.current_example.metadata[:realworld]
- "vcr"
- else
- "fail"
- end
- end
- if artifice
- requires << File.expand_path("../artifice/#{artifice}", __FILE__)
- end
- requires_str = requires.map {|r| "-r#{r}" }.join(" ")
+ dir = options.delete(:dir) || bundled_app
+ custom_load_path = options.delete(:load_path)
load_path = []
- load_path << lib unless system_bundler
- load_path << spec
- load_path_str = "-I#{load_path.join(File::PATH_SEPARATOR)}"
+ load_path << custom_load_path if custom_load_path
+
+ build_env_options = { load_path: load_path, requires: requires, env: env }
+ build_env_options.merge!(artifice: options.delete(:artifice)) if options.key?(:artifice) || cmd.start_with?("exec")
+
+ match_source(cmd)
- env = env.map {|k, v| "#{k}='#{v}'" }.join(" ")
+ env = build_env(build_env_options)
+
+ raise_on_error = options.delete(:raise_on_error)
args = options.map do |k, v|
case v
- when nil
- next
when true
" --#{k}"
when false
@@ -146,219 +101,367 @@ module Spec
end
end.join
- cmd = "#{env} #{sudo} #{Gem.ruby} #{load_path_str} #{requires_str} #{bundle_bin} #{cmd}#{args}"
- sys_exec(cmd) {|i, o, thr| yield i, o, thr if block_given? }
+ cmd = "#{Gem.ruby} #{bundle_bin} #{cmd}#{args}"
+ sys_exec(cmd, { env: env, dir: dir, raise_on_error: raise_on_error }, &block)
end
- bang :bundle
- def forgotten_command_line_options(options)
- remembered = Bundler.bundler_major_version < 3
- options = options.map do |k, v|
- k = Array(k)[remembered ? 0 : -1]
- v = '""' if v && v.to_s.empty?
- [k, v]
- end
- return Hash[options] if remembered
- options.each do |k, v|
- if v.nil?
- bundle! "config --delete #{k}"
- else
- bundle! "config --local #{k} #{v}"
- end
- end
- {}
+ def main_source(dir)
+ gemfile = File.expand_path("Gemfile", dir)
+ return unless File.exist?(gemfile)
+
+ match = File.readlines(gemfile).first.match(/source ["'](?<source>[^"']+)["']/)
+ return unless match
+
+ match[:source]
end
def bundler(cmd, options = {})
- options["bundle_bin"] = bindir.join("bundler")
+ options[:bundle_bin] = system_gem_path("bin/bundler")
bundle(cmd, options)
end
- def bundle_ruby(options = {})
- options["bundle_bin"] = bindir.join("bundle_ruby")
- bundle("", options)
- end
-
def ruby(ruby, options = {})
- env = (options.delete(:env) || {}).map {|k, v| "#{k}='#{v}' " }.join
- ruby = ruby.gsub(/["`\$]/) {|m| "\\#{m}" }
- lib_option = options[:no_lib] ? "" : " -I#{lib}"
- sys_exec(%(#{env}#{Gem.ruby}#{lib_option} -e "#{ruby}"))
+ env = build_env({ artifice: nil }.merge(options))
+ escaped_ruby = ruby.shellescape
+ options[:env] = env if env
+ options[:dir] ||= bundled_app
+ sys_exec(%(#{Gem.ruby} -w -e #{escaped_ruby}), options)
end
- bang :ruby
def load_error_ruby(ruby, name, opts = {})
ruby(<<-R)
begin
#{ruby}
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR"# if e.message.include?("-- #{name}")
+ warn e.message if e.message.include?("-- #{name}")
end
R
end
- def gembin(cmd)
- lib = File.expand_path("../../../lib", __FILE__)
- old = ENV["RUBYOPT"]
- ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -I#{lib}"
- cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/")
- sys_exec(cmd.to_s)
- ensure
- ENV["RUBYOPT"] = old
- end
+ def build_env(options = {})
+ env = options.delete(:env) || {}
+ libs = options.delete(:load_path) || []
+ env["RUBYOPT"] = opt_add("-I#{libs.join(File::PATH_SEPARATOR)}", env["RUBYOPT"]) if libs.any?
+
+ current_example = RSpec.current_example
+
+ main_source = @gemfile_source if defined?(@gemfile_source)
+ compact_index_main_source = main_source&.start_with?("https://gem.repo", "https://gems.security")
- def gem_command(command, args = "", options = {})
- if command == :exec && !options[:no_quote]
- args = args.gsub(/(?=")/, "\\")
- args = %("#{args}")
+ requires = options.delete(:requires) || []
+ requires << hax
+
+ artifice = options.delete(:artifice) do
+ if current_example && current_example.metadata[:realworld]
+ "vcr"
+ elsif compact_index_main_source
+ env["BUNDLER_SPEC_GEM_REPO"] ||=
+ case main_source
+ when "https://gem.repo1" then gem_repo1.to_s
+ when "https://gem.repo2" then gem_repo2.to_s
+ when "https://gem.repo3" then gem_repo3.to_s
+ when "https://gem.repo4" then gem_repo4.to_s
+ when "https://gems.security" then security_repo.to_s
+ end
+
+ "compact_index"
+ else
+ "fail"
+ end
end
- gem = ENV["BUNDLE_GEM"] || "#{Gem.ruby} -rrubygems -S gem --backtrace"
- sys_exec("#{gem} #{command} #{args}")
+ if artifice
+ requires << "#{Path.spec_dir}/support/artifice/#{artifice}.rb"
+ end
+
+ requires.each {|r| env["RUBYOPT"] = opt_add("-r#{r}", env["RUBYOPT"]) }
+
+ env
end
- bang :gem_command
- def rake
- "#{Gem.ruby} -S #{ENV["GEM_PATH"]}/bin/rake"
+ def gembin(cmd, options = {})
+ cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/")
+ sys_exec(cmd.to_s, options)
end
- def sys_exec(cmd)
- command_execution = CommandExecution.new(cmd.to_s, Dir.pwd)
+ def sys_exec(cmd, options = {}, &block)
+ env = options[:env] || {}
+ env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
+ options[:env] = env
- Open3.popen3(cmd.to_s) do |stdin, stdout, stderr, wait_thr|
- yield stdin, stdout, wait_thr if block_given?
- stdin.close
+ sh(cmd, options, &block)
+ end
- command_execution.exitstatus = wait_thr && wait_thr.value.exitstatus
- command_execution.stdout = Thread.new { stdout.read }.value.strip
- command_execution.stderr = Thread.new { stderr.read }.value.strip
+ def bundle_config(config = nil, path = bundled_app(".bundle/config"))
+ if config.is_a?(String)
+ key, value = config.split(" ", 2)
+ config = { Bundler::Settings.key_for(key) => value }
end
- (@command_executions ||= []) << command_execution
+ current = File.exist?(path) ? Psych.load_file(path) : {}
+ return current unless config
- command_execution.stdout
- end
- bang :sys_exec
+ current = {} if current.empty?
- def config(config = nil, path = bundled_app(".bundle/config"))
- return YAML.load_file(path) unless config
FileUtils.mkdir_p(File.dirname(path))
- File.open(path, "w") do |f|
- f.puts config.to_yaml
+
+ new_config = current.merge(config).compact
+
+ File.open(path, "w+") do |f|
+ f.puts new_config.to_yaml
end
- config
+
+ new_config
end
- def global_config(config = nil)
- config(config, home(".bundle/config"))
+ def bundle_config_global(config = nil)
+ bundle_config(config, home(".bundle/config"))
end
- def create_file(*args)
- path = bundled_app(args.shift)
- path = args.shift if args.first.is_a?(Pathname)
- str = args.shift || ""
+ def create_file(path, contents = "")
+ contents = strip_whitespace(contents)
+ path = Pathname.new(path).expand_path(bundled_app) unless path.is_a?(Pathname)
path.dirname.mkpath
- File.open(path.to_s, "w") do |f|
- f.puts strip_whitespace(str)
+ path.write(contents)
+
+ # if the file is a script, create respective bat file on Windows
+ if contents.start_with?("#!")
+ path.chmod(0o755)
+ if Gem.win_platform?
+ path.sub_ext(".bat").write <<~SCRIPT
+ @ECHO OFF
+ @"ruby.exe" "%~dpn0" %*
+ SCRIPT
+ end
end
end
def gemfile(*args)
- if args.empty?
- File.open("Gemfile", "r", &:read)
+ contents = args.pop
+
+ if contents.nil?
+ read_gemfile
else
- create_file("Gemfile", *args)
+ match_source(contents)
+ create_file(args.pop || "Gemfile", contents)
end
end
def lockfile(*args)
- if args.empty?
- File.open("Gemfile.lock", "r", &:read)
+ contents = args.pop
+
+ if contents.nil?
+ read_lockfile
else
- create_file("Gemfile.lock", *args)
+ create_file(args.pop || "Gemfile.lock", contents)
end
end
+ def read_gemfile(file = "Gemfile")
+ read_bundled_app_file(file)
+ end
+
+ def read_lockfile(file = "Gemfile.lock")
+ read_bundled_app_file(file)
+ end
+
+ def read_bundled_app_file(file)
+ bundled_app(file).read
+ end
+
def strip_whitespace(str)
# Trim the leading spaces
spaces = str[/\A\s+/, 0] || ""
str.gsub(/^#{spaces}/, "")
end
- def normalize_uri_file(str)
- # URI::File of Ruby 2.6 normalize localhost variable with file protocol.
- if defined?(URI::File)
- str.gsub(%r{file:\/\/localhost}, "file://")
- else
- str
- end
- end
-
def install_gemfile(*args)
+ opts = args.last.is_a?(Hash) ? args.pop : {}
gemfile(*args)
- opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :install, opts
end
- bang :install_gemfile
def lock_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :lock, opts
end
- def install_gems(*gems)
+ def base_system_gems(*names, **options)
+ system_gems names.map {|name| find_base_path(name) }, **options
+ end
+
+ def system_gems(*gems)
+ gems = gems.flatten
options = gems.last.is_a?(Hash) ? gems.pop : {}
- gem_repo = options.fetch(:gem_repo) { gem_repo1 }
+ install_dir = options.fetch(:path, system_gem_path)
+ default = options.fetch(:default, false)
gems.each do |g|
- path = if g == :bundler
- Dir.chdir(root) { gem_command! :build, gemspec.to_s }
- bundler_path = if ruby_core?
- root + "lib/bundler-#{Bundler::VERSION}.gem"
- else
- root + "bundler-#{Bundler::VERSION}.gem"
- end
- elsif g.to_s =~ %r{\A/.*\.gem\z}
- g
+ gem_name = g.to_s
+ bundler = gem_name.match(/\Abundler-(?<version>.*)\z/)
+
+ if bundler
+ with_built_bundler(bundler[:version], released: options.fetch(:released, false)) {|gem_path| install_gem(gem_path, install_dir, default) }
+ elsif %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}.match?(gem_name)
+ install_gem(gem_name, install_dir, default)
else
- "#{gem_repo}/gems/#{g}.gem"
+ gem_repo = options.fetch(:gem_repo, gem_repo1)
+ install_gem("#{gem_repo}/gems/#{gem_name}.gem", install_dir, default)
end
+ end
+ end
- raise "OMG `#{path}` does not exist!" unless File.exist?(path)
+ def self.install_dev_bundler
+ extend self
- if Gem::VERSION < "2.0.0"
- gem_command! :install, "--no-rdoc --no-ri --ignore-dependencies '#{path}'"
- else
- gem_command! :install, "--no-document --ignore-dependencies '#{path}'"
- end
- bundler_path && bundler_path.rmtree
+ with_built_bundler(nil, build_path: tmp_root) {|gem_path| install_gem(gem_path, pristine_system_gem_path) }
+ end
+
+ def install_gem(path, install_dir, default = false)
+ raise ArgumentError, "`#{path}` does not exist!" unless File.exist?(path)
+
+ require "rubygems/installer"
+
+ with_simulated_platform do
+ installer = Gem::Installer.at(
+ path.to_s,
+ install_dir: install_dir.to_s,
+ document: [],
+ ignore_dependencies: true,
+ wrappers: true,
+ env_shebang: true,
+ force: true
+ )
+ installer.install
+ end
+
+ if default
+ gem = Pathname.new(path).basename.to_s.match(/(.*)\.gem/)[1]
+
+ # Revert Gem::Installer#write_spec and apply Gem::Installer#write_default_spec
+ FileUtils.mkdir_p File.join(install_dir, "specifications", "default")
+ File.rename File.join(install_dir, "specifications", gem + ".gemspec"),
+ File.join(install_dir, "specifications", "default", gem + ".gemspec")
+
+ # Revert Gem::Installer#write_cache_file
+ File.delete File.join(install_dir, "cache", gem + ".gem")
end
end
- alias_method :install_gem, :install_gems
+ def uninstall_gem(name, options = {})
+ require "rubygems/uninstaller"
+
+ gem_home = options.dig(:env, "GEM_HOME") || system_gem_path.to_s
+
+ with_env_vars("GEM_HOME" => gem_home) do
+ Gem.clear_paths
+
+ uninstaller = Gem::Uninstaller.new(
+ name,
+ ignore: true,
+ executables: true,
+ all: true
+ )
+ uninstaller.uninstall
+ ensure
+ Gem.clear_paths
+ end
+ end
+
+ def installed_gems_list(options = {})
+ gem_home = options.dig(:env, "GEM_HOME") || system_gem_path.to_s
+
+ # Temporarily set GEM_HOME for the command
+ old_gem_home = ENV["GEM_HOME"]
+ ENV["GEM_HOME"] = gem_home
+ Gem.clear_paths
+
+ begin
+ require "rubygems/commands/list_command"
+
+ # Capture output from the list command
+ require "stringio"
+ output_io = StringIO.new
+ cmd = Gem::Commands::ListCommand.new
+ cmd.ui = Gem::StreamUI.new(StringIO.new, output_io, StringIO.new, false)
+ cmd.invoke
+ output = output_io.string.strip
+ ensure
+ ENV["GEM_HOME"] = old_gem_home
+ Gem.clear_paths
+ end
+
+ # Create a fake command execution so `out` helper works
+ command_execution = Spec::CommandExecution.new("gem list", timeout: 60)
+ command_execution.original_stdout << output
+ command_execution.exitstatus = 0
+ command_executions << command_execution
+
+ output
+ end
+
+ def with_built_bundler(version = nil, opts = {}, &block)
+ require_relative "builders"
+
+ Builders::BundlerBuilder.new(self, "bundler", version)._build(opts, &block)
+ end
def with_gem_path_as(path)
+ without_env_side_effects do
+ ENV["GEM_HOME"] = path.to_s
+ ENV["GEM_PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_GEM_HOME"] = nil
+ ENV["BUNDLER_ORIG_GEM_PATH"] = nil
+ yield
+ end
+ end
+
+ def with_path_as(path)
+ without_env_side_effects do
+ ENV["PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_PATH"] = nil
+ yield
+ end
+ end
+
+ def without_env_side_effects
backup = ENV.to_hash
- ENV["GEM_HOME"] = path.to_s
- ENV["GEM_PATH"] = path.to_s
- ENV["BUNDLER_ORIG_GEM_PATH"] = nil
yield
ensure
ENV.replace(backup)
end
- def with_path_as(path)
- backup = ENV.to_hash
- ENV["PATH"] = path.to_s
- ENV["BUNDLER_ORIG_PATH"] = nil
+ # Simulate the platform set by BUNDLER_SPEC_PLATFORM for in-process
+ # operations, mirroring what hax.rb does for subprocesses.
+ def with_simulated_platform
+ spec_platform = ENV["BUNDLER_SPEC_PLATFORM"]
+ unless spec_platform
+ return yield
+ end
+
+ old_arch = RbConfig::CONFIG["arch"]
+ old_host_os = RbConfig::CONFIG["host_os"]
+
+ if /mingw|mswin/.match?(spec_platform)
+ Gem.class_variable_set(:@@win_platform, nil) # rubocop:disable Style/ClassVars
+ RbConfig::CONFIG["host_os"] = spec_platform.gsub(/^[^-]+-/, "").tr("-", "_")
+ end
+
+ RbConfig::CONFIG["arch"] = spec_platform
+ Gem::Platform.instance_variable_set(:@local, nil)
+ Gem.instance_variable_set(:@platforms, [])
+
yield
ensure
- ENV.replace(backup)
+ if spec_platform
+ RbConfig::CONFIG["arch"] = old_arch
+ RbConfig::CONFIG["host_os"] = old_host_os
+ Gem::Platform.instance_variable_set(:@local, nil)
+ Gem.instance_variable_set(:@platforms, [])
+ end
end
def with_path_added(path)
- with_path_as(path.to_s + ":" + ENV["PATH"]) do
+ with_path_as([path.to_s, ENV["PATH"]].join(File::PATH_SEPARATOR)) do
yield
end
end
@@ -374,158 +477,74 @@ module Spec
def with_fake_man
FileUtils.mkdir_p(tmp("fake_man"))
- File.open(tmp("fake_man/man"), "w", 0o755) do |f|
- f.puts "#!/usr/bin/env ruby\nputs ARGV.inspect\n"
- end
+ create_file(tmp("fake_man/man"), <<~SCRIPT)
+ #!/usr/bin/env ruby
+ puts ARGV.inspect
+ SCRIPT
with_path_added(tmp("fake_man")) { yield }
end
- def system_gems(*gems)
- opts = gems.last.is_a?(Hash) ? gems.last : {}
- path = opts.fetch(:path, system_gem_path)
- if path == :bundle_path
- path = ruby!(<<-RUBY)
- require "bundler"
- begin
- puts Bundler.bundle_path
- rescue Bundler::GemfileNotFound
- ENV["BUNDLE_GEMFILE"] = "Gemfile"
- retry
- end
-
- RUBY
- end
- gems = gems.flatten
-
- unless opts[:keep_path]
- FileUtils.rm_rf(path)
- FileUtils.mkdir_p(path)
- end
-
- Gem.clear_paths
-
- env_backup = ENV.to_hash
- ENV["GEM_HOME"] = path.to_s
- ENV["GEM_PATH"] = path.to_s
- ENV["BUNDLER_ORIG_GEM_PATH"] = nil
-
- install_gems(*gems)
- return unless block_given?
- begin
- yield
- ensure
- ENV.replace(env_backup)
- end
- end
-
- def realworld_system_gems(*gems)
- gems = gems.flatten
+ def pristine_system_gems(*gems)
+ FileUtils.rm_r(system_gem_path)
- FileUtils.rm_rf(system_gem_path)
- FileUtils.mkdir_p(system_gem_path)
-
- Gem.clear_paths
-
- gem_home = ENV["GEM_HOME"]
- gem_path = ENV["GEM_PATH"]
- path = ENV["PATH"]
- ENV["GEM_HOME"] = system_gem_path.to_s
- ENV["GEM_PATH"] = system_gem_path.to_s
-
- gems.each do |gem|
- gem_command :install, "--no-rdoc --no-ri #{gem}"
- end
- return unless block_given?
- begin
- yield
- ensure
- ENV["GEM_HOME"] = gem_home
- ENV["GEM_PATH"] = gem_path
- ENV["PATH"] = path
+ if gems.any?
+ system_gems(*gems)
+ else
+ default_system_gems
end
end
- def cache_gems(*gems)
+ def cache_gems(*gems, gem_repo: gem_repo1)
gems = gems.flatten
- FileUtils.rm_rf("#{bundled_app}/vendor/cache")
FileUtils.mkdir_p("#{bundled_app}/vendor/cache")
gems.each do |g|
- path = "#{gem_repo1}/gems/#{g}.gem"
- raise "OMG `#{path}` does not exist!" unless File.exist?(path)
+ path = "#{gem_repo}/gems/#{g}.gem"
+ raise ArgumentError, "`#{path}` does not exist!" unless File.exist?(path)
FileUtils.cp(path, "#{bundled_app}/vendor/cache")
end
end
def simulate_new_machine
- system_gems []
- FileUtils.rm_rf system_gem_path
- FileUtils.rm_rf bundled_app(".bundle")
+ FileUtils.rm_r bundled_app(".bundle")
+ pristine_system_gems
end
- def simulate_platform(platform)
- old = ENV["BUNDLER_SPEC_PLATFORM"]
- ENV["BUNDLER_SPEC_PLATFORM"] = platform.to_s
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
+ def default_system_gems
+ FileUtils.cp_r pristine_system_gem_path, system_gem_path
end
- def simulate_ruby_version(version)
- return if version == RUBY_VERSION
- old = ENV["BUNDLER_SPEC_RUBY_VERSION"]
- ENV["BUNDLER_SPEC_RUBY_VERSION"] = version
- yield if block_given?
+ def simulate_ruby_platform(ruby_platform)
+ old = ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+ ENV["BUNDLER_SPEC_RUBY_PLATFORM"] = ruby_platform.to_s
+ yield
ensure
- ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given?
+ ENV["BUNDLER_SPEC_RUBY_PLATFORM"] = old
end
- def simulate_ruby_engine(engine, version = "1.6.0")
- return if engine == local_ruby_engine
-
- old = ENV["BUNDLER_SPEC_RUBY_ENGINE"]
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] = engine
- old_version = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
- ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = version
- yield if block_given?
+ def simulate_platform(platform)
+ old = ENV["BUNDLER_SPEC_PLATFORM"]
+ ENV["BUNDLER_SPEC_PLATFORM"] = platform.to_s
+ yield
ensure
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] = old if block_given?
- ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = old_version if block_given?
+ ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
end
- def simulate_bundler_version(version)
- old = ENV["BUNDLER_SPEC_VERSION"]
- ENV["BUNDLER_SPEC_VERSION"] = version.to_s
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_VERSION"] = old if block_given?
+ def current_ruby_minor
+ Gem.ruby_version.segments.tap {|s| s.delete_at(2) }.join(".")
end
- def simulate_rubygems_version(version)
- old = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"]
- ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = version.to_s
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = old if block_given?
+ def next_ruby_minor
+ ruby_major_minor.map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".")
end
- def simulate_windows(platform = mswin)
- old = ENV["BUNDLER_SPEC_WINDOWS"]
- ENV["BUNDLER_SPEC_WINDOWS"] = "true"
- simulate_platform platform do
- yield
- end
- ensure
- ENV["BUNDLER_SPEC_WINDOWS"] = old
+ def ruby_major_minor
+ Gem.ruby_version.segments[0..1]
end
def revision_for(path)
- Dir.chdir(path) { `git rev-parse HEAD`.strip }
- end
-
- def capture_output
- capture(:stdout)
+ git("rev-parse HEAD", path).strip
end
def with_read_only(pattern)
@@ -542,6 +561,22 @@ module Spec
Dir[pattern].each(&chmod[0o755, 0o644])
end
+ # Simulate replacing TODOs with real values
+ def prepare_gemspec(pathname)
+ process_file(pathname) do |line|
+ case line
+ when /spec\.metadata\["(?:allowed_push_host|homepage_uri|source_code_uri|changelog_uri)"\]/, /spec\.homepage/
+ line.gsub(/\=.*$/, '= "http://example.org"')
+ when /spec\.summary/
+ line.gsub(/\=.*$/, '= "A short summary of my new gem."')
+ when /spec\.description/
+ line.gsub(/\=.*$/, '= "A longer description of my new gem."')
+ else
+ line
+ end
+ end
+ end
+
def process_file(pathname)
changed_lines = pathname.readlines.map do |line|
yield line
@@ -561,40 +596,36 @@ module Spec
end
end
- def require_rack
- # need to hack, so we can require rack
+ def require_rack_test
+ # need to hack, so we can require rack for testing
old_gem_home = ENV["GEM_HOME"]
- ENV["GEM_HOME"] = Spec::Path.base_system_gems.to_s
- require "rack"
+ ENV["GEM_HOME"] = Spec::Path.scoped_base_system_gem_path.to_s
+ require "rack/test"
ENV["GEM_HOME"] = old_gem_home
end
- def wait_for_server(host, port, seconds = 15)
- tries = 0
- sleep 0.5
- TCPSocket.new(host, port)
- rescue => e
- raise(e) if tries > (seconds * 2)
- tries += 1
- retry
+ def exit_status_for_signal(signal_number)
+ # For details see: https://en.wikipedia.org/wiki/Exit_status#Shell_and_scripts
+ 128 + signal_number
end
- def find_unused_port
- port = 21_453
- begin
- port += 1 while TCPSocket.new("127.0.0.1", port)
- rescue
- false
- end
- port
+ def empty_repo4
+ FileUtils.rm_r gem_repo4
+
+ build_repo4 {}
end
- def bundler_fileutils
- if RUBY_VERSION >= "2.4"
- ::Bundler::FileUtils
- else
- ::FileUtils
- end
+ private
+
+ def match_source(contents)
+ match = /source ["']?(?<source>http[^"']+)["']?/.match(contents)
+ return unless match
+
+ @gemfile_source = match[:source]
+ end
+
+ def git_root_dir?
+ root.to_s == `git rev-parse --show-toplevel`.chomp
end
end
end
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index 69f8d9f679..1fbdd49abe 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -14,19 +14,25 @@ module Spec
alias_method :platforms, :platform
- def resolve(args = [])
+ def resolve(args = [], dependency_api_available: true)
@platforms ||= ["ruby"]
- deps = []
- default_source = instance_double("Bundler::Source::Rubygems", :specs => @index)
- source_requirements = { :default => default_source }
+ default_source = instance_double("Bundler::Source::Rubygems", specs: @index, to_s: "locally install gems", dependency_api_available?: dependency_api_available)
+ source_requirements = { default: default_source }
+ base = args[0] || Bundler::SpecSet.new([])
+ base.each {|ls| ls.source = default_source }
+ gem_version_promoter = args[1] || Bundler::GemVersionPromoter.new
+ originally_locked = args[2] || Bundler::SpecSet.new([])
+ unlock = args[3] || []
@deps.each do |d|
- @platforms.each do |p|
- source_requirements[d.name] = d.source = default_source
- deps << Bundler::DepProxy.new(d, p)
- end
+ name = d.name
+ source_requirements[name] = d.source = default_source
end
- source_requirements ||= {}
- Bundler::Resolver.resolve(deps, @index, source_requirements, *args)
+ packages = Bundler::Resolver::Base.new(source_requirements, @deps, base, @platforms, locked_specs: originally_locked, unlock: unlock)
+ Bundler::Resolver.new(packages, gem_version_promoter).start
+ end
+
+ def should_not_resolve
+ expect { resolve }.to raise_error(Bundler::GemNotFound)
end
def should_resolve_as(specs)
@@ -35,6 +41,12 @@ module Spec
expect(got).to eq(specs.sort)
end
+ def should_resolve_without_dependency_api(specs)
+ got = resolve(dependency_api_available: false)
+ got = got.map(&:full_name).sort
+ expect(got).to eq(specs.sort)
+ end
+
def should_resolve_and_include(specs, args = [])
got = resolve(args)
got = got.map(&:full_name).sort
@@ -43,13 +55,6 @@ module Spec
end
end
- def should_conflict_on(names)
- got = resolve
- flunk "The resolve succeeded with: #{got.map(&:full_name).sort.inspect}"
- rescue Bundler::VersionConflict => e
- expect(Array(names).sort).to eq(e.conflicts.sort)
- end
-
def gem(*args, &blk)
build_spec(*args, &blk).first
end
@@ -61,23 +66,21 @@ module Spec
end
def should_conservative_resolve_and_include(opts, unlock, specs)
- # empty unlock means unlock all
opts = Array(opts)
- search = Bundler::GemVersionPromoter.new(@locked, unlock).tap do |s|
+ search = Bundler::GemVersionPromoter.new.tap do |s|
s.level = opts.first
s.strict = opts.include?(:strict)
- s.prerelease_specified = Hash[@deps.map {|d| [d.name, d.requirement.prerelease?] }]
end
- should_resolve_and_include specs, [@base, search]
+ should_resolve_and_include specs, [@base, search, @locked, unlock]
end
def an_awesome_index
build_index do
- gem "rack", %w[0.8 0.9 0.9.1 0.9.2 1.0 1.1]
- gem "rack-mount", %w[0.4 0.5 0.5.1 0.5.2 0.6]
+ gem "myrack", %w[0.8 0.9 0.9.1 0.9.2 1.0 1.1]
+ gem "myrack-mount", %w[0.4 0.5 0.5.1 0.5.2 0.6]
# --- Pre-release support
- gem "rubygems\0", ["1.3.2"]
+ gem "RubyGems\0", ["1.3.2"]
# --- Rails
versions "1.2.3 2.2.3 2.3.5 3.0.0.beta 3.0.0.beta1" do |version|
@@ -85,10 +88,10 @@ module Spec
gem "actionpack", version do
dep "activesupport", version
if version >= v("3.0.0.beta")
- dep "rack", "~> 1.1"
- dep "rack-mount", ">= 0.5"
- elsif version > v("2.3") then dep "rack", "~> 1.0.0"
- elsif version > v("2.0.0") then dep "rack", "~> 0.9.0"
+ dep "myrack", "~> 1.1"
+ dep "myrack-mount", ">= 0.5"
+ elsif version > v("2.3") then dep "myrack", "~> 1.0.0"
+ elsif version > v("2.0.0") then dep "myrack", "~> 0.9.0"
end
end
gem "activerecord", version do
@@ -119,11 +122,11 @@ module Spec
end
versions "1.0 1.2 1.2.1 1.2.2 1.3 1.3.0.1 1.3.5 1.4.0 1.4.2 1.4.2.1" do |version|
- platforms "ruby java mswin32 mingw32 x64-mingw32" do |platform|
+ platforms "ruby java mswin32 mingw32 x64-mingw-ucrt" do |platform|
next if version == v("1.4.2.1") && platform != pl("x86-mswin32")
next if version == v("1.4.2") && platform == pl("x86-mswin32")
gem "nokogiri", version, platform do
- dep "weakling", ">= 0.0.3" if platform =~ pl("java")
+ dep "weakling", ">= 0.0.3" if platform =~ pl("java") # rubocop:disable Performance/RegexpMatch
end
end
end
@@ -300,7 +303,7 @@ module Spec
end
end
- def a_unresovable_child_index
+ def a_unresolvable_child_index
build_index do
gem "json", %w[1.8.0]
@@ -363,7 +366,7 @@ module Spec
def a_circular_index
build_index do
- gem "rack", "1.0.1"
+ gem "myrack", "1.0.1"
gem("foo", "0.2.6") do
dep "bar", ">= 0"
end
@@ -414,7 +417,7 @@ module Spec
gem("b", %w[0.9.0 1.5.0 2.0.0.pre])
# --- Pre-release support
- gem "rubygems\0", ["1.3.2"]
+ gem "RubyGems\0", ["1.3.2"]
end
end
end
diff --git a/spec/bundler/support/less_than_proc.rb b/spec/bundler/support/less_than_proc.rb
deleted file mode 100644
index ddac5458b7..0000000000
--- a/spec/bundler/support/less_than_proc.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class LessThanProc < Proc
- attr_accessor :present
-
- def self.with(present)
- provided = Gem::Version.new(present.dup)
- new do |required|
- if required =~ /[=><~]/
- !Gem::Requirement.new(required).satisfied_by?(provided)
- else
- provided < Gem::Version.new(required)
- end
- end.tap {|l| l.present = present }
- end
-
- def inspect
- "\"=< #{present}\""
- end
-end
diff --git a/spec/bundler/support/manpages.rb b/spec/bundler/support/manpages.rb
deleted file mode 100644
index ce1f72cc49..0000000000
--- a/spec/bundler/support/manpages.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module Manpages
- def self.setup
- man_path = Spec::Path.root.join("man")
- return if man_path.children(false).select {|file| file.extname == ".ronn" }.all? do |man|
- Dir[man_path.join("#{man.to_s[0..-6]}*.txt").to_s].any?
- end
-
- system(Spec::Path.root.join("bin", "rake").to_s, "man:build") || raise("Failed building man pages")
- end
- end
-end
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 8e17be3a02..5a3c38a4db 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
require "forwardable"
-require "support/the_bundle"
+require_relative "the_bundle"
+
module Spec
module Matchers
extend RSpec::Matchers
@@ -51,7 +52,7 @@ module Spec
end
def self.define_compound_matcher(matcher, preconditions, &declarations)
- raise "Must have preconditions to define a compound matcher" if preconditions.empty?
+ raise ArgumentError, "Must have preconditions to define a compound matcher" if preconditions.empty?
define_method(matcher) do |*expected, &block_arg|
Precondition.new(
RSpec::Matchers::DSL::Matcher.new(matcher, declarations, self, *expected, &block_arg),
@@ -60,36 +61,6 @@ module Spec
end
end
- MAJOR_DEPRECATION = /^\[DEPRECATED FOR 2\.0\]\s*/
-
- RSpec::Matchers.define :lack_errors do
- diffable
- match do |actual|
- actual.gsub(/#{MAJOR_DEPRECATION}.+[\n]?/, "") == ""
- end
- end
-
- RSpec::Matchers.define :eq_err do |expected|
- diffable
- match do |actual|
- actual.gsub(/#{MAJOR_DEPRECATION}.+[\n]?/, "") == expected
- end
- end
-
- RSpec::Matchers.define :have_major_deprecation do |expected|
- diffable
- match do |actual|
- deprecations = actual.split(MAJOR_DEPRECATION)
-
- return !expected.nil? if deprecations.size <= 1
- return true if expected.nil?
-
- deprecations.any? do |d|
- !d.empty? && values_match?(expected, d.strip)
- end
- end
- end
-
RSpec::Matchers.define :have_dep do |*args|
dep = Bundler::Dependency.new(*args)
@@ -104,16 +75,6 @@ module Spec
end
end
- RSpec::Matchers.define :have_rubyopts do |*args|
- args = args.flatten
- args = args.first.split(/\s+/) if args.size == 1
-
- match do |actual|
- actual = actual.split(/\s+/) if actual.is_a?(String)
- args.all? {|arg| actual.include?(arg) } && actual.uniq.size == actual.size
- end
- end
-
RSpec::Matchers.define :be_sorted do
diffable
attr_reader :expected
@@ -128,6 +89,14 @@ module Spec
end
end
+ RSpec::Matchers.define :be_well_formed do
+ match(&:empty?)
+
+ failure_message do |actual|
+ actual.join("\n")
+ end
+ end
+
define_compound_matcher :read_as, [exist] do |file_contents|
diffable
@@ -145,63 +114,87 @@ module Spec
match do
opts = names.last.is_a?(Hash) ? names.pop : {}
source = opts.delete(:source)
- groups = Array(opts[:groups])
- groups << opts
- @errors = names.map do |name|
- name, version, platform = name.split(/\s+/)
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
+ opts[:raise_on_error] = false
+ @errors = names.filter_map do |full_name|
+ name, version, platform = full_name.split(/\s+/)
+ platform ||= "ruby"
+ require_path = name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
- begin
- run! "require '#{name}.rb'; puts #{version_const}", *groups
- rescue => e
- next "#{name} is not installed:\n#{indent(e)}"
- end
- last_command.stdout.gsub!(/#{MAJOR_DEPRECATION}.*$/, "")
- actual_version, actual_platform = last_command.stdout.strip.split(/\s+/, 2)
- unless Gem::Version.new(actual_version) == Gem::Version.new(version)
+ source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
+ ruby <<~R, opts
+ require 'bundler'
+ Bundler.setup(#{groups})
+
+ require '#{require_path}'
+ actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
+ actual_platform ||= "ruby"
+ unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
+ puts actual_version
+ exit 64
+ end
+ unless actual_platform.to_s == '#{platform}'
+ puts actual_platform
+ exit 65
+ end
+ require '#{require_path}/source'
+ exit 0 if #{source.nil?}
+ actual_source = #{source_const}
+ unless actual_source == '#{source}'
+ puts actual_source
+ exit 66
+ end
+ R
+ next if exitstatus == 0
+ if exitstatus == 64
+ actual_version = out.split("\n").last
next "#{name} was expected to be at version #{version} but was #{actual_version}"
end
- unless actual_platform == platform
+ if exitstatus == 65
+ actual_platform = out.split("\n").last
next "#{name} was expected to be of platform #{platform} but was #{actual_platform}"
end
- next unless source
- begin
- source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
- run! "require '#{name}/source'; puts #{source_const}", *groups
- rescue
- next "#{name} does not have a source defined:\n#{indent(e)}"
- end
- last_command.stdout.gsub!(/#{MAJOR_DEPRECATION}.*$/, "")
- unless last_command.stdout.strip == source
- next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{out}`"
+ if exitstatus == 66
+ actual_source = out.split("\n").last
+ next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{actual_source}`"
end
- end.compact
+ next "Command to check for inclusion of gem #{full_name} failed"
+ end
@errors.empty?
end
match_when_negated do
opts = names.last.is_a?(Hash) ? names.pop : {}
- groups = Array(opts[:groups]) || []
- @errors = names.map do |name|
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
+ opts[:raise_on_error] = false
+ @errors = names.filter_map do |name|
name, version = name.split(/\s+/, 2)
- begin
- run <<-R, *(groups + [opts])
- begin
- require '#{name}'
- puts #{Spec::Builders.constantize(name)}
- rescue LoadError, NameError
- puts "WIN"
+ ruby <<-R, opts
+ begin
+ require 'bundler'
+ Bundler.setup(#{groups})
+ rescue Bundler::GemNotFound, Bundler::GitError
+ exit 0
+ end
+
+ begin
+ require '#{name}'
+ name_constant = #{Spec::Builders.constantize(name)}
+ if #{version.nil?} || name_constant == '#{version}'
+ exit 64
+ else
+ exit 0
end
- R
- rescue => e
- next "checking for #{name} failed:\n#{e}"
- end
- next if last_command.stdout == "WIN"
+ rescue LoadError, NameError
+ exit 0
+ end
+ R
+ next if exitstatus == 0
+ next "command to check version of #{name} installed failed" unless exitstatus == 64
next "expected #{name} to not be installed, but it was" if version.nil?
- if Gem::Version.new(last_command.stdout) == Gem::Version.new(version)
- next "expected #{name} (#{version}) not to be installed, but it was"
- end
- end.compact
+ next "expected #{name} (#{version}) not to be installed, but it was"
+ end
@errors.empty?
end
@@ -217,10 +210,6 @@ module Spec
RSpec::Matchers.define_negated_matcher :not_include_gems, :include_gems
RSpec::Matchers.alias_matcher :include_gem, :include_gems
- def have_lockfile(expected)
- read_as(strip_whitespace(expected))
- end
-
def plugin_should_be_installed(*names)
names.each do |name|
expect(Bundler::Plugin).to be_installed(name)
@@ -234,13 +223,5 @@ module Spec
expect(Bundler::Plugin).not_to be_installed(name)
end
end
-
- def lockfile_should_be(expected)
- expect(bundled_app("Gemfile.lock")).to read_as(normalize_uri_file(strip_whitespace(expected)))
- end
-
- def gemfile_should_be(expected)
- expect(bundled_app("Gemfile")).to read_as(strip_whitespace(expected))
- end
end
end
diff --git a/spec/bundler/support/options.rb b/spec/bundler/support/options.rb
new file mode 100644
index 0000000000..551fa1acd8
--- /dev/null
+++ b/spec/bundler/support/options.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Spec
+ module Options
+ def opt_add(option, options)
+ [option.strip, options].compact.reject(&:empty?).join(" ")
+ end
+
+ def opt_remove(option, options)
+ return unless options
+
+ options.split(" ").reject {|opt| opt.strip == option.strip }.join(" ")
+ end
+ end
+end
diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb
index 97153226bd..2e6486412f 100644
--- a/spec/bundler/support/path.rb
+++ b/spec/bundler/support/path.rb
@@ -1,101 +1,267 @@
# frozen_string_literal: true
-require "pathname"
+require "pathname" unless defined?(Pathname)
+require "rbconfig"
+
+require_relative "env"
module Spec
module Path
+ include Spec::Env
+
+ def source_root
+ @source_root ||= Pathname.new(ruby_core? ? "../../.." : "../../bundler").expand_path(__dir__)
+ end
+
def root
- @root ||= Pathname.new(ruby_core? ? "../../../.." : "../../..").expand_path(__FILE__)
+ @root ||= system_gem_path("gems/bundler-#{Bundler::VERSION}")
end
def gemspec
- @gemspec ||= root.join(ruby_core? ? "lib/bundler.gemspec" : "bundler.gemspec")
+ @gemspec ||= source_root.join(relative_gemspec)
+ end
+
+ def relative_gemspec
+ @relative_gemspec ||= ruby_core? ? "lib/bundler/bundler.gemspec" : "bundler.gemspec"
+ end
+
+ def loaded_gemspec
+ @loaded_gemspec ||= Dir.chdir(source_root) { Gem::Specification.load(gemspec.to_s) }
+ end
+
+ def test_gemfile
+ @test_gemfile ||= tool_dir.join("test_gems.rb")
+ end
+
+ def rubocop_gemfile
+ @rubocop_gemfile ||= source_root.join(rubocop_gemfile_basename)
+ end
+
+ def standard_gemfile
+ @standard_gemfile ||= source_root.join(standard_gemfile_basename)
+ end
+
+ def dev_gemfile
+ @dev_gemfile ||= tool_dir.join("dev_gems.rb")
+ end
+
+ def dev_binstub
+ @dev_binstub ||= bindir.join("bundle")
end
def bindir
- @bindir ||= root.join(ruby_core? ? "bin" : "exe")
+ @bindir ||= source_root.join(ruby_core? ? "spec/bin" : "../bin")
+ end
+
+ def exedir
+ @exedir ||= source_root.join(ruby_core? ? "libexec" : "exe")
+ end
+
+ def installed_bindir
+ @installed_bindir ||= system_gem_path("bin")
+ end
+
+ def gem_cmd
+ @gem_cmd ||= ruby_core? ? source_root.join("bin/gem") : "gem"
+ end
+
+ def gem_bin
+ @gem_bin ||= ENV["GEM_COMMAND"] || "gem"
+ end
+
+ def path
+ env_path = ENV["PATH"]
+ env_path = env_path.split(File::PATH_SEPARATOR).reject {|path| path == exedir.to_s }.join(File::PATH_SEPARATOR) if ruby_core?
+ env_path
end
def spec_dir
- @spec_dir ||= root.join(ruby_core? ? "spec/bundler" : "spec")
+ @spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "../spec")
+ end
+
+ def man_dir
+ @man_dir ||= lib_dir.join("bundler/man")
+ end
+
+ def hax
+ @hax ||= spec_dir.join("support/hax.rb")
+ end
+
+ def tracked_files
+ @tracked_files ||= git_ls_files(tracked_files_glob)
+ end
+
+ def shipped_files
+ @shipped_files ||= if ruby_core_tarball?
+ loaded_gemspec.files.map {|f| f.gsub(%r{^exe/}, "libexec/") }
+ elsif ruby_core?
+ tracked_files
+ else
+ loaded_gemspec.files
+ end
+ end
+
+ def lib_tracked_files
+ @lib_tracked_files ||= git_ls_files(lib_tracked_files_glob)
+ end
+
+ def man_tracked_files
+ @man_tracked_files ||= git_ls_files(man_tracked_files_glob)
end
def tmp(*path)
- root.join("tmp", *path)
+ tmp_root.join("#{test_env_version}.#{scope}").join(*path)
+ end
+
+ def tmp_root
+ if ruby_core? && (tmpdir = ENV["TMPDIR"])
+ # Use realpath to resolve any symlinks in TMPDIR (e.g., on macOS /var -> /private/var)
+ real = begin
+ File.realpath(tmpdir)
+ rescue Errno::ENOENT, Errno::EACCES
+ tmpdir
+ end
+ Pathname(real)
+ else
+ (ruby_core? ? source_root : source_root.parent).join("tmp")
+ end
+ end
+
+ # Bump this version whenever you make a breaking change to the spec setup
+ # that requires regenerating tmp/.
+
+ def test_env_version
+ 2
+ end
+
+ def scope
+ test_number = ENV["TEST_ENV_NUMBER"]
+ return "1" if test_number.nil?
+
+ test_number.empty? ? "1" : test_number
end
def home(*path)
- tmp.join("home", *path)
+ tmp("home", *path)
end
def default_bundle_path(*path)
- if Bundler::VERSION.split(".").first.to_i < 3
- system_gem_path(*path)
- else
- bundled_app(*[".bundle", ENV.fetch("BUNDLER_SPEC_RUBY_ENGINE", Gem.ruby_engine), Gem::ConfigMap[:ruby_version], *path].compact)
- end
+ system_gem_path(*path)
+ end
+
+ def default_cache_path(*path)
+ default_bundle_path("cache/bundler", *path)
+ end
+
+ def compact_index_cache_path
+ home(".bundle/cache/compact_index")
end
def bundled_app(*path)
- root = tmp.join("bundled_app")
+ root = tmp("bundled_app")
FileUtils.mkdir_p(root)
root.join(*path)
end
- alias_method :bundled_app1, :bundled_app
-
def bundled_app2(*path)
- root = tmp.join("bundled_app2")
+ root = tmp("bundled_app2")
FileUtils.mkdir_p(root)
root.join(*path)
end
def vendored_gems(path = nil)
- bundled_app(*["vendor/bundle", Gem.ruby_engine, Gem::ConfigMap[:ruby_version], path].compact)
+ scoped_gem_path(bundled_app("vendor/bundle")).join(*[path].compact)
end
def cached_gem(path)
bundled_app("vendor/cache/#{path}.gem")
end
- def base_system_gems
- tmp.join("gems/base")
+ def bundled_app_gemfile
+ bundled_app("Gemfile")
+ end
+
+ def bundled_app_lock
+ bundled_app("Gemfile.lock")
+ end
+
+ def scoped_base_system_gem_path
+ scoped_gem_path(base_system_gem_path)
+ end
+
+ def base_system_gem_path
+ tmp_root.join("gems/base")
+ end
+
+ def rubocop_gem_path
+ tmp_root.join("gems/rubocop")
+ end
+
+ def standard_gem_path
+ tmp_root.join("gems/standard")
+ end
+
+ def file_uri_for(path)
+ protocol = "file://"
+ root = Gem.win_platform? ? "/" : ""
+
+ protocol + root + path.to_s
end
def gem_repo1(*args)
- tmp("gems/remote1", *args)
+ gem_path("remote1", *args)
end
def gem_repo_missing(*args)
- tmp("gems/missing", *args)
+ gem_path("missing", *args)
end
def gem_repo2(*args)
- tmp("gems/remote2", *args)
+ gem_path("remote2", *args)
end
def gem_repo3(*args)
- tmp("gems/remote3", *args)
+ gem_path("remote3", *args)
end
def gem_repo4(*args)
- tmp("gems/remote4", *args)
+ gem_path("remote4", *args)
end
def security_repo(*args)
- tmp("gems/security_repo", *args)
+ gem_path("security_repo", *args)
end
def system_gem_path(*path)
- tmp("gems/system", *path)
+ gem_path("system", *path)
+ end
+
+ def pristine_system_gem_path
+ tmp_root.join("gems/pristine_system")
+ end
+
+ def local_gem_path(*path, base: bundled_app)
+ scoped_gem_path(base.join(".bundle")).join(*path)
+ end
+
+ def scoped_gem_path(base)
+ base.join(Gem.ruby_engine, RbConfig::CONFIG["ruby_version"])
+ end
+
+ def gem_path(*args)
+ tmp("gems", *args)
end
def lib_path(*args)
tmp("libs", *args)
end
- def bundler_path
- Pathname.new(File.expand_path(root.join("lib"), __FILE__))
+ def source_lib_dir
+ source_root.join("lib")
+ end
+
+ def lib_dir
+ root.join("lib")
end
def global_plugin_gem(*args)
@@ -110,15 +276,104 @@ module Spec
tmp "tmpdir", *args
end
- def ruby_core?
- # avoid to wornings
- @ruby_core ||= nil
+ def replace_version_file(version, dir: source_root)
+ version_file = File.expand_path("lib/bundler/version.rb", dir)
+ contents = File.read(version_file)
+ contents.sub!(/(^\s+VERSION\s*=\s*).*$/, %(\\1"#{version}"))
+ File.open(version_file, "w") {|f| f << contents }
+ end
+
+ def replace_required_ruby_version(version, dir:)
+ gemspec_file = File.expand_path("bundler.gemspec", dir)
+ contents = File.read(gemspec_file)
+ contents.sub!(/(^\s+s\.required_ruby_version\s*=\s*)"[^"]+"/, %(\\1"#{version}"))
+ File.open(gemspec_file, "w") {|f| f << contents }
+ end
+
+ def replace_changelog(version, dir:)
+ changelog = File.expand_path("CHANGELOG.md", dir)
+ contents = File.readlines(changelog)
+ contents = [contents[0], contents[1], "## #{version} (2100-01-01)\n", *contents[3..-1]].join
+ File.open(changelog, "w") {|f| f << contents }
+ end
+
+ def git_root
+ ruby_core? ? source_root : source_root.parent
+ end
+
+ def rake_path
+ find_base_path("rake")
+ end
+
+ def rake_version
+ File.basename(rake_path).delete_prefix("rake-").delete_suffix(".gem")
+ end
- if @ruby_core.nil?
- @ruby_core = true & (ENV["BUNDLE_RUBY"] && ENV["BUNDLE_GEM"])
+ def sinatra_dependency_paths
+ deps = %w[
+ mustermann
+ rack
+ rack-protection
+ rack-session
+ tilt
+ sinatra
+ base64
+ logger
+ compact_index
+ ]
+ path = if deps.all? {|dep| !Dir[scoped_base_system_gem_path.join("gems/#{dep}-*")].empty? }
+ scoped_base_system_gem_path
+ elsif ruby_core? && deps.all? {|dep| !Dir[source_root.join(".bundle/gems/#{dep}-*")].empty? }
+ source_root.join(".bundle")
else
- @ruby_core
+ scoped_base_system_gem_path
end
+
+ Dir[path.join("gems/{#{deps.join(",")}}-*/lib")].map(&:to_s)
+ end
+
+ private
+
+ def find_base_path(name)
+ Dir["#{scoped_base_system_gem_path}/**/#{name}-*.gem"].first
+ end
+
+ def git_ls_files(glob)
+ skip "Not running on a git context, since running tests from a tarball" if ruby_core_tarball?
+
+ git("ls-files -z -- #{glob}", source_root).split("\x0")
+ end
+
+ def tracked_files_glob
+ ruby_core? ? "libexec/bundle* lib/bundler lib/bundler.rb spec/bundler man/bundle*" : "lib exe CHANGELOG.md LICENSE.md README.md bundler.gemspec"
+ end
+
+ def lib_tracked_files_glob
+ ruby_core? ? "lib/bundler lib/bundler.rb" : "lib"
+ end
+
+ def man_tracked_files_glob
+ "lib/bundler/man/bundle*.1.ronn lib/bundler/man/gemfile*.5.ronn"
+ end
+
+ def ruby_core_tarball?
+ !git_root.join(".git").directory?
+ end
+
+ def rubocop_gemfile_basename
+ tool_dir.join("rubocop_gems.rb")
+ end
+
+ def standard_gemfile_basename
+ tool_dir.join("standard_gems.rb")
+ end
+
+ def tool_dir
+ ruby_core? ? source_root.join("tool/bundler") : source_root.join("../tool/bundler")
+ end
+
+ def templates_dir
+ lib_dir.join("bundler", "templates")
end
extend self
diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb
index 950311d20e..56a0843005 100644
--- a/spec/bundler/support/platforms.rb
+++ b/spec/bundler/support/platforms.rb
@@ -2,90 +2,43 @@
module Spec
module Platforms
- include Bundler::GemHelpers
-
- def rb
- Gem::Platform::RUBY
- end
-
- def mac
- Gem::Platform.new("x86-darwin-10")
- end
-
- def x64_mac
- Gem::Platform.new("x86_64-darwin-15")
- end
-
- def java
- Gem::Platform.new([nil, "java", nil])
- end
-
- def linux
- Gem::Platform.new(["x86", "linux", nil])
- end
-
- def mswin
- Gem::Platform.new(["x86", "mswin32", nil])
- end
-
- def mingw
- Gem::Platform.new(["x86", "mingw32", nil])
- end
-
- def x64_mingw
- Gem::Platform.new(["x64", "mingw32", nil])
- end
-
- def all_platforms
- [rb, java, linux, mswin, mingw, x64_mingw]
- end
-
- def local
- generic_local_platform
+ def not_local
+ generic_local_platform == Gem::Platform::RUBY ? "java" : Gem::Platform::RUBY
end
- def specific_local_platform
+ def local_platform
Bundler.local_platform
end
- def not_local
- all_platforms.find {|p| p != generic_local_platform }
+ def generic_local_platform
+ Gem::Platform.generic(local_platform)
end
def local_tag
- if RUBY_PLATFORM == "java"
+ if Gem.java_platform?
:jruby
+ elsif Gem.win_platform?
+ :windows
else
:ruby
end
end
def not_local_tag
- [:ruby, :jruby].find {|tag| tag != local_tag }
+ [:jruby, :windows, :ruby].find {|tag| tag != local_tag }
end
def local_ruby_engine
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] || (defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby")
+ RUBY_ENGINE
end
def local_engine_version
- return ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] if ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
-
- case local_ruby_engine
- when "ruby"
- RUBY_VERSION
- when "rbx"
- Rubinius::VERSION
- when "jruby"
- JRUBY_VERSION
- else
- RUBY_ENGINE_VERSION
- end
+ RUBY_ENGINE == "ruby" ? Gem.ruby_version : RUBY_ENGINE_VERSION
end
def not_local_engine_version
case not_local_tag
- when :ruby
+ when :ruby, :windows
not_local_ruby_version
when :jruby
"1.6.1"
@@ -100,17 +53,23 @@ module Spec
9999
end
- def lockfile_platforms(*platforms)
- platforms = local_platforms if platforms.empty?
- platforms.map(&:to_s).sort.join("\n ")
+ def default_platform_list(*extra, defaults: default_locked_platforms)
+ defaults.concat(extra).map(&:to_s).uniq
end
- def local_platforms
- if Bundler::VERSION.split(".").first.to_i > 2
- [local, specific_local_platform]
- else
- [local]
- end
+ def lockfile_platforms(*extra, defaults: default_locked_platforms)
+ platforms = default_platform_list(*extra, defaults: defaults)
+ platforms.sort.join("\n ")
+ end
+
+ def default_locked_platforms
+ [local_platform, generic_default_locked_platform].compact
+ end
+
+ def generic_default_locked_platform
+ return unless Bundler::MatchPlatform.generic_local_platform_is_ruby?
+
+ Gem::Platform::RUBY
end
end
end
diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb
index c18f7650fc..812dc4deaa 100644
--- a/spec/bundler/support/rubygems_ext.rb
+++ b/spec/bundler/support/rubygems_ext.rb
@@ -1,71 +1,222 @@
# frozen_string_literal: true
-require "rubygems/user_interaction"
-require "support/path" unless defined?(Spec::Path)
+abort "RubyGems only supports Ruby 3.2 or higher" if RUBY_VERSION < "3.2.0"
+
+require_relative "path"
+
+$LOAD_PATH.unshift(Spec::Path.source_lib_dir.to_s)
module Spec
module Rubygems
- DEPS = begin
- deps = {
- # rack 2.x requires Ruby version >= 2.2.2.
- # artifice doesn't support rack 2.x now.
- # TODO: revert to `< 2` once https://github.com/rack/rack/issues/1168 is
- # addressed
- "rack" => "1.6.6",
- # rack-test 0.7.0 dropped 1.8.7 support
- # https://github.com/rack-test/rack-test/issues/193#issuecomment-314230318
- "rack-test" => "< 0.7.0",
- "artifice" => "~> 0.6.0",
- "compact_index" => "~> 0.11.0",
- "sinatra" => "~> 1.4.7",
- # Rake version has to be consistent for tests to pass
- "rake" => "10.0.2",
- # 3.0.0 breaks 1.9.2 specs
- "builder" => "2.1.2",
- }
- # ruby-graphviz is used by the viz tests
- deps["ruby-graphviz"] = nil if RUBY_VERSION >= "1.9.3"
- deps
- end
-
- def self.setup
- Gem.clear_paths
+ extend self
- ENV["BUNDLE_PATH"] = nil
- ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gems.to_s
- ENV["PATH"] = [Path.bindir, "#{Path.system_gem_path}/bin", ENV["PATH"]].join(File::PATH_SEPARATOR)
-
- manifest = DEPS.to_a.sort_by(&:first).map {|k, v| "#{k} => #{v}\n" }
- manifest_path = "#{Path.base_system_gems}/manifest.txt"
- # it's OK if there are extra gems
- if !File.exist?(manifest_path) || !(manifest - File.readlines(manifest_path)).empty?
- FileUtils.rm_rf(Path.base_system_gems)
- FileUtils.mkdir_p(Path.base_system_gems)
- puts "installing gems for the tests to use..."
- install_gems(DEPS)
- File.open(manifest_path, "w") {|f| f << manifest.join }
- end
+ def gem_load(gem_name, bin_container)
+ require_relative "switch_rubygems"
+
+ gem_load_and_activate(gem_name, bin_container)
+ end
+
+ def gem_load_and_possibly_install(gem_name, bin_container)
+ require_relative "switch_rubygems"
+
+ gem_load_activate_and_possibly_install(gem_name, bin_container)
+ end
+
+ def gem_require(gem_name, entrypoint)
+ gem_activate(gem_name)
+ require entrypoint
+ end
+
+ def test_setup
+ # Install test dependencies unless parallel-rspec is being used, since in that case they should be setup already
+ install_test_deps unless ENV["RSPEC_FORMATTER_OUTPUT_ID"]
+
+ setup_test_paths
+
+ require "fileutils"
+
+ FileUtils.mkdir_p(Path.home)
+ FileUtils.mkdir_p(Path.tmpdir)
ENV["HOME"] = Path.home.to_s
- ENV["TMPDIR"] = Path.tmpdir.to_s
+ # Remove "RUBY_CODESIGN", which is used by mkmf-generated Makefile to
+ # sign extension bundles on macOS, to avoid trying to find the specified key
+ # from the fake $HOME/Library/Keychains directory.
+ ENV.delete "RUBY_CODESIGN"
+ if Path.ruby_core?
+ if (tmpdir = ENV["TMPDIR"])
+ tmpdir_real = begin
+ File.realpath(tmpdir)
+ rescue Errno::ENOENT, Errno::EACCES
+ tmpdir
+ end
+ ENV["TMPDIR"] = tmpdir_real if tmpdir_real != tmpdir
+ end
+ else
+ ENV["TMPDIR"] = Path.tmpdir.to_s
+ end
+ require "rubygems/user_interaction"
Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
end
- def self.install_gems(gems)
- reqs, no_reqs = gems.partition {|_, req| !req.nil? && !req.split(" ").empty? }
- # TODO: remove when we drop ruby 1.8.7-2.2.2 support
- reqs = reqs.sort_by {|name, _| name == "rack" ? 0 : 1 }.sort_by {|name, _| name =~ /rack/ ? 0 : 1 }
- no_reqs.map!(&:first)
- reqs.map! {|name, req| "'#{name}:#{req}'" }
- deps = reqs.concat(no_reqs).join(" ")
- cmd = if Gem::VERSION < "2.0.0"
- "gem install #{deps} --no-rdoc --no-ri --conservative"
+ def setup_test_paths
+ ENV["BUNDLE_PATH"] = nil
+ ENV["PATH"] = [Path.system_gem_path("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ ENV["PATH"] = [Path.exedir, ENV["PATH"]].join(File::PATH_SEPARATOR) if Path.ruby_core?
+ end
+
+ def install_test_deps
+ dev_bundle("install", gemfile: test_gemfile, path: Path.base_system_gem_path.to_s)
+ dev_bundle("install", gemfile: rubocop_gemfile, path: Path.rubocop_gem_path.to_s)
+ dev_bundle("install", gemfile: standard_gemfile, path: Path.standard_gem_path.to_s)
+
+ require_relative "helpers"
+ Helpers.install_dev_bundler
+
+ install_vendored_compact_index
+ end
+
+ # Vendor `rubygems/rubygems.org#lib/compact_index/` under `tmp/compact_index/`
+ # so the artifice can serve compact-index responses without a runtime gem
+ # dependency. Pinned to a reviewed commit; override with COMPACT_INDEX_REF
+ # to refresh against another ref (the existing vendor copy is discarded).
+ def install_vendored_compact_index
+ target_root = Path.tmp_root.join("compact_index")
+ require "fileutils"
+ FileUtils.mkdir_p(Path.tmp_root)
+
+ files = %w[
+ lib/compact_index.rb
+ lib/compact_index/dependency.rb
+ lib/compact_index/gem.rb
+ lib/compact_index/gem_version.rb
+ lib/compact_index/versions_file.rb
+ ]
+
+ # Serialize installs so parallel test setups don't race on the same
+ # vendor tree, and only skip the download when every file is present so
+ # an interrupted run can't leave a partial copy behind.
+ File.open(Path.tmp_root.join("compact_index.lock"), File::CREAT | File::RDWR) do |lock|
+ lock.flock(File::LOCK_EX)
+
+ FileUtils.rm_rf(target_root) if ENV["COMPACT_INDEX_REF"]
+
+ next if files.all? {|path| File.exist?(target_root.join(path)) }
+
+ require "open-uri"
+ ref = ENV["COMPACT_INDEX_REF"] || "7c68a7b39761c61a66f9299f85b889ec39afc02c"
+ files.each do |path|
+ url = "https://raw.githubusercontent.com/rubygems/rubygems.org/#{ref}/#{path}"
+ target = target_root.join(path)
+ FileUtils.mkdir_p(File.dirname(target))
+ tmp = "#{target}.tmp"
+ File.write(tmp, URI.parse(url).open(&:read))
+ File.rename(tmp, target)
+ end
+ end
+ end
+
+ def check_source_control_changes(success_message:, error_message:)
+ require "open3"
+
+ output, status = Open3.capture2e("git status --porcelain")
+
+ if status.success? && output.empty?
+ puts
+ puts success_message
+ puts
+ else
+ system("git diff")
+
+ puts
+ puts error_message
+ puts
+
+ exit(1)
+ end
+ end
+
+ def dev_bundle(*args, gemfile: dev_gemfile, path: nil)
+ old_gemfile = ENV["BUNDLE_GEMFILE"]
+ old_orig_gemfile = ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"]
+ ENV["BUNDLE_GEMFILE"] = gemfile.to_s
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil
+
+ if path
+ old_path = ENV["BUNDLE_PATH"]
+ ENV["BUNDLE_PATH"] = path
else
- "gem install #{deps} --no-document --conservative"
+ old_path__system = ENV["BUNDLE_PATH__SYSTEM"]
+ ENV["BUNDLE_PATH__SYSTEM"] = "true"
end
- puts cmd
- system(cmd) || raise("Installing gems #{deps} for the tests to use failed!")
+
+ require "shellwords"
+ # We don't use `Open3` here because it does not work on JRuby + Windows
+ output = `ruby #{Path.dev_binstub} #{args.shelljoin}`
+ raise output unless $?.success?
+ output
+ ensure
+ if path
+ ENV["BUNDLE_PATH"] = old_path
+ else
+ ENV["BUNDLE_PATH__SYSTEM"] = old_path__system
+ end
+
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = old_orig_gemfile
+ ENV["BUNDLE_GEMFILE"] = old_gemfile
+ end
+
+ private
+
+ def gem_load_and_activate(gem_name, bin_container)
+ gem_activate(gem_name)
+ load Gem.bin_path(gem_name, bin_container)
+ rescue Gem::LoadError => e
+ abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
+ end
+
+ def gem_load_activate_and_possibly_install(gem_name, bin_container)
+ gem_activate_and_possibly_install(gem_name)
+ load Gem.bin_path(gem_name, bin_container)
+ end
+
+ def gem_activate_and_possibly_install(gem_name)
+ gem_activate(gem_name)
+ rescue Gem::LoadError => e
+ Gem.install(gem_name, e.requirement)
+ retry
+ end
+
+ def gem_activate(gem_name)
+ require_relative "activate"
+ require "bundler"
+ gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).specs.find {|spec| spec.name == gem_name }.version
+ gem gem_name, gem_requirement
+ end
+
+ def test_gemfile
+ Path.test_gemfile
+ end
+
+ def rubocop_gemfile
+ Path.rubocop_gemfile
+ end
+
+ def standard_gemfile
+ Path.standard_gemfile
+ end
+
+ def dev_gemfile
+ Path.dev_gemfile
+ end
+
+ def dev_lockfile
+ lockfile_for(dev_gemfile)
+ end
+
+ def lockfile_for(gemfile)
+ Pathname.new("#{gemfile.expand_path}.lock")
end
end
end
diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb
new file mode 100644
index 0000000000..c174c461f0
--- /dev/null
+++ b/spec/bundler/support/rubygems_version_manager.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require_relative "options"
+require_relative "env"
+require_relative "subprocess"
+
+class RubygemsVersionManager
+ include Spec::Options
+ include Spec::Env
+ include Spec::Subprocess
+
+ def initialize(source)
+ @source = source
+ end
+
+ def switch
+ return if use_system?
+
+ assert_system_features_not_loaded!
+
+ switch_local_copy_if_needed
+
+ reexec_if_needed
+ end
+
+ def assert_system_features_not_loaded!
+ at_exit do
+ rubylibdir = RbConfig::CONFIG["rubylibdir"]
+
+ rubygems_path = rubylibdir + "/rubygems"
+ rubygems_default_path = rubygems_path + "/defaults"
+
+ bundler_path = rubylibdir + "/bundler"
+
+ bad_loaded_features = $LOADED_FEATURES.select do |loaded_feature|
+ (loaded_feature.start_with?(rubygems_path) && !loaded_feature.start_with?(rubygems_default_path)) ||
+ loaded_feature.start_with?(bundler_path)
+ end
+
+ errors = if bad_loaded_features.any?
+ all_commands_output + "the following features were incorrectly loaded:\n#{bad_loaded_features.join("\n")}"
+ end
+
+ raise errors if errors
+ end
+ end
+
+ private
+
+ def use_system?
+ @source.nil?
+ end
+
+ def reexec_if_needed
+ return unless rubygems_unrequire_needed?
+
+ require "rbconfig"
+
+ cmd = [RbConfig.ruby, $0, *ARGV].compact
+
+ ENV["RUBYOPT"] = opt_add("-I#{File.join(local_copy_path, "lib")}", opt_remove("--disable-gems", ENV["RUBYOPT"]))
+
+ exec(ENV, *cmd)
+ end
+
+ def switch_local_copy_if_needed
+ return unless local_copy_switch_needed?
+
+ git("checkout #{target_tag}", local_copy_path)
+
+ ENV["RGV"] = local_copy_path
+ end
+
+ def rubygems_unrequire_needed?
+ require "rubygems"
+ !$LOADED_FEATURES.include?(File.join(local_copy_path, "lib/rubygems.rb"))
+ end
+
+ def local_copy_switch_needed?
+ !source_is_path? && target_tag != local_copy_tag
+ end
+
+ def target_tag
+ @target_tag ||= resolve_target_tag
+ end
+
+ def local_copy_tag
+ git("rev-parse --abbrev-ref HEAD", local_copy_path)
+ end
+
+ def local_copy_path
+ @local_copy_path ||= resolve_local_copy_path
+ end
+
+ def resolve_local_copy_path
+ return expanded_source if source_is_path?
+
+ rubygems_path = File.join(source_root, "tmp/rubygems")
+
+ unless File.directory?(rubygems_path)
+ git("clone .. #{rubygems_path}", source_root)
+ end
+
+ rubygems_path
+ end
+
+ def source_is_path?
+ File.directory?(expanded_source)
+ end
+
+ def expanded_source
+ @expanded_source ||= File.expand_path(@source, source_root)
+ end
+
+ def source_root
+ @source_root ||= File.expand_path(ruby_core? ? "../../.." : "../..", __dir__)
+ end
+
+ def resolve_target_tag
+ return "v#{@source}" if @source.match?(/^\d/)
+
+ @source
+ end
+end
diff --git a/spec/bundler/support/setup.rb b/spec/bundler/support/setup.rb
new file mode 100644
index 0000000000..4ac2e5b472
--- /dev/null
+++ b/spec/bundler/support/setup.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative "switch_rubygems"
+
+require_relative "rubygems_ext"
+Spec::Rubygems.install_test_deps
+
+require_relative "path"
+$LOAD_PATH.unshift(File.expand_path("../../lib", __dir__)) if Spec::Path.ruby_core?
diff --git a/spec/bundler/support/shards.rb b/spec/bundler/support/shards.rb
new file mode 100644
index 0000000000..ce33896539
--- /dev/null
+++ b/spec/bundler/support/shards.rb
@@ -0,0 +1,200 @@
+# frozen_string_literal: true
+
+# This classifies test files into 4 shards by running `bin/rspec --profile 10000`
+# to ensure balanced execution times. When adding new test files, it is recommended to
+# re-aggregate and adjust the shards to keep them balanced.
+# For now, please add new files to shard 'shard_d'.
+
+module Spec
+ module Shards
+ EXAMPLE_MAPPINGS = {
+ shard_a: [
+ "spec/runtime/setup_spec.rb",
+ "spec/commands/install_spec.rb",
+ "spec/commands/add_spec.rb",
+ "spec/install/gems/compact_index_spec.rb",
+ "spec/commands/config_spec.rb",
+ "spec/commands/pristine_spec.rb",
+ "spec/install/gemfile/path_spec.rb",
+ "spec/update/git_spec.rb",
+ "spec/commands/open_spec.rb",
+ "spec/commands/remove_spec.rb",
+ "spec/commands/show_spec.rb",
+ "spec/plugins/source/example_spec.rb",
+ "spec/commands/console_spec.rb",
+ "spec/runtime/require_spec.rb",
+ "spec/runtime/env_helpers_spec.rb",
+ "spec/runtime/gem_tasks_spec.rb",
+ "spec/install/gemfile_spec.rb",
+ "spec/commands/fund_spec.rb",
+ "spec/commands/init_spec.rb",
+ "spec/bundler/ruby_dsl_spec.rb",
+ "spec/bundler/mirror_spec.rb",
+ "spec/bundler/source/git/git_proxy_spec.rb",
+ "spec/bundler/source_list_spec.rb",
+ "spec/bundler/plugin/installer_spec.rb",
+ "spec/bundler/errors_spec.rb",
+ "spec/bundler/friendly_errors_spec.rb",
+ "spec/resolver/platform_spec.rb",
+ "spec/bundler/fetcher/downloader_spec.rb",
+ "spec/update/force_spec.rb",
+ "spec/bundler/env_spec.rb",
+ "spec/install/gems/mirror_spec.rb",
+ "spec/install/failure_spec.rb",
+ "spec/bundler/yaml_serializer_spec.rb",
+ "spec/bundler/environment_preserver_spec.rb",
+ "spec/install/gemfile/install_if_spec.rb",
+ "spec/install/gems/gemfile_source_header_spec.rb",
+ "spec/bundler/fetcher/base_spec.rb",
+ "spec/bundler/rubygems_integration_spec.rb",
+ "spec/bundler/worker_spec.rb",
+ "spec/bundler/dependency_spec.rb",
+ "spec/bundler/ui_spec.rb",
+ "spec/bundler/plugin/source_list_spec.rb",
+ "spec/bundler/source/path_spec.rb",
+ ],
+ shard_b: [
+ "spec/install/gemfile/git_spec.rb",
+ "spec/install/gems/standalone_spec.rb",
+ "spec/commands/lock_spec.rb",
+ "spec/cache/gems_spec.rb",
+ "spec/other/major_deprecation_spec.rb",
+ "spec/install/gems/dependency_api_spec.rb",
+ "spec/install/gemfile/gemspec_spec.rb",
+ "spec/plugins/install_spec.rb",
+ "spec/commands/binstubs_spec.rb",
+ "spec/install/gems/flex_spec.rb",
+ "spec/runtime/inline_spec.rb",
+ "spec/commands/post_bundle_message_spec.rb",
+ "spec/runtime/executable_spec.rb",
+ "spec/lock/git_spec.rb",
+ "spec/plugins/hook_spec.rb",
+ "spec/install/allow_offline_install_spec.rb",
+ "spec/install/gems/post_install_spec.rb",
+ "spec/install/gemfile/ruby_spec.rb",
+ "spec/install/security_policy_spec.rb",
+ "spec/install/yanked_spec.rb",
+ "spec/update/gemfile_spec.rb",
+ "spec/runtime/load_spec.rb",
+ "spec/plugins/command_spec.rb",
+ "spec/commands/version_spec.rb",
+ "spec/install/prereleases_spec.rb",
+ "spec/bundler/uri_credentials_filter_spec.rb",
+ "spec/bundler/plugin_spec.rb",
+ "spec/install/gems/mirror_probe_spec.rb",
+ "spec/plugins/list_spec.rb",
+ "spec/bundler/compact_index_client/parser_spec.rb",
+ "spec/bundler/gem_version_promoter_spec.rb",
+ "spec/other/cli_dispatch_spec.rb",
+ "spec/bundler/source/rubygems_spec.rb",
+ "spec/cache/platform_spec.rb",
+ "spec/update/gems/fund_spec.rb",
+ "spec/bundler/stub_specification_spec.rb",
+ "spec/bundler/retry_spec.rb",
+ "spec/bundler/installer/spec_installation_spec.rb",
+ "spec/bundler/spec_set_spec.rb",
+ "spec/quality_es_spec.rb",
+ "spec/bundler/index_spec.rb",
+ "spec/other/cli_man_pages_spec.rb",
+ ],
+ shard_c: [
+ "spec/commands/newgem_spec.rb",
+ "spec/commands/exec_spec.rb",
+ "spec/commands/clean_spec.rb",
+ "spec/commands/platform_spec.rb",
+ "spec/cache/git_spec.rb",
+ "spec/install/gemfile/groups_spec.rb",
+ "spec/commands/cache_spec.rb",
+ "spec/commands/check_spec.rb",
+ "spec/commands/list_spec.rb",
+ "spec/install/path_spec.rb",
+ "spec/bundler/cli_spec.rb",
+ "spec/install/bundler_spec.rb",
+ "spec/install/git_spec.rb",
+ "spec/commands/doctor_spec.rb",
+ "spec/bundler/dsl_spec.rb",
+ "spec/install/gems/fund_spec.rb",
+ "spec/install/gems/env_spec.rb",
+ "spec/bundler/ruby_version_spec.rb",
+ "spec/bundler/definition_spec.rb",
+ "spec/install/gemfile/eval_gemfile_spec.rb",
+ "spec/plugins/source_spec.rb",
+ "spec/install/gems/dependency_api_fallback_spec.rb",
+ "spec/plugins/uninstall_spec.rb",
+ "spec/bundler/plugin/index_spec.rb",
+ "spec/bundler/bundler_spec.rb",
+ "spec/bundler/fetcher_spec.rb",
+ "spec/bundler/source/rubygems/remote_spec.rb",
+ "spec/bundler/lockfile_parser_spec.rb",
+ "spec/cache/cache_path_spec.rb",
+ "spec/bundler/source/git_spec.rb",
+ "spec/bundler/source_spec.rb",
+ "spec/commands/ssl_spec.rb",
+ "spec/bundler/fetcher/compact_index_spec.rb",
+ "spec/bundler/plugin/api_spec.rb",
+ "spec/bundler/endpoint_specification_spec.rb",
+ "spec/bundler/fetcher/index_spec.rb",
+ "spec/bundler/settings/validator_spec.rb",
+ "spec/bundler/build_metadata_spec.rb",
+ "spec/bundler/current_ruby_spec.rb",
+ "spec/bundler/installer/gem_installer_spec.rb",
+ "spec/bundler/installer/parallel_installer_spec.rb",
+ "spec/bundler/cli_common_spec.rb",
+ "spec/bundler/ci_detector_spec.rb",
+ ],
+ shard_d: [
+ "spec/bundler/rubygems_ext_spec.rb",
+ "spec/bundler/resolver/cooldown_spec.rb",
+ "spec/install/cooldown_spec.rb",
+ "spec/commands/outdated_spec.rb",
+ "spec/commands/update_spec.rb",
+ "spec/lock/lockfile_spec.rb",
+ "spec/install/deploy_spec.rb",
+ "spec/install/gemfile/sources_spec.rb",
+ "spec/runtime/self_management_spec.rb",
+ "spec/install/gemfile/specific_platform_spec.rb",
+ "spec/commands/info_spec.rb",
+ "spec/install/gems/resolving_spec.rb",
+ "spec/install/gemfile/platform_spec.rb",
+ "spec/bundler/gem_helper_spec.rb",
+ "spec/install/global_cache_spec.rb",
+ "spec/runtime/platform_spec.rb",
+ "spec/update/gems/post_install_spec.rb",
+ "spec/install/gems/native_extensions_spec.rb",
+ "spec/install/force_spec.rb",
+ "spec/cache/path_spec.rb",
+ "spec/install/gemspecs_spec.rb",
+ "spec/commands/help_spec.rb",
+ "spec/bundler/shared_helpers_spec.rb",
+ "spec/bundler/settings_spec.rb",
+ "spec/resolver/basic_spec.rb",
+ "spec/install/gemfile/force_ruby_platform_spec.rb",
+ "spec/commands/licenses_spec.rb",
+ "spec/install/gemfile/lockfile_spec.rb",
+ "spec/bundler/fetcher/dependency_spec.rb",
+ "spec/quality_spec.rb",
+ "spec/bundler/remote_specification_spec.rb",
+ "spec/install/process_lock_spec.rb",
+ "spec/install/binstubs_spec.rb",
+ "spec/bundler/compact_index_client/updater_spec.rb",
+ "spec/bundler/ui/shell_spec.rb",
+ "spec/other/ext_spec.rb",
+ "spec/commands/issue_spec.rb",
+ "spec/update/path_spec.rb",
+ "spec/bundler/plugin/api/source_spec.rb",
+ "spec/install/gems/win32_spec.rb",
+ "spec/bundler/plugin/dsl_spec.rb",
+ "spec/runtime/requiring_spec.rb",
+ "spec/bundler/plugin/events_spec.rb",
+ "spec/bundler/resolver/candidate_spec.rb",
+ "spec/bundler/digest_spec.rb",
+ "spec/bundler/fetcher/gem_remote_fetcher_spec.rb",
+ "spec/bundler/uri_normalizer_spec.rb",
+ "spec/install/gems/no_build_extension_spec.rb",
+ "spec/install/gems/no_install_plugin_spec.rb",
+ "spec/bundler/override_spec.rb",
+ "spec/install/gemfile/override_spec.rb",
+ ],
+ }.freeze
+ end
+end
diff --git a/spec/bundler/support/silent_logger.rb b/spec/bundler/support/silent_logger.rb
deleted file mode 100644
index 8665beb2c9..0000000000
--- a/spec/bundler/support/silent_logger.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-require "logger"
-module Spec
- class SilentLogger
- (::Logger.instance_methods - Object.instance_methods).each do |logger_instance_method|
- define_method(logger_instance_method) {|*args, &blk| }
- end
- end
-end
diff --git a/spec/bundler/support/sometimes.rb b/spec/bundler/support/sometimes.rb
deleted file mode 100644
index 65a95ed59c..0000000000
--- a/spec/bundler/support/sometimes.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Sometimes
- def run_with_retries(example_to_run, retries)
- example = RSpec.current_example
- example.metadata[:retries] ||= retries
-
- retries.times do |t|
- example.metadata[:retried] = t + 1
- example.instance_variable_set(:@exception, nil)
- example_to_run.run
- break unless example.exception
- end
-
- if e = example.exception
- new_exception = e.exception(e.message + "[Retried #{retries} times]")
- new_exception.set_backtrace e.backtrace
- example.instance_variable_set(:@exception, new_exception)
- end
- end
-end
-
-RSpec.configure do |config|
- config.include Sometimes
- config.alias_example_to :sometimes, :sometimes => true
- config.add_setting :sometimes_retry_count, :default => 5
-
- config.around(:each, :sometimes => true) do |example|
- retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count
- run_with_retries(example, retries)
- end
-
- config.after(:suite) do
- message = proc do |color, text|
- colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color)
- notification = RSpec::Core::Notifications::MessageNotification.new(colored)
- formatter = RSpec.configuration.formatters.first
- formatter.message(notification) if formatter.respond_to?(:message)
- end
-
- retried_examples = RSpec.world.example_groups.map do |g|
- g.descendants.map do |d|
- d.filtered_examples.select do |e|
- e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1
- end
- end
- end.flatten
-
- message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}")
-
- retried_examples.each do |e|
- message.call(:cyan, " #{e.full_description}")
- path = RSpec::Core::Metadata.relative_path(e.location)
- message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path)
- end
- end
-end
diff --git a/spec/bundler/support/streams.rb b/spec/bundler/support/streams.rb
deleted file mode 100644
index a947eebf6f..0000000000
--- a/spec/bundler/support/streams.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require "stringio"
-
-def capture(*args)
- opts = args.pop if args.last.is_a?(Hash)
- opts ||= {}
-
- args.map!(&:to_s)
- begin
- result = StringIO.new
- result.close if opts[:closed]
- args.each {|stream| eval "$#{stream} = result" }
- yield
- ensure
- args.each {|stream| eval("$#{stream} = #{stream.upcase}") }
- end
- result.string
-end
diff --git a/spec/bundler/support/subprocess.rb b/spec/bundler/support/subprocess.rb
new file mode 100644
index 0000000000..91db80da48
--- /dev/null
+++ b/spec/bundler/support/subprocess.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+require_relative "command_execution"
+
+module Spec
+ module Subprocess
+ class TimeoutExceeded < StandardError; end
+
+ def command_executions
+ @command_executions ||= []
+ end
+
+ def last_command
+ command_executions.last || raise("There is no last command")
+ end
+
+ def out
+ last_command.stdout
+ end
+
+ def err
+ last_command.stderr
+ end
+
+ def stdboth
+ last_command.stdboth
+ end
+
+ def exitstatus
+ last_command.exitstatus
+ end
+
+ def git(cmd, path = Dir.pwd, options = {})
+ sh("git #{cmd}", options.merge(dir: path))
+ end
+
+ def sh(cmd, options = {})
+ dir = options[:dir]
+ env = options[:env] || {}
+
+ command_execution = CommandExecution.new(cmd.to_s, timeout: options[:timeout] || 60)
+
+ open3_opts = {}
+ open3_opts[:chdir] = dir if dir
+
+ require "open3"
+ require "shellwords"
+ Open3.popen3(env, *cmd.shellsplit, **open3_opts) do |stdin, stdout, stderr, wait_thr|
+ yield stdin, stdout, wait_thr if block_given?
+ stdin.close
+
+ stdout_handler = ->(data) { command_execution.original_stdout << data }
+ stderr_handler = ->(data) { command_execution.original_stderr << data }
+
+ stdout_thread = read_stream(stdout, stdout_handler, timeout: command_execution.timeout)
+ stderr_thread = read_stream(stderr, stderr_handler, timeout: command_execution.timeout)
+
+ stdout_thread.join
+ stderr_thread.join
+
+ status = wait_thr.value
+ command_execution.exitstatus = if status.exited?
+ status.exitstatus
+ elsif status.signaled?
+ exit_status_for_signal(status.termsig)
+ end
+ rescue TimeoutExceeded
+ command_execution.failure_reason = :timeout
+ command_execution.exitstatus = exit_status_for_signal(Signal.list["INT"])
+ end
+
+ unless options[:raise_on_error] == false || command_execution.success?
+ command_execution.raise_error!
+ end
+
+ command_executions << command_execution
+
+ command_execution.stdout
+ end
+
+ # Mostly copied from https://github.com/piotrmurach/tty-command/blob/49c37a895ccea107e8b78d20e4cb29de6a1a53c8/lib/tty/command/process_runner.rb#L165-L193
+ def read_stream(stream, handler, timeout:)
+ Thread.new do
+ Thread.current.report_on_exception = false
+ cmd_start = Time.now
+ readers = [stream]
+
+ while readers.any?
+ ready = IO.select(readers, nil, readers, timeout)
+ raise TimeoutExceeded if ready.nil?
+
+ ready[0].each do |reader|
+ chunk = reader.readpartial(16 * 1024)
+ handler.call(chunk)
+
+ # control total time spent reading
+ runtime = Time.now - cmd_start
+ time_left = timeout - runtime
+ raise TimeoutExceeded if time_left < 0.0
+ rescue Errno::EAGAIN, Errno::EINTR
+ rescue EOFError, Errno::EPIPE, Errno::EIO
+ readers.delete(reader)
+ reader.close
+ end
+ end
+ end
+ end
+
+ def all_commands_output
+ return "" if command_executions.empty?
+
+ "\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}"
+ end
+ end
+end
diff --git a/spec/bundler/support/sudo.rb b/spec/bundler/support/sudo.rb
deleted file mode 100644
index 04e9443945..0000000000
--- a/spec/bundler/support/sudo.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module Sudo
- def self.present?
- @which_sudo ||= Bundler.which("sudo")
- end
-
- def sudo(cmd)
- raise "sudo not present" unless Sudo.present?
- sys_exec("sudo #{cmd}")
- end
-
- def chown_system_gems_to_root
- sudo "chown -R root #{system_gem_path}"
- end
- end
-end
diff --git a/spec/bundler/support/switch_rubygems.rb b/spec/bundler/support/switch_rubygems.rb
new file mode 100644
index 0000000000..640b9f83b7
--- /dev/null
+++ b/spec/bundler/support/switch_rubygems.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+require_relative "rubygems_version_manager"
+ENV["RGV"] ||= "."
+RubygemsVersionManager.new(ENV["RGV"]).switch
diff --git a/spec/bundler/support/the_bundle.rb b/spec/bundler/support/the_bundle.rb
index c994eaae78..452abd7d41 100644
--- a/spec/bundler/support/the_bundle.rb
+++ b/spec/bundler/support/the_bundle.rb
@@ -1,19 +1,15 @@
# frozen_string_literal: true
-require "support/helpers"
-require "support/path"
+require_relative "path"
module Spec
class TheBundle
- include Spec::Helpers
include Spec::Path
attr_accessor :bundle_dir
- def initialize(opts = {})
- opts = opts.dup
- @bundle_dir = Pathname.new(opts.delete(:bundle_dir) { bundled_app })
- raise "Too many options! #{opts}" unless opts.empty?
+ def initialize
+ @bundle_dir = Pathname.new(bundled_app)
end
def to_s
@@ -30,8 +26,16 @@ module Spec
end
def locked_gems
- raise "Cannot read lockfile if it doesn't exist" unless locked?
+ raise ArgumentError, "Cannot read lockfile if it doesn't exist" unless locked?
Bundler::LockfileParser.new(lockfile.read)
end
+
+ def locked_specs
+ locked_gems.specs.map(&:full_name)
+ end
+
+ def locked_platforms
+ locked_gems.platforms.map(&:to_s)
+ end
end
end
diff --git a/spec/bundler/support/vendored_net_http.rb b/spec/bundler/support/vendored_net_http.rb
new file mode 100644
index 0000000000..8ff2ccd1fe
--- /dev/null
+++ b/spec/bundler/support/vendored_net_http.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# This defined? guard can be removed once RubyGems 3.4 support is dropped.
+#
+# Bundler specs load this code from `spec/support/vendored_net_http.rb` to avoid
+# activating the Bundler gem too early. Without this guard, we get redefinition
+# warnings once Bundler is actually activated and
+# `lib/bundler/vendored_net_http.rb` is required. This is not an issue in
+# RubyGems versions including `rubygems/vendored_net_http` since `require` takes
+# care of avoiding the double load.
+#
+unless defined?(Gem::Net)
+ begin
+ require "rubygems/vendored_net_http"
+ rescue LoadError
+ begin
+ require "rubygems/net/http"
+ rescue LoadError
+ require "net/http"
+ Gem::Net = Net
+ end
+ end
+end
diff --git a/spec/bundler/update/force_spec.rb b/spec/bundler/update/force_spec.rb
new file mode 100644
index 0000000000..325f58088a
--- /dev/null
+++ b/spec/bundler/update/force_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle update" do
+ before :each do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "re-installs installed gems with --force" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :update, force: true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "re-installs installed gems with --redownload" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :update, redownload: true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+end
diff --git a/spec/bundler/update/gemfile_spec.rb b/spec/bundler/update/gemfile_spec.rb
index f59f3a2d32..f8849640b6 100644
--- a/spec/bundler/update/gemfile_spec.rb
+++ b/spec/bundler/update/gemfile_spec.rb
@@ -4,63 +4,44 @@ RSpec.describe "bundle update" do
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- bundle! :install, :gemfile => bundled_app("NotGemfile")
- bundle! :update, :gemfile => bundled_app("NotGemfile"), :all => bundle_update_requires_all?
+ bundle :install, gemfile: bundled_app("NotGemfile")
+ bundle :update, gemfile: bundled_app("NotGemfile"), all: true
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with gemfile set via config" do
before do
gemfile bundled_app("NotGemfile"), <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- bundle "config --local gemfile #{bundled_app("NotGemfile")}"
- bundle! :install
+ bundle_config "gemfile #{bundled_app("NotGemfile")}"
+ bundle :install
end
it "uses the gemfile to update" do
- bundle! "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
bundle "list"
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- bundle! "update", :all => bundle_update_requires_all?
- bundle "list"
+ bundle "update", all: true, dir: bundled_app("subdir")
+ bundle "list", dir: bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
- end
- end
- end
-
- context "with prefer_gems_rb set" do
- before { bundle! "config prefer_gems_rb true" }
-
- it "prefers gems.rb to Gemfile" do
- create_file("gems.rb", "gem 'bundler'")
- create_file("Gemfile", "raise 'wrong Gemfile!'")
-
- bundle! :install
- bundle! :update, :all => bundle_update_requires_all?
-
- expect(bundled_app("gems.rb")).to be_file
- expect(bundled_app("Gemfile.lock")).not_to be_file
-
- expect(the_bundle).to include_gem "bundler #{Bundler::VERSION}"
+ expect(out).to include("myrack (1.0.0)")
end
end
end
diff --git a/spec/bundler/update/gems/fund_spec.rb b/spec/bundler/update/gems/fund_spec.rb
new file mode 100644
index 0000000000..a5624d3e0a
--- /dev/null
+++ b/spec/bundler/update/gems/fund_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle update" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding', '< 2.0'
+ G
+
+ bundle :install
+ end
+
+ context "when listed gems are updated" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ G
+
+ bundle :update, all: true
+ end
+
+ it "displays fund message" do
+ expect(out).to include("2 installed gems you directly depend on are looking for funding.")
+ end
+ end
+end
diff --git a/spec/bundler/update/gems/post_install_spec.rb b/spec/bundler/update/gems/post_install_spec.rb
index 2fb3547806..9c71f6e0e3 100644
--- a/spec/bundler/update/gems/post_install_spec.rb
+++ b/spec/bundler/update/gems/post_install_spec.rb
@@ -5,22 +5,22 @@ RSpec.describe "bundle update" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack', "< 1.0"
+ source "https://gem.repo1"
+ gem 'myrack', "< 1.0"
gem 'thin'
G
- bundle! "config #{config}" if config
+ bundle "config set #{config}" if config
- bundle! :install
+ bundle :install
end
shared_examples "a config observer" do
context "when ignore post-install messages for gem is set" do
- let(:config) { "ignore_messages.rack true" }
+ let(:config) { "ignore_messages.myrack true" }
it "doesn't display gem's post-install message" do
- expect(out).not_to include("Rack's post install message")
+ expect(out).not_to include("Myrack's post install message")
end
end
@@ -35,8 +35,8 @@ RSpec.describe "bundle update" do
shared_examples "a post-install message outputter" do
it "should display post-install messages for updated gems" do
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
it "should not display the post-install message for non-updated gems" do
@@ -47,12 +47,12 @@ RSpec.describe "bundle update" do
context "when listed gem is updated" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gem 'thin'
G
- bundle! :update, :all => bundle_update_requires_all?
+ bundle :update, all: true
end
it_behaves_like "a post-install message outputter"
@@ -62,12 +62,12 @@ RSpec.describe "bundle update" do
context "when dependency triggers update" do
before do
gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack-obama'
+ source "https://gem.repo1"
+ gem 'myrack-obama'
gem 'thin'
G
- bundle! :update, :all => bundle_update_requires_all?
+ bundle :update, all: true
end
it_behaves_like "a post-install message outputter"
diff --git a/spec/bundler/update/git_spec.rb b/spec/bundler/update/git_spec.rb
index d97760e84b..526e988ab7 100644
--- a/spec/bundler/update/git_spec.rb
+++ b/spec/bundler/update/git_spec.rb
@@ -4,48 +4,51 @@ RSpec.describe "bundle update" do
describe "git sources" do
it "floats on a branch when :branch is used" do
build_git "foo", "1.0"
- update_git "foo", :branch => "omg"
+ update_git "foo", branch: "omg"
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :branch => "omg" do
gem 'foo'
end
G
- update_git "foo", :branch => "omg" do |s|
+ update_git "foo" do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
- bundle "update", :all => bundle_update_requires_all?
+ bundle "update", all: true
expect(the_bundle).to include_gems "foo 1.1"
end
it "updates correctly when you have like craziness" do
- build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport")
- build_git "rails", "3.0", :path => lib_path("rails") do |s|
+ build_lib "activesupport", "3.0", path: lib_path("rails/activesupport")
+ build_git "rails", "3.0", path: lib_path("rails") do |s|
s.add_dependency "activesupport", "= 3.0"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "https://gem.repo1"
gem "rails", :git => "#{lib_path("rails")}"
G
- bundle! "update rails"
+ bundle "update rails"
expect(the_bundle).to include_gems "rails 3.0", "activesupport 3.0"
end
it "floats on a branch when :branch is used and the source is specified in the update" do
- build_git "foo", "1.0", :path => lib_path("foo")
- update_git "foo", :branch => "omg", :path => lib_path("foo")
+ build_git "foo", "1.0", path: lib_path("foo")
+ update_git "foo", branch: "omg", path: lib_path("foo")
install_gemfile <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo")}", :branch => "omg" do
gem 'foo'
end
G
- update_git "foo", :branch => "omg", :path => lib_path("foo") do |s|
+ update_git "foo", path: lib_path("foo") do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
@@ -54,18 +57,19 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems "foo 1.1"
end
- it "floats on master when updating all gems that are pinned to the source even if you have child dependencies" do
- build_git "foo", :path => lib_path("foo")
- build_gem "bar", :to_bundle => true do |s|
+ it "floats on main when updating all gems that are pinned to the source even if you have child dependencies" do
+ build_git "foo", path: lib_path("foo")
+ build_gem "bar", to_bundle: true do |s|
s.add_dependency "foo"
end
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo")}"
gem "bar"
G
- update_git "foo", :path => lib_path("foo") do |s|
+ update_git "foo", path: lib_path("foo") do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
@@ -75,48 +79,55 @@ RSpec.describe "bundle update" do
end
it "notices when you change the repo url in the Gemfile" do
- build_git "foo", :path => lib_path("foo_one")
- build_git "foo", :path => lib_path("foo_two")
+ build_git "foo", path: lib_path("foo_one")
+ build_git "foo", path: lib_path("foo_two")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo_one")}"
G
- FileUtils.rm_rf lib_path("foo_one")
+ FileUtils.rm_r lib_path("foo_one")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo_two")}"
G
- expect(err).to lack_errors
+ expect(err).to be_empty
expect(out).to include("Fetching #{lib_path}/foo_two")
expect(out).to include("Bundle complete!")
end
it "fetches tags from the remote" do
build_git "foo"
- @remote = build_git("bar", :bare => true)
- update_git "foo", :remote => @remote.path
- update_git "foo", :push => "master"
+ @remote = build_git("bar", bare: true)
+ update_git "foo", remote: @remote.path
+ update_git "foo", push: "main"
install_gemfile <<-G
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}"
G
# Create a new tag on the remote that needs fetching
- update_git "foo", :tag => "fubar"
- update_git "foo", :push => "fubar"
+ update_git "foo", tag: "fubar"
+ update_git "foo", push: "fubar"
gemfile <<-G
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}", :tag => "fubar"
G
- bundle "update", :all => bundle_update_requires_all?
- expect(exitstatus).to eq(0) if exitstatus
+ bundle "update", all: true
+ expect(err).to be_empty
end
describe "with submodules" do
before :each do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_repo4 do
build_gem "submodule" do |s|
s.write "lib/submodule.rb", "puts 'GEM'"
@@ -131,15 +142,13 @@ RSpec.describe "bundle update" do
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
end
it "it unlocks the source when submodules are added to a git source" do
install_gemfile <<-G
- source "file:#{gem_repo4}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
@@ -149,7 +158,7 @@ RSpec.describe "bundle update" do
expect(out).to eq("GEM")
install_gemfile <<-G
- source "file:#{gem_repo4}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -159,25 +168,25 @@ RSpec.describe "bundle update" do
expect(out).to eq("GIT")
end
- it "unlocks the source when submodules are removed from git source", :git => ">= 2.9.0" do
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
+ it "unlocks the source when submodules are removed from git source", git: ">= 2.9.0" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
G
- run! "require 'submodule'"
+ run "require 'submodule'"
expect(out).to eq("GIT")
- install_gemfile! <<-G
- source "file:#{gem_repo4}"
+ install_gemfile <<-G
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
G
- run! "require 'submodule'"
+ run "require 'submodule'"
expect(out).to eq("GEM")
end
end
@@ -186,91 +195,80 @@ RSpec.describe "bundle update" do
build_git "foo", "1.0"
install_gemfile <<-G
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- lib_path("foo-1.0").join(".git").rmtree
+ FileUtils.rm_rf lib_path("foo-1.0").join(".git")
- bundle :update, :all => bundle_update_requires_all?
- expect(last_command.bundler_err).to include(lib_path("foo-1.0").to_s).
+ bundle :update, all: true, raise_on_error: false
+ expect(err).to include(lib_path("foo-1.0").to_s).
and match(/Git error: command `git fetch.+has failed/)
end
it "should not explode on invalid revision on update of gem by name" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config local.rack #{lib_path("local-rack")})
- bundle "update rack"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle "update myrack"
expect(out).to include("Bundle updated!")
end
it "shows the previous version of the gem" do
- build_git "rails", "3.0", :path => lib_path("rails")
+ build_git "rails", "2.3.2", path: lib_path("rails")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "rails", :git => "#{lib_path("rails")}"
G
- lockfile <<-G
- GIT
- remote: #{lib_path("rails")}
- specs:
- rails (2.3.2)
-
- PLATFORMS
- #{generic_local_platform}
+ update_git "rails", "3.0", path: lib_path("rails"), gemspec: true
- DEPENDENCIES
- rails!
- G
-
- bundle "update", :all => bundle_update_requires_all?
- expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path("rails")} (at master@#{revision_for(lib_path("rails"))[0..6]})")
+ bundle "update", all: true
+ expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path("rails")} (at main@#{revision_for(lib_path("rails"))[0..6]})")
end
end
describe "with --source flag" do
before :each do
build_repo2
- @git = build_git "foo", :path => lib_path("foo") do |s|
+ @git = build_git "foo", path: lib_path("foo") do |s|
s.executables = "foobar"
end
install_gemfile <<-G
- source "file://#{gem_repo2}"
+ source "https://gem.repo2"
git "#{lib_path("foo")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
it "updates the source" do
- update_git "foo", :path => @git.path
+ update_git "foo", path: @git.path
bundle "update --source foo"
- in_app_root do
- run <<-RUBY
- require 'foo'
- puts "WIN" if defined?(FOO_PREV_REF)
- RUBY
+ run <<-RUBY
+ require 'foo'
+ puts "WIN" if defined?(FOO_PREV_REF)
+ RUBY
- expect(out).to eq("WIN")
- end
+ expect(out).to eq("WIN")
end
it "unlocks gems that were originally pulled in by the source" do
- update_git "foo", "2.0", :path => @git.path
+ update_git "foo", "2.0", path: @git.path
bundle "update --source foo"
expect(the_bundle).to include_gems "foo 2.0"
@@ -278,40 +276,45 @@ RSpec.describe "bundle update" do
it "leaves all other gems frozen" do
update_repo2
- update_git "foo", :path => @git.path
+ update_git "foo", path: @git.path
bundle "update --source foo"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
context "when the gem and the repository have different names" do
before :each do
build_repo2
- @git = build_git "foo", :path => lib_path("bar")
+ @git = build_git "foo", path: lib_path("bar")
install_gemfile <<-G
- source "file://localhost#{gem_repo2}"
+ source "https://gem.repo2"
git "#{lib_path("bar")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
- it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "> 3" do
+ it "the --source flag updates version of gems that were originally pulled in by the source" do
spec_lines = lib_path("bar/foo.gemspec").read.split("\n")
spec_lines[5] = "s.version = '2.0'"
- update_git "foo", "2.0", :path => @git.path do |s|
+ update_git "foo", "2.0", path: @git.path do |s|
s.write "foo.gemspec", spec_lines.join("\n")
end
- ref = @git.ref_for "master"
+ ref = @git.ref_for "main"
bundle "update --source bar"
- lockfile_should_be <<-G
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "2.0"
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~G
GIT
remote: #{@git.path}
revision: #{ref}
@@ -319,55 +322,19 @@ RSpec.describe "bundle update" do
foo (2.0)
GEM
- remote: file://localhost#{gem_repo2}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- foo!
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "3" do
- spec_lines = lib_path("bar/foo.gemspec").read.split("\n")
- spec_lines[5] = "s.version = '2.0'"
-
- update_git "foo", "2.0", :path => @git.path do |s|
- s.write "foo.gemspec", spec_lines.join("\n")
- end
-
- ref = @git.ref_for "master"
-
- bundle "update --source bar"
-
- lockfile_should_be <<-G
- GEM
- remote: file://localhost#{gem_repo2}/
- specs:
- rack (1.0.0)
-
- GIT
- remote: #{@git.path}
- revision: #{ref}
- specs:
- foo (2.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
diff --git a/spec/bundler/update/path_spec.rb b/spec/bundler/update/path_spec.rb
index 38c125e04b..8c76c94e1a 100644
--- a/spec/bundler/update/path_spec.rb
+++ b/spec/bundler/update/path_spec.rb
@@ -3,13 +3,14 @@
RSpec.describe "path sources" do
describe "bundle update --source" do
it "shows the previous version of the gem when updated from path source" do
- build_lib "activesupport", "2.3.5", :path => lib_path("rails/activesupport")
+ build_lib "activesupport", "2.3.5", path: lib_path("rails/activesupport")
install_gemfile <<-G
+ source "https://gem.repo1"
gem "activesupport", :path => "#{lib_path("rails/activesupport")}"
G
- build_lib "activesupport", "3.0", :path => lib_path("rails/activesupport")
+ build_lib "activesupport", "3.0", path: lib_path("rails/activesupport")
bundle "update --source activesupport"
expect(out).to include("Using activesupport 3.0 (was 2.3.5) from source at `#{lib_path("rails/activesupport")}`")
diff --git a/spec/bundler/update/redownload_spec.rb b/spec/bundler/update/redownload_spec.rb
deleted file mode 100644
index 1bbc3a66fc..0000000000
--- a/spec/bundler/update/redownload_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle update", :bundler => "< 3", :ruby => ">= 2.0" do
- before :each do
- install_gemfile <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
- end
-
- before { bundle "config major_deprecations yes" }
-
- describe "with --force" do
- it "shows a deprecation when single flag passed" do
- bundle! "update rack --force"
- expect(out).to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
-
- it "shows a deprecation when multiple flags passed" do
- bundle! "update rack --no-color --force"
- expect(out).to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
- end
-
- describe "with --redownload" do
- it "does not show a deprecation when single flag passed" do
- bundle! "update rack --redownload"
- expect(out).not_to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
-
- it "does not show a deprecation when single multiple flags passed" do
- bundle! "update rack --no-color --redownload"
- expect(out).not_to include "[DEPRECATED FOR 3.0] The `--force` option has been renamed to `--redownload`"
- end
- end
-end
diff --git a/spec/default.mspec b/spec/default.mspec
index 8791058f95..d756dc31ff 100644
--- a/spec/default.mspec
+++ b/spec/default.mspec
@@ -3,60 +3,58 @@ $VERBOSE = false
if (opt = ENV["RUBYOPT"]) and (opt = opt.dup).sub!(/(?:\A|\s)-w(?=\z|\s)/, '')
ENV["RUBYOPT"] = opt
end
+
+# Enable constant leak checks by ruby/mspec
+ENV["CHECK_CONSTANT_LEAKS"] ||= "true"
+
require "./rbconfig" unless defined?(RbConfig)
+require_relative "../tool/test-coverage" if ENV.key?("COVERAGE")
+require_relative "../tool/lib/test/jobserver"
load File.dirname(__FILE__) + '/ruby/default.mspec'
-OBJDIR = File.expand_path("spec/ruby/optional/capi/ext")
+OBJDIR = File.expand_path("spec/ruby/optional/capi/ext") unless defined?(OBJDIR)
class MSpecScript
+ @testing_ruby = true
+
builddir = Dir.pwd
srcdir = ENV['SRCDIR']
- if !srcdir and File.exist?("#{builddir}/Makefile") then
- File.open("#{builddir}/Makefile", "r:US-ASCII") {|f|
- f.read[/^\s*srcdir\s*=\s*(.+)/i] and srcdir = $1
- }
- end
- srcdir = File.expand_path(srcdir)
+ srcdir ||= File.read("Makefile", encoding: "US-ASCII")[/^\s*srcdir\s*=\s*(.+)/i, 1] rescue nil
config = RbConfig::CONFIG
# The default implementation to run the specs.
set :target, File.join(builddir, "miniruby#{config['exeext']}")
set :prefix, File.expand_path('ruby', File.dirname(__FILE__))
- set :flags, %W[
- -I#{srcdir}/lib
- #{srcdir}/tool/runruby.rb --archdir=#{Dir.pwd} --extout=#{config['EXTOUT']}
- --
- ]
+ if srcdir
+ srcdir = File.expand_path(srcdir)
+ set :flags, %W[
+ -I#{srcdir}/lib
+ #{srcdir}/tool/runruby.rb --archdir=#{builddir} --extout=#{config['EXTOUT']}
+ --
+ ]
+ end
+
+ # Disable to run for bundled gems in test-spec
+ set :bundled_gems, (File.readlines("#{srcdir}/gems/bundled_gems").map do |line|
+ next if /^\s*(?:#|$)/ =~ line
+ gem = line.split.first
+ gem = "openstruct" if gem == "ostruct"
+ "#{srcdir}/spec/ruby/library/#{gem}"
+ end.compact)
+ set :stdlibs, Dir.glob("#{srcdir}/spec/ruby/library/*")
+ set :library, get(:stdlibs).to_a - get(:bundled_gems).to_a
+
+ set :files, get(:command_line) + get(:language) + get(:core) + get(:library) + get(:security) + get(:optional)
+
+ if ENV.key?("COVERAGE")
+ set :excludes, ["Coverage"]
+ end
end
module MSpecScript::JobServer
def cores(max = 1)
- if max > 1 and /(?:\A|\s)--jobserver-(?:auth|fds)=(\d+),(\d+)/ =~ ENV["MAKEFLAGS"]
- cores = 1
- begin
- r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
- w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
- jobtokens = r.read_nonblock(max - 1)
- cores = jobtokens.size
- if cores > 0
- cores += 1
- jobserver = w
- w = nil
- at_exit {
- jobserver.print(jobtokens)
- jobserver.close
- }
- MSpecScript::JobServer.module_eval do
- remove_method :cores
- define_method(:cores) do
- cores
- end
- end
- return cores
- end
- rescue Errno::EBADF
- ensure
- r&.close
- w&.close
- end
+ MSpecScript::JobServer.remove_method :cores
+ if cores = Test::JobServer.max_jobs(max)
+ MSpecScript::JobServer.define_method(:cores) { cores }
+ return cores
end
super
end
@@ -65,3 +63,76 @@ end
class MSpecScript
prepend JobServer
end
+
+require 'mspec/runner/formatters/dotted'
+
+class DottedFormatter
+ prepend Module.new {
+ BASE = __dir__ + "/ruby/" unless defined?(BASE)
+ COUNT_WIDTH = 6 unless defined?(COUNT_WIDTH)
+
+ def initialize(out = nil)
+ super
+ if out
+ @columns = nil
+ else
+ columns = ENV["COLUMNS"]&.to_i
+ columns = 80 unless columns&.nonzero?
+ w = COUNT_WIDTH + 1
+ round = 20
+ @columns = (columns - w) / round * round + w
+ end
+ @dotted = 0
+ @loaded = false
+ @count = 0
+ end
+
+ def register
+ super
+ MSpec.register :load, self
+ MSpec.register :unload, self
+ end
+
+ def after(*)
+ if @columns
+ if @dotted == 0
+ s = sprintf("%*d ", COUNT_WIDTH, @count)
+ print(s)
+ @dotted += s.size
+ end
+ @count +=1
+ end
+ super
+ if @columns and (@dotted += 1) >= @columns
+ print "\n"
+ @dotted = 0
+ end
+ end
+
+ def load(*)
+ file = MSpec.file || MSpec.files_array.first
+ @loaded = true
+ s = "#{file.delete_prefix(BASE)}:"
+ print s
+ if @columns
+ if (@dotted += s.size) >= @columns
+ print "\n"
+ @dotted = 0
+ else
+ print " "
+ @dotted += 1
+ end
+ end
+ @count = 0
+ end
+
+ def unload
+ super
+ if @loaded
+ print "\n" if @dotted > 0
+ @dotted = 0
+ @loaded = nil
+ end
+ end
+ }
+end
diff --git a/spec/lib/formatter_overrides.rb b/spec/lib/formatter_overrides.rb
new file mode 100644
index 0000000000..4a61d425d1
--- /dev/null
+++ b/spec/lib/formatter_overrides.rb
@@ -0,0 +1,6 @@
+module FormatterOverrides
+ def example_pending(_); end
+ def dump_pending(_); end
+end
+
+RSpec::Core::Formatters::ProgressFormatter.prepend FormatterOverrides
diff --git a/spec/lib/spec_coverage.rb b/spec/lib/spec_coverage.rb
new file mode 100644
index 0000000000..34aed32f72
--- /dev/null
+++ b/spec/lib/spec_coverage.rb
@@ -0,0 +1 @@
+require_relative "../../tool/test-coverage" if ENV.key?('COVERAGE')
diff --git a/spec/mmtk.mspec b/spec/mmtk.mspec
new file mode 100644
index 0000000000..ac0998708c
--- /dev/null
+++ b/spec/mmtk.mspec
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# Testing behaviour specific to default GC
+MSpec.register(:exclude, "GC.stat increases major_gc_count after GC is run")
+MSpec.register(:exclude, "GC.stat provides some number for heap_free_slots")
+# GC::Profiler is not implemented
+MSpec.register(:exclude, "GC::Profiler.disable disables the profiler")
+MSpec.register(:exclude, "GC::Profiler.enable enables the profiler")
+MSpec.register(:exclude, "GC::Profiler.enabled? reports as disabled when disabled")
+MSpec.register(:exclude, "GC::Profiler.enabled? reports as enabled when enabled")
+MSpec.register(:exclude, "GC::Profiler.result returns a string")
+MSpec.register(:exclude, "GC::Profiler.total_time returns an float")
diff --git a/spec/mspec/.rspec b/spec/mspec/.rspec
new file mode 100644
index 0000000000..4e1e0d2f72
--- /dev/null
+++ b/spec/mspec/.rspec
@@ -0,0 +1 @@
+--color
diff --git a/spec/mspec/Gemfile b/spec/mspec/Gemfile
index 3dc3c4145b..617a995cad 100644
--- a/spec/mspec/Gemfile
+++ b/spec/mspec/Gemfile
@@ -1,4 +1,4 @@
source 'https://rubygems.org'
-gem "rake", "~> 10.0"
-gem "rspec", "~> 2.14.1"
+gem "rake", "~> 12.3"
+gem "rspec", "~> 3.0"
diff --git a/spec/mspec/Gemfile.lock b/spec/mspec/Gemfile.lock
index e977989f8c..cd39906044 100644
--- a/spec/mspec/Gemfile.lock
+++ b/spec/mspec/Gemfile.lock
@@ -1,24 +1,26 @@
GEM
remote: https://rubygems.org/
specs:
- diff-lcs (1.3)
- rake (10.5.0)
- rspec (2.14.1)
- rspec-core (~> 2.14.0)
- rspec-expectations (~> 2.14.0)
- rspec-mocks (~> 2.14.0)
- rspec-core (2.14.8)
- rspec-expectations (2.14.5)
- diff-lcs (>= 1.1.3, < 2.0)
- rspec-mocks (2.14.6)
+ diff-lcs (1.4.4)
+ rake (12.3.3)
+ rspec (3.10.0)
+ rspec-core (~> 3.10.0)
+ rspec-expectations (~> 3.10.0)
+ rspec-mocks (~> 3.10.0)
+ rspec-core (3.10.1)
+ rspec-support (~> 3.10.0)
+ rspec-expectations (3.10.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-mocks (3.10.2)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-support (3.10.2)
PLATFORMS
java
ruby
DEPENDENCIES
- rake (~> 10.0)
- rspec (~> 2.14.1)
-
-BUNDLED WITH
- 1.16.1
+ rake (~> 12.3)
+ rspec (~> 3.0)
diff --git a/spec/mspec/README.md b/spec/mspec/README.md
index 23986c92e4..94ab608031 100644
--- a/spec/mspec/README.md
+++ b/spec/mspec/README.md
@@ -1,14 +1,13 @@
-[![Build Status](https://travis-ci.org/ruby/mspec.svg?branch=master)](https://travis-ci.org/ruby/mspec)
-
## Overview
-MSpec is a specialized framework that is syntax-compatible with RSpec for
-basic things like 'describe', 'it' blocks and 'before', 'after' actions. MSpec
-contains additional features that assist in writing the RubySpecs used by
-multiple Ruby implementations.
+MSpec is a specialized framework that is syntax-compatible with RSpec 2 for
+basic things like `describe`, `it` blocks and `before`, `after` actions.
+MSpec contains additional features that assist in writing specs for
+Ruby implementations in [ruby/spec](https://github.com/ruby/spec).
MSpec attempts to use the simplest Ruby language features so that beginning
-Ruby implementations can run the Ruby specs.
+Ruby implementations can run the Ruby specs. For example, no file from the
+standard library or RubyGems is necessary to run MSpec.
MSpec is not intended as a replacement for RSpec. MSpec attempts to provide a
subset of RSpec's features in some cases and a superset in others. It does not
@@ -23,8 +22,6 @@ specs in a manner compatible with multiple Ruby implementations.
2. MSpec provides a different shared spec implementation specifically
designed to ease writing specs for the numerous aliased methods in Ruby.
- The MSpec shared spec implementation should not conflict with RSpec's own
- shared behavior facility.
3. MSpec provides various helper methods to simplify some specs, for
example, creating temporary file names.
@@ -33,9 +30,13 @@ specs in a manner compatible with multiple Ruby implementations.
configuration facility with a default project file and user-specific
overrides.
+ 5. MSpec support "tagging", that is excluding specs known as failing on
+ a particular Ruby implementation, and automatically adding and removing tags
+ while running the specs.
+
## Requirements
-MSpec requires Ruby 2.3 or more recent.
+MSpec requires Ruby 2.6 or more recent.
## Bundler
@@ -52,10 +53,10 @@ To install the gem dependencies with Bundler, run the following:
ruby -S bundle install
```
-## Running Specs
+## Development
Use RSpec to run the MSpec specs. There are no plans currently to make the
-MSpec specs runnable by MSpec.
+MSpec specs runnable by MSpec: https://github.com/ruby/mspec/issues/19.
After installing the gem dependencies, the specs can be run as follows:
@@ -63,29 +64,21 @@ After installing the gem dependencies, the specs can be run as follows:
ruby -S bundle exec rspec
```
-Or
-
-```bash
-ruby -S rake
-```
-
To run an individual spec file, use the following example:
```bash
ruby -S bundle exec rspec spec/helpers/ruby_exe_spec.rb
```
-
## Documentation
-See http://ruby.github.io/rubyspec.github.io/
-
+See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) in ruby/spec
+for a list of matchers and how to use `mspec`.
## Source Code
See https://github.com/ruby/mspec
-
## License
See the LICENSE in the source code.
diff --git a/spec/mspec/bin/mspec b/spec/mspec/bin/mspec
index f833257bb0..5bd753c06d 100755
--- a/spec/mspec/bin/mspec
+++ b/spec/mspec/bin/mspec
@@ -4,4 +4,4 @@ $:.unshift File.expand_path('../../lib', __FILE__)
require 'mspec/commands/mspec'
-MSpecMain.main
+MSpecMain.main(false)
diff --git a/spec/mspec/lib/mspec.rb b/spec/mspec/lib/mspec.rb
index 42d590c99a..d24abd96f1 100644
--- a/spec/mspec/lib/mspec.rb
+++ b/spec/mspec/lib/mspec.rb
@@ -1,3 +1,4 @@
+require 'mspec/utils/format'
require 'mspec/matchers'
require 'mspec/expectations'
require 'mspec/mocks'
@@ -5,16 +6,3 @@ require 'mspec/runner'
require 'mspec/guards'
require 'mspec/helpers'
require 'mspec/version'
-
-# If the implementation on which the specs are run cannot
-# load pp from the standard library, add a pp.rb file that
-# defines the #pretty_inspect method on Object or Kernel.
-begin
- require 'pp'
-rescue LoadError
- module Kernel
- def pretty_inspect
- inspect
- end
- end
-end
diff --git a/spec/mspec/lib/mspec/commands/mkspec.rb b/spec/mspec/lib/mspec/commands/mkspec.rb
index 49a2e6b616..f75e683b19 100755..100644
--- a/spec/mspec/lib/mspec/commands/mkspec.rb
+++ b/spec/mspec/lib/mspec/commands/mkspec.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'rbconfig'
require 'mspec/version'
require 'mspec/utils/options'
@@ -19,7 +17,7 @@ class MkSpec
@map = NameMap.new true
end
- def options(argv=ARGV)
+ def options(argv = ARGV)
options = MSpecOptions.new "mkspec [options]", 32
options.on("-c", "--constant", "CONSTANT",
@@ -95,7 +93,9 @@ class MkSpec
def write_spec(file, meth, exists)
if exists
- out = `#{ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}`
+ command = "#{RbConfig.ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}"
+ puts "$ #{command}" if $DEBUG
+ out = `#{command}`
return if out.include?(meth)
end
@@ -133,18 +133,6 @@ EOS
end
end
- ##
- # Determine and return the path of the ruby executable.
-
- def ruby
- ruby = File.join(RbConfig::CONFIG['bindir'],
- RbConfig::CONFIG['ruby_install_name'])
-
- ruby.gsub! File::SEPARATOR, File::ALT_SEPARATOR if File::ALT_SEPARATOR
-
- return ruby
- end
-
def self.main
ENV['MSPEC_RUNNER'] = '1'
diff --git a/spec/mspec/lib/mspec/commands/mspec-ci.rb b/spec/mspec/lib/mspec/commands/mspec-ci.rb
index cb0193f42d..8951572f69 100644
--- a/spec/mspec/lib/mspec/commands/mspec-ci.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-ci.rb
@@ -1,14 +1,10 @@
-#!/usr/bin/env ruby
-
-$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
class MSpecCI < MSpecScript
- def options(argv=ARGV)
+ def options(argv = ARGV)
options = MSpecOptions.new "mspec ci [options] (FILE|DIRECTORY|GLOB)+", 30, config
options.doc " Ask yourself:"
@@ -22,8 +18,10 @@ class MSpecCI < MSpecScript
options.chdir
options.prefix
options.configure { |f| load f }
+ options.repeat
options.pretend
options.interrupt
+ options.timeout
options.doc "\n How to modify the guard behavior"
options.unguarded
diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb
index 249f9f5771..0fb338fa23 100644
--- a/spec/mspec/lib/mspec/commands/mspec-run.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-run.rb
@@ -1,7 +1,3 @@
-#!/usr/bin/env ruby
-
-$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
@@ -14,7 +10,7 @@ class MSpecRun < MSpecScript
config[:files] = []
end
- def options(argv=ARGV)
+ def options(argv = ARGV)
options = MSpecOptions.new "mspec run [options] (FILE|DIRECTORY|GLOB)+", 30, config
options.doc " Ask yourself:"
@@ -32,10 +28,12 @@ class MSpecRun < MSpecScript
options.chdir
options.prefix
options.configure { |f| load f }
+ options.env
options.randomize
options.repeat
options.pretend
options.interrupt
+ options.timeout
options.doc "\n How to modify the guard behavior"
options.unguarded
@@ -51,6 +49,9 @@ class MSpecRun < MSpecScript
options.doc "\n When to perform it"
options.action_filters
+ options.doc "\n Launchable"
+ options.launchable
+
options.doc "\n Help!"
options.debug
options.version MSpec::VERSION
diff --git a/spec/mspec/lib/mspec/commands/mspec-tag.rb b/spec/mspec/lib/mspec/commands/mspec-tag.rb
index 8bc3382e91..9ce9f048c6 100644
--- a/spec/mspec/lib/mspec/commands/mspec-tag.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-tag.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
@@ -15,7 +13,7 @@ class MSpecTag < MSpecScript
config[:ltags] = []
end
- def options(argv=ARGV)
+ def options(argv = ARGV)
options = MSpecOptions.new "mspec tag [options] (FILE|DIRECTORY|GLOB)+", 30, config
options.doc " Ask yourself:"
@@ -33,6 +31,7 @@ class MSpecTag < MSpecScript
options.pretend
options.unguarded
options.interrupt
+ options.timeout
options.doc "\n How to display their output"
options.formatters
@@ -113,6 +112,7 @@ class MSpecTag < MSpecScript
MSpec.register_mode :pretend
MSpec.register_mode :unguarded
config[:formatter] = false
+ config[:xtags] = []
else
raise ArgumentError, "No recognized action given"
end
diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb
index 0ccea82a5c..a9d94ca354 100755..100644
--- a/spec/mspec/lib/mspec/commands/mspec.rb
+++ b/spec/mspec/lib/mspec/commands/mspec.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
@@ -21,10 +19,11 @@ class MSpecMain < MSpecScript
config[:launch] = []
end
- def options(argv=ARGV)
+ def options(argv = ARGV)
config[:command] = argv.shift if ["ci", "run", "tag"].include?(argv[0])
options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config
+ @options = options
options.doc " The mspec command sets up and invokes the sub-commands"
options.doc " (see below) to enable, for instance, running the specs"
@@ -37,11 +36,6 @@ class MSpecMain < MSpecScript
options.targets
- options.on("--warnings", "Don't suppress warnings") do
- config[:flags] << '-w'
- ENV['OUTPUT_WARNINGS'] = '1'
- end
-
options.on("-j", "--multi", "Run multiple (possibly parallel) subprocesses") do
config[:multi] = true
end
@@ -90,8 +84,7 @@ class MSpecMain < MSpecScript
def multi_exec(argv)
require 'mspec/runner/formatters/multi'
- formatter = MultiFormatter.new
- warn "formatter options is ignored due to multi option" if config[:formatter]
+ formatter = config_formatter.extend(MultiFormatter)
require 'mspec/runner/parallel'
processes = cores(@files.size)
@@ -111,8 +104,9 @@ class MSpecMain < MSpecScript
if config[:multi]
exit multi_exec(argv)
else
- $stderr.puts "$ #{argv.join(' ')}"
- $stderr.flush
+ log = config[:options].include?('--error-output') ? $stdout : $stderr
+ log.puts "$ #{argv.join(' ')}"
+ log.flush
exec(*argv, close_others: false)
end
end
diff --git a/spec/mspec/lib/mspec/expectations/expectations.rb b/spec/mspec/lib/mspec/expectations/expectations.rb
index cfdc2b63a3..09852ab557 100644
--- a/spec/mspec/lib/mspec/expectations/expectations.rb
+++ b/spec/mspec/lib/mspec/expectations/expectations.rb
@@ -7,15 +7,33 @@ class SpecExpectationNotFoundError < StandardError
end
end
+class SkippedSpecError < StandardError
+end
+
class SpecExpectation
def self.fail_with(expected, actual)
expected_to_s = expected.to_s
actual_to_s = actual.to_s
if expected_to_s.size + actual_to_s.size > 80
- message = "#{expected_to_s.chomp}\n#{actual_to_s}"
+ message = "#{expected_to_s}\n#{actual_to_s}"
else
message = "#{expected_to_s} #{actual_to_s}"
end
- Kernel.raise SpecExpectationNotMetError, message
+ raise SpecExpectationNotMetError, message
+ end
+
+ def self.fail_predicate(receiver, predicate, args, block, result, expectation)
+ receiver_to_s = MSpec.format(receiver)
+ before_method = predicate.to_s =~ /^[a-z]/ ? "." : " "
+ predicate_to_s = "#{before_method}#{predicate}"
+ predicate_to_s += " " unless args.empty?
+ args_to_s = args.map { |arg| MSpec.format(arg) }.join(', ')
+ args_to_s += " { ... }" if block
+ result_to_s = MSpec.format(result)
+ raise SpecExpectationNotMetError, "Expected #{receiver_to_s}#{predicate_to_s}#{args_to_s}\n#{expectation} but was #{result_to_s}"
+ end
+
+ def self.fail_single_arg_predicate(receiver, predicate, arg, result, expectation)
+ fail_predicate(receiver, predicate, [arg], nil, result, expectation)
end
end
diff --git a/spec/mspec/lib/mspec/expectations/should.rb b/spec/mspec/lib/mspec/expectations/should.rb
index f6d83053f5..c1790e0ac8 100644
--- a/spec/mspec/lib/mspec/expectations/should.rb
+++ b/spec/mspec/lib/mspec/expectations/should.rb
@@ -1,29 +1,41 @@
class Object
NO_MATCHER_GIVEN = Object.new
- def should(matcher = NO_MATCHER_GIVEN)
+ def should(matcher = NO_MATCHER_GIVEN, &block)
MSpec.expectation
- MSpec.actions :expectation, MSpec.current.state
- unless matcher.equal? NO_MATCHER_GIVEN
+ state = MSpec.current.state
+ raise "should outside example" unless state
+ MSpec.actions :expectation, state
+
+ if NO_MATCHER_GIVEN.equal?(matcher)
+ SpecPositiveOperatorMatcher.new(self)
+ else
+ # The block was given to #should syntactically, but it was intended for a matcher like #raise_error
+ matcher.block = block if block
+
unless matcher.matches? self
expected, actual = matcher.failure_message
SpecExpectation.fail_with(expected, actual)
end
- else
- SpecPositiveOperatorMatcher.new(self)
end
end
- def should_not(matcher = NO_MATCHER_GIVEN)
+ def should_not(matcher = NO_MATCHER_GIVEN, &block)
MSpec.expectation
- MSpec.actions :expectation, MSpec.current.state
- unless matcher.equal? NO_MATCHER_GIVEN
+ state = MSpec.current.state
+ raise "should_not outside example" unless state
+ MSpec.actions :expectation, state
+
+ if NO_MATCHER_GIVEN.equal?(matcher)
+ SpecNegativeOperatorMatcher.new(self)
+ else
+ # The block was given to #should_not syntactically, but it was intended for the matcher
+ matcher.block = block if block
+
if matcher.matches? self
expected, actual = matcher.negative_failure_message
SpecExpectation.fail_with(expected, actual)
end
- else
- SpecNegativeOperatorMatcher.new(self)
end
end
end
diff --git a/spec/mspec/lib/mspec/guards/bug.rb b/spec/mspec/lib/mspec/guards/bug.rb
index b1bfc6413e..a6af0ef964 100644
--- a/spec/mspec/lib/mspec/guards/bug.rb
+++ b/spec/mspec/lib/mspec/guards/bug.rb
@@ -1,28 +1,29 @@
require 'mspec/guards/version'
class BugGuard < VersionGuard
- def initialize(bug, version)
+ def initialize(bug, requirement)
@bug = bug
- if String === version
+ if String === requirement
MSpec.deprecate "ruby_bug with a single version", 'an exclusive range ("2.1"..."2.3")'
- @version = SpecVersion.new version, true
+ super(FULL_RUBY_VERSION, requirement)
+ @requirement = SpecVersion.new requirement, true
else
- super(version)
+ super(FULL_RUBY_VERSION, requirement)
end
- @parameters = [@bug, @version]
end
def match?
return false if MSpec.mode? :no_ruby_bug
return false unless PlatformGuard.standard?
- if Range === @version
+
+ if Range === @requirement
super
else
- FULL_RUBY_VERSION <= @version
+ FULL_RUBY_VERSION <= @requirement
end
end
end
-def ruby_bug(bug, version, &block)
- BugGuard.new(bug, version).run_unless(:ruby_bug, &block)
+def ruby_bug(bug, requirement, &block)
+ BugGuard.new(bug, requirement).run_unless(:ruby_bug, &block)
end
diff --git a/spec/mspec/lib/mspec/guards/guard.rb b/spec/mspec/lib/mspec/guards/guard.rb
index 322a08145d..3a6372a660 100644
--- a/spec/mspec/lib/mspec/guards/guard.rb
+++ b/spec/mspec/lib/mspec/guards/guard.rb
@@ -111,7 +111,7 @@ class SpecGuard
def add(example)
record example.description
- MSpec.retrieve(:formatter).tally.counter.guards!
+ MSpec.formatter.tally.counter.guards!
end
def unregister
diff --git a/spec/mspec/lib/mspec/guards/platform.rb b/spec/mspec/lib/mspec/guards/platform.rb
index 9543b1dd05..fadd8d75ef 100644
--- a/spec/mspec/lib/mspec/guards/platform.rb
+++ b/spec/mspec/lib/mspec/guards/platform.rb
@@ -6,10 +6,8 @@ class PlatformGuard < SpecGuard
case name
when :rubinius
RUBY_ENGINE.start_with?('rbx')
- when :ruby, :jruby, :truffleruby, :ironruby, :macruby, :maglev, :topaz, :opal
- RUBY_ENGINE.start_with?(name.to_s)
else
- raise "unknown implementation #{name}"
+ RUBY_ENGINE.start_with?(name.to_s)
end
end
end
@@ -18,20 +16,23 @@ class PlatformGuard < SpecGuard
implementation? :ruby
end
- HOST_OS = begin
+ PLATFORM = if RUBY_ENGINE == "jruby"
require 'rbconfig'
- RbConfig::CONFIG['host_os'] || RUBY_PLATFORM
- rescue LoadError
+ "#{RbConfig::CONFIG['host_cpu']}-#{RbConfig::CONFIG['host_os']}"
+ else
RUBY_PLATFORM
- end.downcase
+ end
def self.os?(*oses)
oses.any? do |os|
raise ":java is not a valid OS" if os == :java
- if os == :windows
- HOST_OS =~ /(mswin|mingw)/
+ case os
+ when :windows
+ PLATFORM =~ /(mswin|mingw)/
+ when :wsl
+ wsl?
else
- HOST_OS.include?(os.to_s)
+ PLATFORM.include?(os.to_s)
end
end
end
@@ -40,16 +41,39 @@ class PlatformGuard < SpecGuard
os?(:windows)
end
+ def self.wasi?
+ os?(:wasi)
+ end
+
+ def self.wsl?
+ if defined?(@wsl_p)
+ @wsl_p
+ else
+ @wsl_p = `uname -r`.match?(/microsoft/i)
+ end
+ end
+
+ # In bits
WORD_SIZE = 1.size * 8
+ deprecate_constant :WORD_SIZE
+ # In bits
POINTER_SIZE = begin
require 'rbconfig/sizeof'
RbConfig::SIZEOF["void*"] * 8
rescue LoadError
- WORD_SIZE
+ [0].pack('j').size * 8
+ end
+
+ # In bits
+ C_LONG_SIZE = if defined?(RbConfig::SIZEOF[])
+ RbConfig::SIZEOF["long"] * 8
+ else
+ [0].pack('l!').size * 8
end
def self.wordsize?(size)
+ warn "#wordsize? is deprecated, use #c_long_size?"
size == WORD_SIZE
end
@@ -57,6 +81,10 @@ class PlatformGuard < SpecGuard
size == POINTER_SIZE
end
+ def self.c_long_size?(size)
+ size == C_LONG_SIZE
+ end
+
def initialize(*args)
if args.last.is_a?(Hash)
@options, @platforms = args.last, args[0..-2]
@@ -72,10 +100,13 @@ class PlatformGuard < SpecGuard
case key
when :os
match &&= PlatformGuard.os?(*value)
- when :wordsize
- match &&= PlatformGuard.wordsize? value
when :pointer_size
match &&= PlatformGuard.pointer_size? value
+ when :wordsize
+ warn ":wordsize is deprecated, use :c_long_size"
+ match &&= PlatformGuard.wordsize? value
+ when :c_long_size
+ match &&= PlatformGuard::c_long_size? value
end
end
match
diff --git a/spec/mspec/lib/mspec/guards/superuser.rb b/spec/mspec/lib/mspec/guards/superuser.rb
index e92ea7e862..24daf9b26c 100644
--- a/spec/mspec/lib/mspec/guards/superuser.rb
+++ b/spec/mspec/lib/mspec/guards/superuser.rb
@@ -6,10 +6,20 @@ class SuperUserGuard < SpecGuard
end
end
+class RealSuperUserGuard < SpecGuard
+ def match?
+ Process.uid == 0
+ end
+end
+
def as_superuser(&block)
SuperUserGuard.new.run_if(:as_superuser, &block)
end
+def as_real_superuser(&block)
+ RealSuperUserGuard.new.run_if(:as_real_superuser, &block)
+end
+
def as_user(&block)
SuperUserGuard.new.run_unless(:as_user, &block)
end
diff --git a/spec/mspec/lib/mspec/guards/version.rb b/spec/mspec/lib/mspec/guards/version.rb
index cb08fdac73..f5ea1988ae 100644
--- a/spec/mspec/lib/mspec/guards/version.rb
+++ b/spec/mspec/lib/mspec/guards/version.rb
@@ -5,33 +5,68 @@ require 'mspec/guards/guard'
class VersionGuard < SpecGuard
FULL_RUBY_VERSION = SpecVersion.new SpecGuard.ruby_version(:full)
- def initialize(version)
- case version
+ def initialize(version, requirement)
+ version = SpecVersion.new(version) unless SpecVersion === version
+ @version = version
+
+ case requirement
when String
- @version = SpecVersion.new version
+ @requirement = SpecVersion.new requirement
when Range
- MSpec.deprecate "an empty version range end", 'a specific version' if version.end.empty?
- a = SpecVersion.new version.begin
- b = SpecVersion.new version.end
- unless version.exclude_end?
+ MSpec.deprecate "an empty version range end", 'a specific version' if requirement.end.empty?
+ a = SpecVersion.new requirement.begin
+ b = SpecVersion.new requirement.end
+ unless requirement.exclude_end?
MSpec.deprecate "ruby_version_is with an inclusive range", 'an exclusive range ("2.1"..."2.3")'
end
- @version = version.exclude_end? ? a...b : a..b
+ @requirement = requirement.exclude_end? ? a...b : a..b
else
- raise "version must be a String or Range but was a #{version.class}"
+ raise "version must be a String or Range but was a #{requirement.class}"
end
- @parameters = [version]
+ super(@version, @requirement)
end
def match?
- if Range === @version
- @version.include? FULL_RUBY_VERSION
+ if Range === @requirement
+ @requirement.include? @version
+ else
+ @version >= @requirement
+ end
+ end
+
+ @kernel_version = nil
+ def self.kernel_version
+ if @kernel_version
+ @kernel_version
else
- FULL_RUBY_VERSION >= @version
+ if v = RUBY_PLATFORM[/darwin(\d+)/, 1] # build time version
+ uname = v
+ else
+ begin
+ require 'etc'
+ etc = true
+ rescue LoadError
+ etc = false
+ end
+ if etc and Etc.respond_to?(:uname)
+ uname = Etc.uname.fetch(:release)
+ else
+ uname = `uname -r`.chomp
+ end
+ end
+ @kernel_version = uname
end
end
end
-def ruby_version_is(*args, &block)
- VersionGuard.new(*args).run_if(:ruby_version_is, &block)
+def version_is(base_version, requirement, &block)
+ VersionGuard.new(base_version, requirement).run_if(:version_is, &block)
+end
+
+def ruby_version_is(requirement, &block)
+ VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, requirement).run_if(:ruby_version_is, &block)
+end
+
+def kernel_version_is(requirement, &block)
+ VersionGuard.new(VersionGuard.kernel_version, requirement).run_if(:kernel_version_is, &block)
end
diff --git a/spec/mspec/lib/mspec/helpers.rb b/spec/mspec/lib/mspec/helpers.rb
index b7ac9f4e85..90f9fd3fd4 100644
--- a/spec/mspec/lib/mspec/helpers.rb
+++ b/spec/mspec/lib/mspec/helpers.rb
@@ -3,7 +3,6 @@ require 'mspec/helpers/argv'
require 'mspec/helpers/datetime'
require 'mspec/helpers/fixture'
require 'mspec/helpers/flunk'
-require 'mspec/helpers/frozen_error_class'
require 'mspec/helpers/fs'
require 'mspec/helpers/io'
require 'mspec/helpers/mock_to_path'
diff --git a/spec/mspec/lib/mspec/helpers/datetime.rb b/spec/mspec/lib/mspec/helpers/datetime.rb
index 1520b971ea..84ac86b686 100644
--- a/spec/mspec/lib/mspec/helpers/datetime.rb
+++ b/spec/mspec/lib/mspec/helpers/datetime.rb
@@ -6,7 +6,7 @@
#
# Possible keys are:
# :year, :month, :day, :hour, :minute, :second, :offset and :sg.
-def new_datetime(opts={})
+def new_datetime(opts = {})
require 'date'
value = {
@@ -25,6 +25,7 @@ def new_datetime(opts={})
end
def with_timezone(name, offset = nil, daylight_saving_zone = "")
+ skip "WASI doesn't have TZ concept" if PlatformGuard.wasi?
zone = name.dup
if offset
diff --git a/spec/mspec/lib/mspec/helpers/flunk.rb b/spec/mspec/lib/mspec/helpers/flunk.rb
index 68fb3cadac..84fb3ab39c 100644
--- a/spec/mspec/lib/mspec/helpers/flunk.rb
+++ b/spec/mspec/lib/mspec/helpers/flunk.rb
@@ -1,3 +1,3 @@
-def flunk(msg="This example is a failure")
+def flunk(msg = "This example is a failure")
SpecExpectation.fail_with "Failed:", msg
end
diff --git a/spec/mspec/lib/mspec/helpers/frozen_error_class.rb b/spec/mspec/lib/mspec/helpers/frozen_error_class.rb
deleted file mode 100644
index 07cc2b4ba2..0000000000
--- a/spec/mspec/lib/mspec/helpers/frozen_error_class.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'mspec/guards/version'
-
-# This helper makes it easy to write version independent
-# specs for frozen objects.
-unless respond_to? :frozen_error_class, true
- ruby_version_is "2.5" do
- def frozen_error_class
- FrozenError
- end
- end
-
- ruby_version_is ""..."2.5" do
- def frozen_error_class
- RuntimeError
- end
- end
-end
diff --git a/spec/mspec/lib/mspec/helpers/fs.rb b/spec/mspec/lib/mspec/helpers/fs.rb
index fb2c0f702c..67453eb302 100644
--- a/spec/mspec/lib/mspec/helpers/fs.rb
+++ b/spec/mspec/lib/mspec/helpers/fs.rb
@@ -1,12 +1,6 @@
# Copies a file
def cp(source, dest)
- File.open(dest, "wb") do |d|
- File.open(source, "rb") do |s|
- while data = s.read(1024)
- d.write data
- end
- end
- end
+ IO.copy_stream source, dest
end
# Creates each directory in path that does not exist.
@@ -61,7 +55,7 @@ end
# Creates a file +name+. Creates the directory for +name+
# if it does not exist.
-def touch(name, mode="w")
+def touch(name, mode = "w")
mkdir_p File.dirname(name)
File.open(name, mode) do |f|
diff --git a/spec/mspec/lib/mspec/helpers/io.rb b/spec/mspec/lib/mspec/helpers/io.rb
index 57dc0d53a4..2ad14f47a1 100644
--- a/spec/mspec/lib/mspec/helpers/io.rb
+++ b/spec/mspec/lib/mspec/helpers/io.rb
@@ -7,7 +7,7 @@ class IOStub
end
def write(*str)
- self << str.join
+ self << str.join('')
end
def << str
@@ -16,7 +16,7 @@ class IOStub
end
def print(*str)
- write(str.join + $\.to_s)
+ write(str.join('') + $\.to_s)
end
def method_missing(name, *args, &block)
@@ -64,9 +64,7 @@ end
# Creates a "bare" file descriptor (i.e. one that is not associated
# with any Ruby object). The file descriptor can safely be passed
# to IO.new without creating a Ruby object alias to the fd.
-def new_fd(name, mode="w:utf-8")
- mode = options_or_mode(mode)
-
+def new_fd(name, mode = "w:utf-8")
if mode.kind_of? Hash
if mode.key? :mode
mode = mode[:mode]
@@ -75,37 +73,15 @@ def new_fd(name, mode="w:utf-8")
end
end
- IO.sysopen name, fmode(mode)
+ IO.sysopen name, mode
end
# Creates an IO instance for a temporary file name. The file
# must be deleted.
-def new_io(name, mode="w:utf-8")
- IO.new new_fd(name, options_or_mode(mode)), options_or_mode(mode)
-end
-
-# This helper simplifies passing file access modes regardless of
-# whether the :encoding feature is enabled. Only the access specifier
-# itself will be returned if :encoding is not enabled. Otherwise,
-# the full mode string will be returned (i.e. the helper is a no-op).
-def fmode(mode)
- if FeatureGuard.enabled? :encoding
- mode
- else
- mode.split(':').first
- end
-end
-
-# This helper simplifies passing file access modes or options regardless of
-# whether the :encoding feature is enabled. Only the access specifier itself
-# will be returned if :encoding is not enabled. Otherwise, the full mode
-# string or option will be returned (i.e. the helper is a no-op).
-def options_or_mode(oom)
- return fmode(oom) if oom.kind_of? String
-
- if FeatureGuard.enabled? :encoding
- oom
+def new_io(name, mode = "w:utf-8")
+ if Hash === mode # Avoid kwargs warnings on Ruby 2.7+
+ File.new(name, **mode)
else
- fmode(oom[:mode] || "r:utf-8")
+ File.new(name, mode)
end
end
diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb
index 312aafae35..0b47855cd2 100644
--- a/spec/mspec/lib/mspec/helpers/numeric.rb
+++ b/spec/mspec/lib/mspec/helpers/numeric.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
require 'mspec/guards/platform'
def nan_value
@@ -8,8 +9,18 @@ def infinity_value
1/0.0
end
-def bignum_value(plus=0)
- 0x8000_0000_0000_0000 + plus
+def bignum_value(plus = 0)
+ # Must be >= fixnum_max + 2, so -bignum_value is < fixnum_min
+ # A fixed value has the advantage to be the same numeric value for all Rubies and is much easier to spec
+ (2**64) + plus
+end
+
+def max_long
+ 2**(PlatformGuard::C_LONG_SIZE - 1) - 1
+end
+
+def min_long
+ -(2**(PlatformGuard::C_LONG_SIZE - 1))
end
# This is a bit hairy, but we need to be able to write specs that cover the
@@ -18,7 +29,24 @@ end
# specs based on the relationship between values rather than specific
# values.
if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
- if PlatformGuard.wordsize? 32
+ limits_available = begin
+ require 'rbconfig/sizeof'
+ defined?(RbConfig::LIMITS.[]) && ['FIXNUM_MAX', 'FIXNUM_MIN'].all? do |key|
+ Integer === RbConfig::LIMITS[key]
+ end
+ rescue LoadError
+ false
+ end
+
+ if limits_available
+ def fixnum_max
+ RbConfig::LIMITS['FIXNUM_MAX']
+ end
+
+ def fixnum_min
+ RbConfig::LIMITS['FIXNUM_MIN']
+ end
+ elsif PlatformGuard.c_long_size? 32
def fixnum_max
(2**30) - 1
end
@@ -26,7 +54,7 @@ if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
def fixnum_min
-(2**30)
end
- elsif PlatformGuard.wordsize? 64
+ elsif PlatformGuard.c_long_size? 64
def fixnum_max
(2**62) - 1
end
diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
index f74ed014ce..2e499d6f9a 100644
--- a/spec/mspec/lib/mspec/helpers/ruby_exe.rb
+++ b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
@@ -2,11 +2,12 @@ require 'mspec/guards/platform'
require 'mspec/helpers/tmp'
# The ruby_exe helper provides a wrapper for invoking the
-# same Ruby interpreter with the same falgs as the one running
+# same Ruby interpreter with the same flags as the one running
# the specs and getting the output from running the code.
+#
# If +code+ is a file that exists, it will be run.
-# Otherwise, +code+ should be Ruby code that will be run with
-# the -e command line option. For example:
+# Otherwise, +code+ will be written to a temporary file and be run.
+# For example:
#
# ruby_exe('path/to/some/file.rb')
#
@@ -14,27 +15,24 @@ require 'mspec/helpers/tmp'
#
# `#{RUBY_EXE} 'path/to/some/file.rb'`
#
-# while
-#
-# ruby_exe('puts "hello, world."')
-#
-# will be executed as
-#
-# `#{RUBY_EXE} -e 'puts "hello, world."'`
+# The ruby_exe helper also accepts an options hash with four
+# keys: :options, :args :env and :exception.
#
-# The ruby_exe helper also accepts an options hash with three
-# keys: :options, :args and :env. For example:
+# For example:
#
# ruby_exe('file.rb', :options => "-w",
-# :args => "> file.txt",
+# :args => "arg1 arg2",
# :env => { :FOO => "bar" })
#
# will be executed as
#
-# `#{RUBY_EXE} -w #{'file.rb'} > file.txt`
+# `#{RUBY_EXE} -w file.rb arg1 arg2`
#
# with access to ENV["FOO"] with value "bar".
#
+# When `exception: false` and Ruby command fails then exception will not be
+# raised.
+#
# If +nil+ is passed for the first argument, the command line
# will be built only from the options hash.
#
@@ -49,38 +47,18 @@ require 'mspec/helpers/tmp'
# The RUBY_EXE constant is setup by mspec automatically
# and is used by ruby_exe and ruby_cmd. The mspec runner script
# will set ENV['RUBY_EXE'] to the name of the executable used
-# to invoke the mspec-run script. The value of RUBY_EXE will be
-# constructed as follows:
-#
-# 1. the value of ENV['RUBY_EXE']
-# 2. an explicit value based on RUBY_ENGINE
-# 3. cwd/(RUBY_ENGINE + $(EXEEXT) || $(exeext) || '')
-# 4. $(bindir)/$(RUBY_INSTALL_NAME)
+# to invoke the mspec-run script.
#
# The value will only be used if the file exists and is executable.
-# The flags will then be appended to the resulting value.
-#
-# These 4 ways correspond to the following scenarios:
-#
-# 1. Using the MSpec runner scripts, the name of the
-# executable is explicitly passed by ENV['RUBY_EXE']
-# so there is no ambiguity.
-#
-# Otherwise, if using RSpec (or something else)
-#
-# 2. Running the specs while developing an alternative
-# Ruby implementation. This explicitly names the
-# executable in the development directory based on
-# the value of RUBY_ENGINE.
-# 3. Running the specs within the source directory for
-# some implementation. (E.g. a local build directory.)
-# 4. Running the specs against some installed Ruby
-# implementation.
+# The flags will then be appended to the resulting value, such that
+# the RUBY_EXE constant contains both the executable and the flags.
#
# Additionally, the flags passed to mspec
# (with -T on the command line or in the config with set :flags)
# will be appended to RUBY_EXE so that the interpreter
# is always called with those flags.
+#
+# Failure of a Ruby command leads to raising exception by default.
def ruby_exe_options(option)
case option
@@ -101,12 +79,12 @@ def ruby_exe_options(option)
end
when :name
require 'rbconfig'
- bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
+ bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || '')
File.join(".", bin)
when :install_name
require 'rbconfig'
bin = RbConfig::CONFIG["RUBY_INSTALL_NAME"] || RbConfig::CONFIG["ruby_install_name"]
- bin << (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
+ bin << (RbConfig::CONFIG['EXEEXT'] || '')
File.join(RbConfig::CONFIG['bindir'], bin)
end
end
@@ -129,7 +107,13 @@ def resolve_ruby_exe
raise Exception, "Unable to find a suitable ruby executable."
end
+unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE
+ RUBY_EXE = resolve_ruby_exe
+end
+
def ruby_exe(code = :not_given, opts = {})
+ skip "WASI doesn't provide subprocess" if PlatformGuard.wasi?
+
if opts[:dir]
raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir"
end
@@ -153,10 +137,47 @@ def ruby_exe(code = :not_given, opts = {})
code = tmpfile
end
+ expected_status = opts.fetch(:exit_status, 0)
+
begin
- platform_is_not :opal do
- `#{ruby_cmd(code, opts)}`
+ command = ruby_cmd(code, opts)
+
+ # Try to avoid the extra shell for 2>&1
+ # This is notably useful for TimeoutAction which can then signal the ruby subprocess and not the shell
+ popen_options = []
+ if command.end_with?(' 2>&1')
+ command = command[0...-5]
+ popen_options = [{ err: [:child, :out] }]
end
+
+ output = IO.popen(command, *popen_options) do |io|
+ pid = io.pid
+ MSpec.subprocesses << pid
+ begin
+ io.read
+ ensure
+ MSpec.subprocesses.delete(pid)
+ end
+ end
+
+ status = Process.last_status
+
+ exit_status = if status.exited?
+ status.exitstatus
+ elsif status.signaled?
+ signame = Signal.signame status.termsig
+ raise "No signal name?" unless signame
+ :"SIG#{signame}"
+ else
+ raise SpecExpectationNotMetError, "#{exit_status.inspect} is neither exited? nor signaled?"
+ end
+ if exit_status != expected_status
+ formatted_output = output.lines.map { |line| " #{line}" }.join
+ raise SpecExpectationNotMetError,
+ "Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}"
+ end
+
+ output
ensure
saved_env.each { |key, value| ENV[key] = value }
env.keys.each do |key|
@@ -178,9 +199,7 @@ def ruby_cmd(code, opts = {})
body = "-e #{code.inspect}"
end
- [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ')
-end
-
-unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE
- RUBY_EXE = resolve_ruby_exe
+ command = [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ')
+ STDERR.puts "\nruby_cmd: #{command}" if ENV["DEBUG_MSPEC_RUBY_CMD"] == "true"
+ command
end
diff --git a/spec/mspec/lib/mspec/helpers/scratch.rb b/spec/mspec/lib/mspec/helpers/scratch.rb
index a6b0c02748..0da3315cd8 100644
--- a/spec/mspec/lib/mspec/helpers/scratch.rb
+++ b/spec/mspec/lib/mspec/helpers/scratch.rb
@@ -14,4 +14,8 @@ module ScratchPad
def self.recorded
@record
end
+
+ def self.inspect
+ "<ScratchPad @record=#{@record.inspect}>"
+ end
end
diff --git a/spec/mspec/lib/mspec/helpers/tmp.rb b/spec/mspec/lib/mspec/helpers/tmp.rb
index 4e1273dcfe..e903dd9f50 100644
--- a/spec/mspec/lib/mspec/helpers/tmp.rb
+++ b/spec/mspec/lib/mspec/helpers/tmp.rb
@@ -3,11 +3,16 @@
# should clean up any temporary files created so that the temp
# directory is empty when the process exits.
-SPEC_TEMP_DIR = File.expand_path(ENV["SPEC_TEMP_DIR"] || "rubyspec_temp")
+SPEC_TEMP_DIR_PID = Process.pid
-SPEC_TEMP_UNIQUIFIER = "0"
+if spec_temp_dir = ENV["SPEC_TEMP_DIR"]
+ spec_temp_dir = File.realdirpath(spec_temp_dir)
+else
+ spec_temp_dir = "#{File.realpath(Dir.pwd)}/rubyspec_temp/#{SPEC_TEMP_DIR_PID}"
+end
+SPEC_TEMP_DIR = spec_temp_dir
-SPEC_TEMP_DIR_PID = Process.pid
+SPEC_TEMP_UNIQUIFIER = +"0"
at_exit do
begin
@@ -30,12 +35,26 @@ all specs are cleaning up temporary files:
end
end
-def tmp(name, uniquify=true)
- Dir.mkdir SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR
+def tmp(name, uniquify = true)
+ if Dir.exist? SPEC_TEMP_DIR
+ stat = File.stat(SPEC_TEMP_DIR)
+ if stat.world_writable? and !stat.sticky?
+ raise ArgumentError, "SPEC_TEMP_DIR (#{SPEC_TEMP_DIR}) is world writable but not sticky"
+ end
+ else
+ platform_is_not :windows do
+ umask = File.umask
+ if (umask & 0002) == 0 # o+w
+ raise ArgumentError, "File.umask #=> #{umask.to_s(8)} (world-writable)"
+ end
+ end
+ mkdir_p SPEC_TEMP_DIR
+ end
if uniquify and !name.empty?
slash = name.rindex "/"
index = slash ? slash + 1 : 0
+ name = +name
name.insert index, "#{SPEC_TEMP_UNIQUIFIER.succ!}-"
end
diff --git a/spec/mspec/lib/mspec/helpers/warning.rb b/spec/mspec/lib/mspec/helpers/warning.rb
index 9e093074e5..e3d72b78bd 100644
--- a/spec/mspec/lib/mspec/helpers/warning.rb
+++ b/spec/mspec/lib/mspec/helpers/warning.rb
@@ -1,3 +1,7 @@
+require 'mspec/guards/version'
+
+# You might be looking for #silence_warnings, use #suppress_warning instead.
+# MSpec calls it #suppress_warning for consistency with EnvUtil.suppress_warning in CRuby test/.
def suppress_warning
verbose = $VERBOSE
$VERBOSE = nil
@@ -5,3 +9,13 @@ def suppress_warning
ensure
$VERBOSE = verbose
end
+
+if ruby_version_is("2.7")
+ def suppress_keyword_warning(&block)
+ suppress_warning(&block)
+ end
+else
+ def suppress_keyword_warning
+ yield
+ end
+end
diff --git a/spec/mspec/lib/mspec/matchers.rb b/spec/mspec/lib/mspec/matchers.rb
index f3e8e7bb73..356e4a9f32 100644
--- a/spec/mspec/lib/mspec/matchers.rb
+++ b/spec/mspec/lib/mspec/matchers.rb
@@ -34,3 +34,4 @@ require 'mspec/matchers/output_to_fd'
require 'mspec/matchers/respond_to'
require 'mspec/matchers/signed_zero'
require 'mspec/matchers/block_caller'
+require 'mspec/matchers/skip'
diff --git a/spec/mspec/lib/mspec/matchers/base.rb b/spec/mspec/lib/mspec/matchers/base.rb
index fc2d36c84a..3534520d88 100644
--- a/spec/mspec/lib/mspec/matchers/base.rb
+++ b/spec/mspec/lib/mspec/matchers/base.rb
@@ -10,98 +10,86 @@ class Module
include MSpecMatchers
end
-class SpecPositiveOperatorMatcher
+class SpecPositiveOperatorMatcher < BasicObject
def initialize(actual)
@actual = actual
end
def ==(expected)
- unless @actual == expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to equal #{expected.pretty_inspect}")
+ result = @actual == expected
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be truthy")
end
end
- def <(expected)
- unless @actual < expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to be less than #{expected.pretty_inspect}")
+ def !=(expected)
+ result = @actual != expected
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be truthy")
end
end
- def <=(expected)
- unless @actual <= expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to be less than or equal to #{expected.pretty_inspect}")
+ def equal?(expected)
+ result = @actual.equal?(expected)
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, result, "to be truthy")
end
end
- def >(expected)
- unless @actual > expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to be greater than #{expected.pretty_inspect}")
+ def raise(exception = ::Exception, message = nil, options = nil, &block)
+ matcher = ::RaiseErrorMatcher.new(exception, message, options, &block)
+ unless matcher.matches? @actual
+ expected, actual = matcher.failure_message
+ ::SpecExpectation.fail_with(expected, actual)
end
end
- def >=(expected)
- unless @actual >= expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to be greater than or equal to #{expected.pretty_inspect}")
- end
- end
-
- def =~(expected)
- unless @actual =~ expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "to match #{expected.pretty_inspect}")
+ def method_missing(name, *args, &block)
+ result = @actual.__send__(name, *args, &block)
+ unless result
+ ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be truthy")
end
end
end
-class SpecNegativeOperatorMatcher
+class SpecNegativeOperatorMatcher < BasicObject
def initialize(actual)
@actual = actual
end
def ==(expected)
- if @actual == expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to equal #{expected.pretty_inspect}")
- end
- end
-
- def <(expected)
- if @actual < expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to be less than #{expected.pretty_inspect}")
+ result = @actual == expected
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be falsy")
end
end
- def <=(expected)
- if @actual <= expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to be less than or equal to #{expected.pretty_inspect}")
+ def !=(expected)
+ result = @actual != expected
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be falsy")
end
end
- def >(expected)
- if @actual > expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to be greater than #{expected.pretty_inspect}")
+ def equal?(expected)
+ result = @actual.equal?(expected)
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, result, "to be falsy")
end
end
- def >=(expected)
- if @actual >= expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to be greater than or equal to #{expected.pretty_inspect}")
+ def raise(exception = ::Exception, message = nil, options = nil, &block)
+ matcher = ::RaiseErrorMatcher.new(exception, message, options, &block)
+ if matcher.matches? @actual
+ expected, actual = matcher.negative_failure_message
+ ::SpecExpectation.fail_with(expected, actual)
end
end
- def =~(expected)
- if @actual =~ expected
- SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
- "not to match #{expected.pretty_inspect}")
+ def method_missing(name, *args, &block)
+ result = @actual.__send__(name, *args, &block)
+ if result
+ ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be falsy")
end
end
end
diff --git a/spec/mspec/lib/mspec/matchers/be_close.rb b/spec/mspec/lib/mspec/matchers/be_close.rb
index ea9e7f5496..d6a6626f31 100644
--- a/spec/mspec/lib/mspec/matchers/be_close.rb
+++ b/spec/mspec/lib/mspec/matchers/be_close.rb
@@ -1,4 +1,6 @@
TOLERANCE = 0.00003 unless Object.const_defined?(:TOLERANCE)
+# To account for GC, context switches, other processes, load, etc.
+TIME_TOLERANCE = 20.0 unless Object.const_defined?(:TIME_TOLERANCE)
class BeCloseMatcher
def initialize(expected, tolerance)
diff --git a/spec/mspec/lib/mspec/matchers/block_caller.rb b/spec/mspec/lib/mspec/matchers/block_caller.rb
index 4149586747..30fab4fc68 100644
--- a/spec/mspec/lib/mspec/matchers/block_caller.rb
+++ b/spec/mspec/lib/mspec/matchers/block_caller.rb
@@ -1,26 +1,24 @@
class BlockingMatcher
def matches?(block)
- started = false
- blocking = true
-
- thread = Thread.new do
- started = true
+ t = Thread.new do
block.call
-
- blocking = false
end
- Thread.pass while !started
-
- # Wait until the Thread status is "sleep" (then it's blocking)
- # or nil (the Thread finished execution, it did not block)
- while status = thread.status and status != "sleep"
- Thread.pass
+ loop do
+ case t.status
+ when "sleep" # blocked
+ t.kill
+ t.join
+ return true
+ when false # terminated normally, so never blocked
+ t.join
+ return false
+ when nil # terminated exceptionally
+ t.value
+ else
+ Thread.pass
+ end
end
- thread.kill
- thread.join
-
- blocking
end
def failure_message
@@ -33,7 +31,7 @@ class BlockingMatcher
end
module MSpecMatchers
- private def block_caller(timeout = 0.1)
+ private def block_caller
BlockingMatcher.new
end
end
diff --git a/spec/mspec/lib/mspec/matchers/complain.rb b/spec/mspec/lib/mspec/matchers/complain.rb
index 4bcb255040..19310c0bbb 100644
--- a/spec/mspec/lib/mspec/matchers/complain.rb
+++ b/spec/mspec/lib/mspec/matchers/complain.rb
@@ -1,22 +1,31 @@
require 'mspec/helpers/io'
class ComplainMatcher
- def initialize(complaint)
- @complaint = complaint
+ def initialize(complaint = nil, options = nil)
+ # the proper solution is to use double splat operator e.g.
+ # def initialize(complaint = nil, **options)
+ # but we are trying to minimize language features required to run MSpec
+ if complaint.is_a?(Hash)
+ @complaint = nil
+ @options = complaint
+ else
+ @complaint = complaint
+ @options = options || {}
+ end
end
def matches?(proc)
@saved_err = $stderr
@verbose = $VERBOSE
+ err = IOStub.new
+
+ $stderr = err
+ $VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false
begin
- err = $stderr = IOStub.new
- $VERBOSE = false
- Thread.current[:in_mspec_complain_matcher] = true
proc.call
ensure
$VERBOSE = @verbose
$stderr = @saved_err
- Thread.current[:in_mspec_complain_matcher] = false
end
@warning = err.to_s
@@ -54,7 +63,7 @@ class ComplainMatcher
end
module MSpecMatchers
- private def complain(complaint=nil)
- ComplainMatcher.new(complaint)
+ private def complain(complaint = nil, options = nil)
+ ComplainMatcher.new(complaint, options)
end
end
diff --git a/spec/mspec/lib/mspec/matchers/eql.rb b/spec/mspec/lib/mspec/matchers/eql.rb
index a855789550..bcab88ebee 100644
--- a/spec/mspec/lib/mspec/matchers/eql.rb
+++ b/spec/mspec/lib/mspec/matchers/eql.rb
@@ -9,13 +9,13 @@ class EqlMatcher
end
def failure_message
- ["Expected #{@actual.pretty_inspect}",
- "to have same value and type as #{@expected.pretty_inspect}"]
+ ["Expected #{MSpec.format(@actual)}",
+ "to have same value and type as #{MSpec.format(@expected)}"]
end
def negative_failure_message
- ["Expected #{@actual.pretty_inspect}",
- "not to have same value or type as #{@expected.pretty_inspect}"]
+ ["Expected #{MSpec.format(@actual)}",
+ "not to have same value or type as #{MSpec.format(@expected)}"]
end
end
diff --git a/spec/mspec/lib/mspec/matchers/equal.rb b/spec/mspec/lib/mspec/matchers/equal.rb
index 5dc77d27ea..5ba4856d82 100644
--- a/spec/mspec/lib/mspec/matchers/equal.rb
+++ b/spec/mspec/lib/mspec/matchers/equal.rb
@@ -9,13 +9,13 @@ class EqualMatcher
end
def failure_message
- ["Expected #{@actual.pretty_inspect}",
- "to be identical to #{@expected.pretty_inspect}"]
+ ["Expected #{MSpec.format(@actual)}",
+ "to be identical to #{MSpec.format(@expected)}"]
end
def negative_failure_message
- ["Expected #{@actual.pretty_inspect}",
- "not to be identical to #{@expected.pretty_inspect}"]
+ ["Expected #{MSpec.format(@actual)}",
+ "not to be identical to #{MSpec.format(@expected)}"]
end
end
diff --git a/spec/mspec/lib/mspec/matchers/equal_element.rb b/spec/mspec/lib/mspec/matchers/equal_element.rb
index 1e9dfbcca1..8da2567fcf 100644
--- a/spec/mspec/lib/mspec/matchers/equal_element.rb
+++ b/spec/mspec/lib/mspec/matchers/equal_element.rb
@@ -37,12 +37,12 @@ class EqualElementMatcher
end
def failure_message
- ["Expected #{@actual.pretty_inspect}",
+ ["Expected #{MSpec.format(@actual)}",
"to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
end
def negative_failure_message
- ["Expected #{@actual.pretty_inspect}",
+ ["Expected #{MSpec.format(@actual)}",
"not to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
end
diff --git a/spec/mspec/lib/mspec/matchers/have_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_instance_method.rb
index 636aaf3e47..9a5a31aa0f 100644
--- a/spec/mspec/lib/mspec/matchers/have_instance_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_instance_method.rb
@@ -18,7 +18,7 @@ class HaveInstanceMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_instance_method(method, include_super=true)
+ private def have_instance_method(method, include_super = true)
HaveInstanceMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_method.rb b/spec/mspec/lib/mspec/matchers/have_method.rb
index 35dae03af0..e962e69e0a 100644
--- a/spec/mspec/lib/mspec/matchers/have_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_method.rb
@@ -18,7 +18,7 @@ class HaveMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_method(method, include_super=true)
+ private def have_method(method, include_super = true)
HaveMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb
index 4eb7133055..d32db76c6a 100644
--- a/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb
@@ -18,7 +18,7 @@ class HavePrivateInstanceMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_private_instance_method(method, include_super=true)
+ private def have_private_instance_method(method, include_super = true)
HavePrivateInstanceMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_private_method.rb b/spec/mspec/lib/mspec/matchers/have_private_method.rb
index 3433d982cc..c74165cfc7 100644
--- a/spec/mspec/lib/mspec/matchers/have_private_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_private_method.rb
@@ -18,7 +18,7 @@ class HavePrivateMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_private_method(method, include_super=true)
+ private def have_private_method(method, include_super = true)
HavePrivateMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb
index 641d4d0dc2..1deb2f995d 100644
--- a/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb
@@ -18,7 +18,7 @@ class HaveProtectedInstanceMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_protected_instance_method(method, include_super=true)
+ private def have_protected_instance_method(method, include_super = true)
HaveProtectedInstanceMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb
index 501c0a418e..0e620532c0 100644
--- a/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb
@@ -18,7 +18,7 @@ class HavePublicInstanceMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_public_instance_method(method, include_super=true)
+ private def have_public_instance_method(method, include_super = true)
HavePublicInstanceMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/have_singleton_method.rb b/spec/mspec/lib/mspec/matchers/have_singleton_method.rb
index 95d78709ff..b60dd2536b 100644
--- a/spec/mspec/lib/mspec/matchers/have_singleton_method.rb
+++ b/spec/mspec/lib/mspec/matchers/have_singleton_method.rb
@@ -18,7 +18,7 @@ class HaveSingletonMethodMatcher < MethodMatcher
end
module MSpecMatchers
- private def have_singleton_method(method, include_super=true)
+ private def have_singleton_method(method, include_super = true)
HaveSingletonMethodMatcher.new method, include_super
end
end
diff --git a/spec/mspec/lib/mspec/matchers/include.rb b/spec/mspec/lib/mspec/matchers/include.rb
index 0b7eaf3ce2..3f07f35548 100644
--- a/spec/mspec/lib/mspec/matchers/include.rb
+++ b/spec/mspec/lib/mspec/matchers/include.rb
@@ -15,11 +15,11 @@ class IncludeMatcher
end
def failure_message
- ["Expected #{@actual.inspect}", "to include #{@element.inspect}"]
+ ["Expected #{MSpec.format(@actual)}", "to include #{MSpec.format(@element)}"]
end
def negative_failure_message
- ["Expected #{@actual.inspect}", "not to include #{@element.inspect}"]
+ ["Expected #{MSpec.format(@actual)}", "not to include #{MSpec.format(@element)}"]
end
end
diff --git a/spec/mspec/lib/mspec/matchers/match_yaml.rb b/spec/mspec/lib/mspec/matchers/match_yaml.rb
index 920d85a14f..30561627c3 100644
--- a/spec/mspec/lib/mspec/matchers/match_yaml.rb
+++ b/spec/mspec/lib/mspec/matchers/match_yaml.rb
@@ -30,7 +30,11 @@ class MatchYAMLMatcher
def valid_yaml?(obj)
require 'yaml'
begin
- YAML.load(obj)
+ if YAML.respond_to?(:unsafe_load)
+ YAML.unsafe_load(obj)
+ else
+ YAML.load(obj)
+ end
rescue
false
else
diff --git a/spec/mspec/lib/mspec/matchers/method.rb b/spec/mspec/lib/mspec/matchers/method.rb
index e8cdfa62ff..2b54419faa 100644
--- a/spec/mspec/lib/mspec/matchers/method.rb
+++ b/spec/mspec/lib/mspec/matchers/method.rb
@@ -1,5 +1,5 @@
class MethodMatcher
- def initialize(method, include_super=true)
+ def initialize(method, include_super = true)
@include_super = include_super
@method = method.to_sym
end
diff --git a/spec/mspec/lib/mspec/matchers/output.rb b/spec/mspec/lib/mspec/matchers/output.rb
index b89b6ca0f6..5bb5d55027 100644
--- a/spec/mspec/lib/mspec/matchers/output.rb
+++ b/spec/mspec/lib/mspec/matchers/output.rb
@@ -42,12 +42,12 @@ class OutputMatcher
expected_out = "\n"
actual_out = "\n"
unless @out.nil?
- expected_out += " $stdout: #{@out.inspect}\n"
- actual_out += " $stdout: #{@stdout.inspect}\n"
+ expected_out += " $stdout: #{MSpec.format(@out)}\n"
+ actual_out += " $stdout: #{MSpec.format(@stdout.to_s)}\n"
end
unless @err.nil?
- expected_out += " $stderr: #{@err.inspect}\n"
- actual_out += " $stderr: #{@stderr.inspect}\n"
+ expected_out += " $stderr: #{MSpec.format(@err)}\n"
+ actual_out += " $stderr: #{MSpec.format(@stderr.to_s)}\n"
end
["Expected:#{expected_out}", " got:#{actual_out}"]
end
@@ -61,7 +61,7 @@ class OutputMatcher
end
module MSpecMatchers
- private def output(stdout=nil, stderr=nil)
+ private def output(stdout = nil, stderr = nil)
OutputMatcher.new(stdout, stderr)
end
end
diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb
index a051ea12f7..8cba842ce3 100644
--- a/spec/mspec/lib/mspec/matchers/raise_error.rb
+++ b/spec/mspec/lib/mspec/matchers/raise_error.rb
@@ -1,69 +1,105 @@
class RaiseErrorMatcher
- def initialize(exception, message, &block)
+ FAILURE_MESSAGE_FOR_EXCEPTION = {}.compare_by_identity
+ UNDEF_CAUSE = Object.new
+
+ attr_writer :block
+
+ def initialize(exception, message = nil, options = nil, &block)
+ if message.is_a? Hash
+ @message = nil
+ options = message
+ else
+ @message = message
+ end
+ @cause = options ? options.fetch(:cause, UNDEF_CAUSE) : UNDEF_CAUSE
@exception = exception
- @message = message
@block = block
@actual = nil
end
+ # This #matches? method is unusual because it doesn't always return a boolean but instead
+ # re-raises the original exception if proc.call raises an exception and #matching_exception? is false.
+ # The reasoning is the original exception class matters and we don't want to change it by raising another exception,
+ # so instead we attach the #failure_message and extract it in ExceptionState#message.
def matches?(proc)
@result = proc.call
return false
- rescue Exception => actual
+ rescue Object => actual
@actual = actual
+
if matching_exception?(actual)
+ # The block has its own expectations and will throw an exception if it fails
+ @block[actual] if @block
return true
else
+ FAILURE_MESSAGE_FOR_EXCEPTION[actual] = failure_message
raise actual
end
end
- def matching_exception?(exc)
- return false unless @exception === exc
- if @message then
- case @message
- when String
- return false if @message != exc.message
- when Regexp
- return false if @message !~ exc.message
- end
+ def matching_class?(exc)
+ @exception === exc
+ end
+
+ def matching_message?(exc)
+ case @message
+ when String
+ @message == exc.message
+ when Regexp
+ @message =~ exc.message
+ else
+ true
end
+ end
- # The block has its own expectations and will throw an exception if it fails
- @block[exc] if @block
+ def matching_cause?(exc)
+ case @cause
+ when UNDEF_CAUSE
+ true
+ else
+ @cause == exc.cause
+ end
+ end
- return true
+ def matching_exception?(exc)
+ matching_class?(exc) and matching_message?(exc) and matching_cause?(exc)
end
- def exception_class_and_message(exception_class, message)
- if message
- "#{exception_class} (#{message})"
- else
- "#{exception_class}"
+ def exception_class_and_message_and_cause(exception_class, message, cause)
+ string = "#{exception_class}"
+ prefixed = false
+ prefix = -> { prefixed ? ", " : prefixed = "(" }
+
+ if message != nil
+ string << "#{prefix.()}#{message.inspect}"
end
+
+ if cause != UNDEF_CAUSE
+ string << "#{prefix.()}cause: #{cause.inspect}"
+ end
+
+ string << ")" if prefixed
+
+ string
end
def format_expected_exception
- exception_class_and_message(@exception, @message)
+ exception_class_and_message_and_cause(@exception, @message, @cause)
end
def format_exception(exception)
- exception_class_and_message(exception.class, exception.message)
- end
-
- def format_result(result)
- result.pretty_inspect.chomp
- rescue => e
- "#pretty_inspect raised #{e.class}; A #<#{result.class}>"
+ exception_class_and_message_and_cause(exception.class,
+ @message == nil ? nil : exception.message,
+ @cause == UNDEF_CAUSE ? UNDEF_CAUSE : exception.cause)
end
def failure_message
message = ["Expected #{format_expected_exception}"]
if @actual
- message << "but got #{format_exception(@actual)}"
+ message << "but got: #{format_exception(@actual)}"
else
- message << "but no exception was raised (#{format_result(@result)} was returned)"
+ message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
end
message
@@ -72,14 +108,25 @@ class RaiseErrorMatcher
def negative_failure_message
message = ["Expected to not get #{format_expected_exception}", ""]
unless @actual.class == @exception
- message[1] = "but got #{format_exception(@actual)}"
+ message[1] = "but got: #{format_exception(@actual)}"
end
message
end
end
module MSpecMatchers
- private def raise_error(exception=Exception, message=nil, &block)
- RaiseErrorMatcher.new(exception, message, &block)
+ private def raise_error(exception = Exception, message = nil, options = nil, &block)
+ RaiseErrorMatcher.new(exception, message, options, &block)
+ end
+
+ # CRuby < 4.1 has inconsistent coercion errors:
+ # https://bugs.ruby-lang.org/issues/21864
+ # This matcher ignores the message on CRuby < 4.1
+ # and checks the message for all other cases, including other Rubies
+ private def raise_consistent_error(exception = Exception, message = nil, options = nil, &block)
+ if RUBY_ENGINE == "ruby" and ruby_version_is ""..."4.1"
+ message = nil
+ end
+ RaiseErrorMatcher.new(exception, message, options, &block)
end
end
diff --git a/spec/mspec/lib/mspec/matchers/skip.rb b/spec/mspec/lib/mspec/matchers/skip.rb
new file mode 100644
index 0000000000..7c175d358d
--- /dev/null
+++ b/spec/mspec/lib/mspec/matchers/skip.rb
@@ -0,0 +1,5 @@
+module MSpecMatchers
+ private def skip(reason = 'no reason')
+ raise SkippedSpecError, reason
+ end
+end
diff --git a/spec/mspec/lib/mspec/mocks/mock.rb b/spec/mspec/lib/mspec/mocks/mock.rb
index cb4875bbd6..c61ba35ea7 100644
--- a/spec/mspec/lib/mspec/mocks/mock.rb
+++ b/spec/mspec/lib/mspec/mocks/mock.rb
@@ -18,20 +18,16 @@ module Mock
@stubs ||= Hash.new { |h,k| h[k] = [] }
end
- def self.replaced_name(obj, sym)
- :"__mspec_#{obj.__id__}_#{sym}__"
+ def self.replaced_name(key)
+ :"__mspec_#{key.last}__"
end
def self.replaced_key(obj, sym)
- [replaced_name(obj, sym), sym]
+ [obj.__id__, sym]
end
- def self.has_key?(keys, sym)
- !!keys.find { |k| k.first == sym }
- end
-
- def self.replaced?(sym)
- has_key?(mocks.keys, sym) or has_key?(stubs.keys, sym)
+ def self.replaced?(key)
+ mocks.include?(key) or stubs.include?(key)
end
def self.clear_replaced(key)
@@ -40,15 +36,16 @@ module Mock
end
def self.mock_respond_to?(obj, sym, include_private = false)
- name = replaced_name(obj, :respond_to?)
- if replaced? name
+ key = replaced_key(obj, :respond_to?)
+ if replaced? key
+ name = replaced_name(key)
obj.__send__ name, sym, include_private
else
obj.respond_to? sym, include_private
end
end
- def self.install_method(obj, sym, type=nil)
+ def self.install_method(obj, sym, type = nil)
meta = obj.singleton_class
key = replaced_key obj, sym
@@ -59,8 +56,8 @@ module Mock
return
end
- if (sym == :respond_to? or mock_respond_to?(obj, sym, true)) and !replaced?(key.first)
- meta.__send__ :alias_method, key.first, sym
+ if (sym == :respond_to? or mock_respond_to?(obj, sym, true)) and !replaced?(key)
+ meta.__send__ :alias_method, replaced_name(key), sym
end
suppress_warning {
@@ -180,7 +177,7 @@ module Mock
mock_respond_to? obj, *args
else
SpecExpectation.fail_with("Mock '#{name_or_inspect obj}': method #{sym}\n",
- "called with unexpected arguments #{inspect_args compare}")
+ "called with unexpected arguments #{inspect_args args}")
end
end
@@ -191,7 +188,7 @@ module Mock
next
end
- replaced = key.first
+ replaced = replaced_name(key)
sym = key.last
meta = obj.singleton_class
diff --git a/spec/mspec/lib/mspec/mocks/object.rb b/spec/mspec/lib/mspec/mocks/object.rb
index 19a50ac4e1..fcaa1caef0 100644
--- a/spec/mspec/lib/mspec/mocks/object.rb
+++ b/spec/mspec/lib/mspec/mocks/object.rb
@@ -15,7 +15,7 @@ class Object
end
end
-def mock(name, options={})
+def mock(name, options = {})
MockObject.new name, options
end
@@ -23,6 +23,6 @@ def mock_int(val)
MockIntObject.new(val)
end
-def mock_numeric(name, options={})
+def mock_numeric(name, options = {})
NumericMockObject.new name, options
end
diff --git a/spec/mspec/lib/mspec/mocks/proxy.rb b/spec/mspec/lib/mspec/mocks/proxy.rb
index f5acc89d62..8473132b0b 100644
--- a/spec/mspec/lib/mspec/mocks/proxy.rb
+++ b/spec/mspec/lib/mspec/mocks/proxy.rb
@@ -1,5 +1,5 @@
class MockObject
- def initialize(name, options={})
+ def initialize(name, options = {})
@name = name
@null = options[:null_object]
end
@@ -11,7 +11,7 @@ class MockObject
end
class NumericMockObject < Numeric
- def initialize(name, options={})
+ def initialize(name, options = {})
@name = name
@null = options[:null_object]
end
@@ -50,7 +50,7 @@ end
class MockProxy
attr_reader :raising, :yielding
- def initialize(type=nil)
+ def initialize(type = nil)
@multiple_returns = nil
@returning = nil
@raising = nil
diff --git a/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb
new file mode 100644
index 0000000000..abfb6dd0ee
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb
@@ -0,0 +1,84 @@
+class ConstantsLockFile
+ LOCK_FILE_NAME = '.mspec.constants'
+
+ def self.lock_file
+ @prefix ||= File.expand_path(MSpecScript.get(:prefix) || '.')
+ "#{@prefix}/#{LOCK_FILE_NAME}"
+ end
+
+ def self.load
+ if File.exist?(lock_file)
+ File.readlines(lock_file).map(&:chomp)
+ else
+ []
+ end
+ end
+
+ def self.dump(ary)
+ contents = ary.map(&:to_s).uniq.sort.join("\n") + "\n"
+ File.write(lock_file, contents)
+ end
+end
+
+class ConstantLeakError < StandardError
+end
+
+class ConstantsLeakCheckerAction
+ def initialize(save)
+ @save = save
+ @check = !save
+ @constants_locked = ConstantsLockFile.load
+ @exclude_patterns = MSpecScript.get(:toplevel_constants_excludes) || []
+ end
+
+ def register
+ MSpec.register :start, self
+ MSpec.register :before, self
+ MSpec.register :after, self
+ MSpec.register :finish, self
+ end
+
+ def start
+ @constants_start = constants_now
+ end
+
+ def before(state)
+ @constants_before = constants_now
+ end
+
+ def after(state)
+ constants = remove_excludes(constants_now - @constants_before - @constants_locked)
+
+ if @check && !constants.empty?
+ MSpec.protect 'Constants leak check' do
+ raise ConstantLeakError, "Top level constants leaked: #{constants.join(', ')}"
+ end
+ end
+ end
+
+ def finish
+ constants = remove_excludes(constants_now - @constants_start - @constants_locked)
+
+ if @save
+ ConstantsLockFile.dump(@constants_locked + constants)
+ end
+
+ if @check && !constants.empty?
+ MSpec.protect 'Global constants leak check' do
+ raise ConstantLeakError, "Top level constants leaked in the whole test suite: #{constants.join(', ')}"
+ end
+ end
+ end
+
+ private
+
+ def constants_now
+ Object.constants.map(&:to_s)
+ end
+
+ def remove_excludes(constants)
+ constants.reject { |name|
+ @exclude_patterns.any? { |pattern| pattern === name }
+ }
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/actions/filter.rb b/spec/mspec/lib/mspec/runner/actions/filter.rb
index 35899c8dc8..b0ad7080da 100644
--- a/spec/mspec/lib/mspec/runner/actions/filter.rb
+++ b/spec/mspec/lib/mspec/runner/actions/filter.rb
@@ -10,7 +10,7 @@ require 'mspec/runner/filters/match'
# trigger the action.
class ActionFilter
- def initialize(tags=nil, descs=nil)
+ def initialize(tags = nil, descs = nil)
@tags = Array(tags)
descs = Array(descs)
@sfilter = descs.empty? ? nil : MatchFilter.new(nil, *descs)
diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
index ec17a156bf..0a8c9c3252 100644
--- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
@@ -24,29 +24,36 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
+class LeakError < StandardError
+end
+
class LeakChecker
+ attr_reader :leaks
+
def initialize
@fd_info = find_fds
@tempfile_info = find_tempfiles
@thread_info = find_threads
@env_info = find_env
@argv_info = find_argv
+ @globals_info = find_globals
@encoding_info = find_encodings
end
- def check(test_name)
- @no_leaks = true
- leaks = [
- check_fd_leak(test_name),
- check_tempfile_leak(test_name),
- check_thread_leak(test_name),
- check_process_leak(test_name),
- check_env(test_name),
- check_argv(test_name),
- check_encodings(test_name)
- ]
- GC.start if leaks.any?
- return leaks.none?
+ def check(state)
+ @state = state
+ @leaks = []
+ check_fd_leak
+ check_tempfile_leak
+ check_thread_leak
+ check_process_leak
+ check_env
+ check_argv
+ check_globals
+ check_encodings
+ check_tracepoints
+ GC.start unless @leaks.empty?
+ @leaks.empty?
end
private
@@ -66,8 +73,7 @@ class LeakChecker
end
end
- def check_fd_leak(test_name)
- leaked = false
+ def check_fd_leak
live1 = @fd_info
if IO.respond_to?(:console) and (m = IO.method(:console)).arity.nonzero?
m[:close]
@@ -76,12 +82,11 @@ class LeakChecker
fd_closed = live1 - live2
if !fd_closed.empty?
fd_closed.each {|fd|
- puts "Closed file descriptor: #{test_name}: #{fd}"
+ leak "Closed file descriptor: #{fd}"
}
end
fd_leaked = live2 - live1
if !fd_leaked.empty?
- leaked = true
h = {}
ObjectSpace.each_object(IO) {|io|
inspect = io.inspect
@@ -105,19 +110,18 @@ class LeakChecker
str << s
}
end
- puts "Leaked file descriptor: #{test_name}: #{fd}#{str}"
+ leak "Leaked file descriptor: #{fd}#{str}"
}
#system("lsof -p #$$") if !fd_leaked.empty?
h.each {|fd, list|
next if list.length <= 1
if 1 < list.count {|io, autoclose, inspect| autoclose }
str = list.map {|io, autoclose, inspect| " #{inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join
- puts "Multiple autoclose IO object for a file descriptor:#{str}"
+ leak "Multiple autoclose IO object for a file descriptor:#{str}"
end
}
end
@fd_info = live2
- return leaked
end
def extend_tempfile_counter
@@ -128,19 +132,19 @@ class LeakChecker
attr_accessor :count
end
- def new(data)
+ def new(...)
LeakChecker::TempfileCounter.count += 1
- super(data)
+ super
end
}
LeakChecker.const_set(:TempfileCounter, m)
- class << Tempfile::Remover
+ class << Tempfile
prepend LeakChecker::TempfileCounter
end
end
- def find_tempfiles(prev_count=-1)
+ def find_tempfiles(prev_count = -1)
return [prev_count, []] unless defined? Tempfile
extend_tempfile_counter
count = TempfileCounter.count
@@ -152,132 +156,141 @@ class LeakChecker
end
end
- def check_tempfile_leak(test_name)
+ def check_tempfile_leak
return false unless defined? Tempfile
count1, initial_tempfiles = @tempfile_info
count2, current_tempfiles = find_tempfiles(count1)
- leaked = false
tempfiles_leaked = current_tempfiles - initial_tempfiles
if !tempfiles_leaked.empty?
- leaked = true
list = tempfiles_leaked.map {|t| t.inspect }.sort
list.each {|str|
- puts "Leaked tempfile: #{test_name}: #{str}"
+ leak "Leaked tempfile: #{str}"
}
tempfiles_leaked.each {|t| t.close! }
end
@tempfile_info = [count2, initial_tempfiles]
- return leaked
end
def find_threads
Thread.list.find_all {|t|
- t != Thread.current && t.alive?
+ t != Thread.current && t.alive? &&
+ !(t.thread_variable?(:"\0__detached_thread__") && t.thread_variable_get(:"\0__detached_thread__"))
}
end
- def check_thread_leak(test_name)
+ def check_thread_leak
live1 = @thread_info
live2 = find_threads
thread_finished = live1 - live2
- leaked = false
if !thread_finished.empty?
list = thread_finished.map {|t| t.inspect }.sort
list.each {|str|
- puts "Finished thread: #{test_name}: #{str}"
+ leak "Finished thread: #{str}"
}
end
thread_leaked = live2 - live1
if !thread_leaked.empty?
- leaked = true
list = thread_leaked.map {|t| t.inspect }.sort
list.each {|str|
- puts "Leaked thread: #{test_name}: #{str}"
+ leak "Leaked thread: #{str}"
}
end
@thread_info = live2
- return leaked
end
- def check_process_leak(test_name)
+ def check_process_leak
subprocesses_leaked = Process.waitall
subprocesses_leaked.each { |pid, status|
- puts "Leaked subprocess: #{pid}: #{status}"
+ leak "Leaked subprocess: #{pid}: #{status}"
}
- return !subprocesses_leaked.empty?
end
def find_env
ENV.to_h
end
- def check_env(test_name)
+ def check_env
old_env = @env_info
new_env = find_env
- return false if old_env == new_env
+ return if old_env == new_env
+
(old_env.keys | new_env.keys).sort.each {|k|
if old_env.has_key?(k)
if new_env.has_key?(k)
if old_env[k] != new_env[k]
- puts "Environment variable changed: #{test_name} : #{k.inspect} changed : #{old_env[k].inspect} -> #{new_env[k].inspect}"
+ leak "Environment variable changed : #{k.inspect} changed : #{old_env[k].inspect} -> #{new_env[k].inspect}"
end
else
- puts "Environment variable changed: #{test_name} : #{k.inspect} deleted"
+ leak "Environment variable changed: #{k.inspect} deleted"
end
else
if new_env.has_key?(k)
- puts "Environment variable changed: #{test_name} : #{k.inspect} added"
+ leak "Environment variable changed: #{k.inspect} added"
else
flunk "unreachable"
end
end
}
@env_info = new_env
- return true
end
def find_argv
ARGV.map { |e| e.dup }
end
- def check_argv(test_name)
+ def check_argv
old_argv = @argv_info
new_argv = find_argv
- leaked = false
if new_argv != old_argv
- puts "ARGV changed: #{test_name} : #{old_argv.inspect} to #{new_argv.inspect}"
+ leak "ARGV changed: #{old_argv.inspect} to #{new_argv.inspect}"
@argv_info = new_argv
- leaked = true
end
- return leaked
+ end
+
+ def find_globals
+ { verbose: $VERBOSE, debug: $DEBUG }
+ end
+
+ def check_globals
+ old_globals = @globals_info
+ new_globals = find_globals
+ if new_globals != old_globals
+ leak "Globals changed: #{old_globals.inspect} to #{new_globals.inspect}"
+ @globals_info = new_globals
+ end
end
def find_encodings
[Encoding.default_internal, Encoding.default_external]
end
- def check_encodings(test_name)
+ def check_encodings
old_internal, old_external = @encoding_info
new_internal, new_external = find_encodings
- leaked = false
if new_internal != old_internal
- leaked = true
- puts "Encoding.default_internal changed: #{test_name} : #{old_internal.inspect} to #{new_internal.inspect}"
+ leak "Encoding.default_internal changed: #{old_internal.inspect} to #{new_internal.inspect}"
end
if new_external != old_external
- leaked = true
- puts "Encoding.default_external changed: #{test_name} : #{old_external.inspect} to #{new_external.inspect}"
+ leak "Encoding.default_external changed: #{old_external.inspect} to #{new_external.inspect}"
end
@encoding_info = [new_internal, new_external]
- return leaked
end
- def puts(*args)
- if @no_leaks
- @no_leaks = false
- print "\n"
+ def check_tracepoints
+ ObjectSpace.each_object(TracePoint) do |tp|
+ if tp.enabled?
+ leak "TracePoint is still enabled: #{tp.inspect}"
+ end
+ end
+ end
+
+ def leak(message)
+ if @leaks.empty?
+ $stderr.puts "\n"
+ $stderr.puts @state.description
end
- super(*args)
+ @leaks << message
+ $stderr.puts message
end
end
@@ -288,14 +301,77 @@ class LeakCheckerAction
end
def start
+ disable_nss_modules
@checker = LeakChecker.new
end
def after(state)
- unless @checker.check(state.description)
+ unless @checker.check(state)
+ leak_messages = @checker.leaks
+ location = state.description
if state.example
- puts state.example.source_location.join(':')
+ location = "#{location}\n#{state.example.source_location.join(':')}"
+ end
+ MSpec.protect(location) do
+ raise LeakError, leak_messages.join("\n")
end
end
end
+
+ private
+
+ # This function is intended to disable all NSS modules when ruby is compiled
+ # against glibc. NSS modules allow the system administrator to load custom
+ # shared objects into all processes using glibc, and use them to customise
+ # the behaviour of username, groupname, hostname, etc lookups. This is
+ # normally configured in the file /etc/nsswitch.conf.
+ # These modules often do things like open cache files or connect to system
+ # daemons like sssd or dbus, which of course means they have open file
+ # descriptors of their own. This can cause the leak-checking functionality
+ # in this file to report that such descriptors have been leaked, and fail
+ # the test suite.
+ # This function uses glibc's __nss_configure_lookup function to override any
+ # configuration in /etc/nsswitch.conf, and just use the built in files/dns
+ # name lookup functionality (which is of course perfectly sufficient for
+ # running ruby/spec).
+ def disable_nss_modules
+ begin
+ require 'fiddle'
+ rescue LoadError
+ # Make sure it's possible to run the test suite on a ruby implementation
+ # which does not (yet?) have Fiddle.
+ return
+ end
+
+ begin
+ libc = Fiddle.dlopen(nil)
+ # Older versions of fiddle don't have Fiddle::Type (and instead rely on Fiddle::TYPE_)
+ # Even older versions of fiddle don't have CONST_STRING,
+ string_type = defined?(Fiddle::TYPE_CONST_STRING) ? Fiddle::TYPE_CONST_STRING : Fiddle::TYPE_VOIDP
+ nss_configure_lookup = Fiddle::Function.new(
+ libc['__nss_configure_lookup'],
+ [string_type, string_type],
+ Fiddle::TYPE_INT
+ )
+ rescue Fiddle::DLError
+ # We're not running with glibc - no need to do this.
+ return
+ end
+
+ nss_configure_lookup.call 'passwd', 'files'
+ nss_configure_lookup.call 'shadow', 'files'
+ nss_configure_lookup.call 'group', 'files'
+ nss_configure_lookup.call 'hosts', 'files dns'
+ nss_configure_lookup.call 'services', 'files'
+ nss_configure_lookup.call 'netgroup', 'files'
+ nss_configure_lookup.call 'automount', 'files'
+ nss_configure_lookup.call 'aliases', 'files'
+ nss_configure_lookup.call 'ethers', 'files'
+ nss_configure_lookup.call 'gshadow', 'files'
+ nss_configure_lookup.call 'initgroups', 'files'
+ nss_configure_lookup.call 'networks', 'files dns'
+ nss_configure_lookup.call 'protocols', 'files'
+ nss_configure_lookup.call 'publickey', 'files'
+ nss_configure_lookup.call 'rpc', 'files'
+ end
end
diff --git a/spec/mspec/lib/mspec/runner/actions/profile.rb b/spec/mspec/lib/mspec/runner/actions/profile.rb
new file mode 100644
index 0000000000..c743d6e3e8
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/actions/profile.rb
@@ -0,0 +1,60 @@
+class ProfileAction
+ def initialize
+ @describe_name = nil
+ @describe_time = nil
+ @describes = []
+ @its = []
+ end
+
+ def register
+ MSpec.register :enter, self
+ MSpec.register :before,self
+ MSpec.register :after, self
+ MSpec.register :finish,self
+ end
+
+ def enter(describe)
+ if @describe_time
+ @describes << [@describe_name, now - @describe_time]
+ end
+
+ @describe_name = describe
+ @describe_time = now
+ end
+
+ def before(state)
+ @it_name = state.it
+ @it_time = now
+ end
+
+ def after(state = nil)
+ @its << [@describe_name, @it_name, now - @it_time]
+ end
+
+ def finish
+ puts "\nProfiling info:"
+
+ desc = @describes.sort { |a,b| b.last <=> a.last }
+ desc.delete_if { |a| a.last <= 0.001 }
+ show = desc[0, 100]
+
+ puts "Top #{show.size} describes:"
+
+ show.each do |des, time|
+ printf "%3.3f - %s\n", time, des
+ end
+
+ its = @its.sort { |a,b| b.last <=> a.last }
+ its.delete_if { |a| a.last <= 0.001 }
+ show = its[0, 100]
+
+ puts "\nTop #{show.size} its:"
+ show.each do |des, it, time|
+ printf "%3.3f - %s %s\n", time, des, it
+ end
+ end
+
+ def now
+ Time.now.to_f
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/actions/tag.rb b/spec/mspec/lib/mspec/runner/actions/tag.rb
index 760152b2a3..d40d562451 100644
--- a/spec/mspec/lib/mspec/runner/actions/tag.rb
+++ b/spec/mspec/lib/mspec/runner/actions/tag.rb
@@ -22,7 +22,7 @@ require 'mspec/runner/actions/filter'
# spec description strings
class TagAction < ActionFilter
- def initialize(action, outcome, tag, comment, tags=nil, descs=nil)
+ def initialize(action, outcome, tag, comment, tags = nil, descs = nil)
super tags, descs
@action = action
@outcome = outcome
diff --git a/spec/mspec/lib/mspec/runner/actions/taglist.rb b/spec/mspec/lib/mspec/runner/actions/taglist.rb
index c1aba53794..3097e655d5 100644
--- a/spec/mspec/lib/mspec/runner/actions/taglist.rb
+++ b/spec/mspec/lib/mspec/runner/actions/taglist.rb
@@ -4,7 +4,7 @@ require 'mspec/runner/actions/filter'
# tagged with +tags+. If +tags+ is an empty list, prints out
# descriptions for any specs that are tagged.
class TagListAction
- def initialize(tags=nil)
+ def initialize(tags = nil)
@tags = tags.nil? || tags.empty? ? nil : Array(tags)
@filter = nil
end
diff --git a/spec/mspec/lib/mspec/runner/actions/tally.rb b/spec/mspec/lib/mspec/runner/actions/tally.rb
index 33f937293c..d6ada53bab 100644
--- a/spec/mspec/lib/mspec/runner/actions/tally.rb
+++ b/spec/mspec/lib/mspec/runner/actions/tally.rb
@@ -5,31 +5,31 @@ class Tally
@files = @examples = @expectations = @failures = @errors = @guards = @tagged = 0
end
- def files!(add=1)
+ def files!(add = 1)
@files += add
end
- def examples!(add=1)
+ def examples!(add = 1)
@examples += add
end
- def expectations!(add=1)
+ def expectations!(add = 1)
@expectations += add
end
- def failures!(add=1)
+ def failures!(add = 1)
@failures += add
end
- def errors!(add=1)
+ def errors!(add = 1)
@errors += add
end
- def guards!(add=1)
+ def guards!(add = 1)
@guards += add
end
- def tagged!(add=1)
+ def tagged!(add = 1)
@tagged += add
end
diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb
new file mode 100644
index 0000000000..1200926872
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb
@@ -0,0 +1,145 @@
+class TimeoutAction
+ def initialize(timeout)
+ @timeout = timeout
+ @queue = Queue.new
+ @started = now
+ @fail = false
+ @error_message = "took longer than the configured timeout of #{@timeout}s"
+ end
+
+ def register
+ MSpec.register :start, self
+ MSpec.register :before, self
+ MSpec.register :after, self
+ MSpec.register :finish, self
+ end
+
+ private def now
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+
+ private def fetch_item
+ @queue.pop(true)
+ rescue ThreadError
+ nil
+ end
+
+ def start
+ @thread = Thread.new do
+ loop do
+ if action = fetch_item
+ action.call
+ else
+ wakeup_at = @started + @timeout
+ left = wakeup_at - now
+ sleep left if left > 0
+ Thread.pass # Let the main thread run
+
+ if @queue.empty?
+ elapsed = now - @started
+ if elapsed > @timeout
+ if @current_state
+ STDERR.puts "\nExample #{@error_message}:"
+ STDERR.puts "#{@current_state.description}"
+ else
+ STDERR.puts "\nSome code outside an example #{@error_message}"
+ end
+ STDERR.flush
+
+ show_backtraces
+ if MSpec.subprocesses.empty?
+ exit! 2
+ else
+ # Do not exit but signal the subprocess so we can get their output
+ MSpec.subprocesses.each do |pid|
+ kill_wait_one_second :SIGTERM, pid
+ hard_kill :SIGKILL, pid
+ end
+ @fail = true
+ @current_state = nil
+ break # stop this thread, will fail in #after
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def before(state = nil)
+ time = now
+ @queue << -> do
+ @current_state = state
+ @started = time
+ end
+ end
+
+ def after(state = nil)
+ @queue << -> do
+ @current_state = nil
+ end
+
+ if @fail
+ STDERR.puts "\n\nThe last example #{@error_message}. See above for the subprocess stacktrace."
+ exit! 2
+ end
+ end
+
+ def finish
+ @thread.kill
+ @thread.join
+ end
+
+ private def hard_kill(signal, pid)
+ begin
+ Process.kill signal, pid
+ rescue Errno::ESRCH
+ # Process already terminated
+ end
+ end
+
+ private def kill_wait_one_second(signal, pid)
+ begin
+ Process.kill signal, pid
+ sleep 1
+ rescue Errno::ESRCH
+ # Process already terminated
+ end
+ end
+
+ private def show_backtraces
+ java_stacktraces = -> pid {
+ if RUBY_ENGINE == 'truffleruby' || RUBY_ENGINE == 'jruby'
+ STDERR.puts 'Java stacktraces:'
+ kill_wait_one_second :SIGQUIT, pid
+ end
+ }
+
+ if MSpec.subprocesses.empty?
+ java_stacktraces.call Process.pid
+
+ STDERR.puts "\nRuby backtraces:"
+ if defined?(Truffle::Debug.show_backtraces)
+ Truffle::Debug.show_backtraces
+ else
+ Thread.list.each do |thread|
+ unless thread == Thread.current
+ STDERR.puts thread.inspect, thread.backtrace, ''
+ end
+ end
+ end
+ else
+ MSpec.subprocesses.each do |pid|
+ STDERR.puts "\nFor subprocess #{pid}"
+ java_stacktraces.call pid
+
+ if RUBY_ENGINE == 'truffleruby'
+ STDERR.puts "\nRuby backtraces:"
+ kill_wait_one_second :SIGALRM, pid
+ else
+ STDERR.puts "Don't know how to print backtraces of a subprocess on #{RUBY_ENGINE}"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/context.rb b/spec/mspec/lib/mspec/runner/context.rb
index 30d8a4ad1b..bcd83b2465 100644
--- a/spec/mspec/lib/mspec/runner/context.rb
+++ b/spec/mspec/lib/mspec/runner/context.rb
@@ -12,15 +12,14 @@
class ContextState
attr_reader :state, :parent, :parents, :children, :examples, :to_s
- def initialize(mod, options=nil)
- @to_s = mod.to_s
- if options.is_a? Hash
- @options = options
- else
- @to_s += "#{".:#".include?(options[0,1]) ? "" : " "}#{options}" if options
- @options = { }
- end
- @options[:shared] ||= false
+ MOCK_VERIFY = -> { Mock.verify_count }
+ MOCK_CLEANUP = -> { Mock.cleanup }
+ EXPECTATION_MISSING = -> { raise SpecExpectationNotFoundError }
+
+ def initialize(description, options = nil)
+ raise "#describe options should be a Hash or nil" unless Hash === options or options.nil?
+ @to_s = description.to_s
+ @shared = options && options[:shared]
@parsed = false
@before = { :all => [], :each => [] }
@@ -28,13 +27,10 @@ class ContextState
@pre = {}
@post = {}
@examples = []
+ @state = nil
@parent = nil
@parents = [self]
@children = []
-
- @mock_verify = Proc.new { Mock.verify_count }
- @mock_cleanup = Proc.new { Mock.cleanup }
- @expectation_missing = Proc.new { raise SpecExpectationNotFoundError }
end
# Remove caching when a ContextState is dup'd for shared specs.
@@ -46,7 +42,7 @@ class ContextState
# Returns true if this is a shared +ContextState+. Essentially, when
# created with: describe "Something", :shared => true { ... }
def shared?
- return @options[:shared]
+ @shared
end
# Set the parent (enclosing) +ContextState+ for this state. Creates
@@ -127,6 +123,7 @@ class ContextState
# Creates an ExampleState instance for the block and stores it
# in a list of examples to evaluate unless the example is filtered.
def it(desc, &block)
+ raise "nested #it" if @state
example = ExampleState.new(self, desc, block)
MSpec.actions :add, example
return if MSpec.guarded?
@@ -174,7 +171,7 @@ class ContextState
# so that exceptions are handled and tallied. Returns true and does
# NOT evaluate any blocks if +check+ is true and
# <tt>MSpec.mode?(:pretend)</tt> is true.
- def protect(what, blocks, check=true)
+ def protect(what, blocks, check = true)
return true if check and MSpec.mode? :pretend
Array(blocks).all? { |block| MSpec.protect what, &block }
end
@@ -205,7 +202,7 @@ class ContextState
if protect "before :all", pre(:all)
@examples.each do |state|
MSpec.repeat do
- @state = state
+ @state = state
example = state.example
MSpec.actions :before, state
@@ -213,21 +210,22 @@ class ContextState
MSpec.clear_expectations
if example
passed = protect nil, example
+ passed = protect nil, -> { MSpec.actions :passed, state, example } if passed
MSpec.actions :example, state, example
- protect nil, @expectation_missing unless MSpec.expectation? or !passed
+ protect nil, EXPECTATION_MISSING if !MSpec.expectation? and passed
end
end
protect "after :each", post(:each)
- protect "Mock.verify_count", @mock_verify
+ protect "Mock.verify_count", MOCK_VERIFY
- protect "Mock.cleanup", @mock_cleanup
+ protect "Mock.cleanup", MOCK_CLEANUP
MSpec.actions :after, state
@state = nil
end
end
protect "after :all", post(:all)
else
- protect "Mock.cleanup", @mock_cleanup
+ protect "Mock.cleanup", MOCK_CLEANUP
end
MSpec.actions :leave
diff --git a/spec/mspec/lib/mspec/runner/evaluate.rb b/spec/mspec/lib/mspec/runner/evaluate.rb
index ecf7460a90..396a84c118 100644
--- a/spec/mspec/lib/mspec/runner/evaluate.rb
+++ b/spec/mspec/lib/mspec/runner/evaluate.rb
@@ -19,7 +19,7 @@ class SpecEvaluate
# single quotes to set if off from the rest of the description string. If
# the source does contain newline characters, sets the indent level to four
# characters.
- def format(ruby, newline=true)
+ def format(ruby, newline = true)
if ruby.include?("\n")
lines = ruby.each_line.to_a
if /( *)/ =~ lines.first
@@ -49,6 +49,6 @@ class SpecEvaluate
end
end
-def evaluate(str, desc=nil, &block)
+def evaluate(str, desc = nil, &block)
SpecEvaluate.new(str, desc).define(&block)
end
diff --git a/spec/mspec/lib/mspec/runner/example.rb b/spec/mspec/lib/mspec/runner/example.rb
index 19eb29b079..0d9f0d618c 100644
--- a/spec/mspec/lib/mspec/runner/example.rb
+++ b/spec/mspec/lib/mspec/runner/example.rb
@@ -3,12 +3,12 @@ require 'mspec/runner/mspec'
# Holds some of the state of the example (i.e. +it+ block) that is
# being evaluated. See also +ContextState+.
class ExampleState
- attr_reader :context, :it, :example
+ attr_reader :context, :it, :example
- def initialize(context, it, example=nil)
- @context = context
- @it = it
- @example = example
+ def initialize(context, it, example = nil)
+ @context = context
+ @it = it
+ @example = example
end
def context=(context)
@@ -25,8 +25,8 @@ class ExampleState
end
def filtered?
- incl = MSpec.retrieve(:include) || []
- excl = MSpec.retrieve(:exclude) || []
+ incl = MSpec.include
+ excl = MSpec.exclude
included = incl.empty? || incl.any? { |f| f === description }
included &&= excl.empty? || !excl.any? { |f| f === description }
!included
diff --git a/spec/mspec/lib/mspec/runner/exception.rb b/spec/mspec/lib/mspec/runner/exception.rb
index 0d9bb43105..23375733e6 100644
--- a/spec/mspec/lib/mspec/runner/exception.rb
+++ b/spec/mspec/lib/mspec/runner/exception.rb
@@ -6,6 +6,7 @@ class ExceptionState
def initialize(state, location, exception)
@exception = exception
+ @failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError
@description = location ? "An exception occurred during: #{location}" : ""
if state
@@ -19,25 +20,35 @@ class ExceptionState
end
def failure?
- [SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e }
+ @failure
end
def message
- if @exception.message.empty?
- "<No message>"
- elsif @exception.class == SpecExpectationNotMetError ||
- @exception.class == SpecExpectationNotFoundError
- @exception.message
+ message = @exception.message
+ message = "<No message>" if message.empty?
+
+ if @failure
+ message
+ elsif raise_error_message = RaiseErrorMatcher::FAILURE_MESSAGE_FOR_EXCEPTION[@exception]
+ raise_error_message.join("\n")
else
- "#{@exception.class}: #{@exception.message}"
+ "#{@exception.class}: #{message}"
end
end
def backtrace
- @backtrace_filter ||= MSpecScript.config[:backtrace_filter]
+ @backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)}
bt = @exception.backtrace || []
-
- bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n")
+ unless $MSPEC_DEBUG
+ # Exclude <internal: entries inside MSpec code, so only after the first ignored entry
+ first_excluded_line = bt.index { |line| @backtrace_filter =~ line }
+ if first_excluded_line
+ bt = bt[0...first_excluded_line] + bt[first_excluded_line..-1].reject { |line|
+ @backtrace_filter =~ line || /^<internal:/ =~ line
+ }
+ end
+ end
+ bt.join("\n")
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters.rb b/spec/mspec/lib/mspec/runner/formatters.rb
index d085031a12..66f515ddff 100644
--- a/spec/mspec/lib/mspec/runner/formatters.rb
+++ b/spec/mspec/lib/mspec/runner/formatters.rb
@@ -7,6 +7,7 @@ require 'mspec/runner/formatters/summary'
require 'mspec/runner/formatters/unit'
require 'mspec/runner/formatters/spinner'
require 'mspec/runner/formatters/method'
+require 'mspec/runner/formatters/stats'
require 'mspec/runner/formatters/yaml'
require 'mspec/runner/formatters/profile'
require 'mspec/runner/formatters/junit'
diff --git a/spec/mspec/lib/mspec/runner/formatters/base.rb b/spec/mspec/lib/mspec/runner/formatters/base.rb
new file mode 100644
index 0000000000..882e15c8c2
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/formatters/base.rb
@@ -0,0 +1,150 @@
+require 'mspec/expectations/expectations'
+require 'mspec/runner/actions/timer'
+require 'mspec/runner/actions/tally'
+require 'mspec/utils/options'
+
+if ENV['CHECK_LEAKS']
+ require 'mspec/runner/actions/leakchecker'
+end
+
+if ENV['CHECK_LEAKS'] || ENV['CHECK_CONSTANT_LEAKS']
+ require 'mspec/runner/actions/constants_leak_checker'
+end
+
+class BaseFormatter
+ attr_reader :exceptions, :timer, :tally
+
+ def initialize(out = nil)
+ @current_state = nil
+ @exception = false
+ @failure = false
+ @exceptions = []
+
+ @count = 0 # For subclasses
+
+ if out
+ @out = File.open out, "w"
+ else
+ @out = $stdout
+ end
+
+ err = MSpecOptions.latest && MSpecOptions.latest.config[:error_output]
+ if err
+ @err = (err == 'stderr') ? $stderr : File.open(err, "w")
+ else
+ @err = @out
+ end
+ end
+
+ # Creates the +TimerAction+ and +TallyAction+ instances and registers them.
+ def register
+ (@timer = TimerAction.new).register
+ (@tally = TallyAction.new).register
+ @counter = @tally.counter
+
+ if ENV['CHECK_LEAKS']
+ LeakCheckerAction.new.register
+ end
+
+ if (ENV['CHECK_LEAKS'] || ENV['CHECK_CONSTANT_LEAKS']) && ENV['CHECK_CONSTANT_LEAKS'] != 'false'
+ save = ENV['CHECK_LEAKS'] == 'save' || ENV['CHECK_CONSTANT_LEAKS'] == 'save'
+ ConstantsLeakCheckerAction.new(save).register
+ end
+
+ MSpec.register :abort, self
+ MSpec.register :before, self
+ MSpec.register :after, self
+ MSpec.register :exception, self
+ MSpec.register :finish, self
+ end
+
+ def abort
+ if @current_state
+ puts "\naborting example: #{@current_state.description}"
+ end
+ end
+
+ # Returns true if any exception is raised while running
+ # an example. This flag is reset before each example
+ # is evaluated.
+ def exception?
+ @exception
+ end
+
+ # Returns true if all exceptions during the evaluation
+ # of an example are failures rather than errors. See
+ # <tt>ExceptionState#failure</tt>. This flag is reset
+ # before each example is evaluated.
+ def failure?
+ @failure
+ end
+
+ # Callback for the MSpec :before event. Resets the
+ # +#exception?+ and +#failure+ flags.
+ def before(state = nil)
+ @current_state = state
+ @failure = @exception = false
+ end
+
+ # Callback for the MSpec :exception event. Stores the
+ # +ExceptionState+ object to generate the list of backtraces
+ # after all the specs are run. Also updates the internal
+ # +#exception?+ and +#failure?+ flags.
+ def exception(exception)
+ @count += 1
+ @failure = @exception ? @failure && exception.failure? : exception.failure?
+ @exception = true
+ @exceptions << exception
+ end
+
+ # Callback for the MSpec :after event.
+ def after(state = nil)
+ @current_state = nil
+ end
+
+ # Callback for the MSpec :start event. Calls :after event.
+ # Defined here, in the base class, and used by MultiFormatter.
+ def start
+ after
+ end
+
+ # Callback for the MSpec :unload event. Calls :after event.
+ # Defined here, in the base class, and used by MultiFormatter.
+ def unload
+ after
+ end
+
+ # Callback for the MSpec :finish event. Prints a description
+ # and backtrace for every exception that occurred while
+ # evaluating the examples.
+ def finish
+ print "\n"
+
+ if MSpecOptions.latest && MSpecOptions.latest.config[:print_skips]
+ print "\nSkips:\n" unless MSpec.skips.empty?
+ MSpec.skips.each do |skip, block|
+ print "#{skip.message} in #{(block.source_location || ['?']).join(':')}\n"
+ end
+ end
+
+ count = 0
+ @exceptions.each do |exc|
+ count += 1
+ print_exception(exc, count)
+ end
+ print "\n#{@timer.format}\n\n#{@tally.format}\n"
+ end
+
+ def print_exception(exc, count)
+ outcome = exc.failure? ? "FAILED" : "ERROR"
+ @err.print "\n#{count})\n#{exc.description} #{outcome}\n"
+ @err.print exc.message, "\n"
+ @err.print exc.backtrace, "\n"
+ end
+
+ # A convenience method to allow printing to different outputs.
+ def print(*args)
+ @out.print(*args)
+ @out.flush
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/formatters/describe.rb b/spec/mspec/lib/mspec/runner/formatters/describe.rb
index 176bd79279..fc4122d13b 100644
--- a/spec/mspec/lib/mspec/runner/formatters/describe.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/describe.rb
@@ -1,5 +1,4 @@
require 'mspec/runner/formatters/dotted'
-require 'mspec/runner/actions/tally'
class DescribeFormatter < DottedFormatter
# Callback for the MSpec :finish event. Prints a summary of
diff --git a/spec/mspec/lib/mspec/runner/formatters/dotted.rb b/spec/mspec/lib/mspec/runner/formatters/dotted.rb
index 61c8e4c27c..672cdf81dc 100644
--- a/spec/mspec/lib/mspec/runner/formatters/dotted.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/dotted.rb
@@ -1,77 +1,9 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/actions/timer'
-require 'mspec/runner/actions/tally'
-require 'mspec/runner/actions/leakchecker' if ENV['CHECK_LEAKS']
+require 'mspec/runner/formatters/base'
-class DottedFormatter
- attr_reader :exceptions, :timer, :tally
-
- def initialize(out=nil)
- @exception = @failure = false
- @exceptions = []
- @count = 0 # For subclasses
- if out.nil?
- @out = $stdout
- else
- @out = File.open out, "w"
- end
-
- @current_state = nil
- end
-
- # Creates the +TimerAction+ and +TallyAction+ instances and
- # registers them. Registers +self+ for the +:exception+,
- # +:before+, +:after+, and +:finish+ actions.
+class DottedFormatter < BaseFormatter
def register
- (@timer = TimerAction.new).register
- (@tally = TallyAction.new).register
- LeakCheckerAction.new.register if ENV['CHECK_LEAKS']
- @counter = @tally.counter
-
- MSpec.register :exception, self
- MSpec.register :before, self
- MSpec.register :after, self
- MSpec.register :finish, self
- MSpec.register :abort, self
- end
-
- def abort
- if @current_state
- puts "\naborting example: #{@current_state.description}"
- end
- end
-
- # Returns true if any exception is raised while running
- # an example. This flag is reset before each example
- # is evaluated.
- def exception?
- @exception
- end
-
- # Returns true if all exceptions during the evaluation
- # of an example are failures rather than errors. See
- # <tt>ExceptionState#failure</tt>. This flag is reset
- # before each example is evaluated.
- def failure?
- @failure
- end
-
- # Callback for the MSpec :before event. Resets the
- # +#exception?+ and +#failure+ flags.
- def before(state=nil)
- @current_state = state
- @failure = @exception = false
- end
-
- # Callback for the MSpec :exception event. Stores the
- # +ExceptionState+ object to generate the list of backtraces
- # after all the specs are run. Also updates the internal
- # +#exception?+ and +#failure?+ flags.
- def exception(exception)
- @count += 1
- @failure = @exception ? @failure && exception.failure? : exception.failure?
- @exception = true
- @exceptions << exception
+ super
+ MSpec.register :after, self
end
# Callback for the MSpec :after event. Prints an indicator
@@ -80,38 +12,12 @@ class DottedFormatter
# F = An SpecExpectationNotMetError was raised
# E = Any exception other than SpecExpectationNotMetError
def after(state = nil)
- @current_state = nil
+ super(state)
- unless exception?
- print "."
- else
+ if exception?
print failure? ? "F" : "E"
+ else
+ print "."
end
end
-
- # Callback for the MSpec :finish event. Prints a description
- # and backtrace for every exception that occurred while
- # evaluating the examples.
- def finish
- print "\n"
- count = 0
- @exceptions.each do |exc|
- count += 1
- print_exception(exc, count)
- end
- print "\n#{@timer.format}\n\n#{@tally.format}\n"
- end
-
- def print_exception(exc, count)
- outcome = exc.failure? ? "FAILED" : "ERROR"
- print "\n#{count})\n#{exc.description} #{outcome}\n"
- print exc.message, "\n"
- print exc.backtrace, "\n"
- end
-
- # A convenience method to allow printing to different outputs.
- def print(*args)
- @out.print(*args)
- @out.flush
- end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/file.rb b/spec/mspec/lib/mspec/runner/formatters/file.rb
index 6db72af4ff..65cfb1f75b 100644
--- a/spec/mspec/lib/mspec/runner/formatters/file.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/file.rb
@@ -14,6 +14,11 @@ class FileFormatter < DottedFormatter
MSpec.register :unload, self
end
- alias_method :load, :before
- alias_method :unload, :after
+ def load(state = nil)
+ before(state)
+ end
+
+ def unload(state = nil)
+ after(state)
+ end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/html.rb b/spec/mspec/lib/mspec/runner/formatters/html.rb
index fd64cd0d20..e37e89a088 100644
--- a/spec/mspec/lib/mspec/runner/formatters/html.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/html.rb
@@ -1,7 +1,6 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class HtmlFormatter < DottedFormatter
+class HtmlFormatter < BaseFormatter
def register
super
MSpec.register :start, self
@@ -44,13 +43,14 @@ EOH
end
def exception(exception)
- super
+ super(exception)
outcome = exception.failure? ? "FAILED" : "ERROR"
print %[<li class="fail">- #{exception.it} (<a href="#details-#{@count}">]
print %[#{outcome} - #{@count}</a>)</li>\n]
end
- def after(state)
+ def after(state = nil)
+ super(state)
print %[<li class="pass">- #{state.it}</li>\n] unless exception?
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/junit.rb b/spec/mspec/lib/mspec/runner/formatters/junit.rb
index 76d46c2414..6351ccbce9 100644
--- a/spec/mspec/lib/mspec/runner/formatters/junit.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/junit.rb
@@ -1,19 +1,18 @@
-require 'mspec/expectations/expectations'
require 'mspec/runner/formatters/yaml'
class JUnitFormatter < YamlFormatter
- def initialize(out=nil)
- super
+ def initialize(out = nil)
+ super(out)
@tests = []
end
def after(state = nil)
- super
+ super(state)
@tests << {:test => state, :exception => false} unless exception?
end
def exception(exception)
- super
+ super(exception)
@tests << {:test => exception, :exception => true}
end
@@ -25,7 +24,7 @@ class JUnitFormatter < YamlFormatter
errors = @tally.counter.errors
failures = @tally.counter.failures
- printf <<-XML
+ print <<-XML
<?xml version="1.0" encoding="UTF-8" ?>
<testsuites
@@ -43,8 +42,8 @@ class JUnitFormatter < YamlFormatter
@tests.each do |h|
description = encode_for_xml h[:test].description
- printf <<-XML, "Spec", description, 0.0
- <testcase classname="%s" name="%s" time="%f">
+ print <<-XML
+ <testcase classname="Spec" name="#{description}" time="0.0">
XML
if h[:exception]
outcome = h[:test].failure? ? "failure" : "error"
diff --git a/spec/mspec/lib/mspec/runner/formatters/launchable.rb b/spec/mspec/lib/mspec/runner/formatters/launchable.rb
new file mode 100644
index 0000000000..f738781c71
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/formatters/launchable.rb
@@ -0,0 +1,88 @@
+module LaunchableFormatter
+ def self.extend_object(obj)
+ super
+ obj.init
+ end
+
+ def self.setDir(dir)
+ @@path = File.join(dir, "#{rand.to_s}.json")
+ self
+ end
+
+ def init
+ @timer = nil
+ @tests = []
+ end
+
+ def before(state = nil)
+ super
+ @timer = TimerAction.new
+ @timer.start
+ end
+
+ def after(state = nil)
+ super
+ @timer.finish
+ file = MSpec.file
+ return if file.nil? || state&.example.nil? || exception?
+
+ @tests << {:test => state, :file => file, :exception => false, duration: @timer.elapsed}
+ end
+
+ def exception(exception)
+ super
+ @timer.finish
+ file = MSpec.file
+ return if file.nil?
+
+ @tests << {:test => exception, :file => file, :exception => true, duration: @timer.elapsed}
+ end
+
+ def finish
+ super
+
+ require_relative '../../../../../../tool/lib/launchable'
+
+ @writer = writer = Launchable::JsonStreamWriter.new(@@path)
+ @writer.write_array('testCases')
+ at_exit {
+ @writer.close
+ }
+
+ repo_path = File.expand_path("#{__dir__}/../../../../../../")
+
+ @tests.each do |t|
+ testcase = t[:test].description
+ relative_path = t[:file].delete_prefix("#{repo_path}/")
+ # The test path is a URL-encoded representation.
+ # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18
+ test_path = {file: relative_path, testcase: testcase}.map{|key, val|
+ "#{encode_test_path_component(key)}=#{encode_test_path_component(val)}"
+ }.join('#')
+
+ status = 'TEST_PASSED'
+ if t[:exception]
+ message = t[:test].message
+ backtrace = t[:test].backtrace
+ e = "#{message}\n#{backtrace}"
+ status = 'TEST_FAILED'
+ end
+
+ @writer.write_object(
+ {
+ testPath: test_path,
+ status: status,
+ duration: t[:duration],
+ createdAt: Time.now.to_s,
+ stderr: e,
+ stdout: nil
+ }
+ )
+ end
+ end
+
+ private
+ def encode_test_path_component component
+ component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26').tr("\x00-\x08", "")
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/formatters/method.rb b/spec/mspec/lib/mspec/runner/formatters/method.rb
index ff115193fd..925858c845 100644
--- a/spec/mspec/lib/mspec/runner/formatters/method.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/method.rb
@@ -1,18 +1,18 @@
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class MethodFormatter < DottedFormatter
+class MethodFormatter < BaseFormatter
attr_accessor :methods
- def initialize(out=nil)
- super
+ def initialize(out = nil)
+ super(out)
@methods = Hash.new do |h, k|
- hash = {}
- hash[:examples] = 0
- hash[:expectations] = 0
- hash[:failures] = 0
- hash[:errors] = 0
- hash[:exceptions] = []
- h[k] = hash
+ h[k] = {
+ examples: 0,
+ expectations: 0,
+ failures: 0,
+ errors: 0,
+ exceptions: []
+ }
end
end
@@ -34,7 +34,7 @@ class MethodFormatter < DottedFormatter
# Resets the tallies so the counts are only for this
# example.
def before(state)
- super
+ super(state)
# The pattern for a method name is not correctly
# restrictive but it is simplistic and useful
@@ -60,7 +60,9 @@ class MethodFormatter < DottedFormatter
# Callback for the MSpec :after event. Sets or adds to
# tallies for the example block.
- def after(state)
+ def after(state = nil)
+ super(state)
+
h = methods[@key]
h[:examples] += tally.counter.examples
h[:expectations] += tally.counter.expectations
diff --git a/spec/mspec/lib/mspec/runner/formatters/multi.rb b/spec/mspec/lib/mspec/runner/formatters/multi.rb
index 5932eeef62..fa1da3766b 100644
--- a/spec/mspec/lib/mspec/runner/formatters/multi.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/multi.rb
@@ -1,13 +1,24 @@
-require 'mspec/runner/formatters/spinner'
+module MultiFormatter
+ def self.extend_object(obj)
+ super
+ obj.multi_initialize
+ end
-class MultiFormatter < SpinnerFormatter
- def initialize(out=nil)
- super(out)
- @counter = @tally = Tally.new
+ def multi_initialize
+ @tally = TallyAction.new
+ @counter = @tally.counter
@timer = TimerAction.new
@timer.start
end
+ def register
+ super
+
+ MSpec.register :start, self
+ MSpec.register :unload, self
+ MSpec.unregister :before, self
+ end
+
def aggregate_results(files)
require 'yaml'
@@ -21,20 +32,16 @@ class MultiFormatter < SpinnerFormatter
if d # The file might be empty if the child process died
@exceptions += Array(d['exceptions'])
- @tally.files! d['files']
- @tally.examples! d['examples']
- @tally.expectations! d['expectations']
- @tally.errors! d['errors']
- @tally.failures! d['failures']
+ @counter.files! d['files']
+ @counter.examples! d['examples']
+ @counter.expectations! d['expectations']
+ @counter.errors! d['errors']
+ @counter.failures! d['failures']
end
end
end
def print_exception(exc, count)
- print "\n#{count})\n#{exc}\n"
- end
-
- def finish
- super(false)
+ @err.print "\n#{count})\n#{exc}\n"
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/profile.rb b/spec/mspec/lib/mspec/runner/formatters/profile.rb
index 498cd4a3b7..38ef5b12ed 100644
--- a/spec/mspec/lib/mspec/runner/formatters/profile.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/profile.rb
@@ -1,9 +1,9 @@
-require 'mspec/expectations/expectations'
require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/actions/profile'
class ProfileFormatter < DottedFormatter
- def initialize(out=nil)
- super
+ def initialize(out = nil)
+ super(out)
@describe_name = nil
@describe_time = nil
@@ -12,59 +12,7 @@ class ProfileFormatter < DottedFormatter
end
def register
- super
- MSpec.register :enter, self
- end
-
- # Callback for the MSpec :enter event. Prints the
- # +describe+ block string.
- def enter(describe)
- if @describe_time
- @describes << [@describe_name, Time.now.to_f - @describe_time]
- end
-
- @describe_name = describe
- @describe_time = Time.now.to_f
- end
-
- # Callback for the MSpec :before event. Prints the
- # +it+ block string.
- def before(state)
- super
-
- @it_name = state.it
- @it_time = Time.now.to_f
- end
-
- # Callback for the MSpec :after event. Prints a
- # newline to finish the description string output.
- def after(state)
- @its << [@describe_name, @it_name, Time.now.to_f - @it_time]
- super
- end
-
- def finish
- puts "\nProfiling info:"
-
- desc = @describes.sort { |a,b| b.last <=> a.last }
- desc.delete_if { |a| a.last <= 0.001 }
- show = desc[0, 100]
-
- puts "Top #{show.size} describes:"
-
- show.each do |des, time|
- printf "%3.3f - %s\n", time, des
- end
-
- its = @its.sort { |a,b| b.last <=> a.last }
- its.delete_if { |a| a.last <= 0.001 }
- show = its[0, 100]
-
- puts "\nTop #{show.size} its:"
- show.each do |des, it, time|
- printf "%3.3f - %s %s\n", time, des, it
- end
-
+ (@profile = ProfileAction.new).register
super
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/specdoc.rb b/spec/mspec/lib/mspec/runner/formatters/specdoc.rb
index 29adde3c5c..d3a5c3d729 100644
--- a/spec/mspec/lib/mspec/runner/formatters/specdoc.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/specdoc.rb
@@ -1,7 +1,6 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class SpecdocFormatter < DottedFormatter
+class SpecdocFormatter < BaseFormatter
def register
super
MSpec.register :enter, self
@@ -16,7 +15,7 @@ class SpecdocFormatter < DottedFormatter
# Callback for the MSpec :before event. Prints the
# +it+ block string.
def before(state)
- super
+ super(state)
print "- #{state.it}"
end
@@ -25,17 +24,18 @@ class SpecdocFormatter < DottedFormatter
# the sequential number of the exception raised. If
# there has already been an exception raised while
# evaluating this example, it prints another +it+
- # block description string so that each discription
+ # block description string so that each description
# string has an associated 'ERROR' or 'FAILED'
def exception(exception)
print "\n- #{exception.it}" if exception?
- super
+ super(exception)
print " (#{exception.failure? ? 'FAILED' : 'ERROR'} - #{@count})"
end
# Callback for the MSpec :after event. Prints a
# newline to finish the description string output.
- def after(state)
+ def after(state = nil)
+ super(state)
print "\n"
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/spinner.rb b/spec/mspec/lib/mspec/runner/formatters/spinner.rb
index f6f35cc476..817d8c02be 100644
--- a/spec/mspec/lib/mspec/runner/formatters/spinner.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/spinner.rb
@@ -1,14 +1,13 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class SpinnerFormatter < DottedFormatter
+class SpinnerFormatter < BaseFormatter
attr_reader :length
Spins = %w!| / - \\!
HOUR = 3600
MIN = 60
- def initialize(out=nil)
+ def initialize(out = nil)
super(nil)
@which = 0
@@ -28,7 +27,6 @@ class SpinnerFormatter < DottedFormatter
MSpec.register :start, self
MSpec.register :unload, self
- MSpec.unregister :before, self
end
def length=(length)
@@ -80,7 +78,7 @@ class SpinnerFormatter < DottedFormatter
# Callback for the MSpec :start event. Stores the total
# number of files that will be processed.
def start
- @total = MSpec.retrieve(:files).size
+ @total = MSpec.files_array.size
compute_progress
print progress_line
end
@@ -102,16 +100,12 @@ class SpinnerFormatter < DottedFormatter
clear_progress_line
print_exception(exception, @count)
+ exceptions.clear
end
# Callback for the MSpec :after event. Updates the spinner.
- def after(state)
+ def after(state = nil)
+ super(state)
print progress_line
end
-
- def finish(printed_exceptions = true)
- # We already printed the exceptions
- @exceptions = [] if printed_exceptions
- super()
- end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/stats.rb b/spec/mspec/lib/mspec/runner/formatters/stats.rb
new file mode 100644
index 0000000000..8cff96d145
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/formatters/stats.rb
@@ -0,0 +1,57 @@
+require 'mspec/runner/formatters/base'
+
+class StatsPerFileFormatter < BaseFormatter
+ def initialize(out = nil)
+ super(out)
+ @data = {}
+ @root = File.expand_path(MSpecScript.get(:prefix) || '.')
+ end
+
+ def register
+ super
+ MSpec.register :load, self
+ MSpec.register :unload, self
+ end
+
+ # Resets the tallies so the counts are only for this file.
+ def load
+ tally.counter.examples = 0
+ tally.counter.errors = 0
+ tally.counter.failures = 0
+ tally.counter.tagged = 0
+ end
+
+ def unload
+ file = format_file MSpec.file
+
+ raise if @data.key?(file)
+ @data[file] = {
+ examples: tally.counter.examples,
+ errors: tally.counter.errors,
+ failures: tally.counter.failures,
+ tagged: tally.counter.tagged,
+ }
+ end
+
+ def finish
+ width = @data.keys.max_by(&:size).size
+ f = "%3d"
+ @data.each_pair do |file, data|
+ total = data[:examples]
+ passing = total - data[:errors] - data[:failures] - data[:tagged]
+ puts "#{file.ljust(width)} #{f % passing}/#{f % total}"
+ end
+
+ require 'yaml'
+ yaml = YAML.dump(@data)
+ File.write "results-#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}.yml", yaml
+ end
+
+ private def format_file(file)
+ if file.start_with?(@root)
+ file[@root.size+1..-1]
+ else
+ raise file
+ end
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/formatters/summary.rb b/spec/mspec/lib/mspec/runner/formatters/summary.rb
index 0c9207194c..41819d2158 100644
--- a/spec/mspec/lib/mspec/runner/formatters/summary.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/summary.rb
@@ -1,11 +1,4 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class SummaryFormatter < DottedFormatter
- # Callback for the MSpec :after event. Overrides the
- # callback provided by +DottedFormatter+ and does not
- # print any output for each example evaluated.
- def after(state)
- # do nothing
- end
+class SummaryFormatter < BaseFormatter
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/unit.rb b/spec/mspec/lib/mspec/runner/formatters/unit.rb
index cebc18a49b..d03ae79e9f 100644
--- a/spec/mspec/lib/mspec/runner/formatters/unit.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/unit.rb
@@ -1,4 +1,3 @@
-require 'mspec/expectations/expectations'
require 'mspec/runner/formatters/dotted'
class UnitdiffFormatter < DottedFormatter
diff --git a/spec/mspec/lib/mspec/runner/formatters/yaml.rb b/spec/mspec/lib/mspec/runner/formatters/yaml.rb
index 090a9b1b9d..6c05cc902f 100644
--- a/spec/mspec/lib/mspec/runner/formatters/yaml.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/yaml.rb
@@ -1,8 +1,7 @@
-require 'mspec/expectations/expectations'
-require 'mspec/runner/formatters/dotted'
+require 'mspec/runner/formatters/base'
-class YamlFormatter < DottedFormatter
- def initialize(out=nil)
+class YamlFormatter < BaseFormatter
+ def initialize(out = nil)
super(nil)
if out.nil?
@@ -16,9 +15,6 @@ class YamlFormatter < DottedFormatter
@out = @finish
end
- def after(state)
- end
-
def finish
switch
diff --git a/spec/mspec/lib/mspec/runner/mspec.rb b/spec/mspec/lib/mspec/runner/mspec.rb
index cfc11840ac..0e016c67a7 100644
--- a/spec/mspec/lib/mspec/runner/mspec.rb
+++ b/spec/mspec/lib/mspec/runner/mspec.rb
@@ -10,7 +10,6 @@ class MSpecEnv
end
module MSpec
-
@exit = nil
@abort = nil
@start = nil
@@ -20,26 +19,35 @@ module MSpec
@after = nil
@leave = nil
@finish = nil
- @exclude = nil
- @include = nil
+ @exclude = []
+ @include = []
@leave = nil
@load = nil
@unload = nil
@tagged = nil
@current = nil
+ @passed = nil
@example = nil
@modes = []
@shared = {}
@guarded = []
@features = {}
@exception = nil
- @randomize = nil
- @repeat = nil
+ @randomize = false
+ @repeat = 1
@expectation = nil
@expectations = false
+ @skips = []
+ @subprocesses = []
+
+ class << self
+ attr_reader :file, :include, :exclude, :skips, :subprocesses
+ attr_writer :repeat, :randomize
+ attr_accessor :formatter
+ end
- def self.describe(mod, options=nil, &block)
- state = ContextState.new mod, options
+ def self.describe(description, options = nil, &block)
+ state = ContextState.new description, options
state.parent = current
MSpec.register_current state
@@ -57,6 +65,10 @@ module MSpec
actions :finish
end
+ def self.files_array
+ @files
+ end
+
def self.each_file(&block)
if ENV["MSPEC_MULTI"]
while file = STDIN.gets
@@ -74,7 +86,7 @@ module MSpec
# The parent closed the connection without QUIT
abort "the parent did not send QUIT"
else
- return unless files = retrieve(:files)
+ return unless files = @files
shuffle files if randomize?
files.each(&block)
end
@@ -83,10 +95,11 @@ module MSpec
def self.files
each_file do |file|
setup_env
- store :file, file
+ @file = file
actions :load
protect("loading #{file}") { Kernel.load file }
actions :unload
+ raise "#{file} was executed but did not reset the current example: #{@current}" if @current
end
end
@@ -101,11 +114,14 @@ module MSpec
def self.protect(location, &block)
begin
- @env.instance_eval(&block)
+ @env.instance_exec(&block)
return true
rescue SystemExit => e
raise e
- rescue Exception => exc
+ rescue SkippedSpecError => e
+ @skips << [e, block]
+ return false
+ rescue Object => exc
register_exit 1
actions :exception, ExceptionState.new(current && current.state, location, exc)
return false
@@ -128,22 +144,24 @@ module MSpec
# Sets the toplevel ContextState to +state+.
def self.register_current(state)
- store :current, state
+ @current = state
end
# Sets the toplevel ContextState to +nil+.
def self.clear_current
- store :current, nil
+ @current = nil
end
# Returns the toplevel ContextState.
def self.current
- retrieve :current
+ @current
end
# Stores the shared ContextState keyed by description.
def self.register_shared(state)
- @shared[state.to_s] = state
+ name = state.to_s
+ raise "duplicated shared #describe: #{name}" if @shared.key?(name)
+ @shared[name] = state
end
# Returns the shared ContextState matching description.
@@ -153,17 +171,17 @@ module MSpec
# Stores the exit code used by the runner scripts.
def self.register_exit(code)
- store :exit, code
+ @exit = code
end
# Retrieves the stored exit code.
def self.exit_code
- retrieve(:exit).to_i
+ @exit.to_i
end
# Stores the list of files to be evaluated.
def self.register_files(files)
- store :files, files
+ @files = files
end
# Stores one or more substitution patterns for transforming
@@ -174,7 +192,7 @@ module MSpec
#
# See also +tags_file+.
def self.register_tags_patterns(patterns)
- store :tags_patterns, patterns
+ @tags_patterns = patterns
end
# Registers an operating mode. Modes recognized by MSpec:
@@ -185,30 +203,30 @@ module MSpec
# :report - specs that are guarded are reported
# :unguarded - all guards are forced off
def self.register_mode(mode)
- modes = retrieve :modes
+ modes = @modes
modes << mode unless modes.include? mode
end
# Clears all registered modes.
def self.clear_modes
- store :modes, []
+ @modes = []
end
# Returns +true+ if +mode+ is registered.
def self.mode?(mode)
- retrieve(:modes).include? mode
+ @modes.include? mode
end
def self.enable_feature(feature)
- retrieve(:features)[feature] = true
+ @features[feature] = true
end
def self.disable_feature(feature)
- retrieve(:features)[feature] = false
+ @features[feature] = false
end
def self.feature_enabled?(feature)
- retrieve(:features)[feature] || false
+ @features[feature] || false
end
def self.retrieve(symbol)
@@ -227,6 +245,7 @@ module MSpec
# :before before a single spec is run
# :add while a describe block is adding examples to run later
# :expectation before a 'should', 'should_receive', etc.
+ # :passed after an example block is run and passes, passed the block, run before :example action
# :example after an example block is run, passed the block
# :exception after an exception is rescued
# :after after a single spec is run
@@ -257,21 +276,17 @@ module MSpec
end
end
- def self.randomize(flag=true)
- @randomize = flag
- end
-
def self.randomize?
- @randomize == true
- end
-
- def self.repeat=(times)
- @repeat = times
+ @randomize
end
def self.repeat
- (@repeat || 1).times do
+ if @repeat == 1
yield
+ else
+ @repeat.times do
+ yield
+ end
end
end
@@ -287,17 +302,17 @@ module MSpec
# Records that an expectation has been encountered in an example.
def self.expectation
- store :expectations, true
+ @expectations = true
end
# Returns true if an expectation has been encountered
def self.expectation?
- retrieve :expectations
+ @expectations
end
# Resets the flag that an expectation has been encountered in an example.
def self.clear_expectations
- store :expectations, false
+ @expectations = false
end
# Transforms a spec filename into a tags filename by applying each
@@ -311,9 +326,9 @@ module MSpec
#
# See also +register_tags_patterns+.
def self.tags_file
- patterns = retrieve(:tags_patterns) ||
+ patterns = @tags_patterns ||
[[%r(spec/), 'spec/tags/'], [/_spec.rb$/, '_tags.txt']]
- patterns.inject(retrieve(:file).dup) do |file, pattern|
+ patterns.inject(@file.dup) do |file, pattern|
file.gsub(*pattern)
end
end
@@ -350,6 +365,7 @@ module MSpec
# Writes each tag in +tags+ to the tag file. Overwrites the
# tag file if it exists.
def self.write_tags(tags)
+ return delete_tags if tags.empty?
file = tags_file
make_tag_dir(file)
File.open(file, "w:utf-8") do |f|
@@ -381,7 +397,7 @@ module MSpec
desc = tag.escape(tag.description)
file = tags_file
if File.exist? file
- lines = IO.readlines(file)
+ lines = File.readlines(file)
File.open(file, "w:utf-8") do |f|
lines.each do |line|
line = line.chomp
diff --git a/spec/mspec/lib/mspec/runner/object.rb b/spec/mspec/lib/mspec/runner/object.rb
index 2ea8197165..58d98cc4df 100644
--- a/spec/mspec/lib/mspec/runner/object.rb
+++ b/spec/mspec/lib/mspec/runner/object.rb
@@ -1,18 +1,18 @@
class Object
- private def before(at=:each, &block)
+ private def before(at = :each, &block)
MSpec.current.before at, &block
end
- private def after(at=:each, &block)
+ private def after(at = :each, &block)
MSpec.current.after at, &block
end
- private def describe(mod, msg=nil, options=nil, &block)
- MSpec.describe mod, msg, &block
+ private def describe(description, options = nil, &block)
+ MSpec.describe description, options, &block
end
- private def it(msg, &block)
- MSpec.current.it msg, &block
+ private def it(desc, &block)
+ MSpec.current.it desc, &block
end
private def it_should_behave_like(desc)
diff --git a/spec/mspec/lib/mspec/runner/parallel.rb b/spec/mspec/lib/mspec/runner/parallel.rb
index 7428b33682..6a9ecd155d 100644
--- a/spec/mspec/lib/mspec/runner/parallel.rb
+++ b/spec/mspec/lib/mspec/runner/parallel.rb
@@ -15,7 +15,7 @@ class ParallelRunner
@output_files << name
env = {
- "SPEC_TEMP_DIR" => "rubyspec_temp_#{i}",
+ "SPEC_TEMP_DIR" => "#{SPEC_TEMP_DIR}_#{i}",
"MSPEC_MULTI" => i.to_s
}
command = @argv + ["-fy", "-o", name]
diff --git a/spec/mspec/lib/mspec/runner/shared.rb b/spec/mspec/lib/mspec/runner/shared.rb
index b606de473b..283711c1d7 100644
--- a/spec/mspec/lib/mspec/runner/shared.rb
+++ b/spec/mspec/lib/mspec/runner/shared.rb
@@ -1,10 +1,14 @@
require 'mspec/runner/mspec'
-def it_behaves_like(desc, meth, obj=nil)
- send :before, :all do
+def it_behaves_like(desc, meth, obj = nil)
+ before :all do
@method = meth
@object = obj
end
+ after :all do
+ @method = nil
+ @object = nil
+ end
- send :it_should_behave_like, desc.to_s
+ it_should_behave_like desc.to_s
end
diff --git a/spec/mspec/lib/mspec/runner/tag.rb b/spec/mspec/lib/mspec/runner/tag.rb
index e2275ad3a6..820df9159e 100644
--- a/spec/mspec/lib/mspec/runner/tag.rb
+++ b/spec/mspec/lib/mspec/runner/tag.rb
@@ -1,7 +1,7 @@
class SpecTag
attr_accessor :tag, :comment, :description
- def initialize(string=nil)
+ def initialize(string = nil)
parse(string) if string
end
diff --git a/spec/mspec/lib/mspec/utils/format.rb b/spec/mspec/lib/mspec/utils/format.rb
new file mode 100644
index 0000000000..425dd4d11c
--- /dev/null
+++ b/spec/mspec/lib/mspec/utils/format.rb
@@ -0,0 +1,24 @@
+# If the implementation on which the specs are run cannot
+# load pp from the standard library, add a pp.rb file that
+# defines the #pretty_inspect method on Object or Kernel.
+begin
+ require 'pp'
+rescue LoadError
+ module Kernel
+ def pretty_inspect
+ inspect
+ end
+ end
+end
+
+module MSpec
+ def self.format(obj)
+ if String === obj and obj.include?("\n")
+ "\n#{obj.inspect.gsub('\n', "\n")}"
+ else
+ obj.pretty_inspect.chomp
+ end
+ rescue => e
+ "#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
+ end
+end
diff --git a/spec/mspec/lib/mspec/utils/name_map.rb b/spec/mspec/lib/mspec/utils/name_map.rb
index a93b0d001e..9b04112e2e 100644
--- a/spec/mspec/lib/mspec/utils/name_map.rb
+++ b/spec/mspec/lib/mspec/utils/name_map.rb
@@ -51,7 +51,11 @@ class NameMap
SpecVersion
]
- def initialize(filter=false)
+ ALWAYS_PRIVATE = %w[
+ initialize initialize_copy initialize_clone initialize_dup respond_to_missing?
+ ].map(&:to_sym)
+
+ def initialize(filter = false)
@seen = {}
@filter = filter
end
@@ -62,10 +66,17 @@ class NameMap
end
def class_or_module(c)
- const = Object.const_get(c, false)
+ begin
+ const = Object.const_get(c, false)
+ rescue NameError, RuntimeError
+ # Either the constant doesn't exist or it is
+ # explicitly raising an error, like `SortedSet`.
+ return nil
+ end
+ return nil unless Module === const
+
filtered = @filter && EXCLUDED.include?(const.name)
- return const if Module === const and !filtered
- rescue NameError
+ return const unless filtered
end
def namespace(mod, const)
@@ -73,7 +84,7 @@ class NameMap
"#{mod}::#{const}"
end
- def map(hash, constants, mod=nil)
+ def map(hash, constants, mod = nil)
@seen = {} unless mod
constants.each do |const|
@@ -86,7 +97,8 @@ class NameMap
hash["#{name}."] = ms.sort unless ms.empty?
ms = m.public_instance_methods(false) +
- m.protected_instance_methods(false)
+ m.protected_instance_methods(false) +
+ (m.private_instance_methods(false) & ALWAYS_PRIVATE)
ms.map! { |x| x.to_s }
hash["#{name}#"] = ms.sort unless ms.empty?
diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb
index 9f8dd01dbf..adeafa1f81 100644
--- a/spec/mspec/lib/mspec/utils/options.rb
+++ b/spec/mspec/lib/mspec/utils/options.rb
@@ -32,9 +32,13 @@ class MSpecOptions
# Raised if an unrecognized option is encountered.
class ParseError < Exception; end
+ class << self
+ attr_accessor :latest
+ end
+
attr_accessor :config, :banner, :width, :options
- def initialize(banner="", width=30, config=nil)
+ def initialize(banner = "", width = 30, config = nil)
@banner = banner
@config = config
@width = width
@@ -46,7 +50,7 @@ class MSpecOptions
@extra << x
}
- yield self if block_given?
+ MSpecOptions.latest = self
end
# Registers an option. Acceptable formats for arguments are:
@@ -94,7 +98,7 @@ class MSpecOptions
@options.find { |o| o.match? opt }
end
- # Processes an option. Calles the #on_extra block (or default) for
+ # Processes an option. Calls the #on_extra block (or default) for
# unrecognized options. For registered options, possibly fetches an
# argument and invokes the option's block if it is not nil.
def process(argv, entry, opt, arg)
@@ -123,7 +127,7 @@ class MSpecOptions
# Parses an array of command line entries, calling blocks for
# registered options.
- def parse(argv=ARGV)
+ def parse(argv = ARGV)
argv = Array(argv).dup
while entry = argv.shift
@@ -200,6 +204,13 @@ class MSpecOptions
"Load FILE containing configuration options", &block)
end
+ def env
+ on("--env", "KEY=VALUE", "Set environment variable") do |env|
+ key, value = env.split('=', 2)
+ ENV[key] = value
+ end
+ end
+
def targets
on("-t", "--target", "TARGET",
"Implementation to run the specs, where TARGET is:") do |t|
@@ -274,6 +285,8 @@ class MSpecOptions
config[:formatter] = SpinnerFormatter
when 't', 'method'
config[:formatter] = MethodFormatter
+ when 'e', 'stats'
+ config[:formatter] = StatsPerFileFormatter
when 'y', 'yaml'
config[:formatter] = YamlFormatter
when 'p', 'profile'
@@ -281,7 +294,7 @@ class MSpecOptions
when 'j', 'junit'
config[:formatter] = JUnitFormatter
else
- abort "Unknown format: #{o}\n#{@parser}" unless File.exist?(o)
+ abort "Unknown format: #{o}" unless File.exist?(o)
require File.expand_path(o)
if Object.const_defined?(:CUSTOM_MSPEC_FORMATTER)
config[:formatter] = CUSTOM_MSPEC_FORMATTER
@@ -300,6 +313,7 @@ class MSpecOptions
doc " m, summary SummaryFormatter"
doc " a, *, spin SpinnerFormatter"
doc " t, method MethodFormatter"
+ doc " e, stats StatsPerFileFormatter"
doc " y, yaml YamlFormatter"
doc " p, profile ProfileFormatter"
doc " j, junit JUnitFormatter\n"
@@ -308,6 +322,11 @@ class MSpecOptions
"Write formatter output to FILE") do |f|
config[:output] = f
end
+
+ on("--error-output", "FILE",
+ "Write error output of failing specs to FILE, or $stderr if value is 'stderr'.") do |f|
+ config[:error_output] = f
+ end
end
def filters
@@ -377,14 +396,14 @@ class MSpecOptions
def randomize
on("-H", "--random",
"Randomize the list of spec files") do
- MSpec.randomize
+ MSpec.randomize = true
end
end
def repeat
on("-R", "--repeat", "NUMBER",
"Repeatedly run an example NUMBER times") do |o|
- MSpec.repeat = o.to_i
+ MSpec.repeat = Integer(o)
end
end
@@ -392,11 +411,11 @@ class MSpecOptions
on("-V", "--verbose", "Output the name of each file processed") do
obj = Object.new
def obj.start
- @width = MSpec.retrieve(:files).inject(0) { |max, f| f.size > max ? f.size : max }
+ @width = MSpec.files_array.inject(0) { |max, f| f.size > max ? f.size : max }
end
def obj.load
- file = MSpec.retrieve :file
- STDERR.print "\n#{file.ljust(@width)}"
+ file = MSpec.file
+ STDERR.print "\n#{file.ljust(@width)}\n"
end
MSpec.register :start, obj
MSpec.register :load, obj
@@ -411,14 +430,26 @@ class MSpecOptions
end
MSpec.register :load, obj
end
+
+ on("--print-skips", "Print skips") do
+ config[:print_skips] = true
+ end
end
def interrupt
- on("--int-spec", "Control-C interupts the current spec only") do
+ on("--int-spec", "Control-C interrupts the current spec only") do
config[:abort] = false
end
end
+ def timeout
+ on("--timeout", "TIMEOUT", "Abort if a spec takes longer than TIMEOUT seconds") do |timeout|
+ require 'mspec/runner/actions/timeout'
+ timeout = Float(timeout)
+ TimeoutAction.new(timeout).register
+ end
+ end
+
def verify
on("--report-on", "GUARD", "Report specs guarded by GUARD") do |g|
MSpec.register_mode :report_on
@@ -453,15 +484,22 @@ class MSpecOptions
def debug
on("-d", "--debug",
- "Set MSpec debugging flag for more verbose output") do
+ "Disable MSpec backtrace filtering") do
$MSPEC_DEBUG = true
end
end
+ def launchable
+ on("--launchable-test-reports", "DIR",
+ "DIR The directory for reporting test results in Launchable JSON format") do |o|
+ require 'mspec/runner/formatters/launchable'
+ config[:launchable] = LaunchableFormatter.setDir(o)
+ end
+ end
+
def all
- # Generated with:
- # puts File.read(__FILE__).scan(/def (\w+).*\n\s*on\(/)
configure {}
+ env
targets
formatters
filters
@@ -473,9 +511,11 @@ class MSpecOptions
repeat
verbose
interrupt
+ timeout
verify
action_filters
actions
debug
+ launchable
end
end
diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb
index 2816618b0f..15fd23fabf 100644
--- a/spec/mspec/lib/mspec/utils/script.rb
+++ b/spec/mspec/lib/mspec/utils/script.rb
@@ -3,7 +3,6 @@ require 'mspec/guards/version'
require 'mspec/utils/warnings'
# MSpecScript provides a skeleton for all the MSpec runner scripts.
-
class MSpecScript
# Returns the config object. Maintained at the class
# level to easily enable simple config files. See the
@@ -38,10 +37,19 @@ class MSpecScript
config[key]
end
+ class << self
+ attr_accessor :child_process
+ end
+
+ # True if the current process is the one going to run the specs with `MSpec.process`.
+ # False for e.g. `mspec` which exec's to `mspec-run`.
+ # This is useful in .mspec config files.
+ def self.child_process?
+ MSpecScript.child_process
+ end
+
def initialize
- ruby_version_is ""..."2.3" do
- abort "MSpec needs Ruby 2.3 or more recent"
- end
+ check_version!
config[:formatter] = nil
config[:includes] = []
@@ -125,14 +133,9 @@ class MSpecScript
require 'mspec/runner/formatters/file'
require 'mspec/runner/filters'
- if config[:formatter].nil?
- config[:formatter] = STDOUT.tty? ? SpinnerFormatter : @files.size < 50 ? DottedFormatter : FileFormatter
- end
-
- if config[:formatter]
- formatter = config[:formatter].new(config[:output])
+ if formatter = config_formatter
formatter.register
- MSpec.store :formatter, formatter
+ MSpec.formatter = formatter
end
MatchFilter.new(:include, *config[:includes]).register unless config[:includes].empty?
@@ -149,6 +152,23 @@ class MSpecScript
custom_register
end
+ # Makes a formatter specified by :formatter option.
+ def config_formatter
+ if config[:formatter].nil?
+ config[:formatter] = STDOUT.tty? ? SpinnerFormatter : @files.size < 50 ? DottedFormatter : FileFormatter
+ end
+
+ if config[:formatter]
+ config[:formatter] = config[:formatter].new(config[:output])
+ end
+
+ if config[:launchable]
+ config[:formatter].extend config[:launchable]
+ end
+
+ config[:formatter]
+ end
+
# Callback for enabling custom actions, etc. This version is a
# no-op. Provide an implementation specific version in a config
# file. Called by #register.
@@ -191,7 +211,7 @@ class MSpecScript
patterns.each do |pattern|
begin
expanded = File.realpath(pattern)
- rescue Errno::ENOENT
+ rescue Errno::ENOENT, Errno::ENOTDIR
next
end
if File.file?(expanded) && expanded.end_with?('.rb')
@@ -264,10 +284,11 @@ class MSpecScript
# Instantiates an instance and calls the series of methods to
# invoke the script.
- def self.main
+ def self.main(child_process = true)
+ MSpecScript.child_process = child_process
+
script = new
script.load_default
- script.try_load '~/.mspecrc'
script.options
script.signals
script.register
@@ -275,4 +296,10 @@ class MSpecScript
require 'mspec'
script.run
end
+
+ private def check_version!
+ ruby_version_is ""..."2.6" do
+ warn "MSpec is supported for Ruby 2.6 and above only"
+ end
+ end
end
diff --git a/spec/mspec/lib/mspec/utils/version.rb b/spec/mspec/lib/mspec/utils/version.rb
index 787a76b053..9c1c58b8df 100644
--- a/spec/mspec/lib/mspec/utils/version.rb
+++ b/spec/mspec/lib/mspec/utils/version.rb
@@ -42,7 +42,7 @@ class SpecVersion
def <=>(other)
if other.respond_to? :to_int
- other = Integer other
+ other = Integer(other.to_int)
else
other = SpecVersion.new(String(other)).to_i
end
diff --git a/spec/mspec/lib/mspec/utils/warnings.rb b/spec/mspec/lib/mspec/utils/warnings.rb
index 4d23474236..23efc696a5 100644
--- a/spec/mspec/lib/mspec/utils/warnings.rb
+++ b/spec/mspec/lib/mspec/utils/warnings.rb
@@ -1,61 +1,10 @@
require 'mspec/guards/version'
-if RUBY_ENGINE == "ruby" and ruby_version_is("2.4")
- ruby_version_is "2.4"..."2.5" do
- # Kernel#warn does not delegate to Warning.warn in 2.4
- module Kernel
- remove_method :warn
- def warn(*messages)
- return if $VERBOSE == nil or messages.empty?
- msg = messages.join("\n")
- msg += "\n" unless msg.end_with?("\n")
- Warning.warn(msg)
- end
- private :warn
- end
- end
-
- def Warning.warn(message)
- if Thread.current[:in_mspec_complain_matcher]
- return $stderr.write(message)
- end
-
- case message
- # $VERBOSE = true warnings
- when /(.+\.rb):(\d+):.+possibly useless use of (<|<=|==|>=|>) in void context/
- # Make sure there is a .should otherwise it is missing
- line_nb = Integer($2)
- unless File.exist?($1) and /\.should(_not)? (<|<=|==|>=|>)/ === File.readlines($1)[line_nb-1]
- $stderr.write message
- end
- when /possibly useless use of (\+|-) in void context/
- when /assigned but unused variable/
- when /method redefined/
- when /previous definition of/
- when /instance variable @.+ not initialized/
- when /statement not reached/
- when /shadowing outer local variable/
- when /setting Encoding.default_(in|ex)ternal/
- when /unknown (un)?pack directive/
- when /(un)?trust(ed\?)? is deprecated/
- when /\.exists\? is a deprecated name/
- when /Float .+ out of range/
- when /passing a block to String#(bytes|chars|codepoints|lines) is deprecated/
- when /core\/string\/modulo_spec\.rb:\d+: warning: too many arguments for format string/
- when /regexp\/shared\/new_ascii(_8bit)?\.rb:\d+: warning: Unknown escape .+ is ignored/
-
- # $VERBOSE = false warnings
- when /constant ::(Fixnum|Bignum) is deprecated/
- when /\/(argf|io|stringio)\/.+(ARGF|IO)#(lines|chars|bytes|codepoints) is deprecated/
- when /Thread\.exclusive is deprecated.+\n.+thread\/exclusive_spec\.rb/
- when /hash\/shared\/index\.rb:\d+: warning: Hash#index is deprecated; use Hash#key/
- when /env\/shared\/key\.rb:\d+: warning: ENV\.index is deprecated; use ENV\.key/
- when /exponent(_spec)?\.rb:\d+: warning: in a\*\*b, b may be too big/
- when /enumerator\/(new|initialize_spec)\.rb:\d+: warning: Enumerator\.new without a block is deprecated/
- else
- $stderr.write message
- end
- end
-else
- $VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
+# Always enable deprecation warnings when running MSpec, as ruby/spec tests for them,
+# and like in most test frameworks, deprecation warnings should be enabled by default,
+# so that deprecations are noticed before the breaking change.
+# Disable experimental warnings, we want to test new experimental features in ruby/spec.
+if Object.const_defined?(:Warning) and Warning.respond_to?(:[]=)
+ Warning[:deprecated] = true
+ Warning[:experimental] = false
end
diff --git a/spec/mspec/spec/commands/mkspec_spec.rb b/spec/mspec/spec/commands/mkspec_spec.rb
index 1b959dcb78..32262723de 100644
--- a/spec/mspec/spec/commands/mkspec_spec.rb
+++ b/spec/mspec/spec/commands/mkspec_spec.rb
@@ -1,18 +1,18 @@
require 'spec_helper'
require 'mspec/commands/mkspec'
+require 'fileutils'
-
-describe "The -c, --constant CONSTANT option" do
+RSpec.describe "The -c, --constant CONSTANT option" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MkSpec.new
@config = @script.config
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-c", "--constant", "CONSTANT",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-c", "--constant", "CONSTANT",
an_instance_of(String))
@script.options []
end
@@ -21,22 +21,22 @@ describe "The -c, --constant CONSTANT option" do
["-c", "--constant"].each do |opt|
@config[:constants] = []
@script.options [opt, "Object"]
- @config[:constants].should include("Object")
+ expect(@config[:constants]).to include("Object")
end
end
end
-describe "The -b, --base DIR option" do
+RSpec.describe "The -b, --base DIR option" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MkSpec.new
@config = @script.config
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-b", "--base", "DIR",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-b", "--base", "DIR",
an_instance_of(String))
@script.options []
end
@@ -45,22 +45,22 @@ describe "The -b, --base DIR option" do
["-b", "--base"].each do |opt|
@config[:base] = nil
@script.options [opt, "superspec"]
- @config[:base].should == File.expand_path("superspec")
+ expect(@config[:base]).to eq(File.expand_path("superspec"))
end
end
end
-describe "The -r, --require LIBRARY option" do
+RSpec.describe "The -r, --require LIBRARY option" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MkSpec.new
@config = @script.config
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-r", "--require", "LIBRARY",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-r", "--require", "LIBRARY",
an_instance_of(String))
@script.options []
end
@@ -69,22 +69,22 @@ describe "The -r, --require LIBRARY option" do
["-r", "--require"].each do |opt|
@config[:requires] = []
@script.options [opt, "libspec"]
- @config[:requires].should include("libspec")
+ expect(@config[:requires]).to include("libspec")
end
end
end
-describe "The -V, --version-guard VERSION option" do
+RSpec.describe "The -V, --version-guard VERSION option" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MkSpec.new
@config = @script.config
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-V", "--version-guard", "VERSION",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-V", "--version-guard", "VERSION",
an_instance_of(String))
@script.options []
end
@@ -93,150 +93,150 @@ describe "The -V, --version-guard VERSION option" do
["-r", "--require"].each do |opt|
@config[:requires] = []
@script.options [opt, "libspec"]
- @config[:requires].should include("libspec")
+ expect(@config[:requires]).to include("libspec")
end
end
end
-describe MkSpec, "#options" do
+RSpec.describe MkSpec, "#options" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MkSpec.new
end
it "parses the command line options" do
- @options.should_receive(:parse).with(["--this", "and", "--that"])
+ expect(@options).to receive(:parse).with(["--this", "and", "--that"])
@script.options ["--this", "and", "--that"]
end
it "parses ARGV unless passed other options" do
- @options.should_receive(:parse).with(ARGV)
+ expect(@options).to receive(:parse).with(ARGV)
@script.options
end
it "prints help and exits if passed an unrecognized option" do
- @options.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String))
- @options.stub(:puts)
- @options.stub(:exit)
+ expect(@options).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String))
+ allow(@options).to receive(:puts)
+ allow(@options).to receive(:exit)
@script.options ["--iunknown"]
end
end
-describe MkSpec, "#create_directory" do
+RSpec.describe MkSpec, "#create_directory" do
before :each do
@script = MkSpec.new
@script.config[:base] = "spec"
end
it "prints a warning if a file with the directory name exists" do
- File.should_receive(:exist?).and_return(true)
- File.should_receive(:directory?).and_return(false)
- FileUtils.should_not_receive(:mkdir_p)
- @script.should_receive(:puts).with("spec/class already exists and is not a directory.")
- @script.create_directory("Class").should == nil
+ expect(File).to receive(:exist?).and_return(true)
+ expect(File).to receive(:directory?).and_return(false)
+ expect(FileUtils).not_to receive(:mkdir_p)
+ expect(@script).to receive(:puts).with("spec/class already exists and is not a directory.")
+ expect(@script.create_directory("Class")).to eq(nil)
end
it "does nothing if the directory already exists" do
- File.should_receive(:exist?).and_return(true)
- File.should_receive(:directory?).and_return(true)
- FileUtils.should_not_receive(:mkdir_p)
- @script.create_directory("Class").should == "spec/class"
+ expect(File).to receive(:exist?).and_return(true)
+ expect(File).to receive(:directory?).and_return(true)
+ expect(FileUtils).not_to receive(:mkdir_p)
+ expect(@script.create_directory("Class")).to eq("spec/class")
end
it "creates the directory if it does not exist" do
- File.should_receive(:exist?).and_return(false)
- @script.should_receive(:mkdir_p).with("spec/class")
- @script.create_directory("Class").should == "spec/class"
+ expect(File).to receive(:exist?).and_return(false)
+ expect(@script).to receive(:mkdir_p).with("spec/class")
+ expect(@script.create_directory("Class")).to eq("spec/class")
end
it "creates the directory for a namespaced module if it does not exist" do
- File.should_receive(:exist?).and_return(false)
- @script.should_receive(:mkdir_p).with("spec/struct/tms")
- @script.create_directory("Struct::Tms").should == "spec/struct/tms"
+ expect(File).to receive(:exist?).and_return(false)
+ expect(@script).to receive(:mkdir_p).with("spec/struct/tms")
+ expect(@script.create_directory("Struct::Tms")).to eq("spec/struct/tms")
end
end
-describe MkSpec, "#write_requires" do
+RSpec.describe MkSpec, "#write_requires" do
before :each do
@script = MkSpec.new
@script.config[:base] = "spec"
@file = double("file")
- File.stub(:open).and_yield(@file)
+ allow(File).to receive(:open).and_yield(@file)
end
it "writes the spec_helper require line" do
- @file.should_receive(:puts).with("require_relative '../../../spec_helper'")
+ expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'")
@script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb")
end
it "writes require lines for each library specified on the command line" do
- @file.stub(:puts)
- @file.should_receive(:puts).with("require_relative '../../../spec_helper'")
- @file.should_receive(:puts).with("require 'complex'")
+ allow(@file).to receive(:puts)
+ expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'")
+ expect(@file).to receive(:puts).with("require 'complex'")
@script.config[:requires] << 'complex'
@script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb")
end
end
-describe MkSpec, "#write_spec" do
+RSpec.describe MkSpec, "#write_spec" do
before :each do
@file = IOStub.new
- File.stub(:open).and_yield(@file)
+ allow(File).to receive(:open).and_yield(@file)
@script = MkSpec.new
- @script.stub(:puts)
+ allow(@script).to receive(:puts)
@response = double("system command response")
- @response.stub(:include?).and_return(false)
- @script.stub(:`).and_return(@response)
+ allow(@response).to receive(:include?).and_return(false)
+ allow(@script).to receive(:`).and_return(@response)
end
it "checks if specs exist for the method if the spec file exists" do
- name = Regexp.escape(@script.ruby)
- @script.should_receive(:`).with(
+ name = Regexp.escape(RbConfig.ruby)
+ expect(@script).to receive(:`).with(
%r"#{name} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e 'Object#inspect' spec/core/tcejbo/inspect_spec.rb")
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
end
it "checks for the method name in the spec file output" do
- @response.should_receive(:include?).with("Array#[]=")
+ expect(@response).to receive(:include?).with("Array#[]=")
@script.write_spec("spec/core/yarra/element_set_spec.rb", "Array#[]=", true)
end
it "returns nil if the spec file exists and contains a spec for the method" do
- @response.stub(:include?).and_return(true)
- @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true).should == nil
+ allow(@response).to receive(:include?).and_return(true)
+ expect(@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)).to eq(nil)
end
it "does not print the spec file name if it exists and contains a spec for the method" do
- @response.stub(:include?).and_return(true)
- @script.should_not_receive(:puts)
+ allow(@response).to receive(:include?).and_return(true)
+ expect(@script).not_to receive(:puts)
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
end
it "prints the spec file name if a template spec is written" do
- @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
+ expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
end
it "writes a template spec to the file if the spec file does not exist" do
- @file.should_receive(:puts).twice
- @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
+ expect(@file).to receive(:puts).twice
+ expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", false)
end
it "writes a template spec to the file if it exists but contains no spec for the method" do
- @response.should_receive(:include?).and_return(false)
- @file.should_receive(:puts).twice
- @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
+ expect(@response).to receive(:include?).and_return(false)
+ expect(@file).to receive(:puts).twice
+ expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
end
it "writes a template spec" do
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
- @file.should == <<EOS
+ expect(@file).to eq <<EOS
describe "Object#inspect" do
it "needs to be reviewed for spec completeness"
@@ -247,7 +247,7 @@ EOS
it "writes a template spec with version guard" do
@script.config[:version] = '""..."1.9"'
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
- @file.should == <<EOS
+ expect(@file).to eq <<EOS
ruby_version_is ""..."1.9" do
describe "Object#inspect" do
@@ -259,105 +259,105 @@ EOS
end
end
-describe MkSpec, "#create_file" do
+RSpec.describe MkSpec, "#create_file" do
before :each do
@script = MkSpec.new
- @script.stub(:write_requires)
- @script.stub(:write_spec)
+ allow(@script).to receive(:write_requires)
+ allow(@script).to receive(:write_spec)
- File.stub(:exist?).and_return(false)
+ allow(File).to receive(:exist?).and_return(false)
end
it "generates a file name based on the directory, class/module, and method" do
- File.should_receive(:join).with("spec/tcejbo", "inspect_spec.rb"
+ expect(File).to receive(:join).with("spec/tcejbo", "inspect_spec.rb"
).and_return("spec/tcejbo/inspect_spec.rb")
@script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect")
end
it "does not call #write_requires if the spec file already exists" do
- File.should_receive(:exist?).and_return(true)
- @script.should_not_receive(:write_requires)
+ expect(File).to receive(:exist?).and_return(true)
+ expect(@script).not_to receive(:write_requires)
@script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect")
end
it "calls #write_requires if the spec file does not exist" do
- File.should_receive(:exist?).and_return(false)
- @script.should_receive(:write_requires).with(
+ expect(File).to receive(:exist?).and_return(false)
+ expect(@script).to receive(:write_requires).with(
"spec/tcejbo", "spec/tcejbo/inspect_spec.rb")
@script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect")
end
it "calls #write_spec with the file, method name" do
- @script.should_receive(:write_spec).with(
+ expect(@script).to receive(:write_spec).with(
"spec/tcejbo/inspect_spec.rb", "Object#inspect", false)
@script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect")
end
end
-describe MkSpec, "#run" do
+RSpec.describe MkSpec, "#run" do
before :each do
@options = MSpecOptions.new
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@map = NameMap.new
- NameMap.stub(:new).and_return(@map)
+ allow(NameMap).to receive(:new).and_return(@map)
@script = MkSpec.new
- @script.stub(:create_directory).and_return("spec/mkspec")
- @script.stub(:create_file)
+ allow(@script).to receive(:create_directory).and_return("spec/mkspec")
+ allow(@script).to receive(:create_file)
@script.config[:constants] = [MkSpec]
end
it "loads files in the requires list" do
- @script.stub(:require)
- @script.should_receive(:require).with("alib")
- @script.should_receive(:require).with("blib")
+ allow(@script).to receive(:require)
+ expect(@script).to receive(:require).with("alib")
+ expect(@script).to receive(:require).with("blib")
@script.config[:requires] = ["alib", "blib"]
@script.run
end
it "creates a map of constants to methods" do
- @map.should_receive(:map).with({}, @script.config[:constants]).and_return({})
+ expect(@map).to receive(:map).with({}, @script.config[:constants]).and_return({})
@script.run
end
it "calls #create_directory for each class/module in the map" do
- @script.should_receive(:create_directory).with("MkSpec").twice
+ expect(@script).to receive(:create_directory).with("MkSpec").twice
@script.run
end
it "calls #create_file for each method on each class/module in the map" do
- @map.should_receive(:map).with({}, @script.config[:constants]
+ expect(@map).to receive(:map).with({}, @script.config[:constants]
).and_return({"MkSpec#" => ["run"]})
- @script.should_receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run")
+ expect(@script).to receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run")
@script.run
end
end
-describe MkSpec, ".main" do
+RSpec.describe MkSpec, ".main" do
before :each do
@script = double("MkSpec").as_null_object
- MkSpec.stub(:new).and_return(@script)
+ allow(MkSpec).to receive(:new).and_return(@script)
end
it "sets MSPEC_RUNNER = '1' in the environment" do
ENV["MSPEC_RUNNER"] = "0"
MkSpec.main
- ENV["MSPEC_RUNNER"].should == "1"
+ expect(ENV["MSPEC_RUNNER"]).to eq("1")
end
it "creates an instance of MSpecScript" do
- MkSpec.should_receive(:new).and_return(@script)
+ expect(MkSpec).to receive(:new).and_return(@script)
MkSpec.main
end
it "calls the #options method on the script" do
- @script.should_receive(:options)
+ expect(@script).to receive(:options)
MkSpec.main
end
it "calls the #run method on the script" do
- @script.should_receive(:run)
+ expect(@script).to receive(:run)
MkSpec.main
end
end
diff --git a/spec/mspec/spec/commands/mspec_ci_spec.rb b/spec/mspec/spec/commands/mspec_ci_spec.rb
index a90cbd8d0d..b8dc9d062f 100644
--- a/spec/mspec/spec/commands/mspec_ci_spec.rb
+++ b/spec/mspec/spec/commands/mspec_ci_spec.rb
@@ -3,148 +3,153 @@ require 'mspec/runner/mspec'
require 'mspec/runner/filters/tag'
require 'mspec/commands/mspec-ci'
-describe MSpecCI, "#options" do
+RSpec.describe MSpecCI, "#options" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecCI.new
- @script.stub(:config).and_return(@config)
- @script.stub(:files).and_return([])
+ allow(@script).to receive(:config).and_return(@config)
+ allow(@script).to receive(:files).and_return([])
end
it "enables the chdir option" do
- @options.should_receive(:chdir)
+ expect(@options).to receive(:chdir)
@script.options []
end
it "enables the prefix option" do
- @options.should_receive(:prefix)
+ expect(@options).to receive(:prefix)
@script.options []
end
it "enables the config option" do
- @options.should_receive(:configure)
+ expect(@options).to receive(:configure)
@script.options []
end
it "provides a custom action (block) to the config option" do
- @script.should_receive(:load).with("cfg.mspec")
+ expect(@script).to receive(:load).with("cfg.mspec")
@script.options ["-B", "cfg.mspec"]
end
it "enables the dry run option" do
- @options.should_receive(:pretend)
+ expect(@options).to receive(:pretend)
@script.options []
end
it "enables the unguarded option" do
- @options.should_receive(:unguarded)
+ expect(@options).to receive(:unguarded)
@script.options []
end
it "enables the interrupt single specs option" do
- @options.should_receive(:interrupt)
+ expect(@options).to receive(:interrupt)
@script.options []
end
it "enables the formatter options" do
- @options.should_receive(:formatters)
+ expect(@options).to receive(:formatters)
@script.options []
end
it "enables the verbose option" do
- @options.should_receive(:verbose)
+ expect(@options).to receive(:verbose)
@script.options []
end
it "enables the action options" do
- @options.should_receive(:actions)
+ expect(@options).to receive(:actions)
@script.options []
end
it "enables the action filter options" do
- @options.should_receive(:action_filters)
+ expect(@options).to receive(:action_filters)
@script.options []
end
it "enables the version option" do
- @options.should_receive(:version)
+ expect(@options).to receive(:version)
@script.options []
end
it "enables the help option" do
- @options.should_receive(:help)
+ expect(@options).to receive(:help)
@script.options []
end
+ it "enables the repeat option" do
+ expect(@options).to receive(:repeat)
+ @script.options @argv
+ end
+
it "calls #custom_options" do
- @script.should_receive(:custom_options).with(@options)
+ expect(@script).to receive(:custom_options).with(@options)
@script.options []
end
end
-describe MSpecCI, "#run" do
+RSpec.describe MSpecCI, "#run" do
before :each do
- MSpec.stub(:process)
+ allow(MSpec).to receive(:process)
@filter = double("TagFilter")
- TagFilter.stub(:new).and_return(@filter)
- @filter.stub(:register)
+ allow(TagFilter).to receive(:new).and_return(@filter)
+ allow(@filter).to receive(:register)
@tags = ["fails", "critical", "unstable", "incomplete", "unsupported"]
@config = { :ci_files => ["one", "two"] }
@script = MSpecCI.new
- @script.stub(:exit)
- @script.stub(:config).and_return(@config)
- @script.stub(:files).and_return(["one", "two"])
+ allow(@script).to receive(:exit)
+ allow(@script).to receive(:config).and_return(@config)
+ allow(@script).to receive(:files).and_return(["one", "two"])
@script.options []
end
it "registers the tags patterns" do
@config[:tags_patterns] = [/spec/, "tags"]
- MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"])
+ expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"])
@script.run
end
it "registers the files to process" do
- MSpec.should_receive(:register_files).with(["one", "two"])
+ expect(MSpec).to receive(:register_files).with(["one", "two"])
@script.run
end
it "registers a tag filter for 'fails', 'unstable', 'incomplete', 'critical', 'unsupported'" do
filter = double("fails filter")
- TagFilter.should_receive(:new).with(:exclude, *@tags).and_return(filter)
- filter.should_receive(:register)
+ expect(TagFilter).to receive(:new).with(:exclude, *@tags).and_return(filter)
+ expect(filter).to receive(:register)
@script.run
end
it "registers an additional exclude tag specified by :ci_xtags" do
@config[:ci_xtags] = "windows"
filter = double("fails filter")
- TagFilter.should_receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter)
- filter.should_receive(:register)
+ expect(TagFilter).to receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter)
+ expect(filter).to receive(:register)
@script.run
end
it "registers additional exclude tags specified by a :ci_xtags array" do
@config[:ci_xtags] = ["windows", "windoze"]
filter = double("fails filter")
- TagFilter.should_receive(:new).with(:exclude,
+ expect(TagFilter).to receive(:new).with(:exclude,
*(@tags + ["windows", "windoze"])).and_return(filter)
- filter.should_receive(:register)
+ expect(filter).to receive(:register)
@script.run
end
it "processes the files" do
- MSpec.should_receive(:process)
+ expect(MSpec).to receive(:process)
@script.run
end
it "exits with the exit code registered with MSpec" do
- MSpec.stub(:exit_code).and_return(7)
- @script.should_receive(:exit).with(7)
+ allow(MSpec).to receive(:exit_code).and_return(7)
+ expect(@script).to receive(:exit).with(7)
@script.run
end
end
diff --git a/spec/mspec/spec/commands/mspec_run_spec.rb b/spec/mspec/spec/commands/mspec_run_spec.rb
index fcb44ad5a9..f96be2b43e 100644
--- a/spec/mspec/spec/commands/mspec_run_spec.rb
+++ b/spec/mspec/spec/commands/mspec_run_spec.rb
@@ -5,130 +5,135 @@ require 'mspec/commands/mspec-run'
one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb'
two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb'
-describe MSpecRun, ".new" do
+RSpec.describe MSpecRun, ".new" do
before :each do
@script = MSpecRun.new
end
it "sets config[:files] to an empty list" do
- @script.config[:files].should == []
+ expect(@script.config[:files]).to eq([])
end
end
-describe MSpecRun, "#options" do
+RSpec.describe MSpecRun, "#options" do
before :each do
@argv = [one_spec, two_spec]
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecRun.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
it "enables the filter options" do
- @options.should_receive(:filters)
+ expect(@options).to receive(:filters)
@script.options @argv
end
it "enables the chdir option" do
- @options.should_receive(:chdir)
+ expect(@options).to receive(:chdir)
@script.options @argv
end
it "enables the prefix option" do
- @options.should_receive(:prefix)
+ expect(@options).to receive(:prefix)
@script.options @argv
end
it "enables the configure option" do
- @options.should_receive(:configure)
+ expect(@options).to receive(:configure)
@script.options @argv
end
it "provides a custom action (block) to the config option" do
- @script.should_receive(:load).with("cfg.mspec")
+ expect(@script).to receive(:load).with("cfg.mspec")
@script.options ["-B", "cfg.mspec", one_spec]
end
it "enables the randomize option to runs specs in random order" do
- @options.should_receive(:randomize)
+ expect(@options).to receive(:randomize)
@script.options @argv
end
it "enables the dry run option" do
- @options.should_receive(:pretend)
+ expect(@options).to receive(:pretend)
@script.options @argv
end
it "enables the unguarded option" do
- @options.should_receive(:unguarded)
+ expect(@options).to receive(:unguarded)
@script.options @argv
end
it "enables the interrupt single specs option" do
- @options.should_receive(:interrupt)
+ expect(@options).to receive(:interrupt)
@script.options @argv
end
it "enables the formatter options" do
- @options.should_receive(:formatters)
+ expect(@options).to receive(:formatters)
@script.options @argv
end
it "enables the verbose option" do
- @options.should_receive(:verbose)
+ expect(@options).to receive(:verbose)
@script.options @argv
end
it "enables the verify options" do
- @options.should_receive(:verify)
+ expect(@options).to receive(:verify)
@script.options @argv
end
it "enables the action options" do
- @options.should_receive(:actions)
+ expect(@options).to receive(:actions)
@script.options @argv
end
it "enables the action filter options" do
- @options.should_receive(:action_filters)
+ expect(@options).to receive(:action_filters)
@script.options @argv
end
it "enables the version option" do
- @options.should_receive(:version)
+ expect(@options).to receive(:version)
@script.options @argv
end
it "enables the help option" do
- @options.should_receive(:help)
+ expect(@options).to receive(:help)
+ @script.options @argv
+ end
+
+ it "enables the repeat option" do
+ expect(@options).to receive(:repeat)
@script.options @argv
end
it "exits if there are no files to process and './spec' is not a directory" do
- File.should_receive(:directory?).with("./spec").and_return(false)
- @options.should_receive(:parse).and_return([])
- @script.should_receive(:abort).with("No files specified.")
+ expect(File).to receive(:directory?).with("./spec").and_return(false)
+ expect(@options).to receive(:parse).and_return([])
+ expect(@script).to receive(:abort).with("No files specified.")
@script.options
end
it "process 'spec/' if it is a directory and no files were specified" do
- File.should_receive(:directory?).with("./spec").and_return(true)
- @options.should_receive(:parse).and_return([])
- @script.should_receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"])
+ expect(File).to receive(:directory?).with("./spec").and_return(true)
+ expect(@options).to receive(:parse).and_return([])
+ expect(@script).to receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"])
@script.options
end
it "calls #custom_options" do
- @script.should_receive(:custom_options).with(@options)
+ expect(@script).to receive(:custom_options).with(@options)
@script.options @argv
end
end
-describe MSpecRun, "#run" do
+RSpec.describe MSpecRun, "#run" do
before :each do
@script = MSpecRun.new
- @script.stub(:exit)
+ allow(@script).to receive(:exit)
@spec_dir = File.expand_path(File.dirname(__FILE__)+"/fixtures")
@file_patterns = [
@spec_dir+"/level2",
@@ -139,35 +144,35 @@ describe MSpecRun, "#run" do
@spec_dir+"/one_spec.rb",
@spec_dir+"/two_spec.rb"]
@script.options @file_patterns
- MSpec.stub :process
+ allow(MSpec).to receive :process
end
it "registers the tags patterns" do
@script.config[:tags_patterns] = [/spec/, "tags"]
- MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"])
+ expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"])
@script.run
end
it "registers the files to process" do
- MSpec.should_receive(:register_files).with(@files)
+ expect(MSpec).to receive(:register_files).with(@files)
@script.run
end
it "uses config[:files] if no files are given on the command line" do
@script.config[:files] = @file_patterns
- MSpec.should_receive(:register_files).with(@files)
+ expect(MSpec).to receive(:register_files).with(@files)
@script.options []
@script.run
end
it "processes the files" do
- MSpec.should_receive(:process)
+ expect(MSpec).to receive(:process)
@script.run
end
it "exits with the exit code registered with MSpec" do
- MSpec.stub(:exit_code).and_return(7)
- @script.should_receive(:exit).with(7)
+ allow(MSpec).to receive(:exit_code).and_return(7)
+ expect(@script).to receive(:exit).with(7)
@script.run
end
end
diff --git a/spec/mspec/spec/commands/mspec_spec.rb b/spec/mspec/spec/commands/mspec_spec.rb
index b01af6b41b..d19bebb2d6 100644
--- a/spec/mspec/spec/commands/mspec_spec.rb
+++ b/spec/mspec/spec/commands/mspec_spec.rb
@@ -2,55 +2,55 @@ require 'spec_helper'
require 'yaml'
require 'mspec/commands/mspec'
-describe MSpecMain, "#options" do
+RSpec.describe MSpecMain, "#options" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecMain.new
- @script.stub(:config).and_return(@config)
- @script.stub(:load)
+ allow(@script).to receive(:config).and_return(@config)
+ allow(@script).to receive(:load)
end
it "enables the configure option" do
- @options.should_receive(:configure)
+ expect(@options).to receive(:configure)
@script.options
end
it "provides a custom action (block) to the config option" do
@script.options ["-B", "config"]
- @config[:options].should include("-B", "config")
+ expect(@config[:options]).to include("-B", "config")
end
it "loads the file specified by the config option" do
- @script.should_receive(:load).with("config")
+ expect(@script).to receive(:load).with("config")
@script.options ["-B", "config"]
end
it "enables the target options" do
- @options.should_receive(:targets)
+ expect(@options).to receive(:targets)
@script.options
end
it "sets config[:options] to all argv entries that are not registered options" do
@options.on "-X", "--exclude", "ARG", "description"
@script.options [".", "-G", "fail", "-X", "ARG", "--list", "unstable", "some/file.rb"]
- @config[:options].should == [".", "-G", "fail", "--list", "unstable", "some/file.rb"]
+ expect(@config[:options]).to eq([".", "-G", "fail", "--list", "unstable", "some/file.rb"])
end
it "calls #custom_options" do
- @script.should_receive(:custom_options).with(@options)
+ expect(@script).to receive(:custom_options).with(@options)
@script.options
end
end
-describe MSpecMain, "#run" do
+RSpec.describe MSpecMain, "#run" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecMain.new
- @script.stub(:config).and_return(@config)
- @script.stub(:exec)
+ allow(@script).to receive(:config).and_return(@config)
+ allow(@script).to receive(:exec)
@err = $stderr
$stderr = IOStub.new
end
@@ -60,76 +60,49 @@ describe MSpecMain, "#run" do
end
it "uses exec to invoke the runner script" do
- @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
+ expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@script.options []
@script.run
end
it "shows the command line on stderr" do
- @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
+ expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@script.options []
@script.run
- $stderr.to_s.should == "$ ruby #{Dir.pwd}/bin/mspec-run\n"
+ expect($stderr.to_s).to eq("$ ruby #{Dir.pwd}/bin/mspec-run\n")
end
it "adds config[:launch] to the exec options" do
- @script.should_receive(:exec).with("ruby",
+ expect(@script).to receive(:exec).with("ruby",
"-Xlaunch.option", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@config[:launch] << "-Xlaunch.option"
@script.options []
@script.run
- $stderr.to_s.should == "$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n"
+ expect($stderr.to_s).to eq("$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n")
end
it "calls #multi_exec if the command is 'ci' and the multi option is passed" do
- @script.should_receive(:multi_exec).and_return do |argv|
- argv.should == ["ruby", "#{MSPEC_HOME}/bin/mspec-ci"]
+ expect(@script).to receive(:multi_exec) do |argv|
+ expect(argv).to eq(["ruby", "#{MSPEC_HOME}/bin/mspec-ci"])
end
@script.options ["ci", "-j"]
- lambda do
+ expect do
@script.run
- end.should raise_error(SystemExit)
+ end.to raise_error(SystemExit)
end
end
-describe "The --warnings option" do
+RSpec.describe "The -j, --multi option" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecMain.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("--warnings", an_instance_of(String))
- @script.options
- end
-
- it "sets flags to -w" do
- @config[:flags] = []
- @script.options ["--warnings"]
- @config[:flags].should include("-w")
- end
-
- it "set OUTPUT_WARNINGS = '1' in the environment" do
- ENV['OUTPUT_WARNINGS'] = '0'
- @script.options ["--warnings"]
- ENV['OUTPUT_WARNINGS'].should == '1'
- end
-end
-
-describe "The -j, --multi option" do
- before :each do
- @options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
- @script = MSpecMain.new
- @script.stub(:config).and_return(@config)
- end
-
- it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-j", "--multi", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-j", "--multi", an_instance_of(String))
@script.options
end
@@ -137,22 +110,22 @@ describe "The -j, --multi option" do
["-j", "--multi"].each do |opt|
@config[:multi] = nil
@script.options [opt]
- @config[:multi].should == true
+ expect(@config[:multi]).to eq(true)
end
end
end
-describe "The -h, --help option" do
+RSpec.describe "The -h, --help option" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecMain.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-h", "--help", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-h", "--help", an_instance_of(String))
@script.options
end
@@ -160,30 +133,30 @@ describe "The -h, --help option" do
["-h", "--help"].each do |opt|
@config[:options] = []
@script.options ["ci", opt]
- @config[:options].sort.should == ["-h"]
+ expect(@config[:options].sort).to eq(["-h"])
end
end
it "prints help and exits" do
- @script.should_receive(:puts).twice
- @script.should_receive(:exit).twice
+ expect(@script).to receive(:puts).twice
+ expect(@script).to receive(:exit).twice
["-h", "--help"].each do |opt|
@script.options [opt]
end
end
end
-describe "The -v, --version option" do
+RSpec.describe "The -v, --version option" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecMain.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
it "is enabled by #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-v", "--version", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-v", "--version", an_instance_of(String))
@script.options
end
@@ -191,15 +164,15 @@ describe "The -v, --version option" do
["-v", "--version"].each do |opt|
@config[:options] = []
@script.options ["ci", opt]
- @config[:options].sort.should == ["-v"]
+ expect(@config[:options].sort).to eq(["-v"])
end
end
it "prints the version and exits if no subscript is invoked" do
@config[:command] = nil
- File.stub(:basename).and_return("mspec")
- @script.should_receive(:puts).twice.with("mspec #{MSpec::VERSION}")
- @script.should_receive(:exit).twice
+ allow(File).to receive(:basename).and_return("mspec")
+ expect(@script).to receive(:puts).twice.with("mspec #{MSpec::VERSION}")
+ expect(@script).to receive(:exit).twice
["-v", "--version"].each do |opt|
@script.options [opt]
end
diff --git a/spec/mspec/spec/commands/mspec_tag_spec.rb b/spec/mspec/spec/commands/mspec_tag_spec.rb
index cdb3ac1a60..1ab5f6ea58 100644
--- a/spec/mspec/spec/commands/mspec_tag_spec.rb
+++ b/spec/mspec/spec/commands/mspec_tag_spec.rb
@@ -8,13 +8,13 @@ require 'mspec/runner/actions/tagpurge'
one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb'
two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb'
-describe MSpecTag, ".new" do
+RSpec.describe MSpecTag, ".new" do
before :each do
@script = MSpecTag.new
end
it "sets config[:ltags] to an empty list" do
- @script.config[:ltags].should == []
+ expect(@script.config[:ltags]).to eq([])
end
it "sets config[:tagger] to :add" do
@@ -30,16 +30,16 @@ describe MSpecTag, ".new" do
end
end
-describe MSpecTag, "#options" do
+RSpec.describe MSpecTag, "#options" do
before :each do
@stdout, $stdout = $stdout, IOStub.new
@argv = [one_spec, two_spec]
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecTag.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
after :each do
@@ -47,80 +47,80 @@ describe MSpecTag, "#options" do
end
it "enables the filter options" do
- @options.should_receive(:filters)
+ expect(@options).to receive(:filters)
@script.options @argv
end
it "enables the configure option" do
- @options.should_receive(:configure)
+ expect(@options).to receive(:configure)
@script.options @argv
end
it "provides a custom action (block) to the config option" do
- @script.should_receive(:load).with("cfg.mspec")
+ expect(@script).to receive(:load).with("cfg.mspec")
@script.options ["-B", "cfg.mspec", one_spec]
end
it "enables the dry run option" do
- @options.should_receive(:pretend)
+ expect(@options).to receive(:pretend)
@script.options @argv
end
it "enables the unguarded option" do
- @options.should_receive(:unguarded)
+ expect(@options).to receive(:unguarded)
@script.options @argv
end
it "enables the interrupt single specs option" do
- @options.should_receive(:interrupt)
+ expect(@options).to receive(:interrupt)
@script.options @argv
end
it "enables the formatter options" do
- @options.should_receive(:formatters)
+ expect(@options).to receive(:formatters)
@script.options @argv
end
it "enables the verbose option" do
- @options.should_receive(:verbose)
+ expect(@options).to receive(:verbose)
@script.options @argv
end
it "enables the version option" do
- @options.should_receive(:version)
+ expect(@options).to receive(:version)
@script.options @argv
end
it "enables the help option" do
- @options.should_receive(:help)
+ expect(@options).to receive(:help)
@script.options @argv
end
it "calls #custom_options" do
- @script.should_receive(:custom_options).with(@options)
+ expect(@script).to receive(:custom_options).with(@options)
@script.options @argv
end
it "exits if there are no files to process" do
- @options.should_receive(:parse).and_return([])
- @script.should_receive(:exit)
+ expect(@options).to receive(:parse).and_return([])
+ expect(@script).to receive(:exit)
@script.options
- $stdout.should include "No files specified"
+ expect($stdout.to_s).to include "No files specified"
end
end
-describe MSpecTag, "options" do
+RSpec.describe MSpecTag, "options" do
before :each do
@options, @config = new_option
- MSpecOptions.stub(:new).and_return(@options)
+ allow(MSpecOptions).to receive(:new).and_return(@options)
@script = MSpecTag.new
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
describe "-N, --add TAG" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-N", "--add", "TAG", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-N", "--add", "TAG", an_instance_of(String))
@script.options [one_spec]
end
@@ -129,16 +129,16 @@ describe MSpecTag, "options" do
@config[:tagger] = nil
@config[:tag] = nil
@script.options [opt, "taggit", one_spec]
- @config[:tagger].should == :add
- @config[:tag].should == "taggit:"
+ expect(@config[:tagger]).to eq(:add)
+ expect(@config[:tag]).to eq("taggit:")
end
end
end
describe "-R, --del TAG" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-R", "--del", "TAG",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-R", "--del", "TAG",
an_instance_of(String))
@script.options [one_spec]
end
@@ -149,17 +149,17 @@ describe MSpecTag, "options" do
@config[:tag] = nil
@config[:outcome] = nil
@script.options [opt, "taggit", one_spec]
- @config[:tagger].should == :del
- @config[:tag].should == "taggit:"
- @config[:outcome].should == :pass
+ expect(@config[:tagger]).to eq(:del)
+ expect(@config[:tag]).to eq("taggit:")
+ expect(@config[:outcome]).to eq(:pass)
end
end
end
describe "-Q, --pass" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-Q", "--pass", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-Q", "--pass", an_instance_of(String))
@script.options [one_spec]
end
@@ -167,15 +167,15 @@ describe MSpecTag, "options" do
["-Q", "--pass"].each do |opt|
@config[:outcome] = nil
@script.options [opt, one_spec]
- @config[:outcome].should == :pass
+ expect(@config[:outcome]).to eq(:pass)
end
end
end
describe "-F, --fail" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-F", "--fail", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-F", "--fail", an_instance_of(String))
@script.options [one_spec]
end
@@ -183,15 +183,15 @@ describe MSpecTag, "options" do
["-F", "--fail"].each do |opt|
@config[:outcome] = nil
@script.options [opt, one_spec]
- @config[:outcome].should == :fail
+ expect(@config[:outcome]).to eq(:fail)
end
end
end
describe "-L, --all" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("-L", "--all", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-L", "--all", an_instance_of(String))
@script.options [one_spec]
end
@@ -199,100 +199,100 @@ describe MSpecTag, "options" do
["-L", "--all"].each do |opt|
@config[:outcome] = nil
@script.options [opt, one_spec]
- @config[:outcome].should == :all
+ expect(@config[:outcome]).to eq(:all)
end
end
end
describe "--list TAG" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("--list", "TAG", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--list", "TAG", an_instance_of(String))
@script.options [one_spec]
end
it "sets the mode to :list" do
@config[:tagger] = nil
@script.options ["--list", "TAG", one_spec]
- @config[:tagger].should == :list
+ expect(@config[:tagger]).to eq(:list)
end
it "sets ltags to include TAG" do
@config[:tag] = nil
@script.options ["--list", "TAG", one_spec]
- @config[:ltags].should == ["TAG"]
+ expect(@config[:ltags]).to eq(["TAG"])
end
end
describe "--list-all" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("--list-all", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--list-all", an_instance_of(String))
@script.options [one_spec]
end
it "sets the mode to :list_all" do
@config[:tagger] = nil
@script.options ["--list-all", one_spec]
- @config[:tagger].should == :list_all
+ expect(@config[:tagger]).to eq(:list_all)
end
end
describe "--purge" do
it "is enabled with #options" do
- @options.stub(:on)
- @options.should_receive(:on).with("--purge", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--purge", an_instance_of(String))
@script.options [one_spec]
end
it "sets the mode to :purge" do
@config[:tagger] = nil
@script.options ["--purge", one_spec]
- @config[:tagger].should == :purge
+ expect(@config[:tagger]).to eq(:purge)
end
end
end
-describe MSpecTag, "#run" do
+RSpec.describe MSpecTag, "#run" do
before :each do
- MSpec.stub(:process)
+ allow(MSpec).to receive(:process)
options = double("MSpecOptions").as_null_object
- options.stub(:parse).and_return(["one", "two"])
- MSpecOptions.stub(:new).and_return(options)
+ allow(options).to receive(:parse).and_return(["one", "two"])
+ allow(MSpecOptions).to receive(:new).and_return(options)
@config = { }
@script = MSpecTag.new
- @script.stub(:exit)
- @script.stub(:config).and_return(@config)
- @script.stub(:files).and_return(["one", "two"])
+ allow(@script).to receive(:exit)
+ allow(@script).to receive(:config).and_return(@config)
+ allow(@script).to receive(:files).and_return(["one", "two"])
@script.options
end
it "registers the tags patterns" do
@config[:tags_patterns] = [/spec/, "tags"]
- MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"])
+ expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"])
@script.run
end
it "registers the files to process" do
- MSpec.should_receive(:register_files).with(["one", "two"])
+ expect(MSpec).to receive(:register_files).with(["one", "two"])
@script.run
end
it "processes the files" do
- MSpec.should_receive(:process)
+ expect(MSpec).to receive(:process)
@script.run
end
it "exits with the exit code registered with MSpec" do
- MSpec.stub(:exit_code).and_return(7)
- @script.should_receive(:exit).with(7)
+ allow(MSpec).to receive(:exit_code).and_return(7)
+ expect(@script).to receive(:exit).with(7)
@script.run
end
end
-describe MSpecTag, "#register" do
+RSpec.describe MSpecTag, "#register" do
before :each do
@script = MSpecTag.new
@config = @script.config
@@ -301,19 +301,19 @@ describe MSpecTag, "#register" do
@config[:astrings] = []
@config[:ltags] = ["fails", "unstable"]
- @script.stub(:files).and_return([])
+ allow(@script).to receive(:files).and_return([])
@script.options "fake"
@t = double("TagAction")
- @t.stub(:register)
+ allow(@t).to receive(:register)
@tl = double("TagListAction")
- @tl.stub(:register)
+ allow(@tl).to receive(:register)
end
it "raises an ArgumentError if no recognized action is given" do
@config[:tagger] = :totally_whack
- lambda { @script.register }.should raise_error(ArgumentError)
+ expect { @script.register }.to raise_error(ArgumentError)
end
describe "when config[:tagger] is the default (:add)" do
@@ -322,93 +322,93 @@ describe MSpecTag, "#register" do
end
it "creates a TagAction" do
- TagAction.should_receive(:new).and_return(@t)
+ expect(TagAction).to receive(:new).and_return(@t)
@script.register
end
it "creates a TagAction if config[:tagger] is :del" do
@config[:tagger] = :del
@config[:outcome] = :pass
- TagAction.should_receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t)
+ expect(TagAction).to receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t)
@script.register
end
it "calls #register on the TagAction instance" do
- TagAction.should_receive(:new).and_return(@t)
- @t.should_receive(:register)
+ expect(TagAction).to receive(:new).and_return(@t)
+ expect(@t).to receive(:register)
@script.register
end
end
describe "when config[:tagger] is :list" do
before :each do
- TagListAction.should_receive(:new).with(@config[:ltags]).and_return(@tl)
+ expect(TagListAction).to receive(:new).with(@config[:ltags]).and_return(@tl)
@config[:tagger] = :list
end
it "creates a TagListAction" do
- @tl.should_receive(:register)
+ expect(@tl).to receive(:register)
@script.register
end
it "registers MSpec pretend mode" do
- MSpec.should_receive(:register_mode).with(:pretend)
+ expect(MSpec).to receive(:register_mode).with(:pretend)
@script.register
end
it "sets config[:formatter] to false" do
@script.register
- @config[:formatter].should be_false
+ expect(@config[:formatter]).to be_falsey
end
end
describe "when config[:tagger] is :list_all" do
before :each do
- TagListAction.should_receive(:new).with(nil).and_return(@tl)
+ expect(TagListAction).to receive(:new).with(nil).and_return(@tl)
@config[:tagger] = :list_all
end
it "creates a TagListAction" do
- @tl.should_receive(:register)
+ expect(@tl).to receive(:register)
@script.register
end
it "registers MSpec pretend mode" do
- MSpec.should_receive(:register_mode).with(:pretend)
+ expect(MSpec).to receive(:register_mode).with(:pretend)
@script.register
end
it "sets config[:formatter] to false" do
@script.register
- @config[:formatter].should be_false
+ expect(@config[:formatter]).to be_falsey
end
end
describe "when config[:tagger] is :purge" do
before :each do
- TagPurgeAction.should_receive(:new).and_return(@tl)
- MSpec.stub(:register_mode)
+ expect(TagPurgeAction).to receive(:new).and_return(@tl)
+ allow(MSpec).to receive(:register_mode)
@config[:tagger] = :purge
end
it "creates a TagPurgeAction" do
- @tl.should_receive(:register)
+ expect(@tl).to receive(:register)
@script.register
end
it "registers MSpec in pretend mode" do
- MSpec.should_receive(:register_mode).with(:pretend)
+ expect(MSpec).to receive(:register_mode).with(:pretend)
@script.register
end
it "registers MSpec in unguarded mode" do
- MSpec.should_receive(:register_mode).with(:unguarded)
+ expect(MSpec).to receive(:register_mode).with(:unguarded)
@script.register
end
it "sets config[:formatter] to false" do
@script.register
- @config[:formatter].should be_false
+ expect(@config[:formatter]).to be_falsey
end
end
end
diff --git a/spec/mspec/spec/expectations/expectations_spec.rb b/spec/mspec/spec/expectations/expectations_spec.rb
index fea692f3e3..371829d4f9 100644
--- a/spec/mspec/spec/expectations/expectations_spec.rb
+++ b/spec/mspec/spec/expectations/expectations_spec.rb
@@ -1,29 +1,29 @@
require 'spec_helper'
require 'mspec/expectations/expectations'
-describe SpecExpectationNotMetError do
+RSpec.describe SpecExpectationNotMetError do
it "is a subclass of StandardError" do
- SpecExpectationNotMetError.ancestors.should include(StandardError)
+ expect(SpecExpectationNotMetError.ancestors).to include(StandardError)
end
end
-describe SpecExpectationNotFoundError do
+RSpec.describe SpecExpectationNotFoundError do
it "is a subclass of StandardError" do
- SpecExpectationNotFoundError.ancestors.should include(StandardError)
+ expect(SpecExpectationNotFoundError.ancestors).to include(StandardError)
end
end
-describe SpecExpectationNotFoundError, "#message" do
+RSpec.describe SpecExpectationNotFoundError, "#message" do
it "returns 'No behavior expectation was found in the example'" do
m = SpecExpectationNotFoundError.new.message
- m.should == "No behavior expectation was found in the example"
+ expect(m).to eq("No behavior expectation was found in the example")
end
end
-describe SpecExpectation, "#fail_with" do
+RSpec.describe SpecExpectation, "#fail_with" do
it "raises an SpecExpectationNotMetError" do
- lambda {
+ expect {
SpecExpectation.fail_with "expected this", "to equal that"
- }.should raise_error(SpecExpectationNotMetError, "expected this to equal that")
+ }.to raise_error(SpecExpectationNotMetError, "expected this to equal that")
end
end
diff --git a/spec/mspec/spec/expectations/should.rb b/spec/mspec/spec/expectations/should.rb
deleted file mode 100644
index 24b1cf2bf8..0000000000
--- a/spec/mspec/spec/expectations/should.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-$: << File.dirname(__FILE__) + '/../../lib'
-require 'mspec'
-require 'mspec/utils/script'
-
-# The purpose of these specs is to confirm that the #should
-# and #should_not methods are functioning appropriately. We
-# use a separate spec file that is invoked from the MSpec
-# specs but is run by MSpec. This avoids conflicting with
-# RSpec's #should and #should_not methods.
-
-class ShouldSpecsMonitor
- def initialize
- @called = 0
- end
-
- def expectation(state)
- @called += 1
- end
-
- def finish
- puts "I was called #{@called} times"
- end
-end
-
-# Simplistic runner
-formatter = DottedFormatter.new
-formatter.register
-
-monitor = ShouldSpecsMonitor.new
-MSpec.register :expectation, monitor
-MSpec.register :finish, monitor
-
-at_exit { MSpec.actions :finish }
-
-MSpec.actions :start
-MSpec.setup_env
-
-# Specs
-describe "MSpec expectation method #should" do
- it "accepts a matcher" do
- :sym.should be_kind_of(Symbol)
- end
-
- it "causes a failue to be recorded" do
- 1.should == 2
- end
-
- it "registers that an expectation has been encountered" do
- # an empty example block causes an exception because
- # no expectation was encountered
- end
-
- it "invokes the MSpec :expectation actions" do
- 1.should == 1
- end
-end
-
-describe "MSpec expectation method #should_not" do
- it "accepts a matcher" do
- "sym".should_not be_kind_of(Symbol)
- end
-
- it "causes a failure to be recorded" do
- 1.should_not == 1
- end
-
- it "registers that an expectation has been encountered" do
- end
-
- it "invokes the MSpec :expectation actions" do
- 1.should_not == 2
- end
-end
diff --git a/spec/mspec/spec/expectations/should_spec.rb b/spec/mspec/spec/expectations/should_spec.rb
index 3258caf13c..472890979d 100644
--- a/spec/mspec/spec/expectations/should_spec.rb
+++ b/spec/mspec/spec/expectations/should_spec.rb
@@ -1,26 +1,26 @@
require 'spec_helper'
require 'rbconfig'
-describe "MSpec" do
+RSpec.describe "MSpec" do
before :all do
path = RbConfig::CONFIG['bindir']
exe = RbConfig::CONFIG['ruby_install_name']
- file = File.dirname(__FILE__) + '/should.rb'
+ file = File.expand_path('../../fixtures/should.rb', __FILE__)
@out = `#{path}/#{exe} #{file}`
end
describe "#should" do
it "records failures" do
- @out.should include <<-EOS
+ expect(@out).to include <<-EOS
1)
-MSpec expectation method #should causes a failue to be recorded FAILED
-Expected 1
- to equal 2
+MSpec expectation method #should causes a failure to be recorded FAILED
+Expected 1 == 2
+to be truthy but was false
EOS
end
it "raises exceptions for examples with no expectations" do
- @out.should include <<-EOS
+ expect(@out).to include <<-EOS
2)
MSpec expectation method #should registers that an expectation has been encountered FAILED
No behavior expectation was found in the example
@@ -30,16 +30,16 @@ EOS
describe "#should_not" do
it "records failures" do
- @out.should include <<-EOS
+ expect(@out).to include <<-EOS
3)
MSpec expectation method #should_not causes a failure to be recorded FAILED
-Expected 1
- not to equal 1
+Expected 1 == 1
+to be falsy but was true
EOS
end
it "raises exceptions for examples with no expectations" do
- @out.should include <<-EOS
+ expect(@out).to include <<-EOS
4)
MSpec expectation method #should_not registers that an expectation has been encountered FAILED
No behavior expectation was found in the example
@@ -48,14 +48,14 @@ EOS
end
it "prints status information" do
- @out.should include ".FF..FF."
+ expect(@out).to include ".FF..FF."
end
it "prints out a summary" do
- @out.should include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors"
+ expect(@out).to include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors"
end
it "records expectations" do
- @out.should include "I was called 6 times"
+ expect(@out).to include "I was called 6 times"
end
end
diff --git a/spec/mspec/spec/fixtures/config.mspec b/spec/mspec/spec/fixtures/config.mspec
index 4a069e2eb0..01654c5094 100644
--- a/spec/mspec/spec/fixtures/config.mspec
+++ b/spec/mspec/spec/fixtures/config.mspec
@@ -1,8 +1,6 @@
class MSpecScript
set :target, 'ruby'
- set :backtrace_filter, /lib\/mspec\//
-
set :tags_patterns, [
[%r(spec/fixtures/), 'spec/fixtures/tags/'],
[/_spec.rb$/, '_tags.txt']
diff --git a/spec/mspec/spec/fixtures/my_ruby b/spec/mspec/spec/fixtures/my_ruby
index 4d552f27fb..eeda3eeeec 100755
--- a/spec/mspec/spec/fixtures/my_ruby
+++ b/spec/mspec/spec/fixtures/my_ruby
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
echo $RUBY_EXE
-ruby "$@"
+exec ruby "$@"
diff --git a/spec/mspec/spec/fixtures/should.rb b/spec/mspec/spec/fixtures/should.rb
new file mode 100644
index 0000000000..f494775c5f
--- /dev/null
+++ b/spec/mspec/spec/fixtures/should.rb
@@ -0,0 +1,75 @@
+$: << File.dirname(__FILE__) + '/../../lib'
+require 'mspec'
+require 'mspec/utils/script'
+
+# The purpose of these specs is to confirm that the #should
+# and #should_not methods are functioning appropriately. We
+# use a separate spec file that is invoked from the MSpec
+# specs but is run by MSpec. This avoids conflicting with
+# RSpec's #should and #should_not methods.
+
+raise "RSpec should not be loaded" if defined?(RSpec)
+
+class ShouldSpecsMonitor
+ def initialize
+ @called = 0
+ end
+
+ def expectation(state)
+ @called += 1
+ end
+
+ def finish
+ puts "I was called #{@called} times"
+ end
+end
+
+# Simplistic runner
+formatter = DottedFormatter.new
+formatter.register
+
+monitor = ShouldSpecsMonitor.new
+MSpec.register :expectation, monitor
+MSpec.register :finish, monitor
+
+at_exit { MSpec.actions :finish }
+
+MSpec.actions :start
+MSpec.setup_env
+
+# Specs
+describe "MSpec expectation method #should" do
+ it "accepts a matcher" do
+ :sym.should be_kind_of(Symbol)
+ end
+
+ it "causes a failure to be recorded" do
+ 1.should == 2
+ end
+
+ it "registers that an expectation has been encountered" do
+ # an empty example block causes an exception because
+ # no expectation was encountered
+ end
+
+ it "invokes the MSpec :expectation actions" do
+ 1.should == 1
+ end
+end
+
+describe "MSpec expectation method #should_not" do
+ it "accepts a matcher" do
+ "sym".should_not be_kind_of(Symbol)
+ end
+
+ it "causes a failure to be recorded" do
+ 1.should_not == 1
+ end
+
+ it "registers that an expectation has been encountered" do
+ end
+
+ it "invokes the MSpec :expectation actions" do
+ 1.should_not == 2
+ end
+end
diff --git a/spec/mspec/spec/guards/block_device_spec.rb b/spec/mspec/spec/guards/block_device_spec.rb
index 3b437b6d74..dd420d4a81 100644
--- a/spec/mspec/spec/guards/block_device_spec.rb
+++ b/spec/mspec/spec/guards/block_device_spec.rb
@@ -1,46 +1,46 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#with_block_device" do
+RSpec.describe Object, "#with_block_device" do
before :each do
ScratchPad.clear
@guard = BlockDeviceGuard.new
- BlockDeviceGuard.stub(:new).and_return(@guard)
+ allow(BlockDeviceGuard).to receive(:new).and_return(@guard)
end
platform_is_not :freebsd, :windows do
it "yields if block device is available" do
- @guard.should_receive(:`).and_return("block devices")
+ expect(@guard).to receive(:`).and_return("block devices")
with_block_device { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield if block device is not available" do
- @guard.should_receive(:`).and_return(nil)
+ expect(@guard).to receive(:`).and_return(nil)
with_block_device { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
platform_is :freebsd, :windows do
it "does not yield, since platform does not support block devices" do
- @guard.should_not_receive(:`)
+ expect(@guard).not_to receive(:`)
with_block_device { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
it "sets the name of the guard to :with_block_device" do
with_block_device { }
- @guard.name.should == :with_block_device
+ expect(@guard.name).to eq(:with_block_device)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(true)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(true)
+ expect(@guard).to receive(:unregister)
+ expect do
with_block_device { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/bug_spec.rb b/spec/mspec/spec/guards/bug_spec.rb
index c8529a49f7..72a3405dbc 100644
--- a/spec/mspec/spec/guards/bug_spec.rb
+++ b/spec/mspec/spec/guards/bug_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
require 'mspec/guards'
-describe BugGuard, "#match? when #implementation? is 'ruby'" do
+RSpec.describe BugGuard, "#match? when #implementation? is 'ruby'" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@@ -23,47 +23,47 @@ describe BugGuard, "#match? when #implementation? is 'ruby'" do
end
it "returns false when version argument is less than RUBY_VERSION" do
- BugGuard.new("#1", "1.8.5").match?.should == false
+ expect(BugGuard.new("#1", "1.8.5").match?).to eq(false)
end
it "returns true when version argument is equal to RUBY_VERSION" do
- BugGuard.new("#1", "1.8.6").match?.should == true
+ expect(BugGuard.new("#1", "1.8.6").match?).to eq(true)
end
it "returns true when version argument is greater than RUBY_VERSION" do
- BugGuard.new("#1", "1.8.7").match?.should == true
+ expect(BugGuard.new("#1", "1.8.7").match?).to eq(true)
end
it "returns true when version argument implicitly includes RUBY_VERSION" do
- BugGuard.new("#1", "1.8").match?.should == true
- BugGuard.new("#1", "1.8.6").match?.should == true
+ expect(BugGuard.new("#1", "1.8").match?).to eq(true)
+ expect(BugGuard.new("#1", "1.8.6").match?).to eq(true)
end
it "returns true when the argument range includes RUBY_VERSION" do
- BugGuard.new("#1", '1.8.5'..'1.8.7').match?.should == true
- BugGuard.new("#1", '1.8'..'1.9').match?.should == true
- BugGuard.new("#1", '1.8'...'1.9').match?.should == true
- BugGuard.new("#1", '1.8'..'1.8.6').match?.should == true
- BugGuard.new("#1", '1.8.5'..'1.8.6').match?.should == true
- BugGuard.new("#1", ''...'1.8.7').match?.should == true
+ expect(BugGuard.new("#1", '1.8.5'..'1.8.7').match?).to eq(true)
+ expect(BugGuard.new("#1", '1.8'..'1.9').match?).to eq(true)
+ expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(true)
+ expect(BugGuard.new("#1", '1.8'..'1.8.6').match?).to eq(true)
+ expect(BugGuard.new("#1", '1.8.5'..'1.8.6').match?).to eq(true)
+ expect(BugGuard.new("#1", ''...'1.8.7').match?).to eq(true)
end
it "returns false when the argument range does not include RUBY_VERSION" do
- BugGuard.new("#1", '1.8.7'..'1.8.9').match?.should == false
- BugGuard.new("#1", '1.8.4'..'1.8.5').match?.should == false
- BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false
- BugGuard.new("#1", '1.8.5'...'1.8.6').match?.should == false
- BugGuard.new("#1", ''...'1.8.6').match?.should == false
+ expect(BugGuard.new("#1", '1.8.7'..'1.8.9').match?).to eq(false)
+ expect(BugGuard.new("#1", '1.8.4'..'1.8.5').match?).to eq(false)
+ expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false)
+ expect(BugGuard.new("#1", '1.8.5'...'1.8.6').match?).to eq(false)
+ expect(BugGuard.new("#1", ''...'1.8.6').match?).to eq(false)
end
it "returns false when MSpec.mode?(:no_ruby_bug) is true" do
- MSpec.should_receive(:mode?).with(:no_ruby_bug).twice.and_return(:true)
- BugGuard.new("#1", "1.8.5").match?.should == false
- BugGuard.new("#1", "1.8").match?.should == false
+ expect(MSpec).to receive(:mode?).with(:no_ruby_bug).twice.and_return(:true)
+ expect(BugGuard.new("#1", "1.8.5").match?).to eq(false)
+ expect(BugGuard.new("#1", "1.8").match?).to eq(false)
end
end
-describe BugGuard, "#match? when #implementation? is not 'ruby'" do
+RSpec.describe BugGuard, "#match? when #implementation? is not 'ruby'" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@@ -88,64 +88,64 @@ describe BugGuard, "#match? when #implementation? is not 'ruby'" do
end
it "returns false when version argument is less than RUBY_VERSION" do
- BugGuard.new("#1", "1.8").match?.should == false
- BugGuard.new("#1", "1.8.6").match?.should == false
+ expect(BugGuard.new("#1", "1.8").match?).to eq(false)
+ expect(BugGuard.new("#1", "1.8.6").match?).to eq(false)
end
it "returns false when version argument is equal to RUBY_VERSION" do
- BugGuard.new("#1", "1.8.6").match?.should == false
+ expect(BugGuard.new("#1", "1.8.6").match?).to eq(false)
end
it "returns false when version argument is greater than RUBY_VERSION" do
- BugGuard.new("#1", "1.8.7").match?.should == false
+ expect(BugGuard.new("#1", "1.8.7").match?).to eq(false)
end
it "returns false no matter if the argument range includes RUBY_VERSION" do
- BugGuard.new("#1", '1.8'...'1.9').match?.should == false
- BugGuard.new("#1", '1.8.5'...'1.8.7').match?.should == false
- BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false
+ expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(false)
+ expect(BugGuard.new("#1", '1.8.5'...'1.8.7').match?).to eq(false)
+ expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false)
end
it "returns false when MSpec.mode?(:no_ruby_bug) is true" do
- MSpec.stub(:mode?).and_return(:true)
- BugGuard.new("#1", "1.8.6").match?.should == false
+ allow(MSpec).to receive(:mode?).and_return(:true)
+ expect(BugGuard.new("#1", "1.8.6").match?).to eq(false)
end
end
-describe Object, "#ruby_bug" do
+RSpec.describe Object, "#ruby_bug" do
before :each do
hide_deprecation_warnings
@guard = BugGuard.new "#1234", "x.x.x"
- BugGuard.stub(:new).and_return(@guard)
+ allow(BugGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields when #match? returns false" do
- @guard.stub(:match?).and_return(false)
+ allow(@guard).to receive(:match?).and_return(false)
ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield when #match? returns true" do
- @guard.stub(:match?).and_return(true)
+ allow(@guard).to receive(:match?).and_return(true)
ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "requires a bug tracker number and a version number" do
- lambda { ruby_bug { } }.should raise_error(ArgumentError)
- lambda { ruby_bug("#1234") { } }.should raise_error(ArgumentError)
+ expect { ruby_bug { } }.to raise_error(ArgumentError)
+ expect { ruby_bug("#1234") { } }.to raise_error(ArgumentError)
end
it "sets the name of the guard to :ruby_bug" do
ruby_bug("#1234", "1.8.6") { }
- @guard.name.should == :ruby_bug
+ expect(@guard.name).to eq(:ruby_bug)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:unregister)
+ expect do
ruby_bug("", "") { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/conflict_spec.rb b/spec/mspec/spec/guards/conflict_spec.rb
index deada96821..7dbe83153d 100644
--- a/spec/mspec/spec/guards/conflict_spec.rb
+++ b/spec/mspec/spec/guards/conflict_spec.rb
@@ -1,53 +1,53 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#conflicts_with" do
+RSpec.describe Object, "#conflicts_with" do
before :each do
hide_deprecation_warnings
ScratchPad.clear
end
it "does not yield if Object.constants includes any of the arguments" do
- Object.stub(:constants).and_return(["SomeClass", "OtherClass"])
+ allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"])
conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "does not yield if Object.constants (as Symbols) includes any of the arguments" do
- Object.stub(:constants).and_return([:SomeClass, :OtherClass])
+ allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass])
conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "yields if Object.constants does not include any of the arguments" do
- Object.stub(:constants).and_return(["SomeClass", "OtherClass"])
+ allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"])
conflicts_with(:AClass, :BClass) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "yields if Object.constants (as Symbols) does not include any of the arguments" do
- Object.stub(:constants).and_return([:SomeClass, :OtherClass])
+ allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass])
conflicts_with(:AClass, :BClass) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
end
-describe Object, "#conflicts_with" do
+RSpec.describe Object, "#conflicts_with" do
before :each do
hide_deprecation_warnings
@guard = ConflictsGuard.new
- ConflictsGuard.stub(:new).and_return(@guard)
+ allow(ConflictsGuard).to receive(:new).and_return(@guard)
end
it "sets the name of the guard to :conflicts_with" do
conflicts_with(:AClass, :BClass) { }
- @guard.name.should == :conflicts_with
+ expect(@guard.name).to eq(:conflicts_with)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:unregister)
+ expect do
conflicts_with(:AClass, :BClass) { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/endian_spec.rb b/spec/mspec/spec/guards/endian_spec.rb
index 5b40c203ab..943b558ed3 100644
--- a/spec/mspec/spec/guards/endian_spec.rb
+++ b/spec/mspec/spec/guards/endian_spec.rb
@@ -1,55 +1,55 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#big_endian" do
+RSpec.describe Object, "#big_endian" do
before :each do
@guard = BigEndianGuard.new
- BigEndianGuard.stub(:new).and_return(@guard)
+ allow(BigEndianGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields on big-endian platforms" do
- @guard.stub(:pattern).and_return([?\001])
+ allow(@guard).to receive(:pattern).and_return([?\001])
big_endian { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield on little-endian platforms" do
- @guard.stub(:pattern).and_return([?\000])
+ allow(@guard).to receive(:pattern).and_return([?\000])
big_endian { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "sets the name of the guard to :big_endian" do
big_endian { }
- @guard.name.should == :big_endian
+ expect(@guard.name).to eq(:big_endian)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.stub(:pattern).and_return([?\001])
- @guard.should_receive(:unregister)
- lambda do
+ allow(@guard).to receive(:pattern).and_return([?\001])
+ expect(@guard).to receive(:unregister)
+ expect do
big_endian { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
-describe Object, "#little_endian" do
+RSpec.describe Object, "#little_endian" do
before :each do
@guard = BigEndianGuard.new
- BigEndianGuard.stub(:new).and_return(@guard)
+ allow(BigEndianGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields on little-endian platforms" do
- @guard.stub(:pattern).and_return([?\000])
+ allow(@guard).to receive(:pattern).and_return([?\000])
little_endian { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield on big-endian platforms" do
- @guard.stub(:pattern).and_return([?\001])
+ allow(@guard).to receive(:pattern).and_return([?\001])
little_endian { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
diff --git a/spec/mspec/spec/guards/feature_spec.rb b/spec/mspec/spec/guards/feature_spec.rb
index 8761cb2fbb..fcb8997591 100644
--- a/spec/mspec/spec/guards/feature_spec.rb
+++ b/spec/mspec/spec/guards/feature_spec.rb
@@ -1,120 +1,120 @@
require 'spec_helper'
require 'mspec/guards'
-describe FeatureGuard, ".enabled?" do
+RSpec.describe FeatureGuard, ".enabled?" do
it "returns true if the feature is enabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true)
- FeatureGuard.enabled?(:encoding).should be_true
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true)
+ expect(FeatureGuard.enabled?(:encoding)).to be_truthy
end
it "returns false if the feature is not enabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false)
- FeatureGuard.enabled?(:encoding).should be_false
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false)
+ expect(FeatureGuard.enabled?(:encoding)).to be_falsey
end
it "returns true if all the features are enabled" do
- MSpec.should_receive(:feature_enabled?).with(:one).and_return(true)
- MSpec.should_receive(:feature_enabled?).with(:two).and_return(true)
- FeatureGuard.enabled?(:one, :two).should be_true
+ expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true)
+ expect(FeatureGuard.enabled?(:one, :two)).to be_truthy
end
it "returns false if any of the features are not enabled" do
- MSpec.should_receive(:feature_enabled?).with(:one).and_return(true)
- MSpec.should_receive(:feature_enabled?).with(:two).and_return(false)
- FeatureGuard.enabled?(:one, :two).should be_false
+ expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false)
+ expect(FeatureGuard.enabled?(:one, :two)).to be_falsey
end
end
-describe Object, "#with_feature" do
+RSpec.describe Object, "#with_feature" do
before :each do
ScratchPad.clear
@guard = FeatureGuard.new :encoding
- FeatureGuard.stub(:new).and_return(@guard)
+ allow(FeatureGuard).to receive(:new).and_return(@guard)
end
it "sets the name of the guard to :with_feature" do
with_feature(:encoding) { }
- @guard.name.should == :with_feature
+ expect(@guard.name).to eq(:with_feature)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(true)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(true)
+ expect(@guard).to receive(:unregister)
+ expect do
with_feature { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
-describe Object, "#with_feature" do
+RSpec.describe Object, "#with_feature" do
before :each do
ScratchPad.clear
end
it "yields if the feature is enabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true)
with_feature(:encoding) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "yields if all the features are enabled" do
- MSpec.should_receive(:feature_enabled?).with(:one).and_return(true)
- MSpec.should_receive(:feature_enabled?).with(:two).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true)
with_feature(:one, :two) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield if the feature is not enabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false)
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false)
with_feature(:encoding) { ScratchPad.record :yield }
- ScratchPad.recorded.should be_nil
+ expect(ScratchPad.recorded).to be_nil
end
it "does not yield if any of the features are not enabled" do
- MSpec.should_receive(:feature_enabled?).with(:one).and_return(true)
- MSpec.should_receive(:feature_enabled?).with(:two).and_return(false)
+ expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false)
with_feature(:one, :two) { ScratchPad.record :yield }
- ScratchPad.recorded.should be_nil
+ expect(ScratchPad.recorded).to be_nil
end
end
-describe Object, "#without_feature" do
+RSpec.describe Object, "#without_feature" do
before :each do
ScratchPad.clear
@guard = FeatureGuard.new :encoding
- FeatureGuard.stub(:new).and_return(@guard)
+ allow(FeatureGuard).to receive(:new).and_return(@guard)
end
it "sets the name of the guard to :without_feature" do
without_feature(:encoding) { }
- @guard.name.should == :without_feature
+ expect(@guard.name).to eq(:without_feature)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(false)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(false)
+ expect(@guard).to receive(:unregister)
+ expect do
without_feature { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
-describe Object, "#without_feature" do
+RSpec.describe Object, "#without_feature" do
before :each do
ScratchPad.clear
end
it "does not yield if the feature is enabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true)
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true)
without_feature(:encoding) { ScratchPad.record :yield }
- ScratchPad.recorded.should be_nil
+ expect(ScratchPad.recorded).to be_nil
end
it "yields if the feature is disabled" do
- MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false)
+ expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false)
without_feature(:encoding) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
end
diff --git a/spec/mspec/spec/guards/guard_spec.rb b/spec/mspec/spec/guards/guard_spec.rb
index 5c3dae4b3f..e29d235747 100644
--- a/spec/mspec/spec/guards/guard_spec.rb
+++ b/spec/mspec/spec/guards/guard_spec.rb
@@ -2,41 +2,41 @@ require 'spec_helper'
require 'mspec/guards'
require 'rbconfig'
-describe SpecGuard, ".ruby_version" do
+RSpec.describe SpecGuard, ".ruby_version" do
before :each do
stub_const "RUBY_VERSION", "8.2.3"
end
it "returns the full version for :full" do
- SpecGuard.ruby_version(:full).should == "8.2.3"
+ expect(SpecGuard.ruby_version(:full)).to eq("8.2.3")
end
it "returns major.minor.tiny for :tiny" do
- SpecGuard.ruby_version(:tiny).should == "8.2.3"
+ expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3")
end
it "returns major.minor.tiny for :teeny" do
- SpecGuard.ruby_version(:tiny).should == "8.2.3"
+ expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3")
end
it "returns major.minor for :minor" do
- SpecGuard.ruby_version(:minor).should == "8.2"
+ expect(SpecGuard.ruby_version(:minor)).to eq("8.2")
end
it "defaults to :minor" do
- SpecGuard.ruby_version.should == "8.2"
+ expect(SpecGuard.ruby_version).to eq("8.2")
end
it "returns major for :major" do
- SpecGuard.ruby_version(:major).should == "8"
+ expect(SpecGuard.ruby_version(:major)).to eq("8")
end
end
-describe SpecGuard, "#yield?" do
+RSpec.describe SpecGuard, "#yield?" do
before :each do
MSpec.clear_modes
@guard = SpecGuard.new
- @guard.stub(:match?).and_return(false)
+ allow(@guard).to receive(:match?).and_return(false)
end
after :each do
@@ -47,77 +47,77 @@ describe SpecGuard, "#yield?" do
it "returns true if MSpec.mode?(:unguarded) is true" do
MSpec.register_mode :unguarded
- @guard.yield?.should == true
+ expect(@guard.yield?).to eq(true)
end
it "returns true if MSpec.mode?(:verify) is true" do
MSpec.register_mode :verify
- @guard.yield?.should == true
+ expect(@guard.yield?).to eq(true)
end
it "returns true if MSpec.mode?(:verify) is true regardless of invert being true" do
MSpec.register_mode :verify
- @guard.yield?(true).should == true
+ expect(@guard.yield?(true)).to eq(true)
end
it "returns true if MSpec.mode?(:report) is true" do
MSpec.register_mode :report
- @guard.yield?.should == true
+ expect(@guard.yield?).to eq(true)
end
it "returns true if MSpec.mode?(:report) is true regardless of invert being true" do
MSpec.register_mode :report
- @guard.yield?(true).should == true
+ expect(@guard.yield?(true)).to eq(true)
end
it "returns true if MSpec.mode?(:report_on) is true and SpecGuards.guards contains the named guard" do
MSpec.register_mode :report_on
SpecGuard.guards << :guard_name
- @guard.yield?.should == false
+ expect(@guard.yield?).to eq(false)
@guard.name = :guard_name
- @guard.yield?.should == true
+ expect(@guard.yield?).to eq(true)
end
it "returns #match? if neither report nor verify mode are true" do
- @guard.stub(:match?).and_return(false)
- @guard.yield?.should == false
- @guard.stub(:match?).and_return(true)
- @guard.yield?.should == true
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.yield?).to eq(false)
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.yield?).to eq(true)
end
it "returns #match? if invert is true and neither report nor verify mode are true" do
- @guard.stub(:match?).and_return(false)
- @guard.yield?(true).should == true
- @guard.stub(:match?).and_return(true)
- @guard.yield?(true).should == false
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.yield?(true)).to eq(true)
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.yield?(true)).to eq(false)
end
end
-describe SpecGuard, "#match?" do
+RSpec.describe SpecGuard, "#match?" do
before :each do
@guard = SpecGuard.new
end
it "must be implemented in subclasses" do
- lambda {
+ expect {
@guard.match?
- }.should raise_error("must be implemented by the subclass")
+ }.to raise_error("must be implemented by the subclass")
end
end
-describe SpecGuard, "#unregister" do
+RSpec.describe SpecGuard, "#unregister" do
before :each do
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:unregister)
@guard = SpecGuard.new
end
it "unregisters from MSpec :add actions" do
- MSpec.should_receive(:unregister).with(:add, @guard)
+ expect(MSpec).to receive(:unregister).with(:add, @guard)
@guard.unregister
end
end
-describe SpecGuard, "#record" do
+RSpec.describe SpecGuard, "#record" do
after :each do
SpecGuard.clear
end
@@ -126,28 +126,28 @@ describe SpecGuard, "#record" do
guard = SpecGuard.new "a", "1.8"..."1.9"
guard.name = :named_guard
guard.record "SomeClass#action returns true"
- SpecGuard.report.should == {
+ expect(SpecGuard.report).to eq({
'named_guard a, 1.8...1.9' => ["SomeClass#action returns true"]
- }
+ })
end
end
-describe SpecGuard, ".guards" do
+RSpec.describe SpecGuard, ".guards" do
it "returns an Array" do
- SpecGuard.guards.should be_kind_of(Array)
+ expect(SpecGuard.guards).to be_kind_of(Array)
end
end
-describe SpecGuard, ".clear_guards" do
+RSpec.describe SpecGuard, ".clear_guards" do
it "resets the array to empty" do
SpecGuard.guards << :guard
- SpecGuard.guards.should == [:guard]
+ expect(SpecGuard.guards).to eq([:guard])
SpecGuard.clear_guards
- SpecGuard.guards.should == []
+ expect(SpecGuard.guards).to eq([])
end
end
-describe SpecGuard, ".finish" do
+RSpec.describe SpecGuard, ".finish" do
before :each do
$stdout = @out = IOStub.new
end
@@ -163,88 +163,88 @@ describe SpecGuard, ".finish" do
guard.record "SomeClass#action returns true"
guard.record "SomeClass#reverse returns false"
SpecGuard.finish
- $stdout.should == %[
+ expect($stdout).to eq(%[
2 specs omitted by guard: named_guard a, 1.8...1.9:
SomeClass#action returns true
SomeClass#reverse returns false
-]
+])
end
end
-describe SpecGuard, ".run_if" do
+RSpec.describe SpecGuard, ".run_if" do
before :each do
@guard = SpecGuard.new
ScratchPad.clear
end
it "yields if match? returns true" do
- @guard.stub(:match?).and_return(true)
+ allow(@guard).to receive(:match?).and_return(true)
@guard.run_if(:name) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield if match? returns false" do
- @guard.stub(:match?).and_return(false)
+ allow(@guard).to receive(:match?).and_return(false)
@guard.run_if(:name) { fail }
end
it "returns the result of the block if match? is true" do
- @guard.stub(:match?).and_return(true)
- @guard.run_if(:name) { 42 }.should == 42
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.run_if(:name) { 42 }).to eq(42)
end
it "returns nil if given a block and match? is false" do
- @guard.stub(:match?).and_return(false)
- @guard.run_if(:name) { 42 }.should == nil
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.run_if(:name) { 42 }).to eq(nil)
end
it "returns what #match? returns when no block is given" do
- @guard.stub(:match?).and_return(true)
- @guard.run_if(:name).should == true
- @guard.stub(:match?).and_return(false)
- @guard.run_if(:name).should == false
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.run_if(:name)).to eq(true)
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.run_if(:name)).to eq(false)
end
end
-describe SpecGuard, ".run_unless" do
+RSpec.describe SpecGuard, ".run_unless" do
before :each do
@guard = SpecGuard.new
ScratchPad.clear
end
it "yields if match? returns false" do
- @guard.stub(:match?).and_return(false)
+ allow(@guard).to receive(:match?).and_return(false)
@guard.run_unless(:name) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield if match? returns true" do
- @guard.stub(:match?).and_return(true)
+ allow(@guard).to receive(:match?).and_return(true)
@guard.run_unless(:name) { fail }
end
it "returns the result of the block if match? is false" do
- @guard.stub(:match?).and_return(false)
- @guard.run_unless(:name) { 42 }.should == 42
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.run_unless(:name) { 42 }).to eq(42)
end
it "returns nil if given a block and match? is true" do
- @guard.stub(:match?).and_return(true)
- @guard.run_unless(:name) { 42 }.should == nil
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.run_unless(:name) { 42 }).to eq(nil)
end
it "returns the opposite of what #match? returns when no block is given" do
- @guard.stub(:match?).and_return(true)
- @guard.run_unless(:name).should == false
- @guard.stub(:match?).and_return(false)
- @guard.run_unless(:name).should == true
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(@guard.run_unless(:name)).to eq(false)
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(@guard.run_unless(:name)).to eq(true)
end
end
-describe Object, "#guard" do
+RSpec.describe Object, "#guard" do
before :each do
ScratchPad.clear
end
@@ -254,32 +254,32 @@ describe Object, "#guard" do
end
it "allows to combine guards" do
- guard1 = VersionGuard.new 'x.x.x'
- VersionGuard.stub(:new).and_return(guard1)
+ guard1 = VersionGuard.new '1.2.3', 'x.x.x'
+ allow(VersionGuard).to receive(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
- PlatformGuard.stub(:new).and_return(guard2)
+ allow(PlatformGuard).to receive(:new).and_return(guard2)
- guard1.stub(:match?).and_return(true)
- guard2.stub(:match?).and_return(true)
+ allow(guard1).to receive(:match?).and_return(true)
+ allow(guard2).to receive(:match?).and_return(true)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield
end
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
- guard1.stub(:match?).and_return(false)
- guard2.stub(:match?).and_return(true)
+ allow(guard1).to receive(:match?).and_return(false)
+ allow(guard2).to receive(:match?).and_return(true)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end
- guard1.stub(:match?).and_return(true)
- guard2.stub(:match?).and_return(false)
+ allow(guard1).to receive(:match?).and_return(true)
+ allow(guard2).to receive(:match?).and_return(false)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end
- guard1.stub(:match?).and_return(false)
- guard2.stub(:match?).and_return(false)
+ allow(guard1).to receive(:match?).and_return(false)
+ allow(guard2).to receive(:match?).and_return(false)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end
@@ -289,7 +289,7 @@ describe Object, "#guard" do
guard -> { true } do
ScratchPad.record :yield
end
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield when the Proc returns false" do
@@ -304,12 +304,12 @@ describe Object, "#guard" do
guard -> { false } do
ScratchPad.record :yield1
end
- ScratchPad.recorded.should == :yield1
+ expect(ScratchPad.recorded).to eq(:yield1)
guard -> { true } do
ScratchPad.record :yield2
end
- ScratchPad.recorded.should == :yield2
+ expect(ScratchPad.recorded).to eq(:yield2)
end
it "yields if MSpec.mode?(:verify) is true" do
@@ -318,12 +318,12 @@ describe Object, "#guard" do
guard -> { false } do
ScratchPad.record :yield1
end
- ScratchPad.recorded.should == :yield1
+ expect(ScratchPad.recorded).to eq(:yield1)
guard -> { true } do
ScratchPad.record :yield2
end
- ScratchPad.recorded.should == :yield2
+ expect(ScratchPad.recorded).to eq(:yield2)
end
it "yields if MSpec.mode?(:report) is true" do
@@ -332,72 +332,72 @@ describe Object, "#guard" do
guard -> { false } do
ScratchPad.record :yield1
end
- ScratchPad.recorded.should == :yield1
+ expect(ScratchPad.recorded).to eq(:yield1)
guard -> { true } do
ScratchPad.record :yield2
end
- ScratchPad.recorded.should == :yield2
+ expect(ScratchPad.recorded).to eq(:yield2)
end
it "raises an error if no Proc is given" do
- -> { guard :foo }.should raise_error(RuntimeError)
+ expect { guard :foo }.to raise_error(RuntimeError)
end
it "requires a block" do
- -> {
+ expect {
guard(-> { true })
- }.should raise_error(LocalJumpError)
- -> {
+ }.to raise_error(LocalJumpError)
+ expect {
guard(-> { false })
- }.should raise_error(LocalJumpError)
+ }.to raise_error(LocalJumpError)
end
end
-describe Object, "#guard_not" do
+RSpec.describe Object, "#guard_not" do
before :each do
ScratchPad.clear
end
it "allows to combine guards" do
- guard1 = VersionGuard.new 'x.x.x'
- VersionGuard.stub(:new).and_return(guard1)
+ guard1 = VersionGuard.new '1.2.3', 'x.x.x'
+ allow(VersionGuard).to receive(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
- PlatformGuard.stub(:new).and_return(guard2)
+ allow(PlatformGuard).to receive(:new).and_return(guard2)
- guard1.stub(:match?).and_return(true)
- guard2.stub(:match?).and_return(true)
+ allow(guard1).to receive(:match?).and_return(true)
+ allow(guard2).to receive(:match?).and_return(true)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end
- guard1.stub(:match?).and_return(false)
- guard2.stub(:match?).and_return(true)
+ allow(guard1).to receive(:match?).and_return(false)
+ allow(guard2).to receive(:match?).and_return(true)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield1
end
- ScratchPad.recorded.should == :yield1
+ expect(ScratchPad.recorded).to eq(:yield1)
- guard1.stub(:match?).and_return(true)
- guard2.stub(:match?).and_return(false)
+ allow(guard1).to receive(:match?).and_return(true)
+ allow(guard2).to receive(:match?).and_return(false)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield2
end
- ScratchPad.recorded.should == :yield2
+ expect(ScratchPad.recorded).to eq(:yield2)
- guard1.stub(:match?).and_return(false)
- guard2.stub(:match?).and_return(false)
+ allow(guard1).to receive(:match?).and_return(false)
+ allow(guard2).to receive(:match?).and_return(false)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield3
end
- ScratchPad.recorded.should == :yield3
+ expect(ScratchPad.recorded).to eq(:yield3)
end
it "yields when the Proc returns false" do
guard_not -> { false } do
ScratchPad.record :yield
end
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield when the Proc returns true" do
@@ -407,15 +407,15 @@ describe Object, "#guard_not" do
end
it "raises an error if no Proc is given" do
- -> { guard_not :foo }.should raise_error(RuntimeError)
+ expect { guard_not :foo }.to raise_error(RuntimeError)
end
it "requires a block" do
- -> {
+ expect {
guard_not(-> { true })
- }.should raise_error(LocalJumpError)
- -> {
+ }.to raise_error(LocalJumpError)
+ expect {
guard_not(-> { false })
- }.should raise_error(LocalJumpError)
+ }.to raise_error(LocalJumpError)
end
end
diff --git a/spec/mspec/spec/guards/platform_spec.rb b/spec/mspec/spec/guards/platform_spec.rb
index 749963d3db..bd37432800 100644
--- a/spec/mspec/spec/guards/platform_spec.rb
+++ b/spec/mspec/spec/guards/platform_spec.rb
@@ -1,243 +1,252 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#platform_is" do
+RSpec.describe Object, "#platform_is" do
before :each do
@guard = PlatformGuard.new :dummy
- PlatformGuard.stub(:new).and_return(@guard)
+ allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "does not yield when #os? returns false" do
- PlatformGuard.stub(:os?).and_return(false)
+ allow(PlatformGuard).to receive(:os?).and_return(false)
platform_is(:ruby) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "yields when #os? returns true" do
- PlatformGuard.stub(:os?).and_return(true)
+ allow(PlatformGuard).to receive(:os?).and_return(true)
platform_is(:solarce) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "returns what #os? returns when no block is given" do
- PlatformGuard.stub(:os?).and_return(true)
- platform_is(:solarce).should == true
- PlatformGuard.stub(:os?).and_return(false)
- platform_is(:solarce).should == false
+ allow(PlatformGuard).to receive(:os?).and_return(true)
+ expect(platform_is(:solarce)).to eq(true)
+ allow(PlatformGuard).to receive(:os?).and_return(false)
+ expect(platform_is(:solarce)).to eq(false)
end
it "sets the name of the guard to :platform_is" do
platform_is(:solarce) { }
- @guard.name.should == :platform_is
+ expect(@guard.name).to eq(:platform_is)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(true)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(true)
+ expect(@guard).to receive(:unregister)
+ expect do
platform_is(:solarce) { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
-describe Object, "#platform_is_not" do
+RSpec.describe Object, "#platform_is_not" do
before :each do
@guard = PlatformGuard.new :dummy
- PlatformGuard.stub(:new).and_return(@guard)
+ allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "does not yield when #os? returns true" do
- PlatformGuard.stub(:os?).and_return(true)
+ allow(PlatformGuard).to receive(:os?).and_return(true)
platform_is_not(:ruby) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "yields when #os? returns false" do
- PlatformGuard.stub(:os?).and_return(false)
+ allow(PlatformGuard).to receive(:os?).and_return(false)
platform_is_not(:solarce) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "returns the opposite of what #os? returns when no block is given" do
- PlatformGuard.stub(:os?).and_return(true)
- platform_is_not(:solarce).should == false
- PlatformGuard.stub(:os?).and_return(false)
- platform_is_not(:solarce).should == true
+ allow(PlatformGuard).to receive(:os?).and_return(true)
+ expect(platform_is_not(:solarce)).to eq(false)
+ allow(PlatformGuard).to receive(:os?).and_return(false)
+ expect(platform_is_not(:solarce)).to eq(true)
end
it "sets the name of the guard to :platform_is_not" do
platform_is_not(:solarce) { }
- @guard.name.should == :platform_is_not
+ expect(@guard.name).to eq(:platform_is_not)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(false)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(false)
+ expect(@guard).to receive(:unregister)
+ expect do
platform_is_not(:solarce) { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
-describe Object, "#platform_is :wordsize => SIZE_SPEC" do
+RSpec.describe Object, "#platform_is :c_long_size => SIZE_SPEC" do
before :each do
- @guard = PlatformGuard.new :darwin, :wordsize => 32
- PlatformGuard.stub(:os?).and_return(true)
- PlatformGuard.stub(:new).and_return(@guard)
+ @guard = PlatformGuard.new :darwin, :c_long_size => 32
+ allow(PlatformGuard).to receive(:os?).and_return(true)
+ allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
- it "yields when #wordsize? returns true" do
- PlatformGuard.stub(:wordsize?).and_return(true)
- platform_is(:wordsize => 32) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ it "yields when #c_long_size? returns true" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
+ platform_is(:c_long_size => 32) { ScratchPad.record :yield }
+ expect(ScratchPad.recorded).to eq(:yield)
end
- it "doesn not yield when #wordsize? returns false" do
- PlatformGuard.stub(:wordsize?).and_return(false)
- platform_is(:wordsize => 32) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ it "doesn not yield when #c_long_size? returns false" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
+ platform_is(:c_long_size => 32) { ScratchPad.record :yield }
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
-describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do
+RSpec.describe Object, "#platform_is_not :c_long_size => SIZE_SPEC" do
before :each do
- @guard = PlatformGuard.new :darwin, :wordsize => 32
- PlatformGuard.stub(:os?).and_return(true)
- PlatformGuard.stub(:new).and_return(@guard)
+ @guard = PlatformGuard.new :darwin, :c_long_size => 32
+ allow(PlatformGuard).to receive(:os?).and_return(true)
+ allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
- it "yields when #wordsize? returns false" do
- PlatformGuard.stub(:wordsize?).and_return(false)
- platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ it "yields when #c_long_size? returns false" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
+ platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
+ expect(ScratchPad.recorded).to eq(:yield)
end
- it "doesn not yield when #wordsize? returns true" do
- PlatformGuard.stub(:wordsize?).and_return(true)
- platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ it "doesn not yield when #c_long_size? returns true" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
+ platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
-describe PlatformGuard, ".implementation?" do
+RSpec.describe PlatformGuard, ".implementation?" do
it "returns true if passed :ruby and RUBY_ENGINE == 'ruby'" do
stub_const 'RUBY_ENGINE', 'ruby'
- PlatformGuard.implementation?(:ruby).should == true
+ expect(PlatformGuard.implementation?(:ruby)).to eq(true)
end
it "returns true if passed :rubinius and RUBY_ENGINE == 'rbx'" do
stub_const 'RUBY_ENGINE', 'rbx'
- PlatformGuard.implementation?(:rubinius).should == true
+ expect(PlatformGuard.implementation?(:rubinius)).to eq(true)
end
it "returns true if passed :jruby and RUBY_ENGINE == 'jruby'" do
stub_const 'RUBY_ENGINE', 'jruby'
- PlatformGuard.implementation?(:jruby).should == true
+ expect(PlatformGuard.implementation?(:jruby)).to eq(true)
end
it "returns true if passed :ironruby and RUBY_ENGINE == 'ironruby'" do
stub_const 'RUBY_ENGINE', 'ironruby'
- PlatformGuard.implementation?(:ironruby).should == true
+ expect(PlatformGuard.implementation?(:ironruby)).to eq(true)
end
it "returns true if passed :maglev and RUBY_ENGINE == 'maglev'" do
stub_const 'RUBY_ENGINE', 'maglev'
- PlatformGuard.implementation?(:maglev).should == true
+ expect(PlatformGuard.implementation?(:maglev)).to eq(true)
end
it "returns true if passed :topaz and RUBY_ENGINE == 'topaz'" do
stub_const 'RUBY_ENGINE', 'topaz'
- PlatformGuard.implementation?(:topaz).should == true
+ expect(PlatformGuard.implementation?(:topaz)).to eq(true)
end
it "returns true if passed :ruby and RUBY_ENGINE matches /^ruby/" do
stub_const 'RUBY_ENGINE', 'ruby'
- PlatformGuard.implementation?(:ruby).should == true
+ expect(PlatformGuard.implementation?(:ruby)).to eq(true)
stub_const 'RUBY_ENGINE', 'ruby1.8'
- PlatformGuard.implementation?(:ruby).should == true
+ expect(PlatformGuard.implementation?(:ruby)).to eq(true)
stub_const 'RUBY_ENGINE', 'ruby1.9'
- PlatformGuard.implementation?(:ruby).should == true
+ expect(PlatformGuard.implementation?(:ruby)).to eq(true)
end
- it "raises an error when passed an unrecognized name" do
- stub_const 'RUBY_ENGINE', 'ruby'
- lambda {
- PlatformGuard.implementation?(:python)
- }.should raise_error(/unknown implementation/)
+ it "works for an unrecognized name" do
+ stub_const 'RUBY_ENGINE', 'myrubyimplementation'
+ expect(PlatformGuard.implementation?(:myrubyimplementation)).to eq(true)
+ expect(PlatformGuard.implementation?(:other)).to eq(false)
end
end
-describe PlatformGuard, ".standard?" do
+RSpec.describe PlatformGuard, ".standard?" do
it "returns true if implementation? returns true" do
- PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(true)
- PlatformGuard.standard?.should be_true
+ expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(true)
+ expect(PlatformGuard.standard?).to be_truthy
end
it "returns false if implementation? returns false" do
- PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(false)
- PlatformGuard.standard?.should be_false
+ expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(false)
+ expect(PlatformGuard.standard?).to be_falsey
end
end
-describe PlatformGuard, ".wordsize?" do
+RSpec.describe PlatformGuard, ".c_long_size?" do
it "returns true when arg is 32 and 1.size is 4" do
- PlatformGuard.wordsize?(32).should == (1.size == 4)
+ expect(PlatformGuard.c_long_size?(32)).to eq(1.size == 4)
end
it "returns true when arg is 64 and 1.size is 8" do
- PlatformGuard.wordsize?(64).should == (1.size == 8)
+ expect(PlatformGuard.c_long_size?(64)).to eq(1.size == 8)
end
end
-describe PlatformGuard, ".os?" do
+RSpec.describe PlatformGuard, ".os?" do
before :each do
- stub_const 'PlatformGuard::HOST_OS', 'solarce'
+ stub_const 'PlatformGuard::PLATFORM', 'solarce'
end
it "returns false when arg does not match the platform" do
- PlatformGuard.os?(:ruby).should == false
+ expect(PlatformGuard.os?(:ruby)).to eq(false)
end
it "returns false when no arg matches the platform" do
- PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev).should == false
+ expect(PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev)).to eq(false)
end
it "returns true when arg matches the platform" do
- PlatformGuard.os?(:solarce).should == true
+ expect(PlatformGuard.os?(:solarce)).to eq(true)
end
it "returns true when any arg matches the platform" do
- PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev).should == true
+ expect(PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev)).to eq(true)
end
it "returns true when arg is :windows and the platform contains 'mswin'" do
- stub_const 'PlatformGuard::HOST_OS', 'mswin32'
- PlatformGuard.os?(:windows).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'mswin32'
+ expect(PlatformGuard.os?(:windows)).to eq(true)
end
it "returns true when arg is :windows and the platform contains 'mingw'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.os?(:windows).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.os?(:windows)).to eq(true)
end
it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mswin32'
- PlatformGuard.os?(:linux).should == false
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32'
+ expect(PlatformGuard.os?(:linux)).to eq(false)
end
it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.os?(:linux).should == false
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.os?(:linux)).to eq(false)
+ end
+end
+
+RSpec.describe PlatformGuard, ".os?" do
+ it "returns true if called with the current OS or architecture" do
+ os = RbConfig::CONFIG["host_os"].sub("-gnu", "")
+ arch = RbConfig::CONFIG["host_arch"]
+ expect(PlatformGuard.os?(os)).to eq(true)
+ expect(PlatformGuard.os?(arch)).to eq(true)
+ expect(PlatformGuard.os?("#{arch}-#{os}")).to eq(true)
end
end
-describe PlatformGuard, ".os? on JRuby" do
+RSpec.describe PlatformGuard, ".os? on JRuby" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@@ -257,72 +266,72 @@ describe PlatformGuard, ".os? on JRuby" do
end
it "raises an error when testing for a :java platform" do
- lambda {
+ expect {
PlatformGuard.os?(:java)
- }.should raise_error(":java is not a valid OS")
+ }.to raise_error(":java is not a valid OS")
end
it "returns true when arg is :windows and RUBY_PLATFORM contains 'java' and os?(:windows) is true" do
- stub_const 'PlatformGuard::HOST_OS', 'mswin32'
- PlatformGuard.os?(:windows).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'mswin32'
+ expect(PlatformGuard.os?(:windows)).to eq(true)
end
it "returns true when RUBY_PLATFORM contains 'java' and os?(argument) is true" do
- stub_const 'PlatformGuard::HOST_OS', 'amiga'
- PlatformGuard.os?(:amiga).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'amiga'
+ expect(PlatformGuard.os?(:amiga)).to eq(true)
end
end
-describe PlatformGuard, ".os?" do
+RSpec.describe PlatformGuard, ".os?" do
before :each do
- stub_const 'PlatformGuard::HOST_OS', 'unreal'
+ stub_const 'PlatformGuard::PLATFORM', 'unreal'
end
it "returns true if argument matches RbConfig::CONFIG['host_os']" do
- PlatformGuard.os?(:unreal).should == true
+ expect(PlatformGuard.os?(:unreal)).to eq(true)
end
it "returns true if any argument matches RbConfig::CONFIG['host_os']" do
- PlatformGuard.os?(:bsd, :unreal, :amiga).should == true
+ expect(PlatformGuard.os?(:bsd, :unreal, :amiga)).to eq(true)
end
it "returns false if no argument matches RbConfig::CONFIG['host_os']" do
- PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos).should == false
+ expect(PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos)).to eq(false)
end
it "returns false if argument does not match RbConfig::CONFIG['host_os']" do
- PlatformGuard.os?(:amiga).should == false
+ expect(PlatformGuard.os?(:amiga)).to eq(false)
end
it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mswin32'
- PlatformGuard.os?(:windows).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32'
+ expect(PlatformGuard.os?(:windows)).to eq(true)
end
it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.os?(:windows).should == true
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.os?(:windows)).to eq(true)
end
it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.os?(:linux).should == false
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.os?(:linux)).to eq(false)
end
it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.os?(:linux).should == false
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.os?(:linux)).to eq(false)
end
end
-describe PlatformGuard, ".windows?" do
+RSpec.describe PlatformGuard, ".windows?" do
it "returns true on windows" do
- stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32'
- PlatformGuard.windows?.should == true
+ stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32'
+ expect(PlatformGuard.windows?).to eq(true)
end
it "returns false on non-windows" do
- stub_const 'PlatformGuard::HOST_OS', 'i586-linux'
- PlatformGuard.windows?.should == false
+ stub_const 'PlatformGuard::PLATFORM', 'i586-linux'
+ expect(PlatformGuard.windows?).to eq(false)
end
end
diff --git a/spec/mspec/spec/guards/quarantine_spec.rb b/spec/mspec/spec/guards/quarantine_spec.rb
index e5c7da7939..eb5ff1da27 100644
--- a/spec/mspec/spec/guards/quarantine_spec.rb
+++ b/spec/mspec/spec/guards/quarantine_spec.rb
@@ -1,35 +1,35 @@
require 'spec_helper'
require 'mspec/guards'
-describe QuarantineGuard, "#match?" do
+RSpec.describe QuarantineGuard, "#match?" do
it "returns true" do
- QuarantineGuard.new.match?.should == true
+ expect(QuarantineGuard.new.match?).to eq(true)
end
end
-describe Object, "#quarantine!" do
+RSpec.describe Object, "#quarantine!" do
before :each do
ScratchPad.clear
@guard = QuarantineGuard.new
- QuarantineGuard.stub(:new).and_return(@guard)
+ allow(QuarantineGuard).to receive(:new).and_return(@guard)
end
it "does not yield" do
quarantine! { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "sets the name of the guard to :quarantine!" do
quarantine! { }
- @guard.name.should == :quarantine!
+ expect(@guard.name).to eq(:quarantine!)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(false)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(false)
+ expect(@guard).to receive(:unregister)
+ expect do
quarantine! { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/superuser_spec.rb b/spec/mspec/spec/guards/superuser_spec.rb
index f8815057e1..aba2cc2bb0 100644
--- a/spec/mspec/spec/guards/superuser_spec.rb
+++ b/spec/mspec/spec/guards/superuser_spec.rb
@@ -1,35 +1,35 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#as_superuser" do
+RSpec.describe Object, "#as_superuser" do
before :each do
@guard = SuperUserGuard.new
- SuperUserGuard.stub(:new).and_return(@guard)
+ allow(SuperUserGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "does not yield when Process.euid is not 0" do
- Process.stub(:euid).and_return(501)
+ allow(Process).to receive(:euid).and_return(501)
as_superuser { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "yields when Process.euid is 0" do
- Process.stub(:euid).and_return(0)
+ allow(Process).to receive(:euid).and_return(0)
as_superuser { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "sets the name of the guard to :as_superuser" do
as_superuser { }
- @guard.name.should == :as_superuser
+ expect(@guard.name).to eq(:as_superuser)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(true)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(true)
+ expect(@guard).to receive(:unregister)
+ expect do
as_superuser { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/support_spec.rb b/spec/mspec/spec/guards/support_spec.rb
index 38414abebd..a61d003d6c 100644
--- a/spec/mspec/spec/guards/support_spec.rb
+++ b/spec/mspec/spec/guards/support_spec.rb
@@ -1,54 +1,54 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#not_supported_on" do
+RSpec.describe Object, "#not_supported_on" do
before :each do
ScratchPad.clear
end
it "raises an Exception when passed :ruby" do
stub_const "RUBY_ENGINE", "jruby"
- lambda {
+ expect {
not_supported_on(:ruby) { ScratchPad.record :yield }
- }.should raise_error(Exception)
- ScratchPad.recorded.should_not == :yield
+ }.to raise_error(Exception)
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "does not yield when #implementation? returns true" do
stub_const "RUBY_ENGINE", "jruby"
not_supported_on(:jruby) { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "yields when #standard? returns true" do
stub_const "RUBY_ENGINE", "ruby"
not_supported_on(:rubinius) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "yields when #implementation? returns false" do
stub_const "RUBY_ENGINE", "jruby"
not_supported_on(:rubinius) { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
end
-describe Object, "#not_supported_on" do
+RSpec.describe Object, "#not_supported_on" do
before :each do
@guard = SupportedGuard.new
- SupportedGuard.stub(:new).and_return(@guard)
+ allow(SupportedGuard).to receive(:new).and_return(@guard)
end
it "sets the name of the guard to :not_supported_on" do
not_supported_on(:rubinius) { }
- @guard.name.should == :not_supported_on
+ expect(@guard.name).to eq(:not_supported_on)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(false)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(false)
+ expect(@guard).to receive(:unregister)
+ expect do
not_supported_on(:rubinius) { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
end
end
diff --git a/spec/mspec/spec/guards/user_spec.rb b/spec/mspec/spec/guards/user_spec.rb
index 2de4db7390..2526504656 100644
--- a/spec/mspec/spec/guards/user_spec.rb
+++ b/spec/mspec/spec/guards/user_spec.rb
@@ -1,20 +1,20 @@
require 'spec_helper'
require 'mspec/guards'
-describe Object, "#as_user" do
+RSpec.describe Object, "#as_user" do
before :each do
ScratchPad.clear
end
it "yields when the Process.euid is not 0" do
- Process.stub(:euid).and_return(501)
+ allow(Process).to receive(:euid).and_return(501)
as_user { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield when the Process.euid is 0" do
- Process.stub(:euid).and_return(0)
+ allow(Process).to receive(:euid).and_return(0)
as_user { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
end
diff --git a/spec/mspec/spec/guards/version_spec.rb b/spec/mspec/spec/guards/version_spec.rb
index 07eb451ec9..5a5f4ddc3b 100644
--- a/spec/mspec/spec/guards/version_spec.rb
+++ b/spec/mspec/spec/guards/version_spec.rb
@@ -11,80 +11,102 @@ require 'mspec/guards'
# is as typically understood: a..b means v >= a and v <= b;
# a...b means v >= a and v < b.
-describe VersionGuard, "#match?" do
+RSpec.describe VersionGuard, "#match?" do
before :each do
hide_deprecation_warnings
- stub_const "VersionGuard::FULL_RUBY_VERSION", SpecVersion.new('1.8.6')
+ @current = '1.8.6'
end
it "returns true when the argument is equal to RUBY_VERSION" do
- VersionGuard.new('1.8.6').match?.should == true
+ expect(VersionGuard.new(@current, '1.8.6').match?).to eq(true)
end
it "returns true when the argument is less than RUBY_VERSION" do
- VersionGuard.new('1.8').match?.should == true
- VersionGuard.new('1.8.5').match?.should == true
+ expect(VersionGuard.new(@current, '1.8').match?).to eq(true)
+ expect(VersionGuard.new(@current, '1.8.5').match?).to eq(true)
end
it "returns false when the argument is greater than RUBY_VERSION" do
- VersionGuard.new('1.8.7').match?.should == false
- VersionGuard.new('1.9.2').match?.should == false
+ expect(VersionGuard.new(@current, '1.8.7').match?).to eq(false)
+ expect(VersionGuard.new(@current, '1.9.2').match?).to eq(false)
end
it "returns true when the argument range includes RUBY_VERSION" do
- VersionGuard.new('1.8.5'..'1.8.7').match?.should == true
- VersionGuard.new('1.8'..'1.9').match?.should == true
- VersionGuard.new('1.8'...'1.9').match?.should == true
- VersionGuard.new('1.8'..'1.8.6').match?.should == true
- VersionGuard.new('1.8.5'..'1.8.6').match?.should == true
- VersionGuard.new(''...'1.8.7').match?.should == true
+ expect(VersionGuard.new(@current, '1.8.5'..'1.8.7').match?).to eq(true)
+ expect(VersionGuard.new(@current, '1.8'..'1.9').match?).to eq(true)
+ expect(VersionGuard.new(@current, '1.8'...'1.9').match?).to eq(true)
+ expect(VersionGuard.new(@current, '1.8'..'1.8.6').match?).to eq(true)
+ expect(VersionGuard.new(@current, '1.8.5'..'1.8.6').match?).to eq(true)
+ expect(VersionGuard.new(@current, ''...'1.8.7').match?).to eq(true)
end
it "returns false when the argument range does not include RUBY_VERSION" do
- VersionGuard.new('1.8.7'..'1.8.9').match?.should == false
- VersionGuard.new('1.8.4'..'1.8.5').match?.should == false
- VersionGuard.new('1.8.4'...'1.8.6').match?.should == false
- VersionGuard.new('1.8.5'...'1.8.6').match?.should == false
- VersionGuard.new(''...'1.8.6').match?.should == false
+ expect(VersionGuard.new(@current, '1.8.7'..'1.8.9').match?).to eq(false)
+ expect(VersionGuard.new(@current, '1.8.4'..'1.8.5').match?).to eq(false)
+ expect(VersionGuard.new(@current, '1.8.4'...'1.8.6').match?).to eq(false)
+ expect(VersionGuard.new(@current, '1.8.5'...'1.8.6').match?).to eq(false)
+ expect(VersionGuard.new(@current, ''...'1.8.6').match?).to eq(false)
end
end
-describe Object, "#ruby_version_is" do
+RSpec.describe Object, "#ruby_version_is" do
before :each do
- @guard = VersionGuard.new 'x.x.x'
- VersionGuard.stub(:new).and_return(@guard)
+ @guard = VersionGuard.new '1.2.3', 'x.x.x'
+ allow(VersionGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields when #match? returns true" do
- @guard.stub(:match?).and_return(true)
+ allow(@guard).to receive(:match?).and_return(true)
ruby_version_is('x.x.x') { ScratchPad.record :yield }
- ScratchPad.recorded.should == :yield
+ expect(ScratchPad.recorded).to eq(:yield)
end
it "does not yield when #match? returns false" do
- @guard.stub(:match?).and_return(false)
+ allow(@guard).to receive(:match?).and_return(false)
ruby_version_is('x.x.x') { ScratchPad.record :yield }
- ScratchPad.recorded.should_not == :yield
+ expect(ScratchPad.recorded).not_to eq(:yield)
end
it "returns what #match? returns when no block is given" do
- @guard.stub(:match?).and_return(true)
- ruby_version_is('x.x.x').should == true
- @guard.stub(:match?).and_return(false)
- ruby_version_is('x.x.x').should == false
+ allow(@guard).to receive(:match?).and_return(true)
+ expect(ruby_version_is('x.x.x')).to eq(true)
+ allow(@guard).to receive(:match?).and_return(false)
+ expect(ruby_version_is('x.x.x')).to eq(false)
end
it "sets the name of the guard to :ruby_version_is" do
ruby_version_is("") { }
- @guard.name.should == :ruby_version_is
+ expect(@guard.name).to eq(:ruby_version_is)
end
it "calls #unregister even when an exception is raised in the guard block" do
- @guard.should_receive(:match?).and_return(true)
- @guard.should_receive(:unregister)
- lambda do
+ expect(@guard).to receive(:match?).and_return(true)
+ expect(@guard).to receive(:unregister)
+ expect do
ruby_version_is("") { raise Exception }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
+ end
+end
+
+RSpec.describe Object, "#version_is" do
+ before :each do
+ hide_deprecation_warnings
+ end
+
+ it "returns the expected values" do
+ expect(version_is('1.2.3', '1.2.2')).to eq(true)
+ expect(version_is('1.2.3', '1.2.3')).to eq(true)
+ expect(version_is('1.2.3', '1.2.4')).to eq(false)
+
+ expect(version_is('1.2.3', '1')).to eq(true)
+ expect(version_is('1.2.3', '1.0')).to eq(true)
+ expect(version_is('1.2.3', '2')).to eq(false)
+ expect(version_is('1.2.3', '2.0')).to eq(false)
+
+ expect(version_is('1.2.3', '1.2.2'..'1.2.4')).to eq(true)
+ expect(version_is('1.2.3', '1.2.2'..'1.2.3')).to eq(true)
+ expect(version_is('1.2.3', '1.2.2'...'1.2.3')).to eq(false)
+ expect(version_is('1.2.3', '1.2.3'..'1.2.4')).to eq(true)
end
end
diff --git a/spec/mspec/spec/helpers/argf_spec.rb b/spec/mspec/spec/helpers/argf_spec.rb
index cf5eb0fe88..1412d71f84 100644
--- a/spec/mspec/spec/helpers/argf_spec.rb
+++ b/spec/mspec/spec/helpers/argf_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#argf" do
+RSpec.describe Object, "#argf" do
before :each do
@saved_argv = ARGV.dup
@argv = [__FILE__]
@@ -10,28 +10,28 @@ describe Object, "#argf" do
it "sets @argf to an instance of ARGF.class with the given argv" do
argf @argv do
- @argf.should be_an_instance_of ARGF.class
- @argf.filename.should == @argv.first
+ expect(@argf).to be_an_instance_of ARGF.class
+ expect(@argf.filename).to eq(@argv.first)
end
- @argf.should be_nil
+ expect(@argf).to be_nil
end
it "does not alter ARGV nor ARGF" do
argf @argv do
end
- ARGV.should == @saved_argv
- ARGF.argv.should == @saved_argv
+ expect(ARGV).to eq(@saved_argv)
+ expect(ARGF.argv).to eq(@saved_argv)
end
it "does not close STDIN" do
argf ['-'] do
end
- STDIN.should_not be_closed
+ expect(STDIN).not_to be_closed
end
it "disallows nested calls" do
argf @argv do
- lambda { argf @argv }.should raise_error
+ expect { argf @argv }.to raise_error
end
end
end
diff --git a/spec/mspec/spec/helpers/argv_spec.rb b/spec/mspec/spec/helpers/argv_spec.rb
index c3b21c7639..1db7e38650 100644
--- a/spec/mspec/spec/helpers/argv_spec.rb
+++ b/spec/mspec/spec/helpers/argv_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#argv" do
+RSpec.describe Object, "#argv" do
before :each do
ScratchPad.clear
@@ -12,16 +12,16 @@ describe Object, "#argv" do
it "replaces and restores the value of ARGV" do
argv @argv
- ARGV.should == @argv
+ expect(ARGV).to eq(@argv)
argv :restore
- ARGV.should == @saved_argv
+ expect(ARGV).to eq(@saved_argv)
end
it "yields to the block after setting ARGV" do
argv @argv do
ScratchPad.record ARGV.dup
end
- ScratchPad.recorded.should == @argv
- ARGV.should == @saved_argv
+ expect(ScratchPad.recorded).to eq(@argv)
+ expect(ARGV).to eq(@saved_argv)
end
end
diff --git a/spec/mspec/spec/helpers/datetime_spec.rb b/spec/mspec/spec/helpers/datetime_spec.rb
index 8696c0c9c7..af4f557376 100644
--- a/spec/mspec/spec/helpers/datetime_spec.rb
+++ b/spec/mspec/spec/helpers/datetime_spec.rb
@@ -2,43 +2,43 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#new_datetime" do
+RSpec.describe Object, "#new_datetime" do
it "returns a default DateTime instance" do
- new_datetime.should == DateTime.new
+ expect(new_datetime).to eq(DateTime.new)
end
it "returns a DateTime instance with the specified year value" do
d = new_datetime :year => 1970
- d.year.should == 1970
+ expect(d.year).to eq(1970)
end
it "returns a DateTime instance with the specified month value" do
d = new_datetime :month => 11
- d.mon.should == 11
+ expect(d.mon).to eq(11)
end
it "returns a DateTime instance with the specified day value" do
d = new_datetime :day => 23
- d.day.should == 23
+ expect(d.day).to eq(23)
end
it "returns a DateTime instance with the specified hour value" do
d = new_datetime :hour => 10
- d.hour.should == 10
+ expect(d.hour).to eq(10)
end
it "returns a DateTime instance with the specified minute value" do
d = new_datetime :minute => 10
- d.min.should == 10
+ expect(d.min).to eq(10)
end
it "returns a DateTime instance with the specified second value" do
d = new_datetime :second => 2
- d.sec.should == 2
+ expect(d.sec).to eq(2)
end
it "returns a DateTime instance with the specified offset value" do
d = new_datetime :offset => Rational(3,24)
- d.offset.should == Rational(3,24)
+ expect(d.offset).to eq(Rational(3,24))
end
end
diff --git a/spec/mspec/spec/helpers/fixture_spec.rb b/spec/mspec/spec/helpers/fixture_spec.rb
index 4dbdd092f1..d8e2ae7be4 100644
--- a/spec/mspec/spec/helpers/fixture_spec.rb
+++ b/spec/mspec/spec/helpers/fixture_spec.rb
@@ -2,24 +2,24 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#fixture" do
+RSpec.describe Object, "#fixture" do
before :each do
@dir = File.realpath("..", __FILE__)
end
it "returns the expanded path to a fixture file" do
name = fixture(__FILE__, "subdir", "file.txt")
- name.should == "#{@dir}/fixtures/subdir/file.txt"
+ expect(name).to eq("#{@dir}/fixtures/subdir/file.txt")
end
it "omits '/shared' if it is the suffix of the directory string" do
name = fixture("#{@dir}/shared/file.rb", "subdir", "file.txt")
- name.should == "#{@dir}/fixtures/subdir/file.txt"
+ expect(name).to eq("#{@dir}/fixtures/subdir/file.txt")
end
it "does not append '/fixtures' if it is the suffix of the directory string" do
commands_dir = "#{File.dirname(@dir)}/commands"
name = fixture("#{commands_dir}/fixtures/file.rb", "subdir", "file.txt")
- name.should == "#{commands_dir}/fixtures/subdir/file.txt"
+ expect(name).to eq("#{commands_dir}/fixtures/subdir/file.txt")
end
end
diff --git a/spec/mspec/spec/helpers/flunk_spec.rb b/spec/mspec/spec/helpers/flunk_spec.rb
index 7b1216d3f7..b6a1f21c12 100644
--- a/spec/mspec/spec/helpers/flunk_spec.rb
+++ b/spec/mspec/spec/helpers/flunk_spec.rb
@@ -4,17 +4,17 @@ require 'mspec/runner/mspec'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#flunk" do
+RSpec.describe Object, "#flunk" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
end
it "raises an SpecExpectationNotMetError unconditionally" do
- lambda { flunk }.should raise_error(SpecExpectationNotMetError)
+ expect { flunk }.to raise_error(SpecExpectationNotMetError)
end
it "accepts on argument for an optional message" do
- lambda {flunk "test"}.should raise_error(SpecExpectationNotMetError)
+ expect {flunk "test"}.to raise_error(SpecExpectationNotMetError)
end
end
diff --git a/spec/mspec/spec/helpers/fs_spec.rb b/spec/mspec/spec/helpers/fs_spec.rb
index e40c6c5607..15bb43903a 100644
--- a/spec/mspec/spec/helpers/fs_spec.rb
+++ b/spec/mspec/spec/helpers/fs_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#cp" do
+RSpec.describe Object, "#cp" do
before :each do
@source = tmp("source.txt")
@copy = tmp("copied.txt")
@@ -19,12 +19,12 @@ describe Object, "#cp" do
it "copies a file" do
cp @source, @copy
data = IO.read(@copy)
- data.should == @contents
- data.should == IO.read(@source)
+ expect(data).to eq(@contents)
+ expect(data).to eq(IO.read(@source))
end
end
-describe Object, "#touch" do
+RSpec.describe Object, "#touch" do
before :all do
@name = tmp("touched.txt")
end
@@ -35,29 +35,29 @@ describe Object, "#touch" do
it "creates a file" do
touch @name
- File.exist?(@name).should be_true
+ expect(File.exist?(@name)).to be_truthy
end
it "accepts an optional mode argument" do
touch @name, "wb"
- File.exist?(@name).should be_true
+ expect(File.exist?(@name)).to be_truthy
end
it "overwrites an existing file" do
File.open(@name, "w") { |f| f.puts "used" }
- File.size(@name).should > 0
+ expect(File.size(@name)).to be > 0
touch @name
- File.size(@name).should == 0
+ expect(File.size(@name)).to eq(0)
end
it "yields the open file if passed a block" do
touch(@name) { |f| f.write "touching" }
- IO.read(@name).should == "touching"
+ expect(IO.read(@name)).to eq("touching")
end
end
-describe Object, "#touch" do
+RSpec.describe Object, "#touch" do
before :all do
@name = tmp("subdir/touched.txt")
end
@@ -68,11 +68,11 @@ describe Object, "#touch" do
it "creates all the directories in the path to the file" do
touch @name
- File.exist?(@name).should be_true
+ expect(File.exist?(@name)).to be_truthy
end
end
-describe Object, "#mkdir_p" do
+RSpec.describe Object, "#mkdir_p" do
before :all do
@dir1 = tmp("/nested")
@dir2 = @dir1 + "/directory"
@@ -86,17 +86,17 @@ describe Object, "#mkdir_p" do
it "creates all the directories in a path" do
mkdir_p @dir2
- File.directory?(@dir2).should be_true
+ expect(File.directory?(@dir2)).to be_truthy
end
it "raises an ArgumentError if a path component is a file" do
File.open(@dir1, "w") { |f| }
- lambda { mkdir_p @dir2 }.should raise_error(ArgumentError)
+ expect { mkdir_p @dir2 }.to raise_error(ArgumentError)
end
it "works if multiple processes try to create the same directory concurrently" do
original = File.method(:directory?)
- File.should_receive(:directory?).at_least(:once) { |dir|
+ expect(File).to receive(:directory?).at_least(:once) { |dir|
ret = original.call(dir)
if !ret and dir == @dir1
Dir.mkdir(dir) # Simulate race
@@ -104,11 +104,11 @@ describe Object, "#mkdir_p" do
ret
}
mkdir_p @dir1
- original.call(@dir1).should be_true
+ expect(original.call(@dir1)).to be_truthy
end
end
-describe Object, "#rm_r" do
+RSpec.describe Object, "#rm_r" do
before :all do
@topdir = tmp("rm_r_tree")
@topfile = @topdir + "/file.txt"
@@ -137,59 +137,59 @@ describe Object, "#rm_r" do
end
it "raises an ArgumentError if the path is not prefixed by MSPEC_RM_PREFIX" do
- lambda { rm_r "some_file.txt" }.should raise_error(ArgumentError)
+ expect { rm_r "some_file.txt" }.to raise_error(ArgumentError)
end
it "removes a single file" do
rm_r @subfile
- File.exist?(@subfile).should be_false
+ expect(File.exist?(@subfile)).to be_falsey
end
it "removes multiple files" do
rm_r @topfile, @subfile
- File.exist?(@topfile).should be_false
- File.exist?(@subfile).should be_false
+ expect(File.exist?(@topfile)).to be_falsey
+ expect(File.exist?(@subfile)).to be_falsey
end
platform_is_not :windows do
it "removes a symlink to a file" do
File.symlink @topfile, @link
rm_r @link
- File.exist?(@link).should be_false
+ expect(File.exist?(@link)).to be_falsey
end
it "removes a symlink to a directory" do
File.symlink @subdir1, @link
rm_r @link
- lambda do
+ expect do
File.lstat(@link)
- end.should raise_error(Errno::ENOENT)
- File.exist?(@subdir1).should be_true
+ end.to raise_error(Errno::ENOENT)
+ expect(File.exist?(@subdir1)).to be_truthy
end
it "removes a dangling symlink" do
File.symlink "non_existent_file", @link
rm_r @link
- lambda do
+ expect do
File.lstat(@link)
- end.should raise_error(Errno::ENOENT)
+ end.to raise_error(Errno::ENOENT)
end
it "removes a socket" do
require 'socket'
UNIXServer.new(@socket).close
rm_r @socket
- File.exist?(@socket).should be_false
+ expect(File.exist?(@socket)).to be_falsey
end
end
it "removes a single directory" do
rm_r @subdir2
- File.directory?(@subdir2).should be_false
+ expect(File.directory?(@subdir2)).to be_falsey
end
it "recursively removes a directory tree" do
rm_r @topdir
- File.directory?(@topdir).should be_false
+ expect(File.directory?(@topdir)).to be_falsey
end
end
diff --git a/spec/mspec/spec/helpers/io_spec.rb b/spec/mspec/spec/helpers/io_spec.rb
index 3219f59947..14c1a2d6b5 100644
--- a/spec/mspec/spec/helpers/io_spec.rb
+++ b/spec/mspec/spec/helpers/io_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe IOStub do
+RSpec.describe IOStub do
before :each do
@out = IOStub.new
@sep = $\
@@ -14,42 +14,42 @@ describe IOStub do
it "provides a write method" do
@out.write "this"
- @out.should == "this"
+ expect(@out).to eq("this")
end
it "concatenates the arguments sent to write" do
@out.write "flim ", "flam"
- @out.should == "flim flam"
+ expect(@out).to eq("flim flam")
end
it "provides a print method that appends the default separator" do
$\ = " [newline] "
@out.print "hello"
@out.print "world"
- @out.should == "hello [newline] world [newline] "
+ expect(@out).to eq("hello [newline] world [newline] ")
end
it "provides a puts method that appends the default separator" do
@out.puts "hello", 1, 2, 3
- @out.should == "hello\n1\n2\n3\n"
+ expect(@out).to eq("hello\n1\n2\n3\n")
end
it "provides a puts method that appends separator if argument not given" do
@out.puts
- @out.should == "\n"
+ expect(@out).to eq("\n")
end
it "provides a printf method" do
@out.printf "%-10s, %03d, %2.1f", "test", 42, 4.2
- @out.should == "test , 042, 4.2"
+ expect(@out).to eq("test , 042, 4.2")
end
it "provides a flush method that does nothing and returns self" do
- @out.flush.should == @out
+ expect(@out.flush).to eq(@out)
end
end
-describe Object, "#new_fd" do
+RSpec.describe Object, "#new_fd" do
before :each do
@name = tmp("io_specs")
@io = nil
@@ -60,36 +60,36 @@ describe Object, "#new_fd" do
rm_r @name
end
- it "returns a Integer that can be used to create an IO instance" do
+ it "returns an Integer that can be used to create an IO instance" do
fd = new_fd @name
- fd.should be_kind_of(Integer)
+ expect(fd).to be_kind_of(Integer)
- @io = IO.new fd, fmode('w:utf-8')
+ @io = IO.new fd, 'w:utf-8'
@io.sync = true
@io.print "io data"
- IO.read(@name).should == "io data"
+ expect(IO.read(@name)).to eq("io data")
end
it "accepts an options Hash" do
- FeatureGuard.stub(:enabled?).and_return(true)
+ allow(FeatureGuard).to receive(:enabled?).and_return(true)
fd = new_fd @name, { :mode => 'w:utf-8' }
- fd.should be_kind_of(Integer)
+ expect(fd).to be_kind_of(Integer)
- @io = IO.new fd, fmode('w:utf-8')
+ @io = IO.new fd, 'w:utf-8'
@io.sync = true
@io.print "io data"
- IO.read(@name).should == "io data"
+ expect(IO.read(@name)).to eq("io data")
end
it "raises an ArgumentError if the options Hash does not include :mode" do
- FeatureGuard.stub(:enabled?).and_return(true)
- lambda { new_fd @name, { :encoding => "utf-8" } }.should raise_error(ArgumentError)
+ allow(FeatureGuard).to receive(:enabled?).and_return(true)
+ expect { new_fd @name, { :encoding => "utf-8" } }.to raise_error(ArgumentError)
end
end
-describe Object, "#new_io" do
+RSpec.describe Object, "#new_io" do
before :each do
@name = tmp("io_specs.txt")
end
@@ -99,16 +99,16 @@ describe Object, "#new_io" do
rm_r @name
end
- it "returns an IO instance" do
+ it "returns a File instance" do
@io = new_io @name
- @io.should be_an_instance_of(IO)
+ expect(@io).to be_an_instance_of(File)
end
it "opens the IO for reading if passed 'r'" do
touch(@name) { |f| f.print "io data" }
@io = new_io @name, "r"
- @io.read.should == "io data"
- lambda { @io.puts "more data" }.should raise_error(IOError)
+ expect(@io.read).to eq("io data")
+ expect { @io.puts "more data" }.to raise_error(IOError)
end
it "opens the IO for writing if passed 'w'" do
@@ -116,14 +116,14 @@ describe Object, "#new_io" do
@io.sync = true
@io.print "io data"
- IO.read(@name).should == "io data"
+ expect(IO.read(@name)).to eq("io data")
end
it "opens the IO for reading if passed { :mode => 'r' }" do
touch(@name) { |f| f.print "io data" }
@io = new_io @name, { :mode => "r" }
- @io.read.should == "io data"
- lambda { @io.puts "more data" }.should raise_error(IOError)
+ expect(@io.read).to eq("io data")
+ expect { @io.puts "more data" }.to raise_error(IOError)
end
it "opens the IO for writing if passed { :mode => 'w' }" do
@@ -131,44 +131,6 @@ describe Object, "#new_io" do
@io.sync = true
@io.print "io data"
- IO.read(@name).should == "io data"
- end
-end
-
-describe Object, "#fmode" do
- it "returns the argument unmodified if :encoding feature is enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true)
- fmode("rb:binary:utf-8").should == "rb:binary:utf-8"
- end
-
- it "returns only the file access mode if :encoding feature is not enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(false)
- fmode("rb:binary:utf-8").should == "rb"
- end
-end
-
-describe Object, "#options_or_mode" do
- describe "if passed a Hash" do
- it "returns a mode string if :encoding feature is not enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).twice.and_return(false)
- options_or_mode(:mode => "rb:binary").should == "rb"
- end
-
- it "returns a Hash if :encoding feature is enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true)
- options_or_mode(:mode => "rb:utf-8").should == { :mode => "rb:utf-8" }
- end
- end
-
- describe "if passed a String" do
- it "returns only the file access mode if :encoding feature is not enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(false)
- options_or_mode("rb:binary:utf-8").should == "rb"
- end
-
- it "returns the argument unmodified if :encoding feature is enabled" do
- FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true)
- options_or_mode("rb:binary:utf-8").should == "rb:binary:utf-8"
- end
+ expect(IO.read(@name)).to eq("io data")
end
end
diff --git a/spec/mspec/spec/helpers/mock_to_path_spec.rb b/spec/mspec/spec/helpers/mock_to_path_spec.rb
index 464e7e5440..c2ce985190 100644
--- a/spec/mspec/spec/helpers/mock_to_path_spec.rb
+++ b/spec/mspec/spec/helpers/mock_to_path_spec.rb
@@ -1,17 +1,23 @@
require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
+require 'mspec/mocks'
+
+RSpec.describe Object, "#mock_to_path" do
+ before :each do
+ state = double("run state").as_null_object
+ expect(MSpec).to receive(:current).and_return(state)
+ end
-describe Object, "#mock_to_path" do
it "returns an object that responds to #to_path" do
obj = mock_to_path("foo")
- obj.should be_a(MockObject)
- obj.should respond_to(:to_path)
+ expect(obj).to be_a(MockObject)
+ expect(obj).to respond_to(:to_path)
obj.to_path
end
it "returns the provided path when #to_path is called" do
obj = mock_to_path("/tmp/foo")
- obj.to_path.should == "/tmp/foo"
+ expect(obj.to_path).to eq("/tmp/foo")
end
end
diff --git a/spec/mspec/spec/helpers/numeric_spec.rb b/spec/mspec/spec/helpers/numeric_spec.rb
index 2ea56e5961..64495b7276 100644
--- a/spec/mspec/spec/helpers/numeric_spec.rb
+++ b/spec/mspec/spec/helpers/numeric_spec.rb
@@ -2,24 +2,30 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#bignum_value" do
+RSpec.describe Object, "#bignum_value" do
it "returns a value that is an instance of Bignum on any platform" do
- bignum_value.should == 0x8000_0000_0000_0000
+ expect(bignum_value).to be > fixnum_max
end
it "returns the default value incremented by the argument" do
- bignum_value(42).should == 0x8000_0000_0000_002a
+ expect(bignum_value(42)).to eq(bignum_value + 42)
end
end
-describe Object, "#nan_value" do
+RSpec.describe Object, "-bignum_value" do
+ it "returns a value that is an instance of Bignum on any platform" do
+ expect(-bignum_value).to be < fixnum_min
+ end
+end
+
+RSpec.describe Object, "#nan_value" do
it "returns NaN" do
- nan_value.nan?.should be_true
+ expect(nan_value.nan?).to be_truthy
end
end
-describe Object, "#infinity_value" do
+RSpec.describe Object, "#infinity_value" do
it "returns Infinity" do
- infinity_value.infinite?.should == 1
+ expect(infinity_value.infinite?).to eq(1)
end
end
diff --git a/spec/mspec/spec/helpers/ruby_exe_spec.rb b/spec/mspec/spec/helpers/ruby_exe_spec.rb
index 8036043578..56bade1ba9 100644
--- a/spec/mspec/spec/helpers/ruby_exe_spec.rb
+++ b/spec/mspec/spec/helpers/ruby_exe_spec.rb
@@ -10,7 +10,7 @@ class RubyExeSpecs
public :ruby_exe
end
-describe "#ruby_exe_options" do
+RSpec.describe "#ruby_exe_options" do
before :each do
@ruby_exe_env = ENV['RUBY_EXE']
@script = RubyExeSpecs.new
@@ -22,89 +22,89 @@ describe "#ruby_exe_options" do
it "returns ENV['RUBY_EXE'] when passed :env" do
ENV['RUBY_EXE'] = "kowabunga"
- @script.ruby_exe_options(:env).should == "kowabunga"
+ expect(@script.ruby_exe_options(:env)).to eq("kowabunga")
end
it "returns 'bin/jruby' when passed :engine and RUBY_ENGINE is 'jruby'" do
stub_const "RUBY_ENGINE", 'jruby'
- @script.ruby_exe_options(:engine).should == 'bin/jruby'
+ expect(@script.ruby_exe_options(:engine)).to eq('bin/jruby')
end
it "returns 'bin/rbx' when passed :engine, RUBY_ENGINE is 'rbx'" do
stub_const "RUBY_ENGINE", 'rbx'
- @script.ruby_exe_options(:engine).should == 'bin/rbx'
+ expect(@script.ruby_exe_options(:engine)).to eq('bin/rbx')
end
it "returns 'ir' when passed :engine and RUBY_ENGINE is 'ironruby'" do
stub_const "RUBY_ENGINE", 'ironruby'
- @script.ruby_exe_options(:engine).should == 'ir'
+ expect(@script.ruby_exe_options(:engine)).to eq('ir')
end
it "returns 'maglev-ruby' when passed :engine and RUBY_ENGINE is 'maglev'" do
stub_const "RUBY_ENGINE", 'maglev'
- @script.ruby_exe_options(:engine).should == 'maglev-ruby'
+ expect(@script.ruby_exe_options(:engine)).to eq('maglev-ruby')
end
it "returns 'topaz' when passed :engine and RUBY_ENGINE is 'topaz'" do
stub_const "RUBY_ENGINE", 'topaz'
- @script.ruby_exe_options(:engine).should == 'topaz'
+ expect(@script.ruby_exe_options(:engine)).to eq('topaz')
end
it "returns RUBY_ENGINE + $(EXEEXT) when passed :name" do
bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
name = File.join ".", bin
- @script.ruby_exe_options(:name).should == name
+ expect(@script.ruby_exe_options(:name)).to eq(name)
end
it "returns $(bindir)/$(RUBY_INSTALL_NAME) + $(EXEEXT) when passed :install_name" do
bin = RbConfig::CONFIG['RUBY_INSTALL_NAME'] + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '')
name = File.join RbConfig::CONFIG['bindir'], bin
- @script.ruby_exe_options(:install_name).should == name
+ expect(@script.ruby_exe_options(:install_name)).to eq(name)
end
end
-describe "#resolve_ruby_exe" do
+RSpec.describe "#resolve_ruby_exe" do
before :each do
@name = "ruby_spec_exe"
@script = RubyExeSpecs.new
end
it "returns the value returned by #ruby_exe_options if it exists and is executable" do
- @script.should_receive(:ruby_exe_options).and_return(@name)
- File.should_receive(:file?).with(@name).and_return(true)
- File.should_receive(:executable?).with(@name).and_return(true)
- File.should_receive(:expand_path).with(@name).and_return(@name)
- @script.resolve_ruby_exe.should == @name
+ expect(@script).to receive(:ruby_exe_options).and_return(@name)
+ expect(File).to receive(:file?).with(@name).and_return(true)
+ expect(File).to receive(:executable?).with(@name).and_return(true)
+ expect(File).to receive(:expand_path).with(@name).and_return(@name)
+ expect(@script.resolve_ruby_exe).to eq(@name)
end
it "expands the path portion of the result of #ruby_exe_options" do
- @script.should_receive(:ruby_exe_options).and_return("#{@name}")
- File.should_receive(:file?).with(@name).and_return(true)
- File.should_receive(:executable?).with(@name).and_return(true)
- File.should_receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}")
- @script.resolve_ruby_exe.should == "/usr/bin/#{@name}"
+ expect(@script).to receive(:ruby_exe_options).and_return("#{@name}")
+ expect(File).to receive(:file?).with(@name).and_return(true)
+ expect(File).to receive(:executable?).with(@name).and_return(true)
+ expect(File).to receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}")
+ expect(@script.resolve_ruby_exe).to eq("/usr/bin/#{@name}")
end
it "adds the flags after the executable" do
@name = 'bin/rbx'
- @script.should_receive(:ruby_exe_options).and_return(@name)
- File.should_receive(:file?).with(@name).and_return(true)
- File.should_receive(:executable?).with(@name).and_return(true)
- File.should_receive(:expand_path).with(@name).and_return(@name)
+ expect(@script).to receive(:ruby_exe_options).and_return(@name)
+ expect(File).to receive(:file?).with(@name).and_return(true)
+ expect(File).to receive(:executable?).with(@name).and_return(true)
+ expect(File).to receive(:expand_path).with(@name).and_return(@name)
- ENV.should_receive(:[]).with("RUBY_FLAGS").and_return('-X19')
- @script.resolve_ruby_exe.should == 'bin/rbx -X19'
+ expect(ENV).to receive(:[]).with("RUBY_FLAGS").and_return('-X19')
+ expect(@script.resolve_ruby_exe).to eq('bin/rbx -X19')
end
it "raises an exception if no exe is found" do
- File.should_receive(:file?).at_least(:once).and_return(false)
- lambda {
+ expect(File).to receive(:file?).at_least(:once).and_return(false)
+ expect {
@script.resolve_ruby_exe
- }.should raise_error(Exception)
+ }.to raise_error(Exception)
end
end
-describe Object, "#ruby_cmd" do
+RSpec.describe Object, "#ruby_cmd" do
before :each do
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
@@ -115,83 +115,142 @@ describe Object, "#ruby_cmd" do
end
it "returns a command that runs the given file if it is a file that exists" do
- File.should_receive(:exist?).with(@file).and_return(true)
- @script.ruby_cmd(@file).should == "ruby_spec_exe -w -Q some/ruby/file.rb"
+ expect(File).to receive(:exist?).with(@file).and_return(true)
+ expect(@script.ruby_cmd(@file)).to eq("ruby_spec_exe -w -Q some/ruby/file.rb")
end
it "includes the given options and arguments with a file" do
- File.should_receive(:exist?).with(@file).and_return(true)
- @script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt").should ==
+ expect(File).to receive(:exist?).with(@file).and_return(true)
+ expect(@script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt")).to eq(
"ruby_spec_exe -w -Q -w -Cdir some/ruby/file.rb < file.txt"
+ )
end
it "includes the given options and arguments with -e" do
- File.should_receive(:exist?).with(@code).and_return(false)
- @script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt").should ==
+ expect(File).to receive(:exist?).with(@code).and_return(false)
+ expect(@script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt")).to eq(
%(ruby_spec_exe -w -Q -W0 -Cdir -e "some \\"real\\" 'ruby' code" < file.txt)
+ )
end
it "returns a command with options and arguments but without code or file" do
- @script.ruby_cmd(nil, :options => "-c", :args => "> file.txt").should ==
+ expect(@script.ruby_cmd(nil, :options => "-c", :args => "> file.txt")).to eq(
"ruby_spec_exe -w -Q -c > file.txt"
+ )
end
end
-describe Object, "#ruby_exe" do
+RSpec.describe Object, "#ruby_exe" do
before :each do
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
@script = RubyExeSpecs.new
- @script.stub(:`)
+ allow(IO).to receive(:popen).and_return('OUTPUT')
+
+ status_successful = double(Process::Status, exited?: true, exitstatus: 0)
+ allow(Process).to receive(:last_status).and_return(status_successful)
+ end
+
+ it "returns command STDOUT when given command" do
+ code = "code"
+ options = {}
+ output = "output"
+ expect(IO).to receive(:popen).and_return(output)
+
+ expect(@script.ruby_exe(code, options)).to eq output
end
it "returns an Array containing the interpreter executable and flags when given no arguments" do
- @script.ruby_exe.should == ['ruby_spec_exe', '-w', '-Q']
+ expect(@script.ruby_exe).to eq(['ruby_spec_exe', '-w', '-Q'])
end
it "executes (using `) the result of calling #ruby_cmd with the given arguments" do
code = "code"
options = {}
- @script.should_receive(:ruby_cmd).and_return("ruby_cmd")
- @script.should_receive(:`).with("ruby_cmd")
+ expect(@script).to receive(:ruby_cmd).and_return("ruby_cmd")
+ expect(IO).to receive(:popen).with("ruby_cmd")
@script.ruby_exe(code, options)
end
+ it "raises exception when command exit status is not successful" do
+ code = "code"
+ options = {}
+
+ status_failed = double(Process::Status, exited?: true, exitstatus: 4)
+ allow(Process).to receive(:last_status).and_return(status_failed)
+
+ expect {
+ @script.ruby_exe(code, options)
+ }.to raise_error(%r{Expected exit status is 0 but actual is 4 for command ruby_exe\(.+\)})
+ end
+
+ it "shows in the exception message if a signal killed the process" do
+ code = "code"
+ options = {}
+
+ status_failed = double(Process::Status, exited?: false, signaled?: true, termsig: Signal.list.fetch('TERM'))
+ allow(Process).to receive(:last_status).and_return(status_failed)
+
+ expect {
+ @script.ruby_exe(code, options)
+ }.to raise_error(%r{Expected exit status is 0 but actual is :SIGTERM for command ruby_exe\(.+\)})
+ end
+
describe "with :dir option" do
it "is deprecated" do
- lambda {
+ expect {
@script.ruby_exe nil, :dir => "tmp"
- }.should raise_error(/no longer supported, use Dir\.chdir/)
+ }.to raise_error(/no longer supported, use Dir\.chdir/)
end
end
describe "with :env option" do
it "preserves the values of existing ENV keys" do
ENV["ABC"] = "123"
- ENV.stub(:[])
- ENV.should_receive(:[]).with("ABC")
+ allow(ENV).to receive(:[])
+ expect(ENV).to receive(:[]).with("ABC")
@script.ruby_exe nil, :env => { :ABC => "xyz" }
end
it "adds the :env entries to ENV" do
- ENV.should_receive(:[]=).with("ABC", "xyz")
+ expect(ENV).to receive(:[]=).with("ABC", "xyz")
@script.ruby_exe nil, :env => { :ABC => "xyz" }
end
it "deletes the :env entries in ENV when an exception is raised" do
- ENV.should_receive(:delete).with("XYZ")
+ expect(ENV).to receive(:delete).with("XYZ")
@script.ruby_exe nil, :env => { :XYZ => "xyz" }
end
it "resets the values of existing ENV keys when an exception is raised" do
ENV["ABC"] = "123"
- ENV.should_receive(:[]=).with("ABC", "xyz")
- ENV.should_receive(:[]=).with("ABC", "123")
+ expect(ENV).to receive(:[]=).with("ABC", "xyz")
+ expect(ENV).to receive(:[]=).with("ABC", "123")
- @script.should_receive(:`).and_raise(Exception)
- lambda do
+ expect(IO).to receive(:popen).and_raise(Exception)
+ expect do
@script.ruby_exe nil, :env => { :ABC => "xyz" }
- end.should raise_error(Exception)
+ end.to raise_error(Exception)
+ end
+ end
+
+ describe "with :exit_status option" do
+ before do
+ status_failed = double(Process::Status, exited?: true, exitstatus: 4)
+ allow(Process).to receive(:last_status).and_return(status_failed)
+ end
+
+ it "raises exception when command ends with not expected status" do
+ expect {
+ @script.ruby_exe("path", exit_status: 1)
+ }.to raise_error(%r{Expected exit status is 1 but actual is 4 for command ruby_exe\(.+\)})
+ end
+
+ it "does not raise exception when command ends with expected status" do
+ output = "output"
+ expect(IO).to receive(:popen).and_return(output)
+
+ expect(@script.ruby_exe("path", exit_status: 4)).to eq output
end
end
end
diff --git a/spec/mspec/spec/helpers/scratch_spec.rb b/spec/mspec/spec/helpers/scratch_spec.rb
index 6a9eb2cf73..9dbef94aa3 100644
--- a/spec/mspec/spec/helpers/scratch_spec.rb
+++ b/spec/mspec/spec/helpers/scratch_spec.rb
@@ -2,23 +2,23 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe ScratchPad do
+RSpec.describe ScratchPad do
it "records an object and returns a previously recorded object" do
ScratchPad.record :this
- ScratchPad.recorded.should == :this
+ expect(ScratchPad.recorded).to eq(:this)
end
it "clears the recorded object" do
ScratchPad.record :that
- ScratchPad.recorded.should == :that
+ expect(ScratchPad.recorded).to eq(:that)
ScratchPad.clear
- ScratchPad.recorded.should == nil
+ expect(ScratchPad.recorded).to eq(nil)
end
it "provides a convenience shortcut to append to a previously recorded object" do
ScratchPad.record []
ScratchPad << :new
ScratchPad << :another
- ScratchPad.recorded.should == [:new, :another]
+ expect(ScratchPad.recorded).to eq([:new, :another])
end
end
diff --git a/spec/mspec/spec/helpers/suppress_warning_spec.rb b/spec/mspec/spec/helpers/suppress_warning_spec.rb
index d16361fa55..4cae189bd3 100644
--- a/spec/mspec/spec/helpers/suppress_warning_spec.rb
+++ b/spec/mspec/spec/helpers/suppress_warning_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#suppress_warning" do
+RSpec.describe Object, "#suppress_warning" do
it "hides warnings" do
suppress_warning do
warn "should not be shown"
@@ -14,6 +14,6 @@ describe Object, "#suppress_warning" do
suppress_warning do
a = 1
end
- a.should == 1
+ expect(a).to eq(1)
end
end
diff --git a/spec/mspec/spec/helpers/tmp_spec.rb b/spec/mspec/spec/helpers/tmp_spec.rb
index afadc7f51c..c41dcd57b3 100644
--- a/spec/mspec/spec/helpers/tmp_spec.rb
+++ b/spec/mspec/spec/helpers/tmp_spec.rb
@@ -2,26 +2,26 @@ require 'spec_helper'
require 'mspec/guards'
require 'mspec/helpers'
-describe Object, "#tmp" do
+RSpec.describe Object, "#tmp" do
before :all do
- @dir = "#{File.expand_path(Dir.pwd)}/rubyspec_temp"
+ @dir = SPEC_TEMP_DIR
end
it "returns a name relative to the current working directory" do
- tmp("test.txt").should == "#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt"
+ expect(tmp("test.txt")).to eq("#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt")
end
it "returns a 'unique' name on repeated calls" do
a = tmp("text.txt")
b = tmp("text.txt")
- a.should_not == b
+ expect(a).not_to eq(b)
end
it "does not 'uniquify' the name if requested not to" do
- tmp("test.txt", false).should == "#{@dir}/test.txt"
+ expect(tmp("test.txt", false)).to eq("#{@dir}/test.txt")
end
it "returns the name of the temporary directory when passed an empty string" do
- tmp("").should == "#{@dir}/"
+ expect(tmp("")).to eq("#{@dir}/")
end
end
diff --git a/spec/mspec/spec/integration/interpreter_spec.rb b/spec/mspec/spec/integration/interpreter_spec.rb
index b6fa6859d1..dbf3987a08 100644
--- a/spec/mspec/spec/integration/interpreter_spec.rb
+++ b/spec/mspec/spec/integration/interpreter_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "The interpreter passed with -t" do
+RSpec.describe "The interpreter passed with -t" do
it "is used in subprocess" do
fixtures = "spec/fixtures"
interpreter = "#{fixtures}/my_ruby"
@@ -8,11 +8,11 @@ describe "The interpreter passed with -t" do
out = out.lines.map(&:chomp).reject { |line|
line == 'RUBY_DESCRIPTION'
}.take(3)
- out.should == [
+ expect(out).to eq([
interpreter,
interpreter,
"CWD/#{interpreter}"
- ]
- ret.success?.should == true
+ ])
+ expect(ret.success?).to eq(true)
end
end
diff --git a/spec/mspec/spec/integration/object_methods_spec.rb b/spec/mspec/spec/integration/object_methods_spec.rb
index 3be704beb6..697fbd10fa 100644
--- a/spec/mspec/spec/integration/object_methods_spec.rb
+++ b/spec/mspec/spec/integration/object_methods_spec.rb
@@ -9,10 +9,10 @@ Finished in D.DDDDDD seconds
1 file, 1 example, 1 expectation, 0 failures, 0 errors, 0 tagged
EOS
-describe "MSpec" do
+RSpec.describe "MSpec" do
it "does not define public methods on Object" do
out, ret = run_mspec("run", "spec/fixtures/object_methods_spec.rb")
- out.should == expected_output
- ret.success?.should == true
+ expect(out).to eq(expected_output)
+ expect(ret.success?).to eq(true)
end
end
diff --git a/spec/mspec/spec/integration/run_spec.rb b/spec/mspec/spec/integration/run_spec.rb
index dc2a9933f9..ea0735e9b2 100644
--- a/spec/mspec/spec/integration/run_spec.rb
+++ b/spec/mspec/spec/integration/run_spec.rb
@@ -1,23 +1,21 @@
require 'spec_helper'
-describe "Running mspec" do
+RSpec.describe "Running mspec" do
+ q = BACKTRACE_QUOTE
a_spec_output = <<EOS
1)
Foo#bar errors FAILED
-Expected 1
- to equal 2
-
-CWD/spec/fixtures/a_spec.rb:8:in `block (2 levels) in <top (required)>'
-CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>'
-CWD/bin/mspec-run:7:in `<main>'
+Expected 1 == 2
+to be truthy but was false
+CWD/spec/fixtures/a_spec.rb:8:in #{q}block (2 levels) in <top (required)>'
+CWD/spec/fixtures/a_spec.rb:2:in #{q}<top (required)>'
2)
Foo#bar fails ERROR
RuntimeError: failure
-CWD/spec/fixtures/a_spec.rb:12:in `block (2 levels) in <top (required)>'
-CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>'
-CWD/bin/mspec-run:7:in `<main>'
+CWD/spec/fixtures/a_spec.rb:12:in #{q}block (2 levels) in <top (required)>'
+CWD/spec/fixtures/a_spec.rb:2:in #{q}<top (required)>'
Finished in D.DDDDDD seconds
EOS
@@ -28,41 +26,47 @@ EOS
it "runs the specs" do
out, ret = run_mspec("run", "#{fixtures}/a_spec.rb")
- out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}"
- ret.success?.should == false
+ expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}")
+ expect(ret.success?).to eq(false)
end
it "directly with mspec-run runs the specs" do
out, ret = run_mspec("-run", "#{fixtures}/a_spec.rb")
- out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}"
- ret.success?.should == false
+ expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}")
+ expect(ret.success?).to eq(false)
end
- it "runs the specs in parallel with -j" do
+ it "runs the specs in parallel with -j using the dotted formatter" do
out, ret = run_mspec("run", "-j #{fixtures}/a_spec.rb #{fixtures}/b_spec.rb")
+ expect(out).to eq("RUBY_DESCRIPTION\n...\n#{a_spec_output}\n#{ab_stats}")
+ expect(ret.success?).to eq(false)
+ end
+
+ it "runs the specs in parallel with -j -fa" do
+ out, ret = run_mspec("run", "-j -fa #{fixtures}/a_spec.rb #{fixtures}/b_spec.rb")
progress_bar =
"\r[/ | 0% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " +
"\r[- | ==================50% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " +
"\r[\\ | ==================100%================== | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m "
- out.should == "RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}"
- ret.success?.should == false
+ expect(out).to eq("RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}")
+ expect(ret.success?).to eq(false)
end
it "gives a useful error message when a subprocess dies in parallel mode" do
out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/die_spec.rb")
lines = out.lines
- lines.should include "A child mspec-run process died unexpectedly while running CWD/spec/fixtures/die_spec.rb\n"
- lines.should include "Finished in D.DDDDDD seconds\n"
- lines.last.should =~ /^\d files?, \d examples?, \d expectations?, 0 failures, 0 errors, 0 tagged$/
- ret.success?.should == false
+ expect(lines).to include "A child mspec-run process died unexpectedly while running CWD/spec/fixtures/die_spec.rb\n"
+ expect(lines).to include "Finished in D.DDDDDD seconds\n"
+ expect(lines.last).to match(/^\d files?, \d examples?, \d expectations?, 0 failures, 0 errors, 0 tagged$/)
+ expect(ret.success?).to eq(false)
end
it "gives a useful error message when a subprocess prints unexpected output on STDOUT in parallel mode" do
out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/chatty_spec.rb")
lines = out.lines
- lines.should include "A child mspec-run process printed unexpected output on STDOUT: #{'"Hello\nIt\'s me!\n"'} while running CWD/spec/fixtures/chatty_spec.rb\n"
- lines.should include "Finished in D.DDDDDD seconds\n"
- lines.last.should == "2 files, 2 examples, 2 expectations, 0 failures, 0 errors, 0 tagged\n"
- ret.success?.should == false
+ expect(lines).to include "A child mspec-run process printed unexpected output on STDOUT: #{'"Hello\nIt\'s me!\n"'} while running CWD/spec/fixtures/chatty_spec.rb\n"
+ expect(lines).to include "Finished in D.DDDDDD seconds\n"
+ expect(lines.last).to eq("2 files, 2 examples, 2 expectations, 0 failures, 0 errors, 0 tagged\n")
+ expect(ret.success?).to eq(false)
end
end
diff --git a/spec/mspec/spec/integration/tag_spec.rb b/spec/mspec/spec/integration/tag_spec.rb
index d980769043..ae08e9d45f 100644
--- a/spec/mspec/spec/integration/tag_spec.rb
+++ b/spec/mspec/spec/integration/tag_spec.rb
@@ -1,7 +1,7 @@
# encoding: utf-8
require 'spec_helper'
-describe "Running mspec tag" do
+RSpec.describe "Running mspec tag" do
before :all do
FileUtils.rm_rf 'spec/fixtures/tags'
end
@@ -13,7 +13,8 @@ describe "Running mspec tag" do
it "tags the failing specs" do
fixtures = "spec/fixtures"
out, ret = run_mspec("tag", "--add fails --fail #{fixtures}/tagging_spec.rb")
- out.should == <<EOS
+ q = BACKTRACE_QUOTE
+ expect(out).to eq <<EOS
RUBY_DESCRIPTION
.FF
TagAction: specs tagged with 'fails':
@@ -24,33 +25,29 @@ Tag#me érròrs in unicode
1)
Tag#me errors FAILED
-Expected 1
- to equal 2
-
-CWD/spec/fixtures/tagging_spec.rb:9:in `block (2 levels) in <top (required)>'
-CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
-CWD/bin/mspec-tag:7:in `<main>'
+Expected 1 == 2
+to be truthy but was false
+CWD/spec/fixtures/tagging_spec.rb:9:in #{q}block (2 levels) in <top (required)>'
+CWD/spec/fixtures/tagging_spec.rb:3:in #{q}<top (required)>'
2)
Tag#me érròrs in unicode FAILED
-Expected 1
- to equal 2
-
-CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in <top (required)>'
-CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
-CWD/bin/mspec-tag:7:in `<main>'
+Expected 1 == 2
+to be truthy but was false
+CWD/spec/fixtures/tagging_spec.rb:13:in #{q}block (2 levels) in <top (required)>'
+CWD/spec/fixtures/tagging_spec.rb:3:in #{q}<top (required)>'
Finished in D.DDDDDD seconds
1 file, 3 examples, 3 expectations, 2 failures, 0 errors, 0 tagged
EOS
- ret.success?.should == false
+ expect(ret.success?).to eq(false)
end
it "does not run already tagged specs" do
fixtures = "spec/fixtures"
out, ret = run_mspec("run", "--excl-tag fails #{fixtures}/tagging_spec.rb")
- out.should == <<EOS
+ expect(out).to eq <<EOS
RUBY_DESCRIPTION
.
@@ -58,6 +55,6 @@ Finished in D.DDDDDD seconds
1 file, 3 examples, 1 expectation, 0 failures, 0 errors, 2 tagged
EOS
- ret.success?.should == true
+ expect(ret.success?).to eq(true)
end
end
diff --git a/spec/mspec/spec/matchers/base_spec.rb b/spec/mspec/spec/matchers/base_spec.rb
index cc13c29d1d..6b5a3fbd72 100644
--- a/spec/mspec/spec/matchers/base_spec.rb
+++ b/spec/mspec/spec/matchers/base_spec.rb
@@ -3,223 +3,226 @@ require 'mspec/expectations/expectations'
require 'mspec/matchers'
require 'time'
-describe SpecPositiveOperatorMatcher, "== operator" do
- it "raises an SpecExpectationNotMetError when expected == actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new(1) == 2
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, "== operator" do
it "provides a failure message that 'Expected x to equal y'" do
- SpecExpectation.should_receive(:fail_with).with("Expected 1\n", "to equal 2\n")
- SpecPositiveOperatorMatcher.new(1) == 2
+ expect {
+ SpecPositiveOperatorMatcher.new(1) == 2
+ }.to raise_error(SpecExpectationNotMetError, "Expected 1 == 2\nto be truthy but was false")
end
- it "does not raise an exception when expected == actual returns true" do
+ it "does not raise an exception when == returns true" do
SpecPositiveOperatorMatcher.new(1) == 1
end
end
-describe SpecPositiveOperatorMatcher, "=~ operator" do
- it "raises an SpecExpectationNotMetError when expected =~ actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new('real') =~ /fake/
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, "=~ operator" do
it "provides a failure message that 'Expected \"x\" to match y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected \"real\"\n", "to match /fake/\n")
- SpecPositiveOperatorMatcher.new('real') =~ /fake/
+ expect {
+ SpecPositiveOperatorMatcher.new('real') =~ /fake/
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /fake/\nto be truthy but was nil")
end
- it "does not raise an exception when expected =~ actual returns true" do
+ it "does not raise an exception when =~ returns true" do
SpecPositiveOperatorMatcher.new('real') =~ /real/
end
end
-describe SpecPositiveOperatorMatcher, "> operator" do
- it "raises an SpecExpectationNotMetError when expected > actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new(4) > 5
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, "> operator" do
it "provides a failure message that 'Expected x to be greater than y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 4\n", "to be greater than 5\n")
- SpecPositiveOperatorMatcher.new(4) > 5
+ expect {
+ SpecPositiveOperatorMatcher.new(4) > 5
+ }.to raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false")
end
- it "does not raise an exception when expected > actual returns true" do
+ it "does not raise an exception when > returns true" do
SpecPositiveOperatorMatcher.new(5) > 4
end
end
-describe SpecPositiveOperatorMatcher, ">= operator" do
- it "raises an SpecExpectationNotMetError when expected >= actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new(4) >= 5
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, ">= operator" do
it "provides a failure message that 'Expected x to be greater than or equal to y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 4\n", "to be greater than or equal to 5\n")
- SpecPositiveOperatorMatcher.new(4) >= 5
+ expect {
+ SpecPositiveOperatorMatcher.new(4) >= 5
+ }.to raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false")
end
- it "does not raise an exception when expected > actual returns true" do
+ it "does not raise an exception when > returns true" do
SpecPositiveOperatorMatcher.new(5) >= 4
SpecPositiveOperatorMatcher.new(5) >= 5
end
end
-describe SpecPositiveOperatorMatcher, "< operater" do
- it "raises an SpecExpectationNotMetError when expected < actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new(5) < 4
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, "< operator" do
it "provides a failure message that 'Expected x to be less than y'" do
- SpecExpectation.should_receive(:fail_with).with("Expected 5\n", "to be less than 4\n")
- SpecPositiveOperatorMatcher.new(5) < 4
+ expect {
+ SpecPositiveOperatorMatcher.new(5) < 4
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false")
end
- it "does not raise an exception when expected < actual returns true" do
+ it "does not raise an exception when < returns true" do
SpecPositiveOperatorMatcher.new(4) < 5
end
end
-describe SpecPositiveOperatorMatcher, "<= operater" do
- it "raises an SpecExpectationNotMetError when expected < actual returns false" do
- lambda {
- SpecPositiveOperatorMatcher.new(5) <= 4
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecPositiveOperatorMatcher, "<= operator" do
it "provides a failure message that 'Expected x to be less than or equal to y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 5\n", "to be less than or equal to 4\n")
- SpecPositiveOperatorMatcher.new(5) <= 4
+ expect {
+ SpecPositiveOperatorMatcher.new(5) <= 4
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false")
end
- it "does not raise an exception when expected < actual returns true" do
+ it "does not raise an exception when < returns true" do
SpecPositiveOperatorMatcher.new(4) <= 5
SpecPositiveOperatorMatcher.new(4) <= 4
end
end
-describe SpecNegativeOperatorMatcher, "== operator" do
- it "raises an SpecExpectationNotMetError when expected == actual returns true" do
- lambda {
- SpecNegativeOperatorMatcher.new(1) == 1
- }.should raise_error(SpecExpectationNotMetError)
+RSpec.describe SpecPositiveOperatorMatcher, "arbitrary predicates" do
+ it "do not raise an exception when the predicate is truthy" do
+ SpecPositiveOperatorMatcher.new(2).eql?(2)
+ SpecPositiveOperatorMatcher.new(2).equal?(2)
+ SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(2)
+ SpecPositiveOperatorMatcher.new("abc").start_with?("ab")
+ SpecPositiveOperatorMatcher.new("abc").start_with?("d", "a")
+ SpecPositiveOperatorMatcher.new(3).odd?
+ SpecPositiveOperatorMatcher.new([1, 2]).any? { |e| e.even? }
+ end
+
+ it "provide a failure message when the predicate returns a falsy value" do
+ expect {
+ SpecPositiveOperatorMatcher.new(2).eql?(3)
+ }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 3\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new(2).equal?(3)
+ }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 3\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(4)
+ }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 4\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new("abc").start_with?("de")
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"de\"\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new("abc").start_with?("d", "e")
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"e\"\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new(2).odd?
+ }.to raise_error(SpecExpectationNotMetError, "Expected 2.odd?\nto be truthy but was false")
+ expect {
+ SpecPositiveOperatorMatcher.new([1, 3]).any? { |e| e.even? }
+ }.to raise_error(SpecExpectationNotMetError, "Expected [1, 3].any? { ... }\nto be truthy but was false")
end
+end
+
+RSpec.describe SpecNegativeOperatorMatcher, "arbitrary predicates" do
+ it "do not raise an exception when the predicate returns a falsy value" do
+ SpecNegativeOperatorMatcher.new(2).eql?(3)
+ SpecNegativeOperatorMatcher.new(2).equal?(3)
+ SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(4)
+ SpecNegativeOperatorMatcher.new("abc").start_with?("de")
+ SpecNegativeOperatorMatcher.new("abc").start_with?("d", "e")
+ SpecNegativeOperatorMatcher.new(2).odd?
+ SpecNegativeOperatorMatcher.new([1, 3]).any? { |e| e.even? }
+ end
+
+ it "provide a failure message when the predicate returns a truthy value" do
+ expect {
+ SpecNegativeOperatorMatcher.new(2).eql?(2)
+ }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 2\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new(2).equal?(2)
+ }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 2\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(2)
+ }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 2\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new("abc").start_with?("ab")
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"ab\"\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new("abc").start_with?("d", "a")
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"a\"\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new(3).odd?
+ }.to raise_error(SpecExpectationNotMetError, "Expected 3.odd?\nto be falsy but was true")
+ expect {
+ SpecNegativeOperatorMatcher.new([1, 2]).any? { |e| e.even? }
+ }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2].any? { ... }\nto be falsy but was true")
+ end
+end
+RSpec.describe SpecNegativeOperatorMatcher, "== operator" do
it "provides a failure message that 'Expected x not to equal y'" do
- SpecExpectation.should_receive(:fail_with).with("Expected 1\n", "not to equal 1\n")
- SpecNegativeOperatorMatcher.new(1) == 1
+ expect {
+ SpecNegativeOperatorMatcher.new(1) == 1
+ }.to raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true")
end
- it "does not raise an exception when expected == actual returns false" do
+ it "does not raise an exception when == returns false" do
SpecNegativeOperatorMatcher.new(1) == 2
end
end
-describe SpecNegativeOperatorMatcher, "=~ operator" do
- it "raises an SpecExpectationNotMetError when expected =~ actual returns true" do
- lambda {
- SpecNegativeOperatorMatcher.new('real') =~ /real/
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecNegativeOperatorMatcher, "=~ operator" do
it "provides a failure message that 'Expected \"x\" not to match /y/'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected \"real\"\n", "not to match /real/\n")
- SpecNegativeOperatorMatcher.new('real') =~ /real/
+ expect {
+ SpecNegativeOperatorMatcher.new('real') =~ /real/
+ }.to raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0")
end
- it "does not raise an exception when expected =~ actual returns false" do
+ it "does not raise an exception when =~ returns false" do
SpecNegativeOperatorMatcher.new('real') =~ /fake/
end
end
-describe SpecNegativeOperatorMatcher, "< operator" do
- it "raises an SpecExpectationNotMetError when expected < actual returns true" do
- lambda {
- SpecNegativeOperatorMatcher.new(4) < 5
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecNegativeOperatorMatcher, "< operator" do
it "provides a failure message that 'Expected x not to be less than y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 4\n", "not to be less than 5\n")
- SpecNegativeOperatorMatcher.new(4) < 5
+ expect {
+ SpecNegativeOperatorMatcher.new(4) < 5
+ }.to raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true")
end
- it "does not raise an exception when expected < actual returns false" do
+ it "does not raise an exception when < returns false" do
SpecNegativeOperatorMatcher.new(5) < 4
end
end
-describe SpecNegativeOperatorMatcher, "<= operator" do
- it "raises an SpecExpectationNotMetError when expected <= actual returns true" do
- lambda {
+RSpec.describe SpecNegativeOperatorMatcher, "<= operator" do
+ it "provides a failure message that 'Expected x not to be less than or equal to y'" do
+ expect {
SpecNegativeOperatorMatcher.new(4) <= 5
- }.should raise_error(SpecExpectationNotMetError)
- lambda {
+ }.to raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true")
+ expect {
SpecNegativeOperatorMatcher.new(5) <= 5
- }.should raise_error(SpecExpectationNotMetError)
- end
-
- it "provides a failure message that 'Expected x not to be less than or equal to y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 4\n", "not to be less than or equal to 5\n")
- SpecNegativeOperatorMatcher.new(4) <= 5
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true")
end
- it "does not raise an exception when expected <= actual returns false" do
+ it "does not raise an exception when <= returns false" do
SpecNegativeOperatorMatcher.new(5) <= 4
end
end
-describe SpecNegativeOperatorMatcher, "> operator" do
- it "raises an SpecExpectationNotMetError when expected > actual returns true" do
- lambda {
- SpecNegativeOperatorMatcher.new(5) > 4
- }.should raise_error(SpecExpectationNotMetError)
- end
-
+RSpec.describe SpecNegativeOperatorMatcher, "> operator" do
it "provides a failure message that 'Expected x not to be greater than y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 5\n", "not to be greater than 4\n")
- SpecNegativeOperatorMatcher.new(5) > 4
+ expect {
+ SpecNegativeOperatorMatcher.new(5) > 4
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true")
end
- it "does not raise an exception when expected > actual returns false" do
+ it "does not raise an exception when > returns false" do
SpecNegativeOperatorMatcher.new(4) > 5
end
end
-describe SpecNegativeOperatorMatcher, ">= operator" do
- it "raises an SpecExpectationNotMetError when expected >= actual returns true" do
- lambda {
+RSpec.describe SpecNegativeOperatorMatcher, ">= operator" do
+ it "provides a failure message that 'Expected x not to be greater than or equal to y'" do
+ expect {
SpecNegativeOperatorMatcher.new(5) >= 4
- }.should raise_error(SpecExpectationNotMetError)
- lambda {
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true")
+ expect {
SpecNegativeOperatorMatcher.new(5) >= 5
- }.should raise_error(SpecExpectationNotMetError)
- end
-
- it "provides a failure message that 'Expected x not to be greater than or equal to y'" do
- SpecExpectation.should_receive(:fail_with).with(
- "Expected 5\n", "not to be greater than or equal to 4\n")
- SpecNegativeOperatorMatcher.new(5) >= 4
+ }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true")
end
- it "does not raise an exception when expected >= actual returns false" do
+ it "does not raise an exception when >= returns false" do
SpecNegativeOperatorMatcher.new(4) >= 5
end
end
diff --git a/spec/mspec/spec/matchers/be_an_instance_of_spec.rb b/spec/mspec/spec/matchers/be_an_instance_of_spec.rb
index 7f2126df7d..7c74249d24 100644
--- a/spec/mspec/spec/matchers/be_an_instance_of_spec.rb
+++ b/spec/mspec/spec/matchers/be_an_instance_of_spec.rb
@@ -13,38 +13,38 @@ module BeAnInOfSpecs
end
end
-describe BeAnInstanceOfMatcher do
+RSpec.describe BeAnInstanceOfMatcher do
it "matches when actual is an instance_of? expected" do
a = BeAnInOfSpecs::A.new
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a).should be_true
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a)).to be_truthy
b = BeAnInOfSpecs::B.new
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b).should be_true
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b)).to be_truthy
end
it "does not match when actual is not an instance_of? expected" do
a = BeAnInOfSpecs::A.new
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a).should be_false
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a)).to be_falsey
b = BeAnInOfSpecs::B.new
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b).should be_false
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b)).to be_falsey
c = BeAnInOfSpecs::C.new
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c).should be_false
- BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c).should be_false
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c)).to be_falsey
+ expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c)).to be_falsey
end
it "provides a useful failure message" do
matcher = BeAnInstanceOfMatcher.new(Numeric)
matcher.matches?("string")
- matcher.failure_message.should == [
- "Expected \"string\" (String)", "to be an instance of Numeric"]
+ expect(matcher.failure_message).to eq([
+ "Expected \"string\" (String)", "to be an instance of Numeric"])
end
it "provides a useful negative failure message" do
matcher = BeAnInstanceOfMatcher.new(Numeric)
matcher.matches?(4.0)
- matcher.negative_failure_message.should == [
- "Expected 4.0 (Float)", "not to be an instance of Numeric"]
+ expect(matcher.negative_failure_message).to eq([
+ "Expected 4.0 (Float)", "not to be an instance of Numeric"])
end
end
diff --git a/spec/mspec/spec/matchers/be_ancestor_of_spec.rb b/spec/mspec/spec/matchers/be_ancestor_of_spec.rb
index c6bd1a26c7..abc05e0f7a 100644
--- a/spec/mspec/spec/matchers/be_ancestor_of_spec.rb
+++ b/spec/mspec/spec/matchers/be_ancestor_of_spec.rb
@@ -5,24 +5,24 @@ require 'mspec/matchers'
class Parent; end
class Child < Parent; end
-describe BeAncestorOfMatcher do
+RSpec.describe BeAncestorOfMatcher do
it "matches when actual is an ancestor of expected" do
- BeAncestorOfMatcher.new(Child).matches?(Parent).should == true
+ expect(BeAncestorOfMatcher.new(Child).matches?(Parent)).to eq(true)
end
it "does not match when actual is not an ancestor of expected" do
- BeAncestorOfMatcher.new(Parent).matches?(Child).should == false
+ expect(BeAncestorOfMatcher.new(Parent).matches?(Child)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeAncestorOfMatcher.new(Parent)
matcher.matches?(Child)
- matcher.failure_message.should == ["Expected Child", "to be an ancestor of Parent"]
+ expect(matcher.failure_message).to eq(["Expected Child", "to be an ancestor of Parent"])
end
it "provides a useful negative failure message" do
matcher = BeAncestorOfMatcher.new(Child)
matcher.matches?(Parent)
- matcher.negative_failure_message.should == ["Expected Parent", "not to be an ancestor of Child"]
+ expect(matcher.negative_failure_message).to eq(["Expected Parent", "not to be an ancestor of Child"])
end
end
diff --git a/spec/mspec/spec/matchers/be_close_spec.rb b/spec/mspec/spec/matchers/be_close_spec.rb
index 6edff98e4a..dfd4f4ddbb 100644
--- a/spec/mspec/spec/matchers/be_close_spec.rb
+++ b/spec/mspec/spec/matchers/be_close_spec.rb
@@ -3,46 +3,46 @@ require 'mspec/expectations/expectations'
require 'mspec/matchers'
# Adapted from RSpec 1.0.8
-describe BeCloseMatcher do
+RSpec.describe BeCloseMatcher do
it "matches when actual == expected" do
- BeCloseMatcher.new(5.0, 0.5).matches?(5.0).should == true
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.0)).to eq(true)
end
it "matches when actual < (expected + tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(5.49).should == true
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.49)).to eq(true)
end
it "matches when actual > (expected - tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(4.51).should == true
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.51)).to eq(true)
end
it "matches when actual == (expected + tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(5.5).should == true
- BeCloseMatcher.new(3, 2).matches?(5).should == true
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.5)).to eq(true)
+ expect(BeCloseMatcher.new(3, 2).matches?(5)).to eq(true)
end
it "matches when actual == (expected - tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(4.5).should == true
- BeCloseMatcher.new(3, 2).matches?(1).should == true
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.5)).to eq(true)
+ expect(BeCloseMatcher.new(3, 2).matches?(1)).to eq(true)
end
it "does not match when actual < (expected - tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(4.49).should == false
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.49)).to eq(false)
end
it "does not match when actual > (expected + tolerance)" do
- BeCloseMatcher.new(5.0, 0.5).matches?(5.51).should == false
+ expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.51)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeCloseMatcher.new(5.0, 0.5)
matcher.matches?(6.5)
- matcher.failure_message.should == ["Expected 6.5", "to be within 5.0 +/- 0.5"]
+ expect(matcher.failure_message).to eq(["Expected 6.5", "to be within 5.0 +/- 0.5"])
end
it "provides a useful negative failure message" do
matcher = BeCloseMatcher.new(5.0, 0.5)
matcher.matches?(4.9)
- matcher.negative_failure_message.should == ["Expected 4.9", "not to be within 5.0 +/- 0.5"]
+ expect(matcher.negative_failure_message).to eq(["Expected 4.9", "not to be within 5.0 +/- 0.5"])
end
end
diff --git a/spec/mspec/spec/matchers/be_computed_by_spec.rb b/spec/mspec/spec/matchers/be_computed_by_spec.rb
index 9833e211a4..f73861a576 100644
--- a/spec/mspec/spec/matchers/be_computed_by_spec.rb
+++ b/spec/mspec/spec/matchers/be_computed_by_spec.rb
@@ -1,35 +1,35 @@
require 'spec_helper'
require 'mspec/matchers'
-describe BeComputedByMatcher do
+RSpec.describe BeComputedByMatcher do
it "matches when all entries in the Array compute" do
array = [ [65, "A"],
[90, "Z"] ]
- BeComputedByMatcher.new(:chr).matches?(array).should be_true
+ expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_truthy
end
it "matches when all entries in the Array with arguments compute" do
array = [ [1, 2, 3],
[2, 4, 6] ]
- BeComputedByMatcher.new(:+).matches?(array).should be_true
+ expect(BeComputedByMatcher.new(:+).matches?(array)).to be_truthy
end
it "does not match when any entry in the Array does not compute" do
array = [ [65, "A" ],
[91, "Z" ] ]
- BeComputedByMatcher.new(:chr).matches?(array).should be_false
+ expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_falsey
end
it "accepts an argument list to apply to each method call" do
array = [ [65, "1000001" ],
[90, "1011010" ] ]
- BeComputedByMatcher.new(:to_s, 2).matches?(array).should be_true
+ expect(BeComputedByMatcher.new(:to_s, 2).matches?(array)).to be_truthy
end
it "does not match when any entry in the Array with arguments does not compute" do
array = [ [1, 2, 3],
[2, 4, 7] ]
- BeComputedByMatcher.new(:+).matches?(array).should be_false
+ expect(BeComputedByMatcher.new(:+).matches?(array)).to be_falsey
end
it "provides a useful failure message" do
@@ -37,6 +37,6 @@ describe BeComputedByMatcher do
[91, "Z" ] ]
matcher = BeComputedByMatcher.new(:chr)
matcher.matches?(array)
- matcher.failure_message.should == ["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"]
+ expect(matcher.failure_message).to eq(["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"])
end
end
diff --git a/spec/mspec/spec/matchers/be_empty_spec.rb b/spec/mspec/spec/matchers/be_empty_spec.rb
index cb8663f5ee..30678fe85f 100644
--- a/spec/mspec/spec/matchers/be_empty_spec.rb
+++ b/spec/mspec/spec/matchers/be_empty_spec.rb
@@ -2,25 +2,25 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeEmptyMatcher do
+RSpec.describe BeEmptyMatcher do
it "matches when actual is empty" do
- BeEmptyMatcher.new.matches?("").should == true
+ expect(BeEmptyMatcher.new.matches?("")).to eq(true)
end
it "does not match when actual is not empty" do
- BeEmptyMatcher.new.matches?([10]).should == false
+ expect(BeEmptyMatcher.new.matches?([10])).to eq(false)
end
it "provides a useful failure message" do
matcher = BeEmptyMatcher.new
matcher.matches?("not empty string")
- matcher.failure_message.should == ["Expected \"not empty string\"", "to be empty"]
+ expect(matcher.failure_message).to eq(["Expected \"not empty string\"", "to be empty"])
end
it "provides a useful negative failure message" do
matcher = BeEmptyMatcher.new
matcher.matches?("")
- matcher.negative_failure_message.should == ["Expected \"\"", "not to be empty"]
+ expect(matcher.negative_failure_message).to eq(["Expected \"\"", "not to be empty"])
end
end
diff --git a/spec/mspec/spec/matchers/be_false_spec.rb b/spec/mspec/spec/matchers/be_false_spec.rb
index 31afd24ebc..46d7253220 100644
--- a/spec/mspec/spec/matchers/be_false_spec.rb
+++ b/spec/mspec/spec/matchers/be_false_spec.rb
@@ -2,27 +2,27 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeFalseMatcher do
+RSpec.describe BeFalseMatcher do
it "matches when actual is false" do
- BeFalseMatcher.new.matches?(false).should == true
+ expect(BeFalseMatcher.new.matches?(false)).to eq(true)
end
it "does not match when actual is not false" do
- BeFalseMatcher.new.matches?("").should == false
- BeFalseMatcher.new.matches?(true).should == false
- BeFalseMatcher.new.matches?(nil).should == false
- BeFalseMatcher.new.matches?(0).should == false
+ expect(BeFalseMatcher.new.matches?("")).to eq(false)
+ expect(BeFalseMatcher.new.matches?(true)).to eq(false)
+ expect(BeFalseMatcher.new.matches?(nil)).to eq(false)
+ expect(BeFalseMatcher.new.matches?(0)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeFalseMatcher.new
matcher.matches?("some string")
- matcher.failure_message.should == ["Expected \"some string\"", "to be false"]
+ expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be false"])
end
it "provides a useful negative failure message" do
matcher = BeFalseMatcher.new
matcher.matches?(false)
- matcher.negative_failure_message.should == ["Expected false", "not to be false"]
+ expect(matcher.negative_failure_message).to eq(["Expected false", "not to be false"])
end
end
diff --git a/spec/mspec/spec/matchers/be_kind_of_spec.rb b/spec/mspec/spec/matchers/be_kind_of_spec.rb
index 7c4a59f7b9..1e19058411 100644
--- a/spec/mspec/spec/matchers/be_kind_of_spec.rb
+++ b/spec/mspec/spec/matchers/be_kind_of_spec.rb
@@ -2,30 +2,30 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeKindOfMatcher do
+RSpec.describe BeKindOfMatcher do
it "matches when actual is a kind_of? expected" do
- BeKindOfMatcher.new(Numeric).matches?(1).should == true
- BeKindOfMatcher.new(Integer).matches?(2).should == true
- BeKindOfMatcher.new(Regexp).matches?(/m/).should == true
+ expect(BeKindOfMatcher.new(Numeric).matches?(1)).to eq(true)
+ expect(BeKindOfMatcher.new(Integer).matches?(2)).to eq(true)
+ expect(BeKindOfMatcher.new(Regexp).matches?(/m/)).to eq(true)
end
it "does not match when actual is not a kind_of? expected" do
- BeKindOfMatcher.new(Integer).matches?(1.5).should == false
- BeKindOfMatcher.new(String).matches?(:a).should == false
- BeKindOfMatcher.new(Hash).matches?([]).should == false
+ expect(BeKindOfMatcher.new(Integer).matches?(1.5)).to eq(false)
+ expect(BeKindOfMatcher.new(String).matches?(:a)).to eq(false)
+ expect(BeKindOfMatcher.new(Hash).matches?([])).to eq(false)
end
it "provides a useful failure message" do
matcher = BeKindOfMatcher.new(Numeric)
matcher.matches?('string')
- matcher.failure_message.should == [
- "Expected \"string\" (String)", "to be kind of Numeric"]
+ expect(matcher.failure_message).to eq([
+ "Expected \"string\" (String)", "to be kind of Numeric"])
end
it "provides a useful negative failure message" do
matcher = BeKindOfMatcher.new(Numeric)
matcher.matches?(4.0)
- matcher.negative_failure_message.should == [
- "Expected 4.0 (Float)", "not to be kind of Numeric"]
+ expect(matcher.negative_failure_message).to eq([
+ "Expected 4.0 (Float)", "not to be kind of Numeric"])
end
end
diff --git a/spec/mspec/spec/matchers/be_nan_spec.rb b/spec/mspec/spec/matchers/be_nan_spec.rb
index 2062763a92..baa7447943 100644
--- a/spec/mspec/spec/matchers/be_nan_spec.rb
+++ b/spec/mspec/spec/matchers/be_nan_spec.rb
@@ -4,25 +4,25 @@ require 'mspec/guards'
require 'mspec/helpers'
require 'mspec/matchers'
-describe BeNaNMatcher do
+RSpec.describe BeNaNMatcher do
it "matches when actual is NaN" do
- BeNaNMatcher.new.matches?(nan_value).should == true
+ expect(BeNaNMatcher.new.matches?(nan_value)).to eq(true)
end
it "does not match when actual is not NaN" do
- BeNaNMatcher.new.matches?(1.0).should == false
- BeNaNMatcher.new.matches?(0).should == false
+ expect(BeNaNMatcher.new.matches?(1.0)).to eq(false)
+ expect(BeNaNMatcher.new.matches?(0)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeNaNMatcher.new
matcher.matches?(0)
- matcher.failure_message.should == ["Expected 0", "to be NaN"]
+ expect(matcher.failure_message).to eq(["Expected 0", "to be NaN"])
end
it "provides a useful negative failure message" do
matcher = BeNaNMatcher.new
matcher.matches?(nan_value)
- matcher.negative_failure_message.should == ["Expected NaN", "not to be NaN"]
+ expect(matcher.negative_failure_message).to eq(["Expected NaN", "not to be NaN"])
end
end
diff --git a/spec/mspec/spec/matchers/be_nil_spec.rb b/spec/mspec/spec/matchers/be_nil_spec.rb
index 6551feb5de..e2768acf83 100644
--- a/spec/mspec/spec/matchers/be_nil_spec.rb
+++ b/spec/mspec/spec/matchers/be_nil_spec.rb
@@ -2,26 +2,26 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeNilMatcher do
+RSpec.describe BeNilMatcher do
it "matches when actual is nil" do
- BeNilMatcher.new.matches?(nil).should == true
+ expect(BeNilMatcher.new.matches?(nil)).to eq(true)
end
it "does not match when actual is not nil" do
- BeNilMatcher.new.matches?("").should == false
- BeNilMatcher.new.matches?(false).should == false
- BeNilMatcher.new.matches?(0).should == false
+ expect(BeNilMatcher.new.matches?("")).to eq(false)
+ expect(BeNilMatcher.new.matches?(false)).to eq(false)
+ expect(BeNilMatcher.new.matches?(0)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeNilMatcher.new
matcher.matches?("some string")
- matcher.failure_message.should == ["Expected \"some string\"", "to be nil"]
+ expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be nil"])
end
it "provides a useful negative failure message" do
matcher = BeNilMatcher.new
matcher.matches?(nil)
- matcher.negative_failure_message.should == ["Expected nil", "not to be nil"]
+ expect(matcher.negative_failure_message).to eq(["Expected nil", "not to be nil"])
end
end
diff --git a/spec/mspec/spec/matchers/be_true_or_false_spec.rb b/spec/mspec/spec/matchers/be_true_or_false_spec.rb
index 3edffcb1b1..e4b456eafc 100644
--- a/spec/mspec/spec/matchers/be_true_or_false_spec.rb
+++ b/spec/mspec/spec/matchers/be_true_or_false_spec.rb
@@ -2,18 +2,18 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeTrueOrFalseMatcher do
+RSpec.describe BeTrueOrFalseMatcher do
it "matches when actual is true" do
- BeTrueOrFalseMatcher.new.matches?(true).should == true
+ expect(BeTrueOrFalseMatcher.new.matches?(true)).to eq(true)
end
it "matches when actual is false" do
- BeTrueOrFalseMatcher.new.matches?(false).should == true
+ expect(BeTrueOrFalseMatcher.new.matches?(false)).to eq(true)
end
it "provides a useful failure message" do
matcher = BeTrueOrFalseMatcher.new
matcher.matches?("some string")
- matcher.failure_message.should == ["Expected \"some string\"", "to be true or false"]
+ expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true or false"])
end
end
diff --git a/spec/mspec/spec/matchers/be_true_spec.rb b/spec/mspec/spec/matchers/be_true_spec.rb
index 90c89b3911..39ef05a0f8 100644
--- a/spec/mspec/spec/matchers/be_true_spec.rb
+++ b/spec/mspec/spec/matchers/be_true_spec.rb
@@ -2,27 +2,27 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BeTrueMatcher do
+RSpec.describe BeTrueMatcher do
it "matches when actual is true" do
- BeTrueMatcher.new.matches?(true).should == true
+ expect(BeTrueMatcher.new.matches?(true)).to eq(true)
end
it "does not match when actual is not true" do
- BeTrueMatcher.new.matches?("").should == false
- BeTrueMatcher.new.matches?(false).should == false
- BeTrueMatcher.new.matches?(nil).should == false
- BeTrueMatcher.new.matches?(0).should == false
+ expect(BeTrueMatcher.new.matches?("")).to eq(false)
+ expect(BeTrueMatcher.new.matches?(false)).to eq(false)
+ expect(BeTrueMatcher.new.matches?(nil)).to eq(false)
+ expect(BeTrueMatcher.new.matches?(0)).to eq(false)
end
it "provides a useful failure message" do
matcher = BeTrueMatcher.new
matcher.matches?("some string")
- matcher.failure_message.should == ["Expected \"some string\"", "to be true"]
+ expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true"])
end
it "provides a useful negative failure message" do
matcher = BeTrueMatcher.new
matcher.matches?(true)
- matcher.negative_failure_message.should == ["Expected true", "not to be true"]
+ expect(matcher.negative_failure_message).to eq(["Expected true", "not to be true"])
end
end
diff --git a/spec/mspec/spec/matchers/block_caller_spec.rb b/spec/mspec/spec/matchers/block_caller_spec.rb
index d6793b9779..5d7085fa63 100644
--- a/spec/mspec/spec/matchers/block_caller_spec.rb
+++ b/spec/mspec/spec/matchers/block_caller_spec.rb
@@ -2,12 +2,12 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe BlockingMatcher do
+RSpec.describe BlockingMatcher do
it 'matches when a Proc blocks the caller' do
- BlockingMatcher.new.matches?(proc { sleep }).should == true
+ expect(BlockingMatcher.new.matches?(proc { sleep })).to eq(true)
end
it 'does not match when a Proc does not block the caller' do
- BlockingMatcher.new.matches?(proc { 1 }).should == false
+ expect(BlockingMatcher.new.matches?(proc { 1 })).to eq(false)
end
end
diff --git a/spec/mspec/spec/matchers/complain_spec.rb b/spec/mspec/spec/matchers/complain_spec.rb
index 709b57be6c..399ef3105b 100644
--- a/spec/mspec/spec/matchers/complain_spec.rb
+++ b/spec/mspec/spec/matchers/complain_spec.rb
@@ -2,51 +2,101 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe ComplainMatcher do
+RSpec.describe ComplainMatcher do
it "matches when executing the proc results in output to $stderr" do
proc = lambda { warn "I'm gonna tell yo mama" }
- ComplainMatcher.new(nil).matches?(proc).should == true
+ expect(ComplainMatcher.new(nil).matches?(proc)).to eq(true)
end
- it "maches when executing the proc results in the expected output to $stderr" do
+ it "matches when executing the proc results in the expected output to $stderr" do
proc = lambda { warn "Que haces?" }
- ComplainMatcher.new("Que haces?\n").matches?(proc).should == true
- ComplainMatcher.new("Que pasa?\n").matches?(proc).should == false
- ComplainMatcher.new(/Que/).matches?(proc).should == true
- ComplainMatcher.new(/Quoi/).matches?(proc).should == false
+ expect(ComplainMatcher.new("Que haces?\n").matches?(proc)).to eq(true)
+ expect(ComplainMatcher.new("Que pasa?\n").matches?(proc)).to eq(false)
+ expect(ComplainMatcher.new(/Que/).matches?(proc)).to eq(true)
+ expect(ComplainMatcher.new(/Quoi/).matches?(proc)).to eq(false)
end
it "does not match when there is no output to $stderr" do
- ComplainMatcher.new(nil).matches?(lambda {}).should == false
+ expect(ComplainMatcher.new(nil).matches?(lambda {})).to eq(false)
end
it "provides a useful failure message" do
matcher = ComplainMatcher.new(nil)
matcher.matches?(lambda { })
- matcher.failure_message.should == ["Expected a warning", "but received none"]
+ expect(matcher.failure_message).to eq(["Expected a warning", "but received none"])
matcher = ComplainMatcher.new("listen here")
matcher.matches?(lambda { warn "look out" })
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected warning: \"listen here\"", "but got: \"look out\""]
+ )
matcher = ComplainMatcher.new(/talk/)
matcher.matches?(lambda { warn "listen up" })
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected warning to match: /talk/", "but got: \"listen up\""]
+ )
end
it "provides a useful negative failure message" do
proc = lambda { warn "ouch" }
matcher = ComplainMatcher.new(nil)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Unexpected warning: ", "\"ouch\""]
+ )
matcher = ComplainMatcher.new("ouchy")
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected warning: \"ouchy\"", "but got: \"ouch\""]
+ )
matcher = ComplainMatcher.new(/ou/)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected warning not to match: /ou/", "but got: \"ouch\""]
+ )
+ end
+
+ context "`verbose` option specified" do
+ before do
+ $VERBOSE, @verbose = nil, $VERBOSE
+ end
+
+ after do
+ $VERBOSE = @verbose
+ end
+
+ it "sets $VERBOSE with specified second optional parameter" do
+ verbose = nil
+ proc = lambda { verbose = $VERBOSE }
+
+ ComplainMatcher.new(nil, verbose: true).matches?(proc)
+ expect(verbose).to eq(true)
+
+ ComplainMatcher.new(nil, verbose: false).matches?(proc)
+ expect(verbose).to eq(false)
+ end
+
+ it "sets $VERBOSE with false by default" do
+ verbose = nil
+ proc = lambda { verbose = $VERBOSE }
+
+ ComplainMatcher.new(nil).matches?(proc)
+ expect(verbose).to eq(false)
+ end
+
+ it "does not have side effect" do
+ proc = lambda { safe_value = $VERBOSE }
+
+ expect do
+ ComplainMatcher.new(nil, verbose: true).matches?(proc)
+ end.not_to change { $VERBOSE }
+ end
+
+ it "accepts a verbose level as single argument" do
+ verbose = nil
+ proc = lambda { verbose = $VERBOSE }
+
+ ComplainMatcher.new(verbose: true).matches?(proc)
+ expect(verbose).to eq(true)
+ end
end
end
diff --git a/spec/mspec/spec/matchers/eql_spec.rb b/spec/mspec/spec/matchers/eql_spec.rb
index 711ebdb679..66307d2a9d 100644
--- a/spec/mspec/spec/matchers/eql_spec.rb
+++ b/spec/mspec/spec/matchers/eql_spec.rb
@@ -2,32 +2,32 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe EqlMatcher do
+RSpec.describe EqlMatcher do
it "matches when actual is eql? to expected" do
- EqlMatcher.new(1).matches?(1).should == true
- EqlMatcher.new(1.5).matches?(1.5).should == true
- EqlMatcher.new("red").matches?("red").should == true
- EqlMatcher.new(:blue).matches?(:blue).should == true
- EqlMatcher.new(Object).matches?(Object).should == true
+ expect(EqlMatcher.new(1).matches?(1)).to eq(true)
+ expect(EqlMatcher.new(1.5).matches?(1.5)).to eq(true)
+ expect(EqlMatcher.new("red").matches?("red")).to eq(true)
+ expect(EqlMatcher.new(:blue).matches?(:blue)).to eq(true)
+ expect(EqlMatcher.new(Object).matches?(Object)).to eq(true)
o = Object.new
- EqlMatcher.new(o).matches?(o).should == true
+ expect(EqlMatcher.new(o).matches?(o)).to eq(true)
end
it "does not match when actual is not eql? to expected" do
- EqlMatcher.new(1).matches?(1.0).should == false
- EqlMatcher.new(Hash).matches?(Object).should == false
+ expect(EqlMatcher.new(1).matches?(1.0)).to eq(false)
+ expect(EqlMatcher.new(Hash).matches?(Object)).to eq(false)
end
it "provides a useful failure message" do
matcher = EqlMatcher.new("red")
matcher.matches?("red")
- matcher.failure_message.should == ["Expected \"red\"\n", "to have same value and type as \"red\"\n"]
+ expect(matcher.failure_message).to eq(["Expected \"red\"", "to have same value and type as \"red\""])
end
it "provides a useful negative failure message" do
matcher = EqlMatcher.new(1)
matcher.matches?(1.0)
- matcher.negative_failure_message.should == ["Expected 1.0\n", "not to have same value or type as 1\n"]
+ expect(matcher.negative_failure_message).to eq(["Expected 1.0", "not to have same value or type as 1"])
end
end
diff --git a/spec/mspec/spec/matchers/equal_element_spec.rb b/spec/mspec/spec/matchers/equal_element_spec.rb
index 45b8390364..3a5ae4ede2 100644
--- a/spec/mspec/spec/matchers/equal_element_spec.rb
+++ b/spec/mspec/spec/matchers/equal_element_spec.rb
@@ -2,74 +2,74 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe EqualElementMatcher do
+RSpec.describe EqualElementMatcher do
it "matches if it finds an element with the passed name, no matter what attributes/content" do
- EqualElementMatcher.new("A").matches?('<A></A>').should be_true
- EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>').should be_true
- EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>').should be_true
+ expect(EqualElementMatcher.new("A").matches?('<A></A>')).to be_truthy
+ expect(EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>')).to be_truthy
+ expect(EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>')).to be_truthy
- EqualElementMatcher.new("BASE").matches?('<BASE></A>').should be_false
- EqualElementMatcher.new("BASE").matches?('<A></BASE>').should be_false
- EqualElementMatcher.new("BASE").matches?('<A></A>').should be_false
- EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>').should be_false
- EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>').should be_false
+ expect(EqualElementMatcher.new("BASE").matches?('<BASE></A>')).to be_falsey
+ expect(EqualElementMatcher.new("BASE").matches?('<A></BASE>')).to be_falsey
+ expect(EqualElementMatcher.new("BASE").matches?('<A></A>')).to be_falsey
+ expect(EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>')).to be_falsey
+ expect(EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>')).to be_falsey
end
it "matches if it finds an element with the passed name and the passed attributes" do
- EqualElementMatcher.new("A", {}).matches?('<A></A>').should be_true
- EqualElementMatcher.new("A", nil).matches?('<A HREF="http://example.com"></A>').should be_true
- EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com"></A>').should be_true
+ expect(EqualElementMatcher.new("A", {}).matches?('<A></A>')).to be_truthy
+ expect(EqualElementMatcher.new("A", nil).matches?('<A HREF="http://example.com"></A>')).to be_truthy
+ expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com"></A>')).to be_truthy
- EqualElementMatcher.new("A", {}).matches?('<A HREF="http://example.com"></A>').should be_false
- EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A></A>').should be_false
- EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://test.com"></A>').should be_false
- EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com" HREF="http://example.com"></A>').should be_false
+ expect(EqualElementMatcher.new("A", {}).matches?('<A HREF="http://example.com"></A>')).to be_falsey
+ expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A></A>')).to be_falsey
+ expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://test.com"></A>')).to be_falsey
+ expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com" HREF="http://example.com"></A>')).to be_falsey
end
it "matches if it finds an element with the passed name, the passed attributes and the passed content" do
- EqualElementMatcher.new("A", {}, "").matches?('<A></A>').should be_true
- EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Example</A>').should be_true
+ expect(EqualElementMatcher.new("A", {}, "").matches?('<A></A>')).to be_truthy
+ expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Example</A>')).to be_truthy
- EqualElementMatcher.new("A", {}, "Test").matches?('<A></A>').should be_false
- EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com"></A>').should be_false
- EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Test</A>').should be_false
+ expect(EqualElementMatcher.new("A", {}, "Test").matches?('<A></A>')).to be_falsey
+ expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com"></A>')).to be_falsey
+ expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Test</A>')).to be_falsey
end
it "can match unclosed elements" do
- EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('<BASE>').should be_true
- EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">').should be_true
- EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_true
+ expect(EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('<BASE>')).to be_truthy
+ expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">')).to be_truthy
+ expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_truthy
- EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">').should be_false
- EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_false
- EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_false
+ expect(EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">')).to be_falsey
+ expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_falsey
+ expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_falsey
end
it "provides a useful failure message" do
equal_element = EqualElementMatcher.new("A", {}, "Test")
- equal_element.matches?('<A></A>').should be_false
- equal_element.failure_message.should == [%{Expected "<A></A>"\n}, %{to be a 'A' element with no attributes and "Test" as content}]
+ expect(equal_element.matches?('<A></A>')).to be_falsey
+ expect(equal_element.failure_message).to eq([%{Expected "<A></A>"}, %{to be a 'A' element with no attributes and "Test" as content}])
equal_element = EqualElementMatcher.new("A", {}, "")
- equal_element.matches?('<A>Test</A>').should be_false
- equal_element.failure_message.should == [%{Expected "<A>Test</A>"\n}, %{to be a 'A' element with no attributes and no content}]
+ expect(equal_element.matches?('<A>Test</A>')).to be_falsey
+ expect(equal_element.failure_message).to eq([%{Expected "<A>Test</A>"}, %{to be a 'A' element with no attributes and no content}])
equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com")
- equal_element.matches?('<A>Test</A>').should be_false
- equal_element.failure_message.should == [%{Expected "<A>Test</A>"\n}, %{to be a 'A' element with HREF="http://www.example.com" and any content}]
+ expect(equal_element.matches?('<A>Test</A>')).to be_falsey
+ expect(equal_element.failure_message).to eq([%{Expected "<A>Test</A>"}, %{to be a 'A' element with HREF="http://www.example.com" and any content}])
end
it "provides a useful negative failure message" do
equal_element = EqualElementMatcher.new("A", {}, "Test")
- equal_element.matches?('<A></A>').should be_false
- equal_element.negative_failure_message.should == [%{Expected "<A></A>"\n}, %{not to be a 'A' element with no attributes and "Test" as content}]
+ expect(equal_element.matches?('<A></A>')).to be_falsey
+ expect(equal_element.negative_failure_message).to eq([%{Expected "<A></A>"}, %{not to be a 'A' element with no attributes and "Test" as content}])
equal_element = EqualElementMatcher.new("A", {}, "")
- equal_element.matches?('<A>Test</A>').should be_false
- equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"\n}, %{not to be a 'A' element with no attributes and no content}]
+ expect(equal_element.matches?('<A>Test</A>')).to be_falsey
+ expect(equal_element.negative_failure_message).to eq([%{Expected "<A>Test</A>"}, %{not to be a 'A' element with no attributes and no content}])
equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com")
- equal_element.matches?('<A>Test</A>').should be_false
- equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"\n}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}]
+ expect(equal_element.matches?('<A>Test</A>')).to be_falsey
+ expect(equal_element.negative_failure_message).to eq([%{Expected "<A>Test</A>"}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}])
end
end
diff --git a/spec/mspec/spec/matchers/equal_spec.rb b/spec/mspec/spec/matchers/equal_spec.rb
index ca7bf83fdd..2df1de54b4 100644
--- a/spec/mspec/spec/matchers/equal_spec.rb
+++ b/spec/mspec/spec/matchers/equal_spec.rb
@@ -2,31 +2,31 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe EqualMatcher do
+RSpec.describe EqualMatcher do
it "matches when actual is equal? to expected" do
- EqualMatcher.new(1).matches?(1).should == true
- EqualMatcher.new(:blue).matches?(:blue).should == true
- EqualMatcher.new(Object).matches?(Object).should == true
+ expect(EqualMatcher.new(1).matches?(1)).to eq(true)
+ expect(EqualMatcher.new(:blue).matches?(:blue)).to eq(true)
+ expect(EqualMatcher.new(Object).matches?(Object)).to eq(true)
o = Object.new
- EqualMatcher.new(o).matches?(o).should == true
+ expect(EqualMatcher.new(o).matches?(o)).to eq(true)
end
it "does not match when actual is not a equal? to expected" do
- EqualMatcher.new(1).matches?(1.0).should == false
- EqualMatcher.new("blue").matches?("blue").should == false
- EqualMatcher.new(Hash).matches?(Object).should == false
+ expect(EqualMatcher.new(1).matches?(1.0)).to eq(false)
+ expect(EqualMatcher.new("blue").matches?("blue")).to eq(false)
+ expect(EqualMatcher.new(Hash).matches?(Object)).to eq(false)
end
it "provides a useful failure message" do
matcher = EqualMatcher.new("red")
matcher.matches?("red")
- matcher.failure_message.should == ["Expected \"red\"\n", "to be identical to \"red\"\n"]
+ expect(matcher.failure_message).to eq(["Expected \"red\"", "to be identical to \"red\""])
end
it "provides a useful negative failure message" do
matcher = EqualMatcher.new(1)
matcher.matches?(1)
- matcher.negative_failure_message.should == ["Expected 1\n", "not to be identical to 1\n"]
+ expect(matcher.negative_failure_message).to eq(["Expected 1", "not to be identical to 1"])
end
end
diff --git a/spec/mspec/spec/matchers/have_class_variable_spec.rb b/spec/mspec/spec/matchers/have_class_variable_spec.rb
index 01ba9d0f57..d6fcf9d4e2 100644
--- a/spec/mspec/spec/matchers/have_class_variable_spec.rb
+++ b/spec/mspec/spec/matchers/have_class_variable_spec.rb
@@ -8,42 +8,42 @@ class IVarModMock
end
end
-describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do
+RSpec.describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do
it "matches when mod has the class variable, given as string" do
matcher = HaveClassVariableMatcher.new('@foo')
- matcher.matches?(IVarModMock).should be_true
+ expect(matcher.matches?(IVarModMock)).to be_truthy
end
it "matches when mod has the class variable, given as symbol" do
matcher = HaveClassVariableMatcher.new(:@foo)
- matcher.matches?(IVarModMock).should be_true
+ expect(matcher.matches?(IVarModMock)).to be_truthy
end
it "does not match when mod hasn't got the class variable, given as string" do
matcher = HaveClassVariableMatcher.new('@bar')
- matcher.matches?(IVarModMock).should be_false
+ expect(matcher.matches?(IVarModMock)).to be_falsey
end
it "does not match when mod hasn't got the class variable, given as symbol" do
matcher = HaveClassVariableMatcher.new(:@bar)
- matcher.matches?(IVarModMock).should be_false
+ expect(matcher.matches?(IVarModMock)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveClassVariableMatcher.new(:@bar)
matcher.matches?(IVarModMock)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected IVarModMock to have class variable '@bar'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveClassVariableMatcher.new(:@bar)
matcher.matches?(IVarModMock)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected IVarModMock NOT to have class variable '@bar'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_constant_spec.rb b/spec/mspec/spec/matchers/have_constant_spec.rb
index 20c5f161d4..0bf44dbe2b 100644
--- a/spec/mspec/spec/matchers/have_constant_spec.rb
+++ b/spec/mspec/spec/matchers/have_constant_spec.rb
@@ -6,32 +6,32 @@ class HCMSpecs
X = :x
end
-describe HaveConstantMatcher do
+RSpec.describe HaveConstantMatcher do
it "matches when mod has the constant" do
matcher = HaveConstantMatcher.new :X
- matcher.matches?(HCMSpecs).should be_true
+ expect(matcher.matches?(HCMSpecs)).to be_truthy
end
it "does not match when mod does not have the constant" do
matcher = HaveConstantMatcher.new :A
- matcher.matches?(HCMSpecs).should be_false
+ expect(matcher.matches?(HCMSpecs)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveConstantMatcher.new :A
matcher.matches?(HCMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HCMSpecs to have constant 'A'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveConstantMatcher.new :X
matcher.matches?(HCMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HCMSpecs NOT to have constant 'X'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_instance_method_spec.rb b/spec/mspec/spec/matchers/have_instance_method_spec.rb
index 738f5f875d..7c2e50dba6 100644
--- a/spec/mspec/spec/matchers/have_instance_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_instance_method_spec.rb
@@ -12,42 +12,42 @@ class HIMMSpecs
end
end
-describe HaveInstanceMethodMatcher do
+RSpec.describe HaveInstanceMethodMatcher do
it "inherits from MethodMatcher" do
- HaveInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HaveInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the instance method" do
matcher = HaveInstanceMethodMatcher.new :instance_method
- matcher.matches?(HIMMSpecs).should be_true
- matcher.matches?(HIMMSpecs::Subclass).should be_true
+ expect(matcher.matches?(HIMMSpecs)).to be_truthy
+ expect(matcher.matches?(HIMMSpecs::Subclass)).to be_truthy
end
it "does not match when mod does not have the instance method" do
matcher = HaveInstanceMethodMatcher.new :another_method
- matcher.matches?(HIMMSpecs).should be_false
+ expect(matcher.matches?(HIMMSpecs)).to be_falsey
end
it "does not match if the method is in a superclass and include_super is false" do
matcher = HaveInstanceMethodMatcher.new :instance_method, false
- matcher.matches?(HIMMSpecs::Subclass).should be_false
+ expect(matcher.matches?(HIMMSpecs::Subclass)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveInstanceMethodMatcher.new :some_method
matcher.matches?(HIMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HIMMSpecs to have instance method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveInstanceMethodMatcher.new :some_method
matcher.matches?(HIMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HIMMSpecs NOT to have instance method 'some_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_instance_variable_spec.rb b/spec/mspec/spec/matchers/have_instance_variable_spec.rb
index 4122c6551b..12e2470f14 100644
--- a/spec/mspec/spec/matchers/have_instance_variable_spec.rb
+++ b/spec/mspec/spec/matchers/have_instance_variable_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe HaveInstanceVariableMatcher do
+RSpec.describe HaveInstanceVariableMatcher do
before :each do
@object = Object.new
def @object.instance_variables
@@ -12,39 +12,39 @@ describe HaveInstanceVariableMatcher do
it "matches when object has the instance variable, given as string" do
matcher = HaveInstanceVariableMatcher.new('@foo')
- matcher.matches?(@object).should be_true
+ expect(matcher.matches?(@object)).to be_truthy
end
it "matches when object has the instance variable, given as symbol" do
matcher = HaveInstanceVariableMatcher.new(:@foo)
- matcher.matches?(@object).should be_true
+ expect(matcher.matches?(@object)).to be_truthy
end
it "does not match when object hasn't got the instance variable, given as string" do
matcher = HaveInstanceVariableMatcher.new('@bar')
- matcher.matches?(@object).should be_false
+ expect(matcher.matches?(@object)).to be_falsey
end
it "does not match when object hasn't got the instance variable, given as symbol" do
matcher = HaveInstanceVariableMatcher.new(:@bar)
- matcher.matches?(@object).should be_false
+ expect(matcher.matches?(@object)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveInstanceVariableMatcher.new(:@bar)
matcher.matches?(@object)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected #{@object.inspect} to have instance variable '@bar'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveInstanceVariableMatcher.new(:@bar)
matcher.matches?(@object)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected #{@object.inspect} NOT to have instance variable '@bar'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_method_spec.rb b/spec/mspec/spec/matchers/have_method_spec.rb
index 41bd485119..4fc0bf5e45 100644
--- a/spec/mspec/spec/matchers/have_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_method_spec.rb
@@ -12,44 +12,44 @@ class HMMSpecs
end
end
-describe HaveMethodMatcher do
+RSpec.describe HaveMethodMatcher do
it "inherits from MethodMatcher" do
- HaveMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HaveMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the method" do
matcher = HaveMethodMatcher.new :instance_method
- matcher.matches?(HMMSpecs).should be_true
- matcher.matches?(HMMSpecs.new).should be_true
- matcher.matches?(HMMSpecs::Subclass).should be_true
- matcher.matches?(HMMSpecs::Subclass.new).should be_true
+ expect(matcher.matches?(HMMSpecs)).to be_truthy
+ expect(matcher.matches?(HMMSpecs.new)).to be_truthy
+ expect(matcher.matches?(HMMSpecs::Subclass)).to be_truthy
+ expect(matcher.matches?(HMMSpecs::Subclass.new)).to be_truthy
end
it "does not match when mod does not have the method" do
matcher = HaveMethodMatcher.new :another_method
- matcher.matches?(HMMSpecs).should be_false
+ expect(matcher.matches?(HMMSpecs)).to be_falsey
end
it "does not match if the method is in a superclass and include_super is false" do
matcher = HaveMethodMatcher.new :instance_method, false
- matcher.matches?(HMMSpecs::Subclass).should be_false
+ expect(matcher.matches?(HMMSpecs::Subclass)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveMethodMatcher.new :some_method
matcher.matches?(HMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HMMSpecs to have method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveMethodMatcher.new :some_method
matcher.matches?(HMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HMMSpecs NOT to have method 'some_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_private_instance_method_spec.rb b/spec/mspec/spec/matchers/have_private_instance_method_spec.rb
index 827c6b6034..0e65c264d9 100644
--- a/spec/mspec/spec/matchers/have_private_instance_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_private_instance_method_spec.rb
@@ -16,42 +16,42 @@ class HPIMMSpecs
end
end
-describe HavePrivateInstanceMethodMatcher do
+RSpec.describe HavePrivateInstanceMethodMatcher do
it "inherits from MethodMatcher" do
- HavePrivateInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HavePrivateInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the private instance method" do
matcher = HavePrivateInstanceMethodMatcher.new :private_method
- matcher.matches?(HPIMMSpecs).should be_true
- matcher.matches?(HPIMMSpecs::Subclass).should be_true
+ expect(matcher.matches?(HPIMMSpecs)).to be_truthy
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy
end
it "does not match when mod does not have the private instance method" do
matcher = HavePrivateInstanceMethodMatcher.new :another_method
- matcher.matches?(HPIMMSpecs).should be_false
+ expect(matcher.matches?(HPIMMSpecs)).to be_falsey
end
it "does not match if the method is in a superclass and include_super is false" do
matcher = HavePrivateInstanceMethodMatcher.new :private_method, false
- matcher.matches?(HPIMMSpecs::Subclass).should be_false
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HavePrivateInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HPIMMSpecs to have private instance method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure message for #should_not" do
matcher = HavePrivateInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HPIMMSpecs NOT to have private instance method 'some_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_private_method_spec.rb b/spec/mspec/spec/matchers/have_private_method_spec.rb
index e63a9a3c2f..f433288057 100644
--- a/spec/mspec/spec/matchers/have_private_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_private_method_spec.rb
@@ -9,36 +9,36 @@ class HPMMSpecs
private_class_method :private_method
end
-describe HavePrivateMethodMatcher do
+RSpec.describe HavePrivateMethodMatcher do
it "inherits from MethodMatcher" do
- HavePrivateMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HavePrivateMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the private method" do
matcher = HavePrivateMethodMatcher.new :private_method
- matcher.matches?(HPMMSpecs).should be_true
+ expect(matcher.matches?(HPMMSpecs)).to be_truthy
end
it "does not match when mod does not have the private method" do
matcher = HavePrivateMethodMatcher.new :another_method
- matcher.matches?(HPMMSpecs).should be_false
+ expect(matcher.matches?(HPMMSpecs)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HavePrivateMethodMatcher.new :some_method
matcher.matches?(HPMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HPMMSpecs to have private method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure message for #should_not" do
matcher = HavePrivateMethodMatcher.new :private_method
matcher.matches?(HPMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HPMMSpecs NOT to have private method 'private_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb b/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb
index 460d0368fb..45b39004a3 100644
--- a/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb
@@ -16,42 +16,42 @@ class HPIMMSpecs
end
end
-describe HaveProtectedInstanceMethodMatcher do
+RSpec.describe HaveProtectedInstanceMethodMatcher do
it "inherits from MethodMatcher" do
- HaveProtectedInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HaveProtectedInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the protected instance method" do
matcher = HaveProtectedInstanceMethodMatcher.new :protected_method
- matcher.matches?(HPIMMSpecs).should be_true
- matcher.matches?(HPIMMSpecs::Subclass).should be_true
+ expect(matcher.matches?(HPIMMSpecs)).to be_truthy
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy
end
it "does not match when mod does not have the protected instance method" do
matcher = HaveProtectedInstanceMethodMatcher.new :another_method
- matcher.matches?(HPIMMSpecs).should be_false
+ expect(matcher.matches?(HPIMMSpecs)).to be_falsey
end
it "does not match if the method is in a superclass and include_super is false" do
matcher = HaveProtectedInstanceMethodMatcher.new :protected_method, false
- matcher.matches?(HPIMMSpecs::Subclass).should be_false
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HaveProtectedInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HPIMMSpecs to have protected instance method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HaveProtectedInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HPIMMSpecs NOT to have protected instance method 'some_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_public_instance_method_spec.rb b/spec/mspec/spec/matchers/have_public_instance_method_spec.rb
index bff1046f04..771d5b7911 100644
--- a/spec/mspec/spec/matchers/have_public_instance_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_public_instance_method_spec.rb
@@ -12,42 +12,42 @@ class HPIMMSpecs
end
end
-describe HavePublicInstanceMethodMatcher do
+RSpec.describe HavePublicInstanceMethodMatcher do
it "inherits from MethodMatcher" do
- HavePublicInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HavePublicInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when mod has the public instance method" do
matcher = HavePublicInstanceMethodMatcher.new :public_method
- matcher.matches?(HPIMMSpecs).should be_true
- matcher.matches?(HPIMMSpecs::Subclass).should be_true
+ expect(matcher.matches?(HPIMMSpecs)).to be_truthy
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy
end
it "does not match when mod does not have the public instance method" do
matcher = HavePublicInstanceMethodMatcher.new :another_method
- matcher.matches?(HPIMMSpecs).should be_false
+ expect(matcher.matches?(HPIMMSpecs)).to be_falsey
end
it "does not match if the method is in a superclass and include_super is false" do
matcher = HavePublicInstanceMethodMatcher.new :public_method, false
- matcher.matches?(HPIMMSpecs::Subclass).should be_false
+ expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey
end
it "provides a failure message for #should" do
matcher = HavePublicInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HPIMMSpecs to have public instance method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure messoge for #should_not" do
matcher = HavePublicInstanceMethodMatcher.new :some_method
matcher.matches?(HPIMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HPIMMSpecs NOT to have public instance method 'some_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/have_singleton_method_spec.rb b/spec/mspec/spec/matchers/have_singleton_method_spec.rb
index 57c37e01d9..61ef00d49c 100644
--- a/spec/mspec/spec/matchers/have_singleton_method_spec.rb
+++ b/spec/mspec/spec/matchers/have_singleton_method_spec.rb
@@ -7,14 +7,14 @@ class HSMMSpecs
end
end
-describe HaveSingletonMethodMatcher do
+RSpec.describe HaveSingletonMethodMatcher do
it "inherits from MethodMatcher" do
- HaveSingletonMethodMatcher.new(:m).should be_kind_of(MethodMatcher)
+ expect(HaveSingletonMethodMatcher.new(:m)).to be_kind_of(MethodMatcher)
end
it "matches when the class has a singleton method" do
matcher = HaveSingletonMethodMatcher.new :singleton_method
- matcher.matches?(HSMMSpecs).should be_true
+ expect(matcher.matches?(HSMMSpecs)).to be_truthy
end
it "matches when the object has a singleton method" do
@@ -22,24 +22,24 @@ describe HaveSingletonMethodMatcher do
def obj.singleton_method; end
matcher = HaveSingletonMethodMatcher.new :singleton_method
- matcher.matches?(obj).should be_true
+ expect(matcher.matches?(obj)).to be_truthy
end
it "provides a failure message for #should" do
matcher = HaveSingletonMethodMatcher.new :some_method
matcher.matches?(HSMMSpecs)
- matcher.failure_message.should == [
+ expect(matcher.failure_message).to eq([
"Expected HSMMSpecs to have singleton method 'some_method'",
"but it does not"
- ]
+ ])
end
it "provides a failure message for #should_not" do
matcher = HaveSingletonMethodMatcher.new :singleton_method
matcher.matches?(HSMMSpecs)
- matcher.negative_failure_message.should == [
+ expect(matcher.negative_failure_message).to eq([
"Expected HSMMSpecs NOT to have singleton method 'singleton_method'",
"but it does"
- ]
+ ])
end
end
diff --git a/spec/mspec/spec/matchers/include_any_of_spec.rb b/spec/mspec/spec/matchers/include_any_of_spec.rb
index 697c8d8886..1473bb6d0b 100644
--- a/spec/mspec/spec/matchers/include_any_of_spec.rb
+++ b/spec/mspec/spec/matchers/include_any_of_spec.rb
@@ -2,41 +2,41 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe IncludeAnyOfMatcher do
+RSpec.describe IncludeAnyOfMatcher do
it "matches when actual includes expected" do
- IncludeAnyOfMatcher.new(2).matches?([1,2,3]).should == true
- IncludeAnyOfMatcher.new("b").matches?("abc").should == true
+ expect(IncludeAnyOfMatcher.new(2).matches?([1,2,3])).to eq(true)
+ expect(IncludeAnyOfMatcher.new("b").matches?("abc")).to eq(true)
end
it "does not match when actual does not include expected" do
- IncludeAnyOfMatcher.new(4).matches?([1,2,3]).should == false
- IncludeAnyOfMatcher.new("d").matches?("abc").should == false
+ expect(IncludeAnyOfMatcher.new(4).matches?([1,2,3])).to eq(false)
+ expect(IncludeAnyOfMatcher.new("d").matches?("abc")).to eq(false)
end
it "matches when actual includes all expected" do
- IncludeAnyOfMatcher.new(3, 2, 1).matches?([1,2,3]).should == true
- IncludeAnyOfMatcher.new("a", "b", "c").matches?("abc").should == true
+ expect(IncludeAnyOfMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true)
+ expect(IncludeAnyOfMatcher.new("a", "b", "c").matches?("abc")).to eq(true)
end
it "matches when actual includes any expected" do
- IncludeAnyOfMatcher.new(3, 4, 5).matches?([1,2,3]).should == true
- IncludeAnyOfMatcher.new("c", "d", "e").matches?("abc").should == true
+ expect(IncludeAnyOfMatcher.new(3, 4, 5).matches?([1,2,3])).to eq(true)
+ expect(IncludeAnyOfMatcher.new("c", "d", "e").matches?("abc")).to eq(true)
end
it "does not match when actual does not include any expected" do
- IncludeAnyOfMatcher.new(4, 5).matches?([1,2,3]).should == false
- IncludeAnyOfMatcher.new("de").matches?("abc").should == false
+ expect(IncludeAnyOfMatcher.new(4, 5).matches?([1,2,3])).to eq(false)
+ expect(IncludeAnyOfMatcher.new("de").matches?("abc")).to eq(false)
end
it "provides a useful failure message" do
matcher = IncludeAnyOfMatcher.new(5, 6)
matcher.matches?([1,2,3])
- matcher.failure_message.should == ["Expected [1, 2, 3]", "to include any of [5, 6]"]
+ expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include any of [5, 6]"])
end
it "provides a useful negative failure message" do
matcher = IncludeAnyOfMatcher.new(1, 2, 3)
matcher.matches?([1,2])
- matcher.negative_failure_message.should == ["Expected [1, 2]", "not to include any of [1, 2, 3]"]
+ expect(matcher.negative_failure_message).to eq(["Expected [1, 2]", "not to include any of [1, 2, 3]"])
end
end
diff --git a/spec/mspec/spec/matchers/include_spec.rb b/spec/mspec/spec/matchers/include_spec.rb
index f045c5e0cb..6bf1bef085 100644
--- a/spec/mspec/spec/matchers/include_spec.rb
+++ b/spec/mspec/spec/matchers/include_spec.rb
@@ -2,36 +2,36 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe IncludeMatcher do
+RSpec.describe IncludeMatcher do
it "matches when actual includes expected" do
- IncludeMatcher.new(2).matches?([1,2,3]).should == true
- IncludeMatcher.new("b").matches?("abc").should == true
+ expect(IncludeMatcher.new(2).matches?([1,2,3])).to eq(true)
+ expect(IncludeMatcher.new("b").matches?("abc")).to eq(true)
end
it "does not match when actual does not include expected" do
- IncludeMatcher.new(4).matches?([1,2,3]).should == false
- IncludeMatcher.new("d").matches?("abc").should == false
+ expect(IncludeMatcher.new(4).matches?([1,2,3])).to eq(false)
+ expect(IncludeMatcher.new("d").matches?("abc")).to eq(false)
end
it "matches when actual includes all expected" do
- IncludeMatcher.new(3, 2, 1).matches?([1,2,3]).should == true
- IncludeMatcher.new("a", "b", "c").matches?("abc").should == true
+ expect(IncludeMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true)
+ expect(IncludeMatcher.new("a", "b", "c").matches?("abc")).to eq(true)
end
it "does not match when actual does not include all expected" do
- IncludeMatcher.new(3, 2, 4).matches?([1,2,3]).should == false
- IncludeMatcher.new("a", "b", "c", "d").matches?("abc").should == false
+ expect(IncludeMatcher.new(3, 2, 4).matches?([1,2,3])).to eq(false)
+ expect(IncludeMatcher.new("a", "b", "c", "d").matches?("abc")).to eq(false)
end
it "provides a useful failure message" do
matcher = IncludeMatcher.new(5, 2)
matcher.matches?([1,2,3])
- matcher.failure_message.should == ["Expected [1, 2, 3]", "to include 5"]
+ expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include 5"])
end
it "provides a useful negative failure message" do
matcher = IncludeMatcher.new(1, 2, 3)
matcher.matches?([1,2,3])
- matcher.negative_failure_message.should == ["Expected [1, 2, 3]", "not to include 3"]
+ expect(matcher.negative_failure_message).to eq(["Expected [1, 2, 3]", "not to include 3"])
end
end
diff --git a/spec/mspec/spec/matchers/infinity_spec.rb b/spec/mspec/spec/matchers/infinity_spec.rb
index 6eb8ac2940..78c4194526 100644
--- a/spec/mspec/spec/matchers/infinity_spec.rb
+++ b/spec/mspec/spec/matchers/infinity_spec.rb
@@ -4,31 +4,31 @@ require 'mspec/guards'
require 'mspec/helpers'
require 'mspec/matchers'
-describe InfinityMatcher do
+RSpec.describe InfinityMatcher do
it "matches when actual is infinite and has the correct sign" do
- InfinityMatcher.new(1).matches?(infinity_value).should == true
- InfinityMatcher.new(-1).matches?(-infinity_value).should == true
+ expect(InfinityMatcher.new(1).matches?(infinity_value)).to eq(true)
+ expect(InfinityMatcher.new(-1).matches?(-infinity_value)).to eq(true)
end
it "does not match when actual is not infinite" do
- InfinityMatcher.new(1).matches?(1.0).should == false
- InfinityMatcher.new(-1).matches?(-1.0).should == false
+ expect(InfinityMatcher.new(1).matches?(1.0)).to eq(false)
+ expect(InfinityMatcher.new(-1).matches?(-1.0)).to eq(false)
end
it "does not match when actual is infinite but has the incorrect sign" do
- InfinityMatcher.new(1).matches?(-infinity_value).should == false
- InfinityMatcher.new(-1).matches?(infinity_value).should == false
+ expect(InfinityMatcher.new(1).matches?(-infinity_value)).to eq(false)
+ expect(InfinityMatcher.new(-1).matches?(infinity_value)).to eq(false)
end
it "provides a useful failure message" do
matcher = InfinityMatcher.new(-1)
matcher.matches?(0)
- matcher.failure_message.should == ["Expected 0", "to be -Infinity"]
+ expect(matcher.failure_message).to eq(["Expected 0", "to be -Infinity"])
end
it "provides a useful negative failure message" do
matcher = InfinityMatcher.new(1)
matcher.matches?(infinity_value)
- matcher.negative_failure_message.should == ["Expected Infinity", "not to be Infinity"]
+ expect(matcher.negative_failure_message).to eq(["Expected Infinity", "not to be Infinity"])
end
end
diff --git a/spec/mspec/spec/matchers/match_yaml_spec.rb b/spec/mspec/spec/matchers/match_yaml_spec.rb
index 4f16aee0ec..85123bb87d 100644
--- a/spec/mspec/spec/matchers/match_yaml_spec.rb
+++ b/spec/mspec/spec/matchers/match_yaml_spec.rb
@@ -2,38 +2,38 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe MatchYAMLMatcher do
+RSpec.describe MatchYAMLMatcher do
before :each do
@matcher = MatchYAMLMatcher.new("--- \nfoo: bar\n")
end
it "compares YAML documents and matches if they're equivalent" do
- @matcher.matches?("--- \nfoo: bar\n").should == true
+ expect(@matcher.matches?("--- \nfoo: bar\n")).to eq(true)
end
it "compares YAML documents and does not match if they're not equivalent" do
- @matcher.matches?("--- \nbar: foo\n").should == false
- @matcher.matches?("--- \nfoo: \nbar\n").should == false
+ expect(@matcher.matches?("--- \nbar: foo\n")).to eq(false)
+ expect(@matcher.matches?("--- \nfoo: \nbar\n")).to eq(false)
end
it "also receives objects that respond_to to_yaml" do
matcher = MatchYAMLMatcher.new("some string")
- matcher.matches?("some string").should == true
+ expect(matcher.matches?("some string")).to eq(true)
matcher = MatchYAMLMatcher.new(['a', 'b'])
- matcher.matches?("--- \n- a\n- b\n").should == true
+ expect(matcher.matches?("--- \n- a\n- b\n")).to eq(true)
matcher = MatchYAMLMatcher.new("foo" => "bar")
- matcher.matches?("--- \nfoo: bar\n").should == true
+ expect(matcher.matches?("--- \nfoo: bar\n")).to eq(true)
end
it "matches documents with trailing whitespace" do
- @matcher.matches?("--- \nfoo: bar \n").should == true
- @matcher.matches?("--- \nfoo: bar \n").should == true
+ expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true)
+ expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true)
end
it "fails with a descriptive error message" do
- @matcher.matches?("foo").should == false
- @matcher.failure_message.should == ["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""]
+ expect(@matcher.matches?("foo")).to eq(false)
+ expect(@matcher.failure_message).to eq(["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""])
end
end
diff --git a/spec/mspec/spec/matchers/output_spec.rb b/spec/mspec/spec/matchers/output_spec.rb
index 264da3b569..3baad9a4b2 100644
--- a/spec/mspec/spec/matchers/output_spec.rb
+++ b/spec/mspec/spec/matchers/output_spec.rb
@@ -2,73 +2,83 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe OutputMatcher do
+RSpec.describe OutputMatcher do
it "matches when executing the proc results in the expected output to $stdout" do
proc = Proc.new { puts "bang!" }
- OutputMatcher.new("bang!\n", nil).matches?(proc).should == true
- OutputMatcher.new("pop", nil).matches?(proc).should == false
- OutputMatcher.new(/bang/, nil).matches?(proc).should == true
- OutputMatcher.new(/po/, nil).matches?(proc).should == false
+ expect(OutputMatcher.new("bang!\n", nil).matches?(proc)).to eq(true)
+ expect(OutputMatcher.new("pop", nil).matches?(proc)).to eq(false)
+ expect(OutputMatcher.new(/bang/, nil).matches?(proc)).to eq(true)
+ expect(OutputMatcher.new(/po/, nil).matches?(proc)).to eq(false)
end
it "matches when executing the proc results in the expected output to $stderr" do
proc = Proc.new { $stderr.write "boom!" }
- OutputMatcher.new(nil, "boom!").matches?(proc).should == true
- OutputMatcher.new(nil, "fizzle").matches?(proc).should == false
- OutputMatcher.new(nil, /boom/).matches?(proc).should == true
- OutputMatcher.new(nil, /fizzl/).matches?(proc).should == false
+ expect(OutputMatcher.new(nil, "boom!").matches?(proc)).to eq(true)
+ expect(OutputMatcher.new(nil, "fizzle").matches?(proc)).to eq(false)
+ expect(OutputMatcher.new(nil, /boom/).matches?(proc)).to eq(true)
+ expect(OutputMatcher.new(nil, /fizzl/).matches?(proc)).to eq(false)
end
it "provides a useful failure message" do
proc = Proc.new { print "unexpected"; $stderr.print "unerror" }
matcher = OutputMatcher.new("expected", "error")
matcher.matches?(proc)
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected:\n $stdout: \"expected\"\n $stderr: \"error\"\n",
" got:\n $stdout: \"unexpected\"\n $stderr: \"unerror\"\n"]
+ )
matcher = OutputMatcher.new("expected", nil)
matcher.matches?(proc)
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected:\n $stdout: \"expected\"\n",
" got:\n $stdout: \"unexpected\"\n"]
+ )
matcher = OutputMatcher.new(nil, "error")
matcher.matches?(proc)
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected:\n $stderr: \"error\"\n",
" got:\n $stderr: \"unerror\"\n"]
+ )
matcher = OutputMatcher.new(/base/, nil)
matcher.matches?(proc)
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected:\n $stdout: /base/\n",
" got:\n $stdout: \"unexpected\"\n"]
+ )
matcher = OutputMatcher.new(nil, /octave/)
matcher.matches?(proc)
- matcher.failure_message.should ==
+ expect(matcher.failure_message).to eq(
["Expected:\n $stderr: /octave/\n",
" got:\n $stderr: \"unerror\"\n"]
+ )
end
it "provides a useful negative failure message" do
proc = Proc.new { puts "expected"; $stderr.puts "error" }
matcher = OutputMatcher.new("expected", "error")
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected output not to be:\n", " $stdout: \"expected\"\n $stderr: \"error\"\n"]
+ )
matcher = OutputMatcher.new("expected", nil)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected output not to be:\n", " $stdout: \"expected\"\n"]
+ )
matcher = OutputMatcher.new(nil, "error")
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected output not to be:\n", " $stderr: \"error\"\n"]
+ )
matcher = OutputMatcher.new(/expect/, nil)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected output not to be:\n", " $stdout: \"expected\"\n"]
+ )
matcher = OutputMatcher.new(nil, /err/)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
+ expect(matcher.negative_failure_message).to eq(
["Expected output not to be:\n", " $stderr: \"error\"\n"]
+ )
end
end
diff --git a/spec/mspec/spec/matchers/output_to_fd_spec.rb b/spec/mspec/spec/matchers/output_to_fd_spec.rb
index e584c4e003..a39cab3206 100644
--- a/spec/mspec/spec/matchers/output_to_fd_spec.rb
+++ b/spec/mspec/spec/matchers/output_to_fd_spec.rb
@@ -2,43 +2,43 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe OutputToFDMatcher do
+RSpec.describe OutputToFDMatcher do
# Figure out how in the hell to achieve this
it "matches when running the block produces the expected output to the given FD" do
- OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" }).should == true
+ expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" })).to eq(true)
end
it "does not match if running the block does not produce the expected output to the FD" do
- OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") }).should == false
+ expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") })).to eq(false)
end
it "propagate the exception if one is thrown while matching" do
exc = RuntimeError.new("propagates")
- lambda {
- OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda {
+ expect {
+ expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda {
raise exc
- }).should == false
- }.should raise_error(exc)
+ })).to eq(false)
+ }.to raise_error(exc)
end
it "defaults to matching against STDOUT" do
object = Object.new
object.extend MSpecMatchers
- object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" }).should == true
+ expect(object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" })).to eq(true)
end
it "accepts any IO instance" do
io = IO.new STDOUT.fileno
- OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" }).should == true
+ expect(OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" })).to eq(true)
end
it "allows matching with a Regexp" do
s = "Hi there\n"
- OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s }).should == true
- OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s }).should == true
- OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s }).should == true
- OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s }).should == true
- OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s }).should == true
- OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s }).should == false
+ expect(OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s })).to eq(true)
+ expect(OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true)
+ expect(OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true)
+ expect(OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s })).to eq(true)
+ expect(OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s })).to eq(true)
+ expect(OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s })).to eq(false)
end
end
diff --git a/spec/mspec/spec/matchers/raise_error_spec.rb b/spec/mspec/spec/matchers/raise_error_spec.rb
index 7c93f0f64c..3849c7dd2a 100644
--- a/spec/mspec/spec/matchers/raise_error_spec.rb
+++ b/spec/mspec/spec/matchers/raise_error_spec.rb
@@ -1,93 +1,153 @@
require 'spec_helper'
-require 'mspec/expectations/expectations'
-require 'mspec/matchers'
class ExpectedException < Exception; end
class UnexpectedException < Exception; end
-describe RaiseErrorMatcher do
+RSpec.describe RaiseErrorMatcher do
+ before :each do
+ state = double("run state").as_null_object
+ allow(MSpec).to receive(:current).and_return(state)
+ end
+
it "matches when the proc raises the expected exception" do
proc = Proc.new { raise ExpectedException }
matcher = RaiseErrorMatcher.new(ExpectedException, nil)
- matcher.matches?(proc).should == true
+ expect(matcher.matches?(proc)).to eq(true)
end
- it "executes it's optional block if matched" do
+ it "executes its optional {/} block if matched" do
+ ensure_mspec_method(-> {}.method(:should))
+
run = false
- proc = Proc.new { raise ExpectedException }
- matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error|
+ -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error { |error|
+ expect(error.class).to eq(ExpectedException)
run = true
- error.class.should == ExpectedException
}
+ expect(run).to eq(true)
+ end
- matcher.matches?(proc).should == true
- run.should == true
+ it "executes its optional do/end block if matched" do
+ ensure_mspec_method(-> {}.method(:should))
+
+ run = false
+ -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error do |error|
+ expect(error.class).to eq(ExpectedException)
+ run = true
+ end
+ expect(run).to eq(true)
end
it "matches when the proc raises the expected exception with the expected message" do
proc = Proc.new { raise ExpectedException, "message" }
matcher = RaiseErrorMatcher.new(ExpectedException, "message")
- matcher.matches?(proc).should == true
+ expect(matcher.matches?(proc)).to eq(true)
end
it "matches when the proc raises the expected exception with a matching message" do
proc = Proc.new { raise ExpectedException, "some message" }
matcher = RaiseErrorMatcher.new(ExpectedException, /some/)
- matcher.matches?(proc).should == true
+ expect(matcher.matches?(proc)).to eq(true)
end
it "does not match when the proc does not raise the expected exception" do
exc = UnexpectedException.new
matcher = RaiseErrorMatcher.new(ExpectedException, nil)
- matcher.matching_exception?(exc).should == false
- lambda {
+ expect(matcher.matching_exception?(exc)).to eq(false)
+ expect {
matcher.matches?(Proc.new { raise exc })
- }.should raise_error(UnexpectedException)
+ }.to raise_error(UnexpectedException)
end
it "does not match when the proc raises the expected exception with an unexpected message" do
exc = ExpectedException.new("unexpected")
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
- matcher.matching_exception?(exc).should == false
- lambda {
+ expect(matcher.matching_exception?(exc)).to eq(false)
+ expect {
matcher.matches?(Proc.new { raise exc })
- }.should raise_error(ExpectedException)
+ }.to raise_error(ExpectedException)
end
it "does not match when the proc does not raise an exception" do
proc = Proc.new {}
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
- matcher.matches?(proc).should == false
+ expect(matcher.matches?(proc)).to eq(false)
+ end
+
+ it "provides a useful failure message when the exception class differs" do
+ exc = UnexpectedException.new("message")
+ matcher = RaiseErrorMatcher.new(ExpectedException, "message")
+
+ expect(matcher.matching_exception?(exc)).to eq(false)
+ begin
+ matcher.matches?(Proc.new { raise exc })
+ rescue UnexpectedException => e
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("message")', 'but got: UnexpectedException("message")']
+ )
+ expect(ExceptionState.new(nil, nil, e).message).to eq(
+ "Expected ExpectedException(\"message\")\nbut got: UnexpectedException(\"message\")"
+ )
+ else
+ raise "no exception"
+ end
+ end
+
+ it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do
+ exc = ExpectedException.new("unexpected")
+ matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
+
+ expect(matcher.matching_exception?(exc)).to eq(false)
+ begin
+ matcher.matches?(Proc.new { raise exc })
+ rescue ExpectedException => e
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("expected")', 'but got: ExpectedException("unexpected")']
+ )
+ expect(ExceptionState.new(nil, nil, e).message).to eq(
+ "Expected ExpectedException(\"expected\")\nbut got: ExpectedException(\"unexpected\")"
+ )
+ else
+ raise "no exception"
+ end
end
- it "provides a useful failure message" do
+ it "provides a useful failure message when both the exception class and message differ" do
exc = UnexpectedException.new("unexpected")
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
- matcher.matching_exception?(exc).should == false
- lambda {
+ expect(matcher.matching_exception?(exc)).to eq(false)
+ begin
matcher.matches?(Proc.new { raise exc })
- }.should raise_error(UnexpectedException)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"]
+ rescue UnexpectedException => e
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("expected")', 'but got: UnexpectedException("unexpected")']
+ )
+ expect(ExceptionState.new(nil, nil, e).message).to eq(
+ "Expected ExpectedException(\"expected\")\nbut got: UnexpectedException(\"unexpected\")"
+ )
+ else
+ raise "no exception"
+ end
end
it "provides a useful failure message when no exception is raised" do
proc = Proc.new { 120 }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but no exception was raised (120 was returned)"]
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("expected")', "but no exception was raised (120 was returned)"]
+ )
end
it "provides a useful failure message when no exception is raised and nil is returned" do
proc = Proc.new { nil }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but no exception was raised (nil was returned)"]
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("expected")', "but no exception was raised (nil was returned)"]
+ )
end
it "provides a useful failure message when no exception is raised and the result raises in #pretty_inspect" do
@@ -98,23 +158,77 @@ describe RaiseErrorMatcher do
proc = Proc.new { result }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but no exception was raised (#pretty_inspect raised ArgumentError; A #<Object> was returned)"]
+ expect(matcher.failure_message).to eq(
+ ['Expected ExpectedException("expected")', 'but no exception was raised (#<Object>(#pretty_inspect raised #<ArgumentError: bad>) was returned)']
+ )
end
it "provides a useful negative failure message" do
proc = Proc.new { raise ExpectedException, "expected" }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
- ["Expected to not get ExpectedException (expected)", ""]
+ expect(matcher.negative_failure_message).to eq(
+ ['Expected to not get ExpectedException("expected")', ""]
+ )
end
it "provides a useful negative failure message for strict subclasses of the matched exception class" do
proc = Proc.new { raise UnexpectedException, "unexpected" }
matcher = RaiseErrorMatcher.new(Exception, nil)
matcher.matches?(proc)
- matcher.negative_failure_message.should ==
- ["Expected to not get Exception", "but got UnexpectedException (unexpected)"]
+ expect(matcher.negative_failure_message).to eq(
+ ['Expected to not get Exception', 'but got: UnexpectedException']
+ )
+ end
+
+ it "matches cause if given" do
+ cause = RuntimeError.new("foo")
+ proc = -> do
+ raise cause
+ rescue
+ raise "bar"
+ end
+
+ matcher = RaiseErrorMatcher.new(RuntimeError, cause: cause)
+ expect(matcher.matches?(proc)).to eq(true)
+ end
+
+ it "matches message and cause if given" do
+ cause = RuntimeError.new("foo")
+ proc = -> do
+ raise cause
+ rescue
+ raise "bar"
+ end
+
+ matcher = RaiseErrorMatcher.new(RuntimeError, "bar", cause: cause)
+ expect(matcher.matches?(proc)).to eq(true)
+ end
+
+ it "provides useful negative failure message when cause does not match" do
+ cause = RuntimeError.new("bar")
+ proc = -> do
+ raise "foo"
+ end
+
+ matcher = RaiseErrorMatcher.new(RuntimeError, cause: cause)
+
+ begin
+ matcher.matches?(proc)
+ rescue RuntimeError
+ expect(matcher.failure_message).to eq(
+ ['Expected RuntimeError(cause: #<RuntimeError: bar>)', 'but got: RuntimeError(cause: nil)']
+ )
+ end
+
+ matcher = RaiseErrorMatcher.new(RuntimeError, "foo", cause: cause)
+
+ begin
+ matcher.matches?(proc)
+ rescue RuntimeError
+ expect(matcher.failure_message).to eq(
+ ['Expected RuntimeError("foo", cause: #<RuntimeError: bar>)', 'but got: RuntimeError("foo", cause: nil)']
+ )
+ end
end
end
diff --git a/spec/mspec/spec/matchers/respond_to_spec.rb b/spec/mspec/spec/matchers/respond_to_spec.rb
index 988caf4dff..6f1cd8d148 100644
--- a/spec/mspec/spec/matchers/respond_to_spec.rb
+++ b/spec/mspec/spec/matchers/respond_to_spec.rb
@@ -2,32 +2,32 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe RespondToMatcher do
+RSpec.describe RespondToMatcher do
it "matches when actual does respond_to? expected" do
- RespondToMatcher.new(:to_s).matches?(Object.new).should == true
- RespondToMatcher.new(:inject).matches?([]).should == true
- RespondToMatcher.new(:[]).matches?(1).should == true
- RespondToMatcher.new(:[]=).matches?("string").should == true
+ expect(RespondToMatcher.new(:to_s).matches?(Object.new)).to eq(true)
+ expect(RespondToMatcher.new(:inject).matches?([])).to eq(true)
+ expect(RespondToMatcher.new(:[]).matches?(1)).to eq(true)
+ expect(RespondToMatcher.new(:[]=).matches?("string")).to eq(true)
end
it "does not match when actual does not respond_to? expected" do
- RespondToMatcher.new(:to_i).matches?(Object.new).should == false
- RespondToMatcher.new(:inject).matches?(1).should == false
- RespondToMatcher.new(:non_existent_method).matches?([]).should == false
- RespondToMatcher.new(:[]=).matches?(1).should == false
+ expect(RespondToMatcher.new(:to_i).matches?(Object.new)).to eq(false)
+ expect(RespondToMatcher.new(:inject).matches?(1)).to eq(false)
+ expect(RespondToMatcher.new(:non_existent_method).matches?([])).to eq(false)
+ expect(RespondToMatcher.new(:[]=).matches?(1)).to eq(false)
end
it "provides a useful failure message" do
matcher = RespondToMatcher.new(:non_existent_method)
matcher.matches?('string')
- matcher.failure_message.should == [
- "Expected \"string\" (String)", "to respond to non_existent_method"]
+ expect(matcher.failure_message).to eq([
+ "Expected \"string\" (String)", "to respond to non_existent_method"])
end
it "provides a useful negative failure message" do
matcher = RespondToMatcher.new(:to_i)
matcher.matches?(4.0)
- matcher.negative_failure_message.should == [
- "Expected 4.0 (Float)", "not to respond to to_i"]
+ expect(matcher.negative_failure_message).to eq([
+ "Expected 4.0 (Float)", "not to respond to to_i"])
end
end
diff --git a/spec/mspec/spec/matchers/signed_zero_spec.rb b/spec/mspec/spec/matchers/signed_zero_spec.rb
index 9c5c50c602..6d1c1007bc 100644
--- a/spec/mspec/spec/matchers/signed_zero_spec.rb
+++ b/spec/mspec/spec/matchers/signed_zero_spec.rb
@@ -2,31 +2,31 @@ require 'spec_helper'
require 'mspec/expectations/expectations'
require 'mspec/matchers'
-describe SignedZeroMatcher do
+RSpec.describe SignedZeroMatcher do
it "matches when actual is zero and has the correct sign" do
- SignedZeroMatcher.new(1).matches?(0.0).should == true
- SignedZeroMatcher.new(-1).matches?(-0.0).should == true
+ expect(SignedZeroMatcher.new(1).matches?(0.0)).to eq(true)
+ expect(SignedZeroMatcher.new(-1).matches?(-0.0)).to eq(true)
end
it "does not match when actual is non-zero" do
- SignedZeroMatcher.new(1).matches?(1.0).should == false
- SignedZeroMatcher.new(-1).matches?(-1.0).should == false
+ expect(SignedZeroMatcher.new(1).matches?(1.0)).to eq(false)
+ expect(SignedZeroMatcher.new(-1).matches?(-1.0)).to eq(false)
end
it "does not match when actual is zero but has the incorrect sign" do
- SignedZeroMatcher.new(1).matches?(-0.0).should == false
- SignedZeroMatcher.new(-1).matches?(0.0).should == false
+ expect(SignedZeroMatcher.new(1).matches?(-0.0)).to eq(false)
+ expect(SignedZeroMatcher.new(-1).matches?(0.0)).to eq(false)
end
it "provides a useful failure message" do
matcher = SignedZeroMatcher.new(-1)
matcher.matches?(0.0)
- matcher.failure_message.should == ["Expected 0.0", "to be -0.0"]
+ expect(matcher.failure_message).to eq(["Expected 0.0", "to be -0.0"])
end
it "provides a useful negative failure message" do
matcher = SignedZeroMatcher.new(-1)
matcher.matches?(-0.0)
- matcher.negative_failure_message.should == ["Expected -0.0", "not to be -0.0"]
+ expect(matcher.negative_failure_message).to eq(["Expected -0.0", "not to be -0.0"])
end
end
diff --git a/spec/mspec/spec/mocks/mock_spec.rb b/spec/mspec/spec/mocks/mock_spec.rb
index 8cf04cf462..7426e0ff88 100644
--- a/spec/mspec/spec/mocks/mock_spec.rb
+++ b/spec/mspec/spec/mocks/mock_spec.rb
@@ -7,78 +7,78 @@ require 'mspec/runner/mspec'
require 'mspec/mocks/mock'
require 'mspec/mocks/proxy'
-describe Mock, ".mocks" do
+RSpec.describe Mock, ".mocks" do
it "returns a Hash" do
- Mock.mocks.should be_kind_of(Hash)
+ expect(Mock.mocks).to be_kind_of(Hash)
end
end
-describe Mock, ".stubs" do
+RSpec.describe Mock, ".stubs" do
it "returns a Hash" do
- Mock.stubs.should be_kind_of(Hash)
+ expect(Mock.stubs).to be_kind_of(Hash)
end
end
-describe Mock, ".replaced_name" do
+RSpec.describe Mock, ".replaced_name" do
it "returns the name for a method that is being replaced by a mock method" do
m = double('a fake id')
- Mock.replaced_name(m, :method_call).should == :"__mspec_#{m.object_id}_method_call__"
+ expect(Mock.replaced_name(Mock.replaced_key(m, :method_call))).to eq(:"__mspec_method_call__")
end
end
-describe Mock, ".replaced_key" do
+RSpec.describe Mock, ".replaced_key" do
it "returns a key used internally by Mock" do
m = double('a fake id')
- Mock.replaced_key(m, :method_call).should == [:"__mspec_#{m.object_id}_method_call__", :method_call]
+ expect(Mock.replaced_key(m, :method_call)).to eq([m.object_id, :method_call])
end
end
-describe Mock, ".replaced?" do
+RSpec.describe Mock, ".replaced?" do
before :each do
@mock = double('install_method')
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
end
it "returns true if a method has been stubbed on an object" do
Mock.install_method @mock, :method_call
- Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true
+ expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_truthy
end
it "returns true if a method has been mocked on an object" do
Mock.install_method @mock, :method_call, :stub
- Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true
+ expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_truthy
end
it "returns false if a method has not been stubbed or mocked" do
- Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_false
+ expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_falsey
end
end
-describe Mock, ".name_or_inspect" do
+RSpec.describe Mock, ".name_or_inspect" do
before :each do
@mock = double("I have a #name")
end
it "returns the value of @name if set" do
@mock.instance_variable_set(:@name, "Myself")
- Mock.name_or_inspect(@mock).should == "Myself"
+ expect(Mock.name_or_inspect(@mock)).to eq("Myself")
end
end
-describe Mock, ".install_method for mocks" do
+RSpec.describe Mock, ".install_method for mocks" do
before :each do
@mock = double('install_method')
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
end
after :each do
- Mock.cleanup
+ Mock.reset
end
it "returns a MockProxy instance" do
- Mock.install_method(@mock, :method_call).should be_an_instance_of(MockProxy)
+ expect(Mock.install_method(@mock, :method_call)).to be_an_instance_of(MockProxy)
end
it "does not override a previously mocked method with the same name" do
@@ -86,7 +86,7 @@ describe Mock, ".install_method for mocks" do
Mock.install_method(@mock, :method_call).with(:c).and_return(2)
@mock.method_call(:a, :b)
@mock.method_call(:c)
- lambda { @mock.method_call(:d) }.should raise_error(SpecExpectationNotMetError)
+ expect { @mock.method_call(:d) }.to raise_error(SpecExpectationNotMetError)
end
# This illustrates RSpec's behavior. This spec fails in mock call count verification
@@ -105,44 +105,44 @@ describe Mock, ".install_method for mocks" do
#
it "does not override a previously mocked method having the same arguments" do
Mock.install_method(@mock, :method_call).with(:a).and_return(true)
- @mock.method_call(:a).should == true
+ expect(@mock.method_call(:a)).to eq(true)
Mock.install_method(@mock, :method_call).with(:a).and_return(false)
- @mock.method_call(:a).should == true
- lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError)
+ expect(@mock.method_call(:a)).to eq(true)
+ expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError)
end
it "properly sends #respond_to? calls to the aliased respond_to? method when not matching mock expectations" do
Mock.install_method(@mock, :respond_to?).with(:to_str).and_return('mock to_str')
Mock.install_method(@mock, :respond_to?).with(:to_int).and_return('mock to_int')
- @mock.respond_to?(:to_str).should == 'mock to_str'
- @mock.respond_to?(:to_int).should == 'mock to_int'
- @mock.respond_to?(:to_s).should == true
- @mock.respond_to?(:not_really_a_real_method_seriously).should == false
+ expect(@mock.respond_to?(:to_str)).to eq('mock to_str')
+ expect(@mock.respond_to?(:to_int)).to eq('mock to_int')
+ expect(@mock.respond_to?(:to_s)).to eq(true)
+ expect(@mock.respond_to?(:not_really_a_real_method_seriously)).to eq(false)
end
it "adds to the expectation tally" do
state = double("run state").as_null_object
- state.stub(:state).and_return(double("spec state"))
- MSpec.should_receive(:current).and_return(state)
- MSpec.should_receive(:actions).with(:expectation, state.state)
+ allow(state).to receive(:state).and_return(double("spec state"))
+ expect(MSpec).to receive(:current).and_return(state)
+ expect(MSpec).to receive(:actions).with(:expectation, state.state)
Mock.install_method(@mock, :method_call).and_return(1)
- @mock.method_call.should == 1
+ expect(@mock.method_call).to eq(1)
end
it "registers that an expectation has been encountered" do
state = double("run state").as_null_object
- state.stub(:state).and_return(double("spec state"))
- MSpec.should_receive(:expectation)
+ allow(state).to receive(:state).and_return(double("spec state"))
+ expect(MSpec).to receive(:expectation)
Mock.install_method(@mock, :method_call).and_return(1)
- @mock.method_call.should == 1
+ expect(@mock.method_call).to eq(1)
end
end
-describe Mock, ".install_method for stubs" do
+RSpec.describe Mock, ".install_method for stubs" do
before :each do
@mock = double('install_method')
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
end
after :each do
@@ -150,7 +150,7 @@ describe Mock, ".install_method for stubs" do
end
it "returns a MockProxy instance" do
- Mock.install_method(@mock, :method_call, :stub).should be_an_instance_of(MockProxy)
+ expect(Mock.install_method(@mock, :method_call, :stub)).to be_an_instance_of(MockProxy)
end
# This illustrates RSpec's behavior. This spec passes on RSpec and we mimic it
@@ -166,26 +166,26 @@ describe Mock, ".install_method for stubs" do
# end
it "inserts new stubs before old stubs" do
Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(true)
- @mock.method_call(:a).should == true
+ expect(@mock.method_call(:a)).to eq(true)
Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(false)
- @mock.method_call(:a).should == false
+ expect(@mock.method_call(:a)).to eq(false)
Mock.verify_count
end
it "does not add to the expectation tally" do
state = double("run state").as_null_object
- state.stub(:state).and_return(double("spec state"))
- MSpec.should_not_receive(:actions)
+ allow(state).to receive(:state).and_return(double("spec state"))
+ expect(MSpec).not_to receive(:actions)
Mock.install_method(@mock, :method_call, :stub).and_return(1)
- @mock.method_call.should == 1
+ expect(@mock.method_call).to eq(1)
end
end
-describe Mock, ".install_method" do
+RSpec.describe Mock, ".install_method" do
before :each do
@mock = double('install_method')
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
end
after :each do
@@ -193,24 +193,24 @@ describe Mock, ".install_method" do
end
it "does not alias a mocked or stubbed method when installing a new mock or stub" do
- @mock.should_not respond_to(:method_call)
+ expect(@mock).not_to respond_to(:method_call)
Mock.install_method @mock, :method_call
- @mock.should respond_to(:method_call)
- @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call))
+ expect(@mock).to respond_to(:method_call)
+ expect(@mock).not_to respond_to(Mock.replaced_name(Mock.replaced_key(@mock, :method_call)))
Mock.install_method @mock, :method_call, :stub
- @mock.should respond_to(:method_call)
- @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call))
+ expect(@mock).to respond_to(:method_call)
+ expect(@mock).not_to respond_to(Mock.replaced_name(Mock.replaced_key(@mock, :method_call)))
end
end
class MockAndRaiseError < Exception; end
-describe Mock, ".verify_call" do
+RSpec.describe Mock, ".verify_call" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
@mock = double('verify_call')
@proxy = Mock.install_method @mock, :method_call
@@ -228,23 +228,23 @@ describe Mock, ".verify_call" do
it "raises an SpecExpectationNotMetError when the mock method does not receive the expected arguments" do
@proxy.with(4, 2)
- lambda {
+ expect {
Mock.verify_call @mock, :method_call, 42
- }.should raise_error(SpecExpectationNotMetError)
+ }.to raise_error(SpecExpectationNotMetError)
end
it "raises an SpecExpectationNotMetError when the mock method is called with arguments but expects none" do
- lambda {
+ expect {
@proxy.with(:no_args)
Mock.verify_call @mock, :method_call, "hello"
- }.should raise_error(SpecExpectationNotMetError)
+ }.to raise_error(SpecExpectationNotMetError)
end
it "raises an SpecExpectationNotMetError when the mock method is called with no arguments but expects some" do
@proxy.with("hello", "beautiful", "world")
- lambda {
+ expect {
Mock.verify_call @mock, :method_call
- }.should raise_error(SpecExpectationNotMetError)
+ }.to raise_error(SpecExpectationNotMetError)
end
it "does not raise an exception when the mock method is called with arguments and is expecting :any_args" do
@@ -257,14 +257,14 @@ describe Mock, ".verify_call" do
Mock.verify_call @mock, :method_call do
ScratchPad.record true
end
- ScratchPad.recorded.should == true
+ expect(ScratchPad.recorded).to eq(true)
end
it "does not yield a passed block when it is not expected to" do
Mock.verify_call @mock, :method_call do
ScratchPad.record true
end
- ScratchPad.recorded.should == nil
+ expect(ScratchPad.recorded).to eq(nil)
end
it "can yield subsequently" do
@@ -274,28 +274,28 @@ describe Mock, ".verify_call" do
Mock.verify_call @mock, :method_call do |arg|
ScratchPad << arg
end
- ScratchPad.recorded.should == [1, 2, 3]
+ expect(ScratchPad.recorded).to eq([1, 2, 3])
end
it "can yield and return an expected value" do
@proxy.and_yield(1).and_return(3)
- Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }.should == 3
- ScratchPad.recorded.should == 1
+ expect(Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }).to eq(3)
+ expect(ScratchPad.recorded).to eq(1)
end
it "raises an exception when it is expected to yield but no block is given" do
@proxy.and_yield(1, 2, 3)
- lambda {
+ expect {
Mock.verify_call(@mock, :method_call)
- }.should raise_error(SpecExpectationNotMetError)
+ }.to raise_error(SpecExpectationNotMetError)
end
it "raises an exception when it is expected to yield more arguments than the block can take" do
@proxy.and_yield(1, 2, 3)
- lambda {
+ expect {
Mock.verify_call(@mock, :method_call) {|a, b|}
- }.should raise_error(SpecExpectationNotMetError)
+ }.to raise_error(SpecExpectationNotMetError)
end
it "does not raise an exception when it is expected to yield to a block that can take any number of arguments" do
@@ -307,16 +307,16 @@ describe Mock, ".verify_call" do
it "raises an exception when expected to" do
@proxy.and_raise(MockAndRaiseError)
- lambda {
+ expect {
Mock.verify_call @mock, :method_call
- }.should raise_error(MockAndRaiseError)
+ }.to raise_error(MockAndRaiseError)
end
end
-describe Mock, ".verify_call mixing mocks and stubs" do
+RSpec.describe Mock, ".verify_call mixing mocks and stubs" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
@mock = double('verify_call')
end
@@ -330,17 +330,17 @@ describe Mock, ".verify_call mixing mocks and stubs" do
Mock.install_method @mock, :method_call, :stub
Mock.install_method(@mock, :method_call, :mock).with("arg")
- -> {
+ expect {
@mock.method_call
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/)
- -> {
+ expect {
@mock.method_call("a", "b")
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/)
- -> {
+ expect {
@mock.method_call("foo")
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/)
@mock.method_call("arg")
end
@@ -349,26 +349,26 @@ describe Mock, ".verify_call mixing mocks and stubs" do
Mock.install_method(@mock, :method_call, :mock).with("arg")
Mock.install_method @mock, :method_call, :stub
- -> {
+ expect {
@mock.method_call
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/)
- -> {
+ expect {
@mock.method_call("a", "b")
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/)
- -> {
+ expect {
@mock.method_call("foo")
- }.should raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/)
+ }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/)
@mock.method_call("arg")
end
end
-describe Mock, ".verify_count" do
+RSpec.describe Mock, ".verify_count" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
@mock = double('verify_count')
@proxy = Mock.install_method @mock, :method_call
@@ -388,7 +388,7 @@ describe Mock, ".verify_count" do
it "raises an SpecExpectationNotMetError when the mock receives less than at least the expected number of calls" do
@proxy.at_least(2)
@mock.method_call
- lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError)
+ expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError)
end
it "does not raise an exception when the mock receives at most the expected number of calls" do
@@ -403,7 +403,7 @@ describe Mock, ".verify_count" do
@mock.method_call
@mock.method_call
@mock.method_call
- lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError)
+ expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError)
end
it "does not raise an exception when the mock receives exactly the expected number of calls" do
@@ -416,7 +416,7 @@ describe Mock, ".verify_count" do
it "raises an SpecExpectationNotMetError when the mock receives less than exactly the expected number of calls" do
@proxy.exactly(2)
@mock.method_call
- lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError)
+ expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError)
end
it "raises an SpecExpectationNotMetError when the mock receives more than exactly the expected number of calls" do
@@ -424,14 +424,14 @@ describe Mock, ".verify_count" do
@mock.method_call
@mock.method_call
@mock.method_call
- lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError)
+ expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError)
end
end
-describe Mock, ".verify_count mixing mocks and stubs" do
+RSpec.describe Mock, ".verify_count mixing mocks and stubs" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
@mock = double('verify_count')
end
@@ -449,9 +449,9 @@ describe Mock, ".verify_count mixing mocks and stubs" do
Mock.install_method @mock, :method_call, :stub
Mock.install_method @mock, :method_call, :mock
- -> {
+ expect {
Mock.verify_count
- }.should raise_error(SpecExpectationNotMetError, /received it 0 times/)
+ }.to raise_error(SpecExpectationNotMetError, /received it 0 times/)
@mock.method_call
Mock.verify_count
@@ -461,19 +461,19 @@ describe Mock, ".verify_count mixing mocks and stubs" do
Mock.install_method @mock, :method_call, :mock
Mock.install_method @mock, :method_call, :stub
- -> {
+ expect {
Mock.verify_count
- }.should raise_error(SpecExpectationNotMetError, /received it 0 times/)
+ }.to raise_error(SpecExpectationNotMetError, /received it 0 times/)
@mock.method_call
Mock.verify_count
end
end
-describe Mock, ".cleanup" do
+RSpec.describe Mock, ".cleanup" do
before :each do
- MSpec.stub(:actions)
- MSpec.stub(:current).and_return(double("spec state").as_null_object)
+ allow(MSpec).to receive(:actions)
+ allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object)
@mock = double('cleanup')
@proxy = Mock.install_method @mock, :method_call
@@ -484,47 +484,46 @@ describe Mock, ".cleanup" do
end
it "removes the mock method call if it did not override an existing method" do
- @mock.should respond_to(:method_call)
+ expect(@mock).to respond_to(:method_call)
Mock.cleanup
- @mock.should_not respond_to(:method_call)
+ expect(@mock).not_to respond_to(:method_call)
end
it "removes the replaced method if the mock method overrides an existing method" do
def @mock.already_here() :hey end
- @mock.should respond_to(:already_here)
- replaced_name = Mock.replaced_name(@mock, :already_here)
+ expect(@mock).to respond_to(:already_here)
+ replaced_name = Mock.replaced_name(Mock.replaced_key(@mock, :already_here))
Mock.install_method @mock, :already_here
- @mock.should respond_to(replaced_name)
+ expect(@mock).to respond_to(replaced_name)
Mock.cleanup
- @mock.should_not respond_to(replaced_name)
- @mock.should respond_to(:already_here)
- @mock.already_here.should == :hey
+ expect(@mock).not_to respond_to(replaced_name)
+ expect(@mock).to respond_to(:already_here)
+ expect(@mock.already_here).to eq(:hey)
end
it "removes all mock expectations" do
- Mock.mocks.should == { Mock.replaced_key(@mock, :method_call) => [@proxy] }
+ expect(Mock.mocks).to eq({ Mock.replaced_key(@mock, :method_call) => [@proxy] })
Mock.cleanup
- Mock.mocks.should == {}
+ expect(Mock.mocks).to eq({})
end
it "removes all stubs" do
Mock.cleanup # remove @proxy
@stub = Mock.install_method @mock, :method_call, :stub
- Mock.stubs.should == { Mock.replaced_key(@mock, :method_call) => [@stub] }
+ expect(Mock.stubs).to eq({ Mock.replaced_key(@mock, :method_call) => [@stub] })
Mock.cleanup
- Mock.stubs.should == {}
+ expect(Mock.stubs).to eq({})
end
it "removes the replaced name for mocks" do
replaced_key = Mock.replaced_key(@mock, :method_call)
- Mock.should_receive(:clear_replaced).with(replaced_key)
+ expect(Mock).to receive(:clear_replaced).with(replaced_key)
- replaced_name = Mock.replaced_name(@mock, :method_call)
- Mock.replaced?(replaced_name).should be_true
+ expect(Mock.replaced?(replaced_key)).to be_truthy
Mock.cleanup
- Mock.replaced?(replaced_name).should be_false
+ expect(Mock.replaced?(replaced_key)).to be_falsey
end
end
diff --git a/spec/mspec/spec/mocks/proxy_spec.rb b/spec/mspec/spec/mocks/proxy_spec.rb
index d9e754b972..b994634694 100644
--- a/spec/mspec/spec/mocks/proxy_spec.rb
+++ b/spec/mspec/spec/mocks/proxy_spec.rb
@@ -1,276 +1,276 @@
require 'spec_helper'
require 'mspec/mocks/proxy'
-describe MockObject, ".new" do
+RSpec.describe MockObject, ".new" do
it "creates a new mock object" do
m = MockObject.new('not a null object')
- lambda { m.not_a_method }.should raise_error(NoMethodError)
+ expect { m.not_a_method }.to raise_error(NoMethodError)
end
it "creates a new mock object that follows the NullObject pattern" do
m = MockObject.new('null object', :null_object => true)
- m.not_really_a_method.should equal(m)
+ expect(m.not_really_a_method).to equal(m)
end
end
-describe MockProxy, ".new" do
+RSpec.describe MockProxy, ".new" do
it "creates a mock proxy by default" do
- MockProxy.new.mock?.should be_true
+ expect(MockProxy.new.mock?).to be_truthy
end
it "creates a stub proxy by request" do
- MockProxy.new(:stub).stub?.should be_true
+ expect(MockProxy.new(:stub).stub?).to be_truthy
end
it "sets the call expectation to 1 call for a mock" do
- MockProxy.new.count.should == [:exactly, 1]
+ expect(MockProxy.new.count).to eq([:exactly, 1])
end
it "sets the call expectation to any number of times for a stub" do
- MockProxy.new(:stub).count.should == [:any_number_of_times, 0]
+ expect(MockProxy.new(:stub).count).to eq([:any_number_of_times, 0])
end
end
-describe MockProxy, "#count" do
+RSpec.describe MockProxy, "#count" do
before :each do
@proxy = MockProxy.new
end
it "returns the expected number of calls the mock should receive" do
- @proxy.count.should == [:exactly, 1]
- @proxy.at_least(3).count.should == [:at_least, 3]
+ expect(@proxy.count).to eq([:exactly, 1])
+ expect(@proxy.at_least(3).count).to eq([:at_least, 3])
end
end
-describe MockProxy, "#arguments" do
+RSpec.describe MockProxy, "#arguments" do
before :each do
@proxy = MockProxy.new
end
it "returns the expected arguments" do
- @proxy.arguments.should == :any_args
+ expect(@proxy.arguments).to eq(:any_args)
end
end
-describe MockProxy, "#with" do
+RSpec.describe MockProxy, "#with" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.with(:a).should be_equal(@proxy)
+ expect(@proxy.with(:a)).to be_equal(@proxy)
end
it "raises an ArgumentError if no arguments are given" do
- lambda { @proxy.with }.should raise_error(ArgumentError)
+ expect { @proxy.with }.to raise_error(ArgumentError)
end
it "accepts any number of arguments" do
- @proxy.with(1, 2, 3).should be_an_instance_of(MockProxy)
- @proxy.arguments.should == [1,2,3]
+ expect(@proxy.with(1, 2, 3)).to be_an_instance_of(MockProxy)
+ expect(@proxy.arguments).to eq([1,2,3])
end
end
-describe MockProxy, "#once" do
+RSpec.describe MockProxy, "#once" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.once.should be_equal(@proxy)
+ expect(@proxy.once).to be_equal(@proxy)
end
it "sets the expected calls to 1" do
@proxy.once
- @proxy.count.should == [:exactly, 1]
+ expect(@proxy.count).to eq([:exactly, 1])
end
it "accepts no arguments" do
- lambda { @proxy.once(:a) }.should raise_error
+ expect { @proxy.once(:a) }.to raise_error
end
end
-describe MockProxy, "#twice" do
+RSpec.describe MockProxy, "#twice" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.twice.should be_equal(@proxy)
+ expect(@proxy.twice).to be_equal(@proxy)
end
it "sets the expected calls to 2" do
@proxy.twice
- @proxy.count.should == [:exactly, 2]
+ expect(@proxy.count).to eq([:exactly, 2])
end
it "accepts no arguments" do
- lambda { @proxy.twice(:b) }.should raise_error
+ expect { @proxy.twice(:b) }.to raise_error
end
end
-describe MockProxy, "#exactly" do
+RSpec.describe MockProxy, "#exactly" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.exactly(2).should be_equal(@proxy)
+ expect(@proxy.exactly(2)).to be_equal(@proxy)
end
it "sets the expected calls to exactly n" do
@proxy.exactly(5)
- @proxy.count.should == [:exactly, 5]
+ expect(@proxy.count).to eq([:exactly, 5])
end
it "does not accept an argument that Integer() cannot convert" do
- lambda { @proxy.exactly('x') }.should raise_error
+ expect { @proxy.exactly('x') }.to raise_error
end
end
-describe MockProxy, "#at_least" do
+RSpec.describe MockProxy, "#at_least" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.at_least(3).should be_equal(@proxy)
+ expect(@proxy.at_least(3)).to be_equal(@proxy)
end
it "sets the expected calls to at least n" do
@proxy.at_least(3)
- @proxy.count.should == [:at_least, 3]
+ expect(@proxy.count).to eq([:at_least, 3])
end
it "accepts :once :twice" do
@proxy.at_least(:once)
- @proxy.count.should == [:at_least, 1]
+ expect(@proxy.count).to eq([:at_least, 1])
@proxy.at_least(:twice)
- @proxy.count.should == [:at_least, 2]
+ expect(@proxy.count).to eq([:at_least, 2])
end
it "does not accept an argument that Integer() cannot convert" do
- lambda { @proxy.at_least('x') }.should raise_error
+ expect { @proxy.at_least('x') }.to raise_error
end
end
-describe MockProxy, "#at_most" do
+RSpec.describe MockProxy, "#at_most" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.at_most(2).should be_equal(@proxy)
+ expect(@proxy.at_most(2)).to be_equal(@proxy)
end
it "sets the expected calls to at most n" do
@proxy.at_most(2)
- @proxy.count.should == [:at_most, 2]
+ expect(@proxy.count).to eq([:at_most, 2])
end
it "accepts :once, :twice" do
@proxy.at_most(:once)
- @proxy.count.should == [:at_most, 1]
+ expect(@proxy.count).to eq([:at_most, 1])
@proxy.at_most(:twice)
- @proxy.count.should == [:at_most, 2]
+ expect(@proxy.count).to eq([:at_most, 2])
end
it "does not accept an argument that Integer() cannot convert" do
- lambda { @proxy.at_most('x') }.should raise_error
+ expect { @proxy.at_most('x') }.to raise_error
end
end
-describe MockProxy, "#any_number_of_times" do
+RSpec.describe MockProxy, "#any_number_of_times" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.any_number_of_times.should be_equal(@proxy)
+ expect(@proxy.any_number_of_times).to be_equal(@proxy)
end
it "sets the expected calls to any number of times" do
@proxy.any_number_of_times
- @proxy.count.should == [:any_number_of_times, 0]
+ expect(@proxy.count).to eq([:any_number_of_times, 0])
end
it "does not accept an argument" do
- lambda { @proxy.any_number_of_times(2) }.should raise_error
+ expect { @proxy.any_number_of_times(2) }.to raise_error
end
end
-describe MockProxy, "#and_return" do
+RSpec.describe MockProxy, "#and_return" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.and_return(false).should equal(@proxy)
+ expect(@proxy.and_return(false)).to equal(@proxy)
end
it "sets the expected return value" do
@proxy.and_return(false)
- @proxy.returning.should == false
+ expect(@proxy.returning).to eq(false)
end
it "accepts any number of return values" do
@proxy.and_return(1, 2, 3)
- @proxy.returning.should == 1
- @proxy.returning.should == 2
- @proxy.returning.should == 3
+ expect(@proxy.returning).to eq(1)
+ expect(@proxy.returning).to eq(2)
+ expect(@proxy.returning).to eq(3)
end
it "implicitly sets the expected number of calls" do
@proxy.and_return(1, 2, 3)
- @proxy.count.should == [:exactly, 3]
+ expect(@proxy.count).to eq([:exactly, 3])
end
it "only sets the expected number of calls if it is higher than what is already set" do
@proxy.at_least(5).times.and_return(1, 2, 3)
- @proxy.count.should == [:at_least, 5]
+ expect(@proxy.count).to eq([:at_least, 5])
@proxy.at_least(2).times.and_return(1, 2, 3)
- @proxy.count.should == [:at_least, 3]
+ expect(@proxy.count).to eq([:at_least, 3])
end
end
-describe MockProxy, "#returning" do
+RSpec.describe MockProxy, "#returning" do
before :each do
@proxy = MockProxy.new
end
it "returns nil by default" do
- @proxy.returning.should be_nil
+ expect(@proxy.returning).to be_nil
end
it "returns the value set by #and_return" do
@proxy.and_return(2)
- @proxy.returning.should == 2
- @proxy.returning.should == 2
+ expect(@proxy.returning).to eq(2)
+ expect(@proxy.returning).to eq(2)
end
it "returns a sequence of values set by #and_return" do
@proxy.and_return(1,2,3,4)
- @proxy.returning.should == 1
- @proxy.returning.should == 2
- @proxy.returning.should == 3
- @proxy.returning.should == 4
- @proxy.returning.should == 4
- @proxy.returning.should == 4
+ expect(@proxy.returning).to eq(1)
+ expect(@proxy.returning).to eq(2)
+ expect(@proxy.returning).to eq(3)
+ expect(@proxy.returning).to eq(4)
+ expect(@proxy.returning).to eq(4)
+ expect(@proxy.returning).to eq(4)
end
end
-describe MockProxy, "#calls" do
+RSpec.describe MockProxy, "#calls" do
before :each do
@proxy = MockProxy.new
end
it "returns the number of times the proxy is called" do
- @proxy.calls.should == 0
+ expect(@proxy.calls).to eq(0)
end
end
-describe MockProxy, "#called" do
+RSpec.describe MockProxy, "#called" do
before :each do
@proxy = MockProxy.new
end
@@ -278,128 +278,128 @@ describe MockProxy, "#called" do
it "increments the number of times the proxy is called" do
@proxy.called
@proxy.called
- @proxy.calls.should == 2
+ expect(@proxy.calls).to eq(2)
end
end
-describe MockProxy, "#times" do
+RSpec.describe MockProxy, "#times" do
before :each do
@proxy = MockProxy.new
end
it "is a no-op" do
- @proxy.times.should == @proxy
+ expect(@proxy.times).to eq(@proxy)
end
end
-describe MockProxy, "#stub?" do
+RSpec.describe MockProxy, "#stub?" do
it "returns true if the proxy is created as a stub" do
- MockProxy.new(:stub).stub?.should be_true
+ expect(MockProxy.new(:stub).stub?).to be_truthy
end
it "returns false if the proxy is created as a mock" do
- MockProxy.new(:mock).stub?.should be_false
+ expect(MockProxy.new(:mock).stub?).to be_falsey
end
end
-describe MockProxy, "#mock?" do
+RSpec.describe MockProxy, "#mock?" do
it "returns true if the proxy is created as a mock" do
- MockProxy.new(:mock).mock?.should be_true
+ expect(MockProxy.new(:mock).mock?).to be_truthy
end
it "returns false if the proxy is created as a stub" do
- MockProxy.new(:stub).mock?.should be_false
+ expect(MockProxy.new(:stub).mock?).to be_falsey
end
end
-describe MockProxy, "#and_yield" do
+RSpec.describe MockProxy, "#and_yield" do
before :each do
@proxy = MockProxy.new
end
it "returns self" do
- @proxy.and_yield(false).should equal(@proxy)
+ expect(@proxy.and_yield(false)).to equal(@proxy)
end
it "sets the expected values to yield" do
- @proxy.and_yield(1).yielding.should == [[1]]
+ expect(@proxy.and_yield(1).yielding).to eq([[1]])
end
it "accepts multiple values to yield" do
- @proxy.and_yield(1, 2, 3).yielding.should == [[1, 2, 3]]
+ expect(@proxy.and_yield(1, 2, 3).yielding).to eq([[1, 2, 3]])
end
end
-describe MockProxy, "#raising" do
+RSpec.describe MockProxy, "#raising" do
before :each do
@proxy = MockProxy.new
end
it "returns nil by default" do
- @proxy.raising.should be_nil
+ expect(@proxy.raising).to be_nil
end
it "returns the exception object passed to #and_raise" do
exc = double("exception")
@proxy.and_raise(exc)
- @proxy.raising.should equal(exc)
+ expect(@proxy.raising).to equal(exc)
end
it "returns an instance of RuntimeError when a String is passed to #and_raise" do
@proxy.and_raise("an error")
exc = @proxy.raising
- exc.should be_an_instance_of(RuntimeError)
- exc.message.should == "an error"
+ expect(exc).to be_an_instance_of(RuntimeError)
+ expect(exc.message).to eq("an error")
end
end
-describe MockProxy, "#yielding" do
+RSpec.describe MockProxy, "#yielding" do
before :each do
@proxy = MockProxy.new
end
it "returns an empty array by default" do
- @proxy.yielding.should == []
+ expect(@proxy.yielding).to eq([])
end
it "returns an array of arrays of values the proxy should yield" do
@proxy.and_yield(3)
- @proxy.yielding.should == [[3]]
+ expect(@proxy.yielding).to eq([[3]])
end
it "returns an accumulation of arrays of values the proxy should yield" do
@proxy.and_yield(1).and_yield(2, 3)
- @proxy.yielding.should == [[1], [2, 3]]
+ expect(@proxy.yielding).to eq([[1], [2, 3]])
end
end
-describe MockProxy, "#yielding?" do
+RSpec.describe MockProxy, "#yielding?" do
before :each do
@proxy = MockProxy.new
end
it "returns false if the proxy is not yielding" do
- @proxy.yielding?.should be_false
+ expect(@proxy.yielding?).to be_falsey
end
it "returns true if the proxy is yielding" do
@proxy.and_yield(1)
- @proxy.yielding?.should be_true
+ expect(@proxy.yielding?).to be_truthy
end
end
-describe MockIntObject, "#to_int" do
+RSpec.describe MockIntObject, "#to_int" do
before :each do
@int = MockIntObject.new(10)
end
it "returns the number if to_int is called" do
- @int.to_int.should == 10
- @int.count.should == [:at_least, 1]
+ expect(@int.to_int).to eq(10)
+ expect(@int.count).to eq([:at_least, 1])
end
it "tries to convert the target to int if to_int is called" do
- MockIntObject.new(@int).to_int.should == 10
- @int.count.should == [:at_least, 1]
+ expect(MockIntObject.new(@int).to_int).to eq(10)
+ expect(@int.count).to eq([:at_least, 1])
end
end
diff --git a/spec/mspec/spec/runner/actions/filter_spec.rb b/spec/mspec/spec/runner/actions/filter_spec.rb
index d185781757..7582b31c1d 100644
--- a/spec/mspec/spec/runner/actions/filter_spec.rb
+++ b/spec/mspec/spec/runner/actions/filter_spec.rb
@@ -3,82 +3,82 @@ require 'mspec/runner/actions/filter'
require 'mspec/runner/mspec'
require 'mspec/runner/tag'
-describe ActionFilter do
+RSpec.describe ActionFilter do
it "creates a filter when not passed a description" do
- MatchFilter.should_not_receive(:new)
+ expect(MatchFilter).not_to receive(:new)
ActionFilter.new(nil, nil)
end
it "creates a filter from a single description" do
- MatchFilter.should_receive(:new).with(nil, "match me")
+ expect(MatchFilter).to receive(:new).with(nil, "match me")
ActionFilter.new(nil, "match me")
end
it "creates a filter from an array of descriptions" do
- MatchFilter.should_receive(:new).with(nil, "match me", "again")
+ expect(MatchFilter).to receive(:new).with(nil, "match me", "again")
ActionFilter.new(nil, ["match me", "again"])
end
end
-describe ActionFilter, "#===" do
+RSpec.describe ActionFilter, "#===" do
before :each do
- MSpec.stub(:read_tags).and_return(["match"])
+ allow(MSpec).to receive(:read_tags).and_return(["match"])
@action = ActionFilter.new(nil, ["catch", "if you"])
end
it "returns false if there are no filters" do
action = ActionFilter.new
- action.===("anything").should == false
+ expect(action.===("anything")).to eq(false)
end
it "returns true if the argument matches any of the descriptions" do
- @action.===("catch").should == true
- @action.===("if you can").should == true
+ expect(@action.===("catch")).to eq(true)
+ expect(@action.===("if you can")).to eq(true)
end
it "returns false if the argument does not match any of the descriptions" do
- @action.===("patch me").should == false
- @action.===("if I can").should == false
+ expect(@action.===("patch me")).to eq(false)
+ expect(@action.===("if I can")).to eq(false)
end
end
-describe ActionFilter, "#load" do
+RSpec.describe ActionFilter, "#load" do
before :each do
@tag = SpecTag.new "tag(comment):description"
end
it "creates a filter from a single tag" do
- MSpec.should_receive(:read_tags).with(["tag"]).and_return([@tag])
- MatchFilter.should_receive(:new).with(nil, "description")
+ expect(MSpec).to receive(:read_tags).with(["tag"]).and_return([@tag])
+ expect(MatchFilter).to receive(:new).with(nil, "description")
ActionFilter.new("tag", nil).load
end
it "creates a filter from an array of tags" do
- MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([@tag])
- MatchFilter.should_receive(:new).with(nil, "description")
+ expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([@tag])
+ expect(MatchFilter).to receive(:new).with(nil, "description")
ActionFilter.new(["tag", "key"], nil).load
end
it "creates a filter from both tags and descriptions" do
- MSpec.should_receive(:read_tags).and_return([@tag])
+ expect(MSpec).to receive(:read_tags).and_return([@tag])
filter = ActionFilter.new("tag", ["match me", "again"])
- MatchFilter.should_receive(:new).with(nil, "description")
+ expect(MatchFilter).to receive(:new).with(nil, "description")
filter.load
end
end
-describe ActionFilter, "#register" do
+RSpec.describe ActionFilter, "#register" do
it "registers itself with MSpec for the :load actions" do
filter = ActionFilter.new
- MSpec.should_receive(:register).with(:load, filter)
+ expect(MSpec).to receive(:register).with(:load, filter)
filter.register
end
end
-describe ActionFilter, "#unregister" do
+RSpec.describe ActionFilter, "#unregister" do
it "unregisters itself with MSpec for the :load actions" do
filter = ActionFilter.new
- MSpec.should_receive(:unregister).with(:load, filter)
+ expect(MSpec).to receive(:unregister).with(:load, filter)
filter.unregister
end
end
diff --git a/spec/mspec/spec/runner/actions/tag_spec.rb b/spec/mspec/spec/runner/actions/tag_spec.rb
index 92df362d02..738e9a18c9 100644
--- a/spec/mspec/spec/runner/actions/tag_spec.rb
+++ b/spec/mspec/spec/runner/actions/tag_spec.rb
@@ -4,211 +4,211 @@ require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/runner/tag'
-describe TagAction, ".new" do
+RSpec.describe TagAction, ".new" do
it "creates an MatchFilter with its tag and desc arguments" do
filter = double('action filter').as_null_object
- MatchFilter.should_receive(:new).with(nil, "some", "thing").and_return(filter)
+ expect(MatchFilter).to receive(:new).with(nil, "some", "thing").and_return(filter)
TagAction.new :add, :all, nil, nil, ["tag", "key"], ["some", "thing"]
end
end
-describe TagAction, "#===" do
+RSpec.describe TagAction, "#===" do
before :each do
- MSpec.stub(:read_tags).and_return(["match"])
+ allow(MSpec).to receive(:read_tags).and_return(["match"])
@action = TagAction.new :add, :fail, nil, nil, nil, ["catch", "if you"]
end
it "returns true if there are no filters" do
action = TagAction.new :add, :all, nil, nil
- action.===("anything").should == true
+ expect(action.===("anything")).to eq(true)
end
it "returns true if the argument matches any of the descriptions" do
- @action.===("catch").should == true
- @action.===("if you can").should == true
+ expect(@action.===("catch")).to eq(true)
+ expect(@action.===("if you can")).to eq(true)
end
it "returns false if the argument does not match any of the descriptions" do
- @action.===("patch me").should == false
- @action.===("if I can").should == false
+ expect(@action.===("patch me")).to eq(false)
+ expect(@action.===("if I can")).to eq(false)
end
end
-describe TagAction, "#exception?" do
+RSpec.describe TagAction, "#exception?" do
before :each do
@action = TagAction.new :add, :fail, nil, nil, nil, nil
end
it "returns false if no exception has been raised while evaluating an example" do
- @action.exception?.should be_false
+ expect(@action.exception?).to be_falsey
end
it "returns true if an exception was raised while evaluating an example" do
@action.exception ExceptionState.new nil, nil, Exception.new("failed")
- @action.exception?.should be_true
+ expect(@action.exception?).to be_truthy
end
end
-describe TagAction, "#outcome?" do
+RSpec.describe TagAction, "#outcome?" do
before :each do
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:read_tags).and_return([])
@exception = ExceptionState.new nil, nil, Exception.new("failed")
end
it "returns true if outcome is :fail and the spec fails" do
action = TagAction.new :add, :fail, nil, nil, nil, nil
action.exception @exception
- action.outcome?.should == true
+ expect(action.outcome?).to eq(true)
end
it "returns false if the outcome is :fail and the spec passes" do
action = TagAction.new :add, :fail, nil, nil, nil, nil
- action.outcome?.should == false
+ expect(action.outcome?).to eq(false)
end
it "returns true if the outcome is :pass and the spec passes" do
action = TagAction.new :del, :pass, nil, nil, nil, nil
- action.outcome?.should == true
+ expect(action.outcome?).to eq(true)
end
it "returns false if the outcome is :pass and the spec fails" do
action = TagAction.new :del, :pass, nil, nil, nil, nil
action.exception @exception
- action.outcome?.should == false
+ expect(action.outcome?).to eq(false)
end
it "returns true if the outcome is :all" do
action = TagAction.new :add, :all, nil, nil, nil, nil
action.exception @exception
- action.outcome?.should == true
+ expect(action.outcome?).to eq(true)
end
end
-describe TagAction, "#before" do
+RSpec.describe TagAction, "#before" do
it "resets the #exception? flag to false" do
action = TagAction.new :add, :fail, nil, nil, nil, nil
- action.exception?.should be_false
+ expect(action.exception?).to be_falsey
action.exception ExceptionState.new(nil, nil, Exception.new("Fail!"))
- action.exception?.should be_true
+ expect(action.exception?).to be_truthy
action.before(ExampleState.new(ContextState.new("describe"), "it"))
- action.exception?.should be_false
+ expect(action.exception?).to be_falsey
end
end
-describe TagAction, "#exception" do
+RSpec.describe TagAction, "#exception" do
it "sets the #exception? flag" do
action = TagAction.new :add, :fail, nil, nil, nil, nil
- action.exception?.should be_false
+ expect(action.exception?).to be_falsey
action.exception ExceptionState.new(nil, nil, Exception.new("Fail!"))
- action.exception?.should be_true
+ expect(action.exception?).to be_truthy
end
end
-describe TagAction, "#after when action is :add" do
+RSpec.describe TagAction, "#after when action is :add" do
before :each do
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:read_tags).and_return([])
context = ContextState.new "Catch#me"
@state = ExampleState.new context, "if you can"
@tag = SpecTag.new "tag(comment):Catch#me if you can"
- SpecTag.stub(:new).and_return(@tag)
+ allow(SpecTag).to receive(:new).and_return(@tag)
@exception = ExceptionState.new nil, nil, Exception.new("failed")
end
it "does not write a tag if the description does not match" do
- MSpec.should_not_receive(:write_tag)
+ expect(MSpec).not_to receive(:write_tag)
action = TagAction.new :add, :all, "tag", "comment", nil, "match"
action.after @state
end
it "does not write a tag if outcome is :fail and the spec passed" do
- MSpec.should_not_receive(:write_tag)
+ expect(MSpec).not_to receive(:write_tag)
action = TagAction.new :add, :fail, "tag", "comment", nil, "can"
action.after @state
end
it "writes a tag if the outcome is :fail and the spec failed" do
- MSpec.should_receive(:write_tag).with(@tag)
+ expect(MSpec).to receive(:write_tag).with(@tag)
action = TagAction.new :add, :fail, "tag", "comment", nil, "can"
action.exception @exception
action.after @state
end
it "does not write a tag if outcome is :pass and the spec failed" do
- MSpec.should_not_receive(:write_tag)
+ expect(MSpec).not_to receive(:write_tag)
action = TagAction.new :add, :pass, "tag", "comment", nil, "can"
action.exception @exception
action.after @state
end
it "writes a tag if the outcome is :pass and the spec passed" do
- MSpec.should_receive(:write_tag).with(@tag)
+ expect(MSpec).to receive(:write_tag).with(@tag)
action = TagAction.new :add, :pass, "tag", "comment", nil, "can"
action.after @state
end
it "writes a tag if the outcome is :all" do
- MSpec.should_receive(:write_tag).with(@tag)
+ expect(MSpec).to receive(:write_tag).with(@tag)
action = TagAction.new :add, :all, "tag", "comment", nil, "can"
action.after @state
end
end
-describe TagAction, "#after when action is :del" do
+RSpec.describe TagAction, "#after when action is :del" do
before :each do
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:read_tags).and_return([])
context = ContextState.new "Catch#me"
@state = ExampleState.new context, "if you can"
@tag = SpecTag.new "tag(comment):Catch#me if you can"
- SpecTag.stub(:new).and_return(@tag)
+ allow(SpecTag).to receive(:new).and_return(@tag)
@exception = ExceptionState.new nil, nil, Exception.new("failed")
end
it "does not delete a tag if the description does not match" do
- MSpec.should_not_receive(:delete_tag)
+ expect(MSpec).not_to receive(:delete_tag)
action = TagAction.new :del, :all, "tag", "comment", nil, "match"
action.after @state
end
it "does not delete a tag if outcome is :fail and the spec passed" do
- MSpec.should_not_receive(:delete_tag)
+ expect(MSpec).not_to receive(:delete_tag)
action = TagAction.new :del, :fail, "tag", "comment", nil, "can"
action.after @state
end
it "deletes a tag if the outcome is :fail and the spec failed" do
- MSpec.should_receive(:delete_tag).with(@tag)
+ expect(MSpec).to receive(:delete_tag).with(@tag)
action = TagAction.new :del, :fail, "tag", "comment", nil, "can"
action.exception @exception
action.after @state
end
it "does not delete a tag if outcome is :pass and the spec failed" do
- MSpec.should_not_receive(:delete_tag)
+ expect(MSpec).not_to receive(:delete_tag)
action = TagAction.new :del, :pass, "tag", "comment", nil, "can"
action.exception @exception
action.after @state
end
it "deletes a tag if the outcome is :pass and the spec passed" do
- MSpec.should_receive(:delete_tag).with(@tag)
+ expect(MSpec).to receive(:delete_tag).with(@tag)
action = TagAction.new :del, :pass, "tag", "comment", nil, "can"
action.after @state
end
it "deletes a tag if the outcome is :all" do
- MSpec.should_receive(:delete_tag).with(@tag)
+ expect(MSpec).to receive(:delete_tag).with(@tag)
action = TagAction.new :del, :all, "tag", "comment", nil, "can"
action.after @state
end
end
-describe TagAction, "#finish" do
+RSpec.describe TagAction, "#finish" do
before :each do
$stdout = @out = IOStub.new
context = ContextState.new "Catch#me"
@state = ExampleState.new context, "if you can"
- MSpec.stub(:write_tag).and_return(true)
- MSpec.stub(:delete_tag).and_return(true)
+ allow(MSpec).to receive(:write_tag).and_return(true)
+ allow(MSpec).to receive(:delete_tag).and_return(true)
end
after :each do
@@ -217,99 +217,97 @@ describe TagAction, "#finish" do
it "reports no specs tagged if none where tagged" do
action = TagAction.new :add, :fail, "tag", "comment", nil, "can"
- action.stub(:outcome?).and_return(false)
+ allow(action).to receive(:outcome?).and_return(false)
action.after @state
action.finish
- @out.should == "\nTagAction: no specs were tagged with 'tag'\n"
+ expect(@out).to eq("\nTagAction: no specs were tagged with 'tag'\n")
end
it "reports no specs tagged if none where tagged" do
action = TagAction.new :del, :fail, "tag", "comment", nil, "can"
- action.stub(:outcome?).and_return(false)
+ allow(action).to receive(:outcome?).and_return(false)
action.after @state
action.finish
- @out.should == "\nTagAction: no tags 'tag' were deleted\n"
+ expect(@out).to eq("\nTagAction: no tags 'tag' were deleted\n")
end
it "reports the spec descriptions that were tagged" do
action = TagAction.new :add, :fail, "tag", "comment", nil, "can"
- action.stub(:outcome?).and_return(true)
+ allow(action).to receive(:outcome?).and_return(true)
action.after @state
action.finish
- @out.should ==
-%[
+ expect(@out).to eq(%[
TagAction: specs tagged with 'tag':
Catch#me if you can
-]
+])
end
it "reports the spec descriptions for the tags that were deleted" do
action = TagAction.new :del, :fail, "tag", "comment", nil, "can"
- action.stub(:outcome?).and_return(true)
+ allow(action).to receive(:outcome?).and_return(true)
action.after @state
action.finish
- @out.should ==
-%[
+ expect(@out).to eq(%[
TagAction: tag 'tag' deleted for specs:
Catch#me if you can
-]
+])
end
end
-describe TagAction, "#register" do
+RSpec.describe TagAction, "#register" do
before :each do
- MSpec.stub(:register)
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:register)
+ allow(MSpec).to receive(:read_tags).and_return([])
@action = TagAction.new :add, :all, nil, nil, nil, nil
end
it "registers itself with MSpec for the :before event" do
- MSpec.should_receive(:register).with(:before, @action)
+ expect(MSpec).to receive(:register).with(:before, @action)
@action.register
end
it "registers itself with MSpec for the :after event" do
- MSpec.should_receive(:register).with(:after, @action)
+ expect(MSpec).to receive(:register).with(:after, @action)
@action.register
end
it "registers itself with MSpec for the :exception event" do
- MSpec.should_receive(:register).with(:exception, @action)
+ expect(MSpec).to receive(:register).with(:exception, @action)
@action.register
end
it "registers itself with MSpec for the :finish event" do
- MSpec.should_receive(:register).with(:finish, @action)
+ expect(MSpec).to receive(:register).with(:finish, @action)
@action.register
end
end
-describe TagAction, "#unregister" do
+RSpec.describe TagAction, "#unregister" do
before :each do
- MSpec.stub(:unregister)
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:unregister)
+ allow(MSpec).to receive(:read_tags).and_return([])
@action = TagAction.new :add, :all, nil, nil, nil, nil
end
it "unregisters itself with MSpec for the :before event" do
- MSpec.should_receive(:unregister).with(:before, @action)
+ expect(MSpec).to receive(:unregister).with(:before, @action)
@action.unregister
end
it "unregisters itself with MSpec for the :after event" do
- MSpec.should_receive(:unregister).with(:after, @action)
+ expect(MSpec).to receive(:unregister).with(:after, @action)
@action.unregister
end
it "unregisters itself with MSpec for the :exception event" do
- MSpec.should_receive(:unregister).with(:exception, @action)
+ expect(MSpec).to receive(:unregister).with(:exception, @action)
@action.unregister
end
it "unregisters itself with MSpec for the :finish event" do
- MSpec.should_receive(:unregister).with(:finish, @action)
+ expect(MSpec).to receive(:unregister).with(:finish, @action)
@action.unregister
end
end
diff --git a/spec/mspec/spec/runner/actions/taglist_spec.rb b/spec/mspec/spec/runner/actions/taglist_spec.rb
index 418c761c2d..b6a5400f7d 100644
--- a/spec/mspec/spec/runner/actions/taglist_spec.rb
+++ b/spec/mspec/spec/runner/actions/taglist_spec.rb
@@ -4,34 +4,34 @@ require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/runner/tag'
-describe TagListAction, "#include?" do
+RSpec.describe TagListAction, "#include?" do
it "returns true" do
- TagListAction.new.include?(:anything).should be_true
+ expect(TagListAction.new.include?(:anything)).to be_truthy
end
end
-describe TagListAction, "#===" do
+RSpec.describe TagListAction, "#===" do
before :each do
tag = SpecTag.new "fails:description"
- MSpec.stub(:read_tags).and_return([tag])
+ allow(MSpec).to receive(:read_tags).and_return([tag])
@filter = double("MatchFilter").as_null_object
- MatchFilter.stub(:new).and_return(@filter)
+ allow(MatchFilter).to receive(:new).and_return(@filter)
@action = TagListAction.new
@action.load
end
it "returns true if filter === string returns true" do
- @filter.should_receive(:===).with("str").and_return(true)
- @action.===("str").should be_true
+ expect(@filter).to receive(:===).with("str").and_return(true)
+ expect(@action.===("str")).to be_truthy
end
it "returns false if filter === string returns false" do
- @filter.should_receive(:===).with("str").and_return(false)
- @action.===("str").should be_false
+ expect(@filter).to receive(:===).with("str").and_return(false)
+ expect(@action.===("str")).to be_falsey
end
end
-describe TagListAction, "#start" do
+RSpec.describe TagListAction, "#start" do
before :each do
@stdout = $stdout
$stdout = IOStub.new
@@ -44,48 +44,48 @@ describe TagListAction, "#start" do
it "prints a banner for specific tags" do
action = TagListAction.new ["fails", "unstable"]
action.start
- $stdout.should == "\nListing specs tagged with 'fails', 'unstable'\n\n"
+ expect($stdout).to eq("\nListing specs tagged with 'fails', 'unstable'\n\n")
end
it "prints a banner for all tags" do
action = TagListAction.new
action.start
- $stdout.should == "\nListing all tagged specs\n\n"
+ expect($stdout).to eq("\nListing all tagged specs\n\n")
end
end
-describe TagListAction, "#load" do
+RSpec.describe TagListAction, "#load" do
before :each do
@t1 = SpecTag.new "fails:I fail"
@t2 = SpecTag.new "unstable:I'm unstable"
end
it "creates a MatchFilter for matching tags" do
- MSpec.should_receive(:read_tags).with(["fails"]).and_return([@t1])
- MatchFilter.should_receive(:new).with(nil, "I fail")
+ expect(MSpec).to receive(:read_tags).with(["fails"]).and_return([@t1])
+ expect(MatchFilter).to receive(:new).with(nil, "I fail")
TagListAction.new(["fails"]).load
end
it "creates a MatchFilter for all tags" do
- MSpec.should_receive(:read_tags).and_return([@t1, @t2])
- MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable")
+ expect(MSpec).to receive(:read_tags).and_return([@t1, @t2])
+ expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable")
TagListAction.new.load
end
it "does not create a MatchFilter if there are no matching tags" do
- MSpec.stub(:read_tags).and_return([])
- MatchFilter.should_not_receive(:new)
+ allow(MSpec).to receive(:read_tags).and_return([])
+ expect(MatchFilter).not_to receive(:new)
TagListAction.new(["fails"]).load
end
end
-describe TagListAction, "#after" do
+RSpec.describe TagListAction, "#after" do
before :each do
@stdout = $stdout
$stdout = IOStub.new
@state = double("ExampleState")
- @state.stub(:description).and_return("str")
+ allow(@state).to receive(:description).and_return("str")
@action = TagListAction.new
end
@@ -95,58 +95,58 @@ describe TagListAction, "#after" do
end
it "prints nothing if the filter does not match" do
- @action.should_receive(:===).with("str").and_return(false)
+ expect(@action).to receive(:===).with("str").and_return(false)
@action.after(@state)
- $stdout.should == ""
+ expect($stdout).to eq("")
end
it "prints the example description if the filter matches" do
- @action.should_receive(:===).with("str").and_return(true)
+ expect(@action).to receive(:===).with("str").and_return(true)
@action.after(@state)
- $stdout.should == "str\n"
+ expect($stdout).to eq("str\n")
end
end
-describe TagListAction, "#register" do
+RSpec.describe TagListAction, "#register" do
before :each do
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@action = TagListAction.new
end
it "registers itself with MSpec for the :start event" do
- MSpec.should_receive(:register).with(:start, @action)
+ expect(MSpec).to receive(:register).with(:start, @action)
@action.register
end
it "registers itself with MSpec for the :load event" do
- MSpec.should_receive(:register).with(:load, @action)
+ expect(MSpec).to receive(:register).with(:load, @action)
@action.register
end
it "registers itself with MSpec for the :after event" do
- MSpec.should_receive(:register).with(:after, @action)
+ expect(MSpec).to receive(:register).with(:after, @action)
@action.register
end
end
-describe TagListAction, "#unregister" do
+RSpec.describe TagListAction, "#unregister" do
before :each do
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:unregister)
@action = TagListAction.new
end
it "unregisters itself with MSpec for the :start event" do
- MSpec.should_receive(:unregister).with(:start, @action)
+ expect(MSpec).to receive(:unregister).with(:start, @action)
@action.unregister
end
it "unregisters itself with MSpec for the :load event" do
- MSpec.should_receive(:unregister).with(:load, @action)
+ expect(MSpec).to receive(:unregister).with(:load, @action)
@action.unregister
end
it "unregisters itself with MSpec for the :after event" do
- MSpec.should_receive(:unregister).with(:after, @action)
+ expect(MSpec).to receive(:unregister).with(:after, @action)
@action.unregister
end
end
diff --git a/spec/mspec/spec/runner/actions/tagpurge_spec.rb b/spec/mspec/spec/runner/actions/tagpurge_spec.rb
index 27ad2a1470..37df0afd5a 100644
--- a/spec/mspec/spec/runner/actions/tagpurge_spec.rb
+++ b/spec/mspec/spec/runner/actions/tagpurge_spec.rb
@@ -4,7 +4,7 @@ require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/runner/tag'
-describe TagPurgeAction, "#start" do
+RSpec.describe TagPurgeAction, "#start" do
before :each do
@stdout = $stdout
$stdout = IOStub.new
@@ -17,45 +17,45 @@ describe TagPurgeAction, "#start" do
it "prints a banner" do
action = TagPurgeAction.new
action.start
- $stdout.should == "\nRemoving tags not matching any specs\n\n"
+ expect($stdout).to eq("\nRemoving tags not matching any specs\n\n")
end
end
-describe TagPurgeAction, "#load" do
+RSpec.describe TagPurgeAction, "#load" do
before :each do
@t1 = SpecTag.new "fails:I fail"
@t2 = SpecTag.new "unstable:I'm unstable"
end
it "creates a MatchFilter for all tags" do
- MSpec.should_receive(:read_tags).and_return([@t1, @t2])
- MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable")
+ expect(MSpec).to receive(:read_tags).and_return([@t1, @t2])
+ expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable")
TagPurgeAction.new.load
end
end
-describe TagPurgeAction, "#after" do
+RSpec.describe TagPurgeAction, "#after" do
before :each do
@state = double("ExampleState")
- @state.stub(:description).and_return("str")
+ allow(@state).to receive(:description).and_return("str")
@action = TagPurgeAction.new
end
it "does not save the description if the filter does not match" do
- @action.should_receive(:===).with("str").and_return(false)
+ expect(@action).to receive(:===).with("str").and_return(false)
@action.after @state
- @action.matching.should == []
+ expect(@action.matching).to eq([])
end
it "saves the description if the filter matches" do
- @action.should_receive(:===).with("str").and_return(true)
+ expect(@action).to receive(:===).with("str").and_return(true)
@action.after @state
- @action.matching.should == ["str"]
+ expect(@action.matching).to eq(["str"])
end
end
-describe TagPurgeAction, "#unload" do
+RSpec.describe TagPurgeAction, "#unload" do
before :each do
@stdout = $stdout
$stdout = IOStub.new
@@ -64,11 +64,11 @@ describe TagPurgeAction, "#unload" do
@t2 = SpecTag.new "unstable:I'm unstable"
@t3 = SpecTag.new "fails:I'm unstable"
- MSpec.stub(:read_tags).and_return([@t1, @t2, @t3])
- MSpec.stub(:write_tags)
+ allow(MSpec).to receive(:read_tags).and_return([@t1, @t2, @t3])
+ allow(MSpec).to receive(:write_tags)
@state = double("ExampleState")
- @state.stub(:description).and_return("I'm unstable")
+ allow(@state).to receive(:description).and_return("I'm unstable")
@action = TagPurgeAction.new
@action.load
@@ -80,37 +80,37 @@ describe TagPurgeAction, "#unload" do
end
it "does not rewrite any tags if there were no tags for the specs" do
- MSpec.should_receive(:read_tags).and_return([])
- MSpec.should_receive(:delete_tags)
- MSpec.should_not_receive(:write_tags)
+ expect(MSpec).to receive(:read_tags).and_return([])
+ expect(MSpec).to receive(:delete_tags)
+ expect(MSpec).not_to receive(:write_tags)
@action.load
@action.after @state
@action.unload
- $stdout.should == ""
+ expect($stdout).to eq("")
end
it "rewrites tags that were matched" do
- MSpec.should_receive(:write_tags).with([@t2, @t3])
+ expect(MSpec).to receive(:write_tags).with([@t2, @t3])
@action.unload
end
it "prints tags that were not matched" do
@action.unload
- $stdout.should == "I fail\n"
+ expect($stdout).to eq("I fail\n")
end
end
-describe TagPurgeAction, "#unload" do
+RSpec.describe TagPurgeAction, "#unload" do
before :each do
@stdout = $stdout
$stdout = IOStub.new
- MSpec.stub(:read_tags).and_return([])
+ allow(MSpec).to receive(:read_tags).and_return([])
@state = double("ExampleState")
- @state.stub(:description).and_return("I'm unstable")
+ allow(@state).to receive(:description).and_return("I'm unstable")
@action = TagPurgeAction.new
@action.load
@@ -122,33 +122,33 @@ describe TagPurgeAction, "#unload" do
end
it "deletes the tag file if no tags were found" do
- MSpec.should_not_receive(:write_tags)
- MSpec.should_receive(:delete_tags)
+ expect(MSpec).not_to receive(:write_tags)
+ expect(MSpec).to receive(:delete_tags)
@action.unload
- $stdout.should == ""
+ expect($stdout).to eq("")
end
end
-describe TagPurgeAction, "#register" do
+RSpec.describe TagPurgeAction, "#register" do
before :each do
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@action = TagPurgeAction.new
end
it "registers itself with MSpec for the :unload event" do
- MSpec.should_receive(:register).with(:unload, @action)
+ expect(MSpec).to receive(:register).with(:unload, @action)
@action.register
end
end
-describe TagPurgeAction, "#unregister" do
+RSpec.describe TagPurgeAction, "#unregister" do
before :each do
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:unregister)
@action = TagPurgeAction.new
end
it "unregisters itself with MSpec for the :unload event" do
- MSpec.should_receive(:unregister).with(:unload, @action)
+ expect(MSpec).to receive(:unregister).with(:unload, @action)
@action.unregister
end
end
diff --git a/spec/mspec/spec/runner/actions/tally_spec.rb b/spec/mspec/spec/runner/actions/tally_spec.rb
index be4635ffeb..d80ab1164a 100644
--- a/spec/mspec/spec/runner/actions/tally_spec.rb
+++ b/spec/mspec/spec/runner/actions/tally_spec.rb
@@ -4,169 +4,169 @@ require 'mspec/runner/actions/tally'
require 'mspec/runner/mspec'
require 'mspec/runner/example'
-describe Tally, "#files!" do
+RSpec.describe Tally, "#files!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #files" do
@tally.files! 3
- @tally.files.should == 3
+ expect(@tally.files).to eq(3)
@tally.files!
- @tally.files.should == 4
+ expect(@tally.files).to eq(4)
end
end
-describe Tally, "#examples!" do
+RSpec.describe Tally, "#examples!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #examples" do
@tally.examples! 2
- @tally.examples.should == 2
+ expect(@tally.examples).to eq(2)
@tally.examples! 2
- @tally.examples.should == 4
+ expect(@tally.examples).to eq(4)
end
end
-describe Tally, "#expectations!" do
+RSpec.describe Tally, "#expectations!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #expectations" do
@tally.expectations!
- @tally.expectations.should == 1
+ expect(@tally.expectations).to eq(1)
@tally.expectations! 3
- @tally.expectations.should == 4
+ expect(@tally.expectations).to eq(4)
end
end
-describe Tally, "#failures!" do
+RSpec.describe Tally, "#failures!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #failures" do
@tally.failures! 1
- @tally.failures.should == 1
+ expect(@tally.failures).to eq(1)
@tally.failures!
- @tally.failures.should == 2
+ expect(@tally.failures).to eq(2)
end
end
-describe Tally, "#errors!" do
+RSpec.describe Tally, "#errors!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #errors" do
@tally.errors!
- @tally.errors.should == 1
+ expect(@tally.errors).to eq(1)
@tally.errors! 2
- @tally.errors.should == 3
+ expect(@tally.errors).to eq(3)
end
end
-describe Tally, "#guards!" do
+RSpec.describe Tally, "#guards!" do
before :each do
@tally = Tally.new
end
it "increments the count returned by #guards" do
@tally.guards!
- @tally.guards.should == 1
+ expect(@tally.guards).to eq(1)
@tally.guards! 2
- @tally.guards.should == 3
+ expect(@tally.guards).to eq(3)
end
end
-describe Tally, "#file" do
+RSpec.describe Tally, "#file" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #files" do
- @tally.file.should == "0 files"
+ expect(@tally.file).to eq("0 files")
@tally.files!
- @tally.file.should == "1 file"
+ expect(@tally.file).to eq("1 file")
@tally.files!
- @tally.file.should == "2 files"
+ expect(@tally.file).to eq("2 files")
end
end
-describe Tally, "#example" do
+RSpec.describe Tally, "#example" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #examples" do
- @tally.example.should == "0 examples"
+ expect(@tally.example).to eq("0 examples")
@tally.examples!
- @tally.example.should == "1 example"
+ expect(@tally.example).to eq("1 example")
@tally.examples!
- @tally.example.should == "2 examples"
+ expect(@tally.example).to eq("2 examples")
end
end
-describe Tally, "#expectation" do
+RSpec.describe Tally, "#expectation" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #expectations" do
- @tally.expectation.should == "0 expectations"
+ expect(@tally.expectation).to eq("0 expectations")
@tally.expectations!
- @tally.expectation.should == "1 expectation"
+ expect(@tally.expectation).to eq("1 expectation")
@tally.expectations!
- @tally.expectation.should == "2 expectations"
+ expect(@tally.expectation).to eq("2 expectations")
end
end
-describe Tally, "#failure" do
+RSpec.describe Tally, "#failure" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #failures" do
- @tally.failure.should == "0 failures"
+ expect(@tally.failure).to eq("0 failures")
@tally.failures!
- @tally.failure.should == "1 failure"
+ expect(@tally.failure).to eq("1 failure")
@tally.failures!
- @tally.failure.should == "2 failures"
+ expect(@tally.failure).to eq("2 failures")
end
end
-describe Tally, "#error" do
+RSpec.describe Tally, "#error" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #errors" do
- @tally.error.should == "0 errors"
+ expect(@tally.error).to eq("0 errors")
@tally.errors!
- @tally.error.should == "1 error"
+ expect(@tally.error).to eq("1 error")
@tally.errors!
- @tally.error.should == "2 errors"
+ expect(@tally.error).to eq("2 errors")
end
end
-describe Tally, "#guard" do
+RSpec.describe Tally, "#guard" do
before :each do
@tally = Tally.new
end
it "returns a formatted string of the number of #guards" do
- @tally.guard.should == "0 guards"
+ expect(@tally.guard).to eq("0 guards")
@tally.guards!
- @tally.guard.should == "1 guard"
+ expect(@tally.guard).to eq("1 guard")
@tally.guards!
- @tally.guard.should == "2 guards"
+ expect(@tally.guard).to eq("2 guards")
end
end
-describe Tally, "#format" do
+RSpec.describe Tally, "#format" do
before :each do
@tally = Tally.new
end
@@ -181,7 +181,7 @@ describe Tally, "#format" do
@tally.expectations! 4
@tally.errors!
@tally.tagged!
- @tally.format.should == "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged"
+ expect(@tally.format).to eq("1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged")
end
it "includes guards if MSpec is in verify mode" do
@@ -192,8 +192,9 @@ describe Tally, "#format" do
@tally.errors!
@tally.tagged!
@tally.guards!
- @tally.format.should ==
+ expect(@tally.format).to eq(
"1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 1 guard"
+ )
end
it "includes guards if MSpec is in report mode" do
@@ -204,8 +205,9 @@ describe Tally, "#format" do
@tally.errors!
@tally.tagged!
@tally.guards! 2
- @tally.format.should ==
+ expect(@tally.format).to eq(
"1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 2 guards"
+ )
end
it "includes guards if MSpec is in report_on mode" do
@@ -215,23 +217,24 @@ describe Tally, "#format" do
@tally.expectations! 4
@tally.errors!
@tally.guards! 2
- @tally.format.should ==
+ expect(@tally.format).to eq(
"1 file, 2 examples, 4 expectations, 0 failures, 1 error, 0 tagged, 2 guards"
+ )
end
end
-describe TallyAction, "#counter" do
+RSpec.describe TallyAction, "#counter" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
end
it "returns the Tally object" do
- @tally.counter.should be_kind_of(Tally)
+ expect(@tally.counter).to be_kind_of(Tally)
end
end
-describe TallyAction, "#load" do
+RSpec.describe TallyAction, "#load" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -239,11 +242,11 @@ describe TallyAction, "#load" do
it "increments the count returned by Tally#files" do
@tally.load
- @tally.counter.files.should == 1
+ expect(@tally.counter.files).to eq(1)
end
end
-describe TallyAction, "#expectation" do
+RSpec.describe TallyAction, "#expectation" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -251,11 +254,11 @@ describe TallyAction, "#expectation" do
it "increments the count returned by Tally#expectations" do
@tally.expectation @state
- @tally.counter.expectations.should == 1
+ expect(@tally.counter.expectations).to eq(1)
end
end
-describe TallyAction, "#example" do
+RSpec.describe TallyAction, "#example" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -263,14 +266,14 @@ describe TallyAction, "#example" do
it "increments counts returned by Tally#examples" do
@tally.example @state, nil
- @tally.counter.examples.should == 1
- @tally.counter.expectations.should == 0
- @tally.counter.failures.should == 0
- @tally.counter.errors.should == 0
+ expect(@tally.counter.examples).to eq(1)
+ expect(@tally.counter.expectations).to eq(0)
+ expect(@tally.counter.failures).to eq(0)
+ expect(@tally.counter.errors).to eq(0)
end
end
-describe TallyAction, "#exception" do
+RSpec.describe TallyAction, "#exception" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -279,14 +282,14 @@ describe TallyAction, "#exception" do
it "increments counts returned by Tally#failures" do
exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!")
@tally.exception exc
- @tally.counter.examples.should == 0
- @tally.counter.expectations.should == 0
- @tally.counter.failures.should == 1
- @tally.counter.errors.should == 0
+ expect(@tally.counter.examples).to eq(0)
+ expect(@tally.counter.expectations).to eq(0)
+ expect(@tally.counter.failures).to eq(1)
+ expect(@tally.counter.errors).to eq(0)
end
end
-describe TallyAction, "#exception" do
+RSpec.describe TallyAction, "#exception" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -295,14 +298,14 @@ describe TallyAction, "#exception" do
it "increments counts returned by Tally#errors" do
exc = ExceptionState.new nil, nil, Exception.new("Error!")
@tally.exception exc
- @tally.counter.examples.should == 0
- @tally.counter.expectations.should == 0
- @tally.counter.failures.should == 0
- @tally.counter.errors.should == 1
+ expect(@tally.counter.examples).to eq(0)
+ expect(@tally.counter.expectations).to eq(0)
+ expect(@tally.counter.failures).to eq(0)
+ expect(@tally.counter.errors).to eq(1)
end
end
-describe TallyAction, "#format" do
+RSpec.describe TallyAction, "#format" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
@@ -315,38 +318,38 @@ describe TallyAction, "#format" do
@tally.expectation @state
exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!")
@tally.exception exc
- @tally.format.should == "1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged"
+ expect(@tally.format).to eq("1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged")
end
end
-describe TallyAction, "#register" do
+RSpec.describe TallyAction, "#register" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
end
it "registers itself with MSpec for appropriate actions" do
- MSpec.should_receive(:register).with(:load, @tally)
- MSpec.should_receive(:register).with(:exception, @tally)
- MSpec.should_receive(:register).with(:example, @tally)
- MSpec.should_receive(:register).with(:tagged, @tally)
- MSpec.should_receive(:register).with(:expectation, @tally)
+ expect(MSpec).to receive(:register).with(:load, @tally)
+ expect(MSpec).to receive(:register).with(:exception, @tally)
+ expect(MSpec).to receive(:register).with(:example, @tally)
+ expect(MSpec).to receive(:register).with(:tagged, @tally)
+ expect(MSpec).to receive(:register).with(:expectation, @tally)
@tally.register
end
end
-describe TallyAction, "#unregister" do
+RSpec.describe TallyAction, "#unregister" do
before :each do
@tally = TallyAction.new
@state = ExampleState.new("describe", "it")
end
it "unregisters itself with MSpec for appropriate actions" do
- MSpec.should_receive(:unregister).with(:load, @tally)
- MSpec.should_receive(:unregister).with(:exception, @tally)
- MSpec.should_receive(:unregister).with(:example, @tally)
- MSpec.should_receive(:unregister).with(:tagged, @tally)
- MSpec.should_receive(:unregister).with(:expectation, @tally)
+ expect(MSpec).to receive(:unregister).with(:load, @tally)
+ expect(MSpec).to receive(:unregister).with(:exception, @tally)
+ expect(MSpec).to receive(:unregister).with(:example, @tally)
+ expect(MSpec).to receive(:unregister).with(:tagged, @tally)
+ expect(MSpec).to receive(:unregister).with(:expectation, @tally)
@tally.unregister
end
end
diff --git a/spec/mspec/spec/runner/actions/timer_spec.rb b/spec/mspec/spec/runner/actions/timer_spec.rb
index 417367d5a2..28a317177b 100644
--- a/spec/mspec/spec/runner/actions/timer_spec.rb
+++ b/spec/mspec/spec/runner/actions/timer_spec.rb
@@ -3,7 +3,7 @@ require 'mspec/runner/actions/timer'
require 'mspec/runner/mspec'
require 'time'
-describe TimerAction do
+RSpec.describe TimerAction do
before :each do
@timer = TimerAction.new
@start_time = Time.utc(2009, 3, 30, 14, 5, 19)
@@ -11,34 +11,34 @@ describe TimerAction do
end
it "responds to #start by recording the current time" do
- Time.should_receive(:now)
+ expect(Time).to receive(:now)
@timer.start
end
it "responds to #finish by recording the current time" do
- Time.should_receive(:now)
+ expect(Time).to receive(:now)
@timer.finish
end
it "responds to #elapsed by returning the difference between stop and start" do
- Time.stub(:now).and_return(@start_time)
+ allow(Time).to receive(:now).and_return(@start_time)
@timer.start
- Time.stub(:now).and_return(@stop_time)
+ allow(Time).to receive(:now).and_return(@stop_time)
@timer.finish
- @timer.elapsed.should == 33
+ expect(@timer.elapsed).to eq(33)
end
it "responds to #format by returning a readable string of elapsed time" do
- Time.stub(:now).and_return(@start_time)
+ allow(Time).to receive(:now).and_return(@start_time)
@timer.start
- Time.stub(:now).and_return(@stop_time)
+ allow(Time).to receive(:now).and_return(@stop_time)
@timer.finish
- @timer.format.should == "Finished in 33.000000 seconds"
+ expect(@timer.format).to eq("Finished in 33.000000 seconds")
end
it "responds to #register by registering itself with MSpec for appropriate actions" do
- MSpec.should_receive(:register).with(:start, @timer)
- MSpec.should_receive(:register).with(:finish, @timer)
+ expect(MSpec).to receive(:register).with(:start, @timer)
+ expect(MSpec).to receive(:register).with(:finish, @timer)
@timer.register
end
end
diff --git a/spec/mspec/spec/runner/context_spec.rb b/spec/mspec/spec/runner/context_spec.rb
index d9c20aa0cf..9ebc708c0c 100644
--- a/spec/mspec/spec/runner/context_spec.rb
+++ b/spec/mspec/spec/runner/context_spec.rb
@@ -6,7 +6,7 @@ require 'mspec/mocks/mock'
require 'mspec/runner/context'
require 'mspec/runner/example'
-describe ContextState, "#describe" do
+RSpec.describe ContextState, "#describe" do
before :each do
@state = ContextState.new "C#m"
@proc = proc { ScratchPad.record :a }
@@ -15,79 +15,63 @@ describe ContextState, "#describe" do
it "evaluates the passed block" do
@state.describe(&@proc)
- ScratchPad.recorded.should == :a
+ expect(ScratchPad.recorded).to eq(:a)
end
it "evaluates the passed block via #protect" do
- @state.should_receive(:protect).with("C#m", @proc, false)
+ expect(@state).to receive(:protect).with("C#m", @proc, false)
@state.describe(&@proc)
end
it "registers #parent as the current MSpec ContextState" do
parent = ContextState.new ""
@state.parent = parent
- MSpec.should_receive(:register_current).with(parent)
+ expect(MSpec).to receive(:register_current).with(parent)
@state.describe { }
end
it "registers self with MSpec when #shared? is true" do
state = ContextState.new "something shared", :shared => true
- MSpec.should_receive(:register_shared).with(state)
+ expect(MSpec).to receive(:register_shared).with(state)
state.describe { }
end
end
-describe ContextState, "#shared?" do
+RSpec.describe ContextState, "#shared?" do
it "returns false when the ContextState is not shared" do
- ContextState.new("").shared?.should be_false
+ expect(ContextState.new("").shared?).to be_falsey
end
it "returns true when the ContextState is shared" do
- ContextState.new("", {:shared => true}).shared?.should be_true
+ expect(ContextState.new("", {:shared => true}).shared?).to be_truthy
end
end
-describe ContextState, "#to_s" do
+RSpec.describe ContextState, "#to_s" do
it "returns a description string for self when passed a Module" do
- ContextState.new(Object).to_s.should == "Object"
+ expect(ContextState.new(Object).to_s).to eq("Object")
end
it "returns a description string for self when passed a String" do
- ContextState.new("SomeClass").to_s.should == "SomeClass"
- end
-
- it "returns a description string for self when passed a Module, String" do
- ContextState.new(Object, "when empty").to_s.should == "Object when empty"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '#'" do
- ContextState.new(Object, "#to_s").to_s.should == "Object#to_s"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '.'" do
- ContextState.new(Object, ".to_s").to_s.should == "Object.to_s"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '::'" do
- ContextState.new(Object, "::to_s").to_s.should == "Object::to_s"
+ expect(ContextState.new("SomeClass").to_s).to eq("SomeClass")
end
end
-describe ContextState, "#description" do
+RSpec.describe ContextState, "#description" do
before :each do
@state = ContextState.new "when empty"
@parent = ContextState.new "Toplevel"
end
it "returns a composite description string from self and all parents" do
- @parent.description.should == "Toplevel"
- @state.description.should == "when empty"
+ expect(@parent.description).to eq("Toplevel")
+ expect(@state.description).to eq("when empty")
@state.parent = @parent
- @state.description.should == "Toplevel when empty"
+ expect(@state.description).to eq("Toplevel when empty")
end
end
-describe ContextState, "#it" do
+RSpec.describe ContextState, "#it" do
before :each do
@state = ContextState.new ""
@proc = lambda {|*| }
@@ -96,25 +80,25 @@ describe ContextState, "#it" do
end
it "creates an ExampleState instance for the block" do
- ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex)
+ expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex)
@state.describe(&@proc)
@state.it("it", &@proc)
end
it "calls registered :add actions" do
- ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex)
+ expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex)
add_action = double("add")
- add_action.should_receive(:add).with(@ex).and_return { ScratchPad.record :add }
+ expect(add_action).to receive(:add).with(@ex) { ScratchPad.record :add }
MSpec.register :add, add_action
@state.it("it", &@proc)
- ScratchPad.recorded.should == :add
+ expect(ScratchPad.recorded).to eq(:add)
MSpec.unregister :add, add_action
end
end
-describe ContextState, "#examples" do
+RSpec.describe ContextState, "#examples" do
before :each do
@state = ContextState.new ""
end
@@ -122,11 +106,11 @@ describe ContextState, "#examples" do
it "returns a list of all examples in this ContextState" do
@state.it("first") { }
@state.it("second") { }
- @state.examples.size.should == 2
+ expect(@state.examples.size).to eq(2)
end
end
-describe ContextState, "#before" do
+RSpec.describe ContextState, "#before" do
before :each do
@state = ContextState.new ""
@proc = lambda {|*| }
@@ -134,16 +118,16 @@ describe ContextState, "#before" do
it "records the block for :each" do
@state.before(:each, &@proc)
- @state.before(:each).should == [@proc]
+ expect(@state.before(:each)).to eq([@proc])
end
it "records the block for :all" do
@state.before(:all, &@proc)
- @state.before(:all).should == [@proc]
+ expect(@state.before(:all)).to eq([@proc])
end
end
-describe ContextState, "#after" do
+RSpec.describe ContextState, "#after" do
before :each do
@state = ContextState.new ""
@proc = lambda {|*| }
@@ -151,16 +135,16 @@ describe ContextState, "#after" do
it "records the block for :each" do
@state.after(:each, &@proc)
- @state.after(:each).should == [@proc]
+ expect(@state.after(:each)).to eq([@proc])
end
it "records the block for :all" do
@state.after(:all, &@proc)
- @state.after(:all).should == [@proc]
+ expect(@state.after(:all)).to eq([@proc])
end
end
-describe ContextState, "#pre" do
+RSpec.describe ContextState, "#pre" do
before :each do
@a = lambda {|*| }
@b = lambda {|*| }
@@ -177,17 +161,17 @@ describe ContextState, "#pre" do
it "returns before(:each) actions in the order they were defined" do
@state.before(:each, &@a)
@state.before(:each, &@b)
- @state.pre(:each).should == [@c, @a, @b]
+ expect(@state.pre(:each)).to eq([@c, @a, @b])
end
it "returns before(:all) actions in the order they were defined" do
@state.before(:all, &@a)
@state.before(:all, &@b)
- @state.pre(:all).should == [@c, @a, @b]
+ expect(@state.pre(:all)).to eq([@c, @a, @b])
end
end
-describe ContextState, "#post" do
+RSpec.describe ContextState, "#post" do
before :each do
@a = lambda {|*| }
@b = lambda {|*| }
@@ -204,17 +188,17 @@ describe ContextState, "#post" do
it "returns after(:each) actions in the reverse order they were defined" do
@state.after(:each, &@a)
@state.after(:each, &@b)
- @state.post(:each).should == [@b, @a, @c]
+ expect(@state.post(:each)).to eq([@b, @a, @c])
end
it "returns after(:all) actions in the reverse order they were defined" do
@state.after(:all, &@a)
@state.after(:all, &@b)
- @state.post(:all).should == [@b, @a, @c]
+ expect(@state.post(:all)).to eq([@b, @a, @c])
end
end
-describe ContextState, "#protect" do
+RSpec.describe ContextState, "#protect" do
before :each do
ScratchPad.record []
@a = lambda {|*| ScratchPad << :a }
@@ -223,41 +207,41 @@ describe ContextState, "#protect" do
end
it "returns true and does execute any blocks if check and MSpec.mode?(:pretend) are true" do
- MSpec.should_receive(:mode?).with(:pretend).and_return(true)
- ContextState.new("").protect("message", [@a, @b]).should be_true
- ScratchPad.recorded.should == []
+ expect(MSpec).to receive(:mode?).with(:pretend).and_return(true)
+ expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy
+ expect(ScratchPad.recorded).to eq([])
end
it "executes the blocks if MSpec.mode?(:pretend) is false" do
- MSpec.should_receive(:mode?).with(:pretend).and_return(false)
+ expect(MSpec).to receive(:mode?).with(:pretend).and_return(false)
ContextState.new("").protect("message", [@a, @b])
- ScratchPad.recorded.should == [:a, :b]
+ expect(ScratchPad.recorded).to eq([:a, :b])
end
it "executes the blocks if check is false" do
ContextState.new("").protect("message", [@a, @b], false)
- ScratchPad.recorded.should == [:a, :b]
+ expect(ScratchPad.recorded).to eq([:a, :b])
end
it "returns true if none of the blocks raise an exception" do
- ContextState.new("").protect("message", [@a, @b]).should be_true
+ expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy
end
it "returns false if any of the blocks raise an exception" do
- ContextState.new("").protect("message", [@a, @c, @b]).should be_false
+ expect(ContextState.new("").protect("message", [@a, @c, @b])).to be_falsey
end
end
-describe ContextState, "#parent=" do
+RSpec.describe ContextState, "#parent=" do
before :each do
@state = ContextState.new ""
@parent = double("describe")
- @parent.stub(:parent).and_return(nil)
- @parent.stub(:child)
+ allow(@parent).to receive(:parent).and_return(nil)
+ allow(@parent).to receive(:child)
end
it "does not set self as a child of parent if shared" do
- @parent.should_not_receive(:child)
+ expect(@parent).not_to receive(:child)
state = ContextState.new "", :shared => true
state.parent = @parent
end
@@ -265,70 +249,70 @@ describe ContextState, "#parent=" do
it "does not set parents if shared" do
state = ContextState.new "", :shared => true
state.parent = @parent
- state.parents.should == [state]
+ expect(state.parents).to eq([state])
end
it "sets self as a child of parent" do
- @parent.should_receive(:child).with(@state)
+ expect(@parent).to receive(:child).with(@state)
@state.parent = @parent
end
it "creates the list of parents" do
@state.parent = @parent
- @state.parents.should == [@parent, @state]
+ expect(@state.parents).to eq([@parent, @state])
end
end
-describe ContextState, "#parent" do
+RSpec.describe ContextState, "#parent" do
before :each do
@state = ContextState.new ""
@parent = double("describe")
- @parent.stub(:parent).and_return(nil)
- @parent.stub(:child)
+ allow(@parent).to receive(:parent).and_return(nil)
+ allow(@parent).to receive(:child)
end
it "returns nil if parent has not been set" do
- @state.parent.should be_nil
+ expect(@state.parent).to be_nil
end
it "returns the parent" do
@state.parent = @parent
- @state.parent.should == @parent
+ expect(@state.parent).to eq(@parent)
end
end
-describe ContextState, "#parents" do
+RSpec.describe ContextState, "#parents" do
before :each do
@first = ContextState.new ""
@second = ContextState.new ""
@parent = double("describe")
- @parent.stub(:parent).and_return(nil)
- @parent.stub(:child)
+ allow(@parent).to receive(:parent).and_return(nil)
+ allow(@parent).to receive(:child)
end
it "returns a list of all enclosing ContextState instances" do
@first.parent = @parent
@second.parent = @first
- @second.parents.should == [@parent, @first, @second]
+ expect(@second.parents).to eq([@parent, @first, @second])
end
end
-describe ContextState, "#child" do
+RSpec.describe ContextState, "#child" do
before :each do
@first = ContextState.new ""
@second = ContextState.new ""
@parent = double("describe")
- @parent.stub(:parent).and_return(nil)
- @parent.stub(:child)
+ allow(@parent).to receive(:parent).and_return(nil)
+ allow(@parent).to receive(:child)
end
it "adds the ContextState to the list of contained ContextStates" do
@first.child @second
- @first.children.should == [@second]
+ expect(@first.children).to eq([@second])
end
end
-describe ContextState, "#children" do
+RSpec.describe ContextState, "#children" do
before :each do
@parent = ContextState.new ""
@first = ContextState.new ""
@@ -338,12 +322,12 @@ describe ContextState, "#children" do
it "returns the list of directly contained ContextStates" do
@first.parent = @parent
@second.parent = @first
- @parent.children.should == [@first]
- @first.children.should == [@second]
+ expect(@parent.children).to eq([@first])
+ expect(@first.children).to eq([@second])
end
end
-describe ContextState, "#state" do
+RSpec.describe ContextState, "#state" do
before :each do
MSpec.store :before, []
MSpec.store :after, []
@@ -352,7 +336,7 @@ describe ContextState, "#state" do
end
it "returns nil if no spec is being executed" do
- @state.state.should == nil
+ expect(@state.state).to eq(nil)
end
it "returns a ExampleState instance if an example is being executed" do
@@ -360,16 +344,16 @@ describe ContextState, "#state" do
@state.describe { }
@state.it("") { ScratchPad.record ScratchPad.recorded.state }
@state.process
- @state.state.should == nil
- ScratchPad.recorded.should be_kind_of(ExampleState)
+ expect(@state.state).to eq(nil)
+ expect(ScratchPad.recorded).to be_kind_of(ExampleState)
end
end
-describe ContextState, "#process" do
+RSpec.describe ContextState, "#process" do
before :each do
MSpec.store :before, []
MSpec.store :after, []
- MSpec.stub(:register_current)
+ allow(MSpec).to receive(:register_current)
@state = ContextState.new ""
@state.describe { }
@@ -384,7 +368,7 @@ describe ContextState, "#process" do
@state.before(:all, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == [:a, :b]
+ expect(ScratchPad.recorded).to eq([:a, :b])
end
it "calls each after(:all) block" do
@@ -392,22 +376,22 @@ describe ContextState, "#process" do
@state.after(:all, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == [:b, :a]
+ expect(ScratchPad.recorded).to eq([:b, :a])
end
it "calls each it block" do
@state.it("one", &@a)
@state.it("two", &@b)
@state.process
- ScratchPad.recorded.should == [:a, :b]
+ expect(ScratchPad.recorded).to eq([:a, :b])
end
it "does not call the #it block if #filtered? returns true" do
@state.it("one", &@a)
@state.it("two", &@b)
- @state.examples.first.stub(:filtered?).and_return(true)
+ allow(@state.examples.first).to receive(:filtered?).and_return(true)
@state.process
- ScratchPad.recorded.should == [:b]
+ expect(ScratchPad.recorded).to eq([:b])
end
it "calls each before(:each) block" do
@@ -415,7 +399,7 @@ describe ContextState, "#process" do
@state.before(:each, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == [:a, :b]
+ expect(ScratchPad.recorded).to eq([:a, :b])
end
it "calls each after(:each) block" do
@@ -423,20 +407,20 @@ describe ContextState, "#process" do
@state.after(:each, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == [:b, :a]
+ expect(ScratchPad.recorded).to eq([:b, :a])
end
it "calls Mock.cleanup for each it block" do
@state.it("") { }
@state.it("") { }
- Mock.should_receive(:cleanup).twice
+ expect(Mock).to receive(:cleanup).twice
@state.process
end
it "calls Mock.verify_count for each it block" do
@state.it("") { }
@state.it("") { }
- Mock.should_receive(:verify_count).twice
+ expect(Mock).to receive(:verify_count).twice
@state.process
end
@@ -444,7 +428,7 @@ describe ContextState, "#process" do
ScratchPad.record []
@state.describe { ScratchPad << :a }
@state.process
- ScratchPad.recorded.should == [:a]
+ expect(ScratchPad.recorded).to eq([:a])
end
it "creates a new ExampleState instance for each example" do
@@ -452,44 +436,47 @@ describe ContextState, "#process" do
@state.describe { }
@state.it("it") { ScratchPad.record ScratchPad.recorded.state }
@state.process
- ScratchPad.recorded.should be_kind_of(ExampleState)
+ expect(ScratchPad.recorded).to be_kind_of(ExampleState)
end
it "clears the expectations flag before evaluating the #it block" do
MSpec.clear_expectations
- MSpec.should_receive(:clear_expectations)
+ expect(MSpec).to receive(:clear_expectations)
@state.it("it") { ScratchPad.record MSpec.expectation? }
@state.process
- ScratchPad.recorded.should be_false
+ expect(ScratchPad.recorded).to be_falsey
end
it "shuffles the spec list if MSpec.randomize? is true" do
- MSpec.randomize
- MSpec.should_receive(:shuffle)
- @state.it("") { }
- @state.process
- MSpec.randomize false
+ MSpec.randomize = true
+ begin
+ expect(MSpec).to receive(:shuffle)
+ @state.it("") { }
+ @state.process
+ ensure
+ MSpec.randomize = false
+ end
end
it "sets the current MSpec ContextState" do
- MSpec.should_receive(:register_current).with(@state)
+ expect(MSpec).to receive(:register_current).with(@state)
@state.process
end
it "resets the current MSpec ContextState to nil when there are examples" do
- MSpec.should_receive(:register_current).with(nil)
+ expect(MSpec).to receive(:register_current).with(nil)
@state.it("") { }
@state.process
end
it "resets the current MSpec ContextState to nil when there are no examples" do
- MSpec.should_receive(:register_current).with(nil)
+ expect(MSpec).to receive(:register_current).with(nil)
@state.process
end
it "call #process on children when there are examples" do
child = ContextState.new ""
- child.should_receive(:process)
+ expect(child).to receive(:process)
@state.child child
@state.it("") { }
@state.process
@@ -497,13 +484,13 @@ describe ContextState, "#process" do
it "call #process on children when there are no examples" do
child = ContextState.new ""
- child.should_receive(:process)
+ expect(child).to receive(:process)
@state.child child
@state.process
end
end
-describe ContextState, "#process" do
+RSpec.describe ContextState, "#process" do
before :each do
MSpec.store :exception, []
@@ -527,23 +514,23 @@ describe ContextState, "#process" do
it "raises an SpecExpectationNotFoundError if an #it block does not contain an expectation" do
@state.it("it") { }
@state.process
- ScratchPad.recorded.should == :exception
+ expect(ScratchPad.recorded).to eq(:exception)
end
it "does not raise an SpecExpectationNotFoundError if an #it block does contain an expectation" do
@state.it("it") { MSpec.expectation }
@state.process
- ScratchPad.recorded.should be_nil
+ expect(ScratchPad.recorded).to be_nil
end
it "does not raise an SpecExpectationNotFoundError if the #it block causes a failure" do
@state.it("it") { raise Exception, "Failed!" }
@state.process
- ScratchPad.recorded.should be_nil
+ expect(ScratchPad.recorded).to be_nil
end
end
-describe ContextState, "#process" do
+RSpec.describe ContextState, "#process" do
before :each do
MSpec.store :example, []
@@ -567,18 +554,18 @@ describe ContextState, "#process" do
@state.it("") { MSpec.expectation }
@state.process
- ScratchPad.recorded.first.should be_kind_of(ExampleState)
- ScratchPad.recorded.last.should be_kind_of(Proc)
+ expect(ScratchPad.recorded.first).to be_kind_of(ExampleState)
+ expect(ScratchPad.recorded.last).to be_kind_of(Proc)
end
it "does not call registered example actions if the example has no block" do
@state.it("empty example")
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
end
-describe ContextState, "#process" do
+RSpec.describe ContextState, "#process" do
before :each do
MSpec.store :before, []
MSpec.store :after, []
@@ -595,30 +582,30 @@ describe ContextState, "#process" do
it "calls registered :before actions with the current ExampleState instance" do
before = double("before")
- before.should_receive(:before).and_return {
+ expect(before).to receive(:before) {
ScratchPad.record :before
@spec_state = @state.state
}
MSpec.register :before, before
@state.process
- ScratchPad.recorded.should == :before
- @spec_state.should be_kind_of(ExampleState)
+ expect(ScratchPad.recorded).to eq(:before)
+ expect(@spec_state).to be_kind_of(ExampleState)
end
it "calls registered :after actions with the current ExampleState instance" do
after = double("after")
- after.should_receive(:after).and_return {
+ expect(after).to receive(:after) {
ScratchPad.record :after
@spec_state = @state.state
}
MSpec.register :after, after
@state.process
- ScratchPad.recorded.should == :after
- @spec_state.should be_kind_of(ExampleState)
+ expect(ScratchPad.recorded).to eq(:after)
+ expect(@spec_state).to be_kind_of(ExampleState)
end
end
-describe ContextState, "#process" do
+RSpec.describe ContextState, "#process" do
before :each do
MSpec.store :enter, []
MSpec.store :leave, []
@@ -635,22 +622,22 @@ describe ContextState, "#process" do
it "calls registered :enter actions with the current #describe string" do
enter = double("enter")
- enter.should_receive(:enter).with("C#m").and_return { ScratchPad.record :enter }
+ expect(enter).to receive(:enter).with("C#m") { ScratchPad.record :enter }
MSpec.register :enter, enter
@state.process
- ScratchPad.recorded.should == :enter
+ expect(ScratchPad.recorded).to eq(:enter)
end
it "calls registered :leave actions" do
leave = double("leave")
- leave.should_receive(:leave).and_return { ScratchPad.record :leave }
+ expect(leave).to receive(:leave) { ScratchPad.record :leave }
MSpec.register :leave, leave
@state.process
- ScratchPad.recorded.should == :leave
+ expect(ScratchPad.recorded).to eq(:leave)
end
end
-describe ContextState, "#process when an exception is raised in before(:all)" do
+RSpec.describe ContextState, "#process when an exception is raised in before(:all)" do
before :each do
MSpec.store :before, []
MSpec.store :after, []
@@ -674,43 +661,43 @@ describe ContextState, "#process when an exception is raised in before(:all)" do
@state.before(:each, &@a)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call the it block" do
@state.it("one", &@a)
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call after(:each)" do
@state.after(:each, &@a)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call after(:each)" do
@state.after(:all, &@a)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call Mock.verify_count" do
@state.it("") { }
- Mock.should_not_receive(:verify_count)
+ expect(Mock).not_to receive(:verify_count)
@state.process
end
it "calls Mock.cleanup" do
@state.it("") { }
- Mock.should_receive(:cleanup)
+ expect(Mock).to receive(:cleanup)
@state.process
end
end
-describe ContextState, "#process when an exception is raised in before(:each)" do
+RSpec.describe ContextState, "#process when an exception is raised in before(:each)" do
before :each do
MSpec.store :before, []
MSpec.store :after, []
@@ -733,24 +720,24 @@ describe ContextState, "#process when an exception is raised in before(:each)" d
it "does not call the it block" do
@state.it("one", &@a)
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
- it "does call after(:each)" do
+ it "calls after(:each)" do
@state.after(:each, &@a)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == [:a]
+ expect(ScratchPad.recorded).to eq([:a])
end
- it "does not call Mock.verify_count" do
+ it "calls Mock.verify_count" do
@state.it("") { }
- Mock.should_not_receive(:verify_count)
+ expect(Mock).to receive(:verify_count)
@state.process
end
end
-describe ContextState, "#process in pretend mode" do
+RSpec.describe ContextState, "#process in pretend mode" do
before :all do
MSpec.register_mode :pretend
end
@@ -776,30 +763,30 @@ describe ContextState, "#process in pretend mode" do
it "calls registered :before actions with the current ExampleState instance" do
before = double("before")
- before.should_receive(:before).and_return {
+ expect(before).to receive(:before) {
ScratchPad.record :before
@spec_state = @state.state
}
MSpec.register :before, before
@state.process
- ScratchPad.recorded.should == :before
- @spec_state.should be_kind_of(ExampleState)
+ expect(ScratchPad.recorded).to eq(:before)
+ expect(@spec_state).to be_kind_of(ExampleState)
end
it "calls registered :after actions with the current ExampleState instance" do
after = double("after")
- after.should_receive(:after).and_return {
+ expect(after).to receive(:after) {
ScratchPad.record :after
@spec_state = @state.state
}
MSpec.register :after, after
@state.process
- ScratchPad.recorded.should == :after
- @spec_state.should be_kind_of(ExampleState)
+ expect(ScratchPad.recorded).to eq(:after)
+ expect(@spec_state).to be_kind_of(ExampleState)
end
end
-describe ContextState, "#process in pretend mode" do
+RSpec.describe ContextState, "#process in pretend mode" do
before :all do
MSpec.register_mode :pretend
end
@@ -824,7 +811,7 @@ describe ContextState, "#process in pretend mode" do
ScratchPad.record []
@state.describe { ScratchPad << :a }
@state.process
- ScratchPad.recorded.should == [:a]
+ expect(ScratchPad.recorded).to eq([:a])
end
it "does not call any before(:all) block" do
@@ -832,7 +819,7 @@ describe ContextState, "#process in pretend mode" do
@state.before(:all, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call any after(:all) block" do
@@ -840,14 +827,14 @@ describe ContextState, "#process in pretend mode" do
@state.after(:all, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call any it block" do
@state.it("one", &@a)
@state.it("two", &@b)
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call any before(:each) block" do
@@ -855,7 +842,7 @@ describe ContextState, "#process in pretend mode" do
@state.before(:each, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call any after(:each) block" do
@@ -863,18 +850,18 @@ describe ContextState, "#process in pretend mode" do
@state.after(:each, &@b)
@state.it("") { }
@state.process
- ScratchPad.recorded.should == []
+ expect(ScratchPad.recorded).to eq([])
end
it "does not call Mock.cleanup" do
@state.it("") { }
@state.it("") { }
- Mock.should_not_receive(:cleanup)
+ expect(Mock).not_to receive(:cleanup)
@state.process
end
end
-describe ContextState, "#process in pretend mode" do
+RSpec.describe ContextState, "#process in pretend mode" do
before :all do
MSpec.register_mode :pretend
end
@@ -899,26 +886,26 @@ describe ContextState, "#process in pretend mode" do
it "calls registered :enter actions with the current #describe string" do
enter = double("enter")
- enter.should_receive(:enter).and_return { ScratchPad.record :enter }
+ expect(enter).to receive(:enter) { ScratchPad.record :enter }
MSpec.register :enter, enter
@state.process
- ScratchPad.recorded.should == :enter
+ expect(ScratchPad.recorded).to eq(:enter)
end
it "calls registered :leave actions" do
leave = double("leave")
- leave.should_receive(:leave).and_return { ScratchPad.record :leave }
+ expect(leave).to receive(:leave) { ScratchPad.record :leave }
MSpec.register :leave, leave
@state.process
- ScratchPad.recorded.should == :leave
+ expect(ScratchPad.recorded).to eq(:leave)
end
end
-describe ContextState, "#it_should_behave_like" do
+RSpec.describe ContextState, "#it_should_behave_like" do
before :each do
@shared_desc = :shared_context
@shared = ContextState.new(@shared_desc, :shared => true)
- MSpec.stub(:retrieve_shared).and_return(@shared)
+ allow(MSpec).to receive(:retrieve_shared).and_return(@shared)
@state = ContextState.new "Top level"
@a = lambda {|*| }
@@ -926,8 +913,8 @@ describe ContextState, "#it_should_behave_like" do
end
it "raises an Exception if unable to find the shared ContextState" do
- MSpec.should_receive(:retrieve_shared).and_return(nil)
- lambda { @state.it_should_behave_like "this" }.should raise_error(Exception)
+ expect(MSpec).to receive(:retrieve_shared).and_return(nil)
+ expect { @state.it_should_behave_like :this }.to raise_error(Exception)
end
describe "for nested ContextState instances" do
@@ -938,24 +925,24 @@ describe ContextState, "#it_should_behave_like" do
@shared.children << @nested
@nested_dup = @nested.dup
- @nested.stub(:dup).and_return(@nested_dup)
+ allow(@nested).to receive(:dup).and_return(@nested_dup)
end
it "duplicates the nested ContextState" do
@state.it_should_behave_like @shared_desc
- @state.children.first.should equal(@nested_dup)
+ expect(@state.children.first).to equal(@nested_dup)
end
it "sets the parent of the nested ContextState to the containing ContextState" do
@state.it_should_behave_like @shared_desc
- @nested_dup.parent.should equal(@state)
+ expect(@nested_dup.parent).to equal(@state)
end
it "sets the context for nested examples to the nested ContextState's dup" do
@shared.it "an example", &@a
@shared.it "another example", &@b
@state.it_should_behave_like @shared_desc
- @nested_dup.examples.each { |x| x.context.should equal(@nested_dup) }
+ @nested_dup.examples.each { |x| expect(x.context).to equal(@nested_dup) }
end
it "omits the shored ContextState's description" do
@@ -963,58 +950,58 @@ describe ContextState, "#it_should_behave_like" do
@nested.it "another example", &@b
@state.it_should_behave_like @shared_desc
- @nested_dup.description.should == "Top level nested context"
- @nested_dup.examples.first.description.should == "Top level nested context an example"
- @nested_dup.examples.last.description.should == "Top level nested context another example"
+ expect(@nested_dup.description).to eq("Top level nested context")
+ expect(@nested_dup.examples.first.description).to eq("Top level nested context an example")
+ expect(@nested_dup.examples.last.description).to eq("Top level nested context another example")
end
end
it "adds duped examples from the shared ContextState" do
@shared.it "some method", &@a
ex_dup = @shared.examples.first.dup
- @shared.examples.first.stub(:dup).and_return(ex_dup)
+ allow(@shared.examples.first).to receive(:dup).and_return(ex_dup)
@state.it_should_behave_like @shared_desc
- @state.examples.should == [ex_dup]
+ expect(@state.examples).to eq([ex_dup])
end
it "sets the context for examples to the containing ContextState" do
@shared.it "an example", &@a
@shared.it "another example", &@b
@state.it_should_behave_like @shared_desc
- @state.examples.each { |x| x.context.should equal(@state) }
+ @state.examples.each { |x| expect(x.context).to equal(@state) }
end
it "adds before(:all) blocks from the shared ContextState" do
@shared.before :all, &@a
@shared.before :all, &@b
@state.it_should_behave_like @shared_desc
- @state.before(:all).should include(*@shared.before(:all))
+ expect(@state.before(:all)).to include(*@shared.before(:all))
end
it "adds before(:each) blocks from the shared ContextState" do
@shared.before :each, &@a
@shared.before :each, &@b
@state.it_should_behave_like @shared_desc
- @state.before(:each).should include(*@shared.before(:each))
+ expect(@state.before(:each)).to include(*@shared.before(:each))
end
it "adds after(:each) blocks from the shared ContextState" do
@shared.after :each, &@a
@shared.after :each, &@b
@state.it_should_behave_like @shared_desc
- @state.after(:each).should include(*@shared.after(:each))
+ expect(@state.after(:each)).to include(*@shared.after(:each))
end
it "adds after(:all) blocks from the shared ContextState" do
@shared.after :all, &@a
@shared.after :all, &@b
@state.it_should_behave_like @shared_desc
- @state.after(:all).should include(*@shared.after(:all))
+ expect(@state.after(:all)).to include(*@shared.after(:all))
end
end
-describe ContextState, "#filter_examples" do
+RSpec.describe ContextState, "#filter_examples" do
before :each do
@state = ContextState.new ""
@state.it("one") { }
@@ -1022,20 +1009,20 @@ describe ContextState, "#filter_examples" do
end
it "removes examples that are filtered" do
- @state.examples.first.stub(:filtered?).and_return(true)
- @state.examples.size.should == 2
+ allow(@state.examples.first).to receive(:filtered?).and_return(true)
+ expect(@state.examples.size).to eq(2)
@state.filter_examples
- @state.examples.size.should == 1
+ expect(@state.examples.size).to eq(1)
end
it "returns true if there are remaining examples to evaluate" do
- @state.examples.first.stub(:filtered?).and_return(true)
- @state.filter_examples.should be_true
+ allow(@state.examples.first).to receive(:filtered?).and_return(true)
+ expect(@state.filter_examples).to be_truthy
end
it "returns false if there are no remaining examples to evaluate" do
- @state.examples.first.stub(:filtered?).and_return(true)
- @state.examples.last.stub(:filtered?).and_return(true)
- @state.filter_examples.should be_false
+ allow(@state.examples.first).to receive(:filtered?).and_return(true)
+ allow(@state.examples.last).to receive(:filtered?).and_return(true)
+ expect(@state.filter_examples).to be_falsey
end
end
diff --git a/spec/mspec/spec/runner/example_spec.rb b/spec/mspec/spec/runner/example_spec.rb
index b4391f802d..8bac166da8 100644
--- a/spec/mspec/spec/runner/example_spec.rb
+++ b/spec/mspec/spec/runner/example_spec.rb
@@ -4,36 +4,36 @@ require 'mspec/runner/mspec'
require 'mspec/mocks/mock'
require 'mspec/runner/example'
-describe ExampleState do
+RSpec.describe ExampleState do
it "is initialized with the ContextState, #it string, and #it block" do
prc = lambda { }
context = ContextState.new ""
- ExampleState.new(context, "does", prc).should be_kind_of(ExampleState)
+ expect(ExampleState.new(context, "does", prc)).to be_kind_of(ExampleState)
end
end
-describe ExampleState, "#describe" do
+RSpec.describe ExampleState, "#describe" do
before :each do
- @context = ContextState.new Object, "#to_s"
+ @context = ContextState.new "Object#to_s"
@state = ExampleState.new @context, "it"
end
it "returns the ContextState#description" do
- @state.describe.should == @context.description
+ expect(@state.describe).to eq(@context.description)
end
end
-describe ExampleState, "#it" do
+RSpec.describe ExampleState, "#it" do
before :each do
@state = ExampleState.new ContextState.new("describe"), "it"
end
it "returns the argument to the #it block" do
- @state.it.should == "it"
+ expect(@state.it).to eq("it")
end
end
-describe ExampleState, "#context=" do
+RSpec.describe ExampleState, "#context=" do
before :each do
@state = ExampleState.new ContextState.new("describe"), "it"
@context = ContextState.new "New#context"
@@ -41,77 +41,77 @@ describe ExampleState, "#context=" do
it "sets the containing ContextState" do
@state.context = @context
- @state.context.should == @context
+ expect(@state.context).to eq(@context)
end
it "resets the description" do
- @state.description.should == "describe it"
+ expect(@state.description).to eq("describe it")
@state.context = @context
- @state.description.should == "New#context it"
+ expect(@state.description).to eq("New#context it")
end
end
-describe ExampleState, "#example" do
+RSpec.describe ExampleState, "#example" do
before :each do
@proc = lambda { }
@state = ExampleState.new ContextState.new("describe"), "it", @proc
end
it "returns the #it block" do
- @state.example.should == @proc
+ expect(@state.example).to eq(@proc)
end
end
-describe ExampleState, "#filtered?" do
+RSpec.describe ExampleState, "#filtered?" do
before :each do
- MSpec.store :include, nil
- MSpec.store :exclude, nil
+ MSpec.store :include, []
+ MSpec.store :exclude, []
@state = ExampleState.new ContextState.new("describe"), "it"
@filter = double("filter")
end
after :each do
- MSpec.store :include, nil
- MSpec.store :exclude, nil
+ MSpec.store :include, []
+ MSpec.store :exclude, []
end
it "returns false if MSpec include filters list is empty" do
- @state.filtered?.should == false
+ expect(@state.filtered?).to eq(false)
end
it "returns false if MSpec include filters match this spec" do
- @filter.should_receive(:===).and_return(true)
+ expect(@filter).to receive(:===).and_return(true)
MSpec.register :include, @filter
- @state.filtered?.should == false
+ expect(@state.filtered?).to eq(false)
end
it "returns true if MSpec include filters do not match this spec" do
- @filter.should_receive(:===).and_return(false)
+ expect(@filter).to receive(:===).and_return(false)
MSpec.register :include, @filter
- @state.filtered?.should == true
+ expect(@state.filtered?).to eq(true)
end
it "returns false if MSpec exclude filters list is empty" do
- @state.filtered?.should == false
+ expect(@state.filtered?).to eq(false)
end
it "returns false if MSpec exclude filters do not match this spec" do
- @filter.should_receive(:===).and_return(false)
+ expect(@filter).to receive(:===).and_return(false)
MSpec.register :exclude, @filter
- @state.filtered?.should == false
+ expect(@state.filtered?).to eq(false)
end
it "returns true if MSpec exclude filters match this spec" do
- @filter.should_receive(:===).and_return(true)
+ expect(@filter).to receive(:===).and_return(true)
MSpec.register :exclude, @filter
- @state.filtered?.should == true
+ expect(@state.filtered?).to eq(true)
end
it "returns true if MSpec include and exclude filters match this spec" do
- @filter.should_receive(:===).twice.and_return(true)
+ expect(@filter).to receive(:===).twice.and_return(true)
MSpec.register :include, @filter
MSpec.register :exclude, @filter
- @state.filtered?.should == true
+ expect(@state.filtered?).to eq(true)
end
end
diff --git a/spec/mspec/spec/runner/exception_spec.rb b/spec/mspec/spec/runner/exception_spec.rb
index 309442435c..a77a2c9cf4 100644
--- a/spec/mspec/spec/runner/exception_spec.rb
+++ b/spec/mspec/spec/runner/exception_spec.rb
@@ -4,16 +4,16 @@ require 'mspec/runner/example'
require 'mspec/runner/exception'
require 'mspec/utils/script'
-describe ExceptionState, "#initialize" do
+RSpec.describe ExceptionState, "#initialize" do
it "takes a state, location (e.g. before :each), and exception" do
context = ContextState.new "Class#method"
state = ExampleState.new context, "does something"
exc = Exception.new "Fail!"
- ExceptionState.new(state, "location", exc).should be_kind_of(ExceptionState)
+ expect(ExceptionState.new(state, "location", exc)).to be_kind_of(ExceptionState)
end
end
-describe ExceptionState, "#description" do
+RSpec.describe ExceptionState, "#description" do
before :each do
context = ContextState.new "Class#method"
@state = ExampleState.new context, "does something"
@@ -21,99 +21,99 @@ describe ExceptionState, "#description" do
it "returns the state description if state was not nil" do
exc = ExceptionState.new(@state, nil, nil)
- exc.description.should == "Class#method does something"
+ expect(exc.description).to eq("Class#method does something")
end
it "returns the location if it is not nil and description is nil" do
exc = ExceptionState.new(nil, "location", nil)
- exc.description.should == "An exception occurred during: location"
+ expect(exc.description).to eq("An exception occurred during: location")
end
it "returns both description and location if neither are nil" do
exc = ExceptionState.new(@state, "location", nil)
- exc.description.should == "An exception occurred during: location\nClass#method does something"
+ expect(exc.description).to eq("An exception occurred during: location\nClass#method does something")
end
end
-describe ExceptionState, "#describe" do
+RSpec.describe ExceptionState, "#describe" do
before :each do
context = ContextState.new "Class#method"
@state = ExampleState.new context, "does something"
end
it "returns the ExampleState#describe string if created with a non-nil state" do
- ExceptionState.new(@state, nil, nil).describe.should == @state.describe
+ expect(ExceptionState.new(@state, nil, nil).describe).to eq(@state.describe)
end
it "returns an empty string if created with a nil state" do
- ExceptionState.new(nil, nil, nil).describe.should == ""
+ expect(ExceptionState.new(nil, nil, nil).describe).to eq("")
end
end
-describe ExceptionState, "#it" do
+RSpec.describe ExceptionState, "#it" do
before :each do
context = ContextState.new "Class#method"
@state = ExampleState.new context, "does something"
end
it "returns the ExampleState#it string if created with a non-nil state" do
- ExceptionState.new(@state, nil, nil).it.should == @state.it
+ expect(ExceptionState.new(@state, nil, nil).it).to eq(@state.it)
end
it "returns an empty string if created with a nil state" do
- ExceptionState.new(nil, nil, nil).it.should == ""
+ expect(ExceptionState.new(nil, nil, nil).it).to eq("")
end
end
-describe ExceptionState, "#failure?" do
+RSpec.describe ExceptionState, "#failure?" do
before :each do
@state = ExampleState.new ContextState.new("C#m"), "works"
end
it "returns true if the exception is an SpecExpectationNotMetError" do
exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!")
- exc.failure?.should be_true
+ expect(exc.failure?).to be_truthy
end
it "returns true if the exception is an SpecExpectationNotFoundError" do
exc = ExceptionState.new @state, "", SpecExpectationNotFoundError.new("Fail!")
- exc.failure?.should be_true
+ expect(exc.failure?).to be_truthy
end
it "returns false if the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do
exc = ExceptionState.new @state, "", Exception.new("Fail!")
- exc.failure?.should be_false
+ expect(exc.failure?).to be_falsey
end
end
-describe ExceptionState, "#message" do
+RSpec.describe ExceptionState, "#message" do
before :each do
@state = ExampleState.new ContextState.new("C#m"), "works"
end
it "returns <No message> if the exception message is empty" do
exc = ExceptionState.new @state, "", Exception.new("")
- exc.message.should == "<No message>"
+ expect(exc.message).to eq("Exception: <No message>")
end
it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do
exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!")
- exc.message.should == "Fail!"
+ expect(exc.message).to eq("Fail!")
end
it "returns SpecExpectationNotFoundError#message when the exception is an SpecExpectationNotFoundError" do
e = SpecExpectationNotFoundError.new
exc = ExceptionState.new @state, "", e
- exc.message.should == e.message
+ expect(exc.message).to eq(e.message)
end
it "returns the message with exception class when the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do
exc = ExceptionState.new @state, "", Exception.new("Fail!")
- exc.message.should == "Exception: Fail!"
+ expect(exc.message).to eq("Exception: Fail!")
end
end
-describe ExceptionState, "#backtrace" do
+RSpec.describe ExceptionState, "#backtrace" do
before :each do
@state = ExampleState.new ContextState.new("C#m"), "works"
begin
@@ -128,19 +128,19 @@ describe ExceptionState, "#backtrace" do
end
it "returns a string representation of the exception backtrace" do
- @exc.backtrace.should be_kind_of(String)
+ expect(@exc.backtrace).to be_kind_of(String)
end
it "does not filter files from the backtrace if $MSPEC_DEBUG is true" do
$MSPEC_DEBUG = true
- @exc.backtrace.should == @exception.backtrace.join("\n")
+ expect(@exc.backtrace).to eq(@exception.backtrace.join("\n"))
end
it "filters files matching config[:backtrace_filter]" do
MSpecScript.set :backtrace_filter, %r[mspec/lib]
$MSPEC_DEBUG = nil
@exc.backtrace.split("\n").each do |line|
- line.should_not =~ %r[mspec/lib]
+ expect(line).not_to match(%r[mspec/lib])
end
end
end
diff --git a/spec/mspec/spec/runner/filters/match_spec.rb b/spec/mspec/spec/runner/filters/match_spec.rb
index f2c665c495..970da00446 100644
--- a/spec/mspec/spec/runner/filters/match_spec.rb
+++ b/spec/mspec/spec/runner/filters/match_spec.rb
@@ -2,33 +2,33 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/mspec'
require 'mspec/runner/filters/match'
-describe MatchFilter, "#===" do
+RSpec.describe MatchFilter, "#===" do
before :each do
@filter = MatchFilter.new nil, 'a', 'b', 'c'
end
it "returns true if the argument matches any of the #initialize strings" do
- @filter.===('aaa').should == true
- @filter.===('bccb').should == true
+ expect(@filter.===('aaa')).to eq(true)
+ expect(@filter.===('bccb')).to eq(true)
end
it "returns false if the argument matches none of the #initialize strings" do
- @filter.===('d').should == false
+ expect(@filter.===('d')).to eq(false)
end
end
-describe MatchFilter, "#register" do
+RSpec.describe MatchFilter, "#register" do
it "registers itself with MSpec for the designated action list" do
filter = MatchFilter.new :include
- MSpec.should_receive(:register).with(:include, filter)
+ expect(MSpec).to receive(:register).with(:include, filter)
filter.register
end
end
-describe MatchFilter, "#unregister" do
+RSpec.describe MatchFilter, "#unregister" do
it "unregisters itself with MSpec for the designated action list" do
filter = MatchFilter.new :exclude
- MSpec.should_receive(:unregister).with(:exclude, filter)
+ expect(MSpec).to receive(:unregister).with(:exclude, filter)
filter.unregister
end
end
diff --git a/spec/mspec/spec/runner/filters/profile_spec.rb b/spec/mspec/spec/runner/filters/profile_spec.rb
index 89d0ad1911..25f5e07aef 100644
--- a/spec/mspec/spec/runner/filters/profile_spec.rb
+++ b/spec/mspec/spec/runner/filters/profile_spec.rb
@@ -2,45 +2,45 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/mspec'
require 'mspec/runner/filters/profile'
-describe ProfileFilter, "#find" do
+RSpec.describe ProfileFilter, "#find" do
before :each do
@filter = ProfileFilter.new nil
- File.stub(:exist?).and_return(false)
+ allow(File).to receive(:exist?).and_return(false)
@file = "rails.yaml"
end
it "attempts to locate the file through the expanded path name" do
- File.should_receive(:expand_path).with(@file).and_return(@file)
- File.should_receive(:exist?).with(@file).and_return(true)
- @filter.find(@file).should == @file
+ expect(File).to receive(:expand_path).with(@file).and_return(@file)
+ expect(File).to receive(:exist?).with(@file).and_return(true)
+ expect(@filter.find(@file)).to eq(@file)
end
it "attempts to locate the file in 'spec/profiles'" do
path = File.join "spec/profiles", @file
- File.should_receive(:exist?).with(path).and_return(true)
- @filter.find(@file).should == path
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(@filter.find(@file)).to eq(path)
end
it "attempts to locate the file in 'spec'" do
path = File.join "spec", @file
- File.should_receive(:exist?).with(path).and_return(true)
- @filter.find(@file).should == path
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(@filter.find(@file)).to eq(path)
end
it "attempts to locate the file in 'profiles'" do
path = File.join "profiles", @file
- File.should_receive(:exist?).with(path).and_return(true)
- @filter.find(@file).should == path
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(@filter.find(@file)).to eq(path)
end
it "attempts to locate the file in '.'" do
path = File.join ".", @file
- File.should_receive(:exist?).with(path).and_return(true)
- @filter.find(@file).should == path
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(@filter.find(@file)).to eq(path)
end
end
-describe ProfileFilter, "#parse" do
+RSpec.describe ProfileFilter, "#parse" do
before :each do
@filter = ProfileFilter.new nil
@file = File.open(File.dirname(__FILE__) + "/b.yaml", "r")
@@ -51,14 +51,14 @@ describe ProfileFilter, "#parse" do
end
it "creates a Hash of the contents of the YAML file" do
- @filter.parse(@file).should == {
+ expect(@filter.parse(@file)).to eq({
"B." => ["b", "bb"],
"B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="]
- }
+ })
end
end
-describe ProfileFilter, "#load" do
+RSpec.describe ProfileFilter, "#load" do
before :each do
@filter = ProfileFilter.new nil
@files = [
@@ -68,50 +68,50 @@ describe ProfileFilter, "#load" do
end
it "generates a composite hash from multiple YAML files" do
- @filter.load(*@files).should == {
+ expect(@filter.load(*@files)).to eq({
"A#" => ["a", "aa"],
"B." => ["b", "bb"],
"B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="]
- }
+ })
end
end
-describe ProfileFilter, "#===" do
+RSpec.describe ProfileFilter, "#===" do
before :each do
@filter = ProfileFilter.new nil
- @filter.stub(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]})
+ allow(@filter).to receive(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]})
@filter.send :initialize, nil
end
it "returns true if the spec description is for a method in the profile" do
- @filter.===("The A#[]= method").should == true
- @filter.===("A#a returns").should == true
- @filter.===("A#a! replaces").should == true
- @filter.===("A#a? returns").should == true
- @filter.===("A#aa= raises").should == true
+ expect(@filter.===("The A#[]= method")).to eq(true)
+ expect(@filter.===("A#a returns")).to eq(true)
+ expect(@filter.===("A#a! replaces")).to eq(true)
+ expect(@filter.===("A#a? returns")).to eq(true)
+ expect(@filter.===("A#aa= raises")).to eq(true)
end
it "returns false if the spec description is for a method not in the profile" do
- @filter.===("The A#[] method").should == false
- @filter.===("B#a returns").should == false
- @filter.===("A.a! replaces").should == false
- @filter.===("AA#a? returns").should == false
- @filter.===("A#aa raises").should == false
+ expect(@filter.===("The A#[] method")).to eq(false)
+ expect(@filter.===("B#a returns")).to eq(false)
+ expect(@filter.===("A.a! replaces")).to eq(false)
+ expect(@filter.===("AA#a? returns")).to eq(false)
+ expect(@filter.===("A#aa raises")).to eq(false)
end
end
-describe ProfileFilter, "#register" do
+RSpec.describe ProfileFilter, "#register" do
it "registers itself with MSpec for the designated action list" do
filter = ProfileFilter.new :include
- MSpec.should_receive(:register).with(:include, filter)
+ expect(MSpec).to receive(:register).with(:include, filter)
filter.register
end
end
-describe ProfileFilter, "#unregister" do
+RSpec.describe ProfileFilter, "#unregister" do
it "unregisters itself with MSpec for the designated action list" do
filter = ProfileFilter.new :exclude
- MSpec.should_receive(:unregister).with(:exclude, filter)
+ expect(MSpec).to receive(:unregister).with(:exclude, filter)
filter.unregister
end
end
diff --git a/spec/mspec/spec/runner/filters/regexp_spec.rb b/spec/mspec/spec/runner/filters/regexp_spec.rb
index 8e9b0ec7e8..1d1d3554f6 100644
--- a/spec/mspec/spec/runner/filters/regexp_spec.rb
+++ b/spec/mspec/spec/runner/filters/regexp_spec.rb
@@ -2,30 +2,30 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/mspec'
require 'mspec/runner/filters/regexp'
-describe MatchFilter, "#===" do
+RSpec.describe MatchFilter, "#===" do
before :each do
@filter = RegexpFilter.new nil, 'a(b|c)', 'b[^ab]', 'cc?'
end
it "returns true if the argument matches any of the #initialize strings" do
- @filter.===('ab').should == true
- @filter.===('bc suffix').should == true
- @filter.===('prefix cc').should == true
+ expect(@filter.===('ab')).to eq(true)
+ expect(@filter.===('bc suffix')).to eq(true)
+ expect(@filter.===('prefix cc')).to eq(true)
end
it "returns false if the argument matches none of the #initialize strings" do
- @filter.===('aa').should == false
- @filter.===('ba').should == false
- @filter.===('prefix d suffix').should == false
+ expect(@filter.===('aa')).to eq(false)
+ expect(@filter.===('ba')).to eq(false)
+ expect(@filter.===('prefix d suffix')).to eq(false)
end
end
-describe RegexpFilter, "#to_regexp" do
+RSpec.describe RegexpFilter, "#to_regexp" do
before :each do
@filter = RegexpFilter.new nil
end
it "converts its arguments to Regexp instances" do
- @filter.send(:to_regexp, 'a(b|c)', 'b[^ab]', 'cc?').should == [/a(b|c)/, /b[^ab]/, /cc?/]
+ expect(@filter.send(:to_regexp, 'a(b|c)', 'b[^ab]', 'cc?')).to eq([/a(b|c)/, /b[^ab]/, /cc?/])
end
end
diff --git a/spec/mspec/spec/runner/filters/tag_spec.rb b/spec/mspec/spec/runner/filters/tag_spec.rb
index fe1f3df039..356175a754 100644
--- a/spec/mspec/spec/runner/filters/tag_spec.rb
+++ b/spec/mspec/spec/runner/filters/tag_spec.rb
@@ -3,90 +3,90 @@ require 'mspec/runner/mspec'
require 'mspec/runner/filters/match'
require 'mspec/runner/filters/tag'
-describe TagFilter, "#load" do
+RSpec.describe TagFilter, "#load" do
before :each do
@match = double("match filter").as_null_object
@filter = TagFilter.new :include, "tag", "key"
@tag = SpecTag.new "tag(comment):description"
- MSpec.stub(:read_tags).and_return([@tag])
- MSpec.stub(:register)
+ allow(MSpec).to receive(:read_tags).and_return([@tag])
+ allow(MSpec).to receive(:register)
end
it "loads tags from the tag file" do
- MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([])
+ expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([])
@filter.load
end
it "registers itself with MSpec for the :include action" do
filter = TagFilter.new(:include)
- MSpec.should_receive(:register).with(:include, filter)
+ expect(MSpec).to receive(:register).with(:include, filter)
filter.load
end
it "registers itself with MSpec for the :exclude action" do
filter = TagFilter.new(:exclude)
- MSpec.should_receive(:register).with(:exclude, filter)
+ expect(MSpec).to receive(:register).with(:exclude, filter)
filter.load
end
end
-describe TagFilter, "#unload" do
+RSpec.describe TagFilter, "#unload" do
before :each do
@filter = TagFilter.new :include, "tag", "key"
@tag = SpecTag.new "tag(comment):description"
- MSpec.stub(:read_tags).and_return([@tag])
- MSpec.stub(:register)
+ allow(MSpec).to receive(:read_tags).and_return([@tag])
+ allow(MSpec).to receive(:register)
end
it "unregisters itself" do
@filter.load
- MSpec.should_receive(:unregister).with(:include, @filter)
+ expect(MSpec).to receive(:unregister).with(:include, @filter)
@filter.unload
end
end
-describe TagFilter, "#register" do
+RSpec.describe TagFilter, "#register" do
before :each do
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
end
it "registers itself with MSpec for the :load, :unload actions" do
filter = TagFilter.new(nil)
- MSpec.should_receive(:register).with(:load, filter)
- MSpec.should_receive(:register).with(:unload, filter)
+ expect(MSpec).to receive(:register).with(:load, filter)
+ expect(MSpec).to receive(:register).with(:unload, filter)
filter.register
end
end
-describe TagFilter, "#unregister" do
+RSpec.describe TagFilter, "#unregister" do
before :each do
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:unregister)
end
it "unregisters itself with MSpec for the :load, :unload actions" do
filter = TagFilter.new(nil)
- MSpec.should_receive(:unregister).with(:load, filter)
- MSpec.should_receive(:unregister).with(:unload, filter)
+ expect(MSpec).to receive(:unregister).with(:load, filter)
+ expect(MSpec).to receive(:unregister).with(:unload, filter)
filter.unregister
end
end
-describe TagFilter, "#===" do
+RSpec.describe TagFilter, "#===" do
before :each do
@filter = TagFilter.new nil, "tag", "key"
@tag = SpecTag.new "tag(comment):description"
- MSpec.stub(:read_tags).and_return([@tag])
- MSpec.stub(:register)
+ allow(MSpec).to receive(:read_tags).and_return([@tag])
+ allow(MSpec).to receive(:register)
@filter.load
end
it "returns true if the argument matches any of the descriptions" do
- @filter.===('description').should == true
+ expect(@filter.===('description')).to eq(true)
end
it "returns false if the argument matches none of the descriptions" do
- @filter.===('descriptionA').should == false
- @filter.===('adescription').should == false
+ expect(@filter.===('descriptionA')).to eq(false)
+ expect(@filter.===('adescription')).to eq(false)
end
end
diff --git a/spec/mspec/spec/runner/formatters/describe_spec.rb b/spec/mspec/spec/runner/formatters/describe_spec.rb
index 415ced71fb..55f497aca6 100644
--- a/spec/mspec/spec/runner/formatters/describe_spec.rb
+++ b/spec/mspec/spec/runner/formatters/describe_spec.rb
@@ -2,14 +2,14 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/formatters/describe'
require 'mspec/runner/example'
-describe DescribeFormatter, "#finish" do
+RSpec.describe DescribeFormatter, "#finish" do
before :each do
- MSpec.stub(:register)
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:register)
+ allow(MSpec).to receive(:unregister)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
- @timer.stub(:format).and_return("Finished in 2.0 seconds")
+ allow(TimerAction).to receive(:new).and_return(@timer)
+ allow(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
$stdout = @out = IOStub.new
context = ContextState.new "Class#method"
@@ -32,36 +32,36 @@ describe DescribeFormatter, "#finish" do
it "prints a summary of elapsed time" do
@formatter.finish
- @out.should =~ /^Finished in 2.0 seconds$/
+ expect(@out).to match(/^Finished in 2.0 seconds$/)
end
it "prints a tally of counts" do
@formatter.finish
- @out.should =~ /^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/
+ expect(@out).to match(/^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/)
end
it "does not print exceptions" do
@formatter.finish
- @out.should == %[
+ expect(@out).to eq(%[
Finished in 2.0 seconds
1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged
-]
+])
end
it "prints a summary of failures and errors for each describe block" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.finish
- @out.should == %[
+ expect(@out).to eq(%[
Class#method 0 failures, 1 error
Finished in 2.0 seconds
1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/dotted_spec.rb b/spec/mspec/spec/runner/formatters/dotted_spec.rb
index 1e9b06f6e1..336b1227ed 100644
--- a/spec/mspec/spec/runner/formatters/dotted_spec.rb
+++ b/spec/mspec/spec/runner/formatters/dotted_spec.rb
@@ -4,7 +4,7 @@ require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/utils/script'
-describe DottedFormatter, "#initialize" do
+RSpec.describe DottedFormatter, "#initialize" do
it "permits zero arguments" do
DottedFormatter.new
end
@@ -14,33 +14,33 @@ describe DottedFormatter, "#initialize" do
end
end
-describe DottedFormatter, "#register" do
+RSpec.describe DottedFormatter, "#register" do
before :each do
@formatter = DottedFormatter.new
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
end
it "registers self with MSpec for appropriate actions" do
- MSpec.should_receive(:register).with(:exception, @formatter)
- MSpec.should_receive(:register).with(:before, @formatter)
- MSpec.should_receive(:register).with(:after, @formatter)
- MSpec.should_receive(:register).with(:finish, @formatter)
+ expect(MSpec).to receive(:register).with(:exception, @formatter)
+ expect(MSpec).to receive(:register).with(:before, @formatter)
+ expect(MSpec).to receive(:register).with(:after, @formatter)
+ expect(MSpec).to receive(:register).with(:finish, @formatter)
@formatter.register
end
it "creates TimerAction and TallyAction" do
timer = double("timer")
tally = double("tally")
- timer.should_receive(:register)
- tally.should_receive(:register)
- tally.should_receive(:counter)
- TimerAction.should_receive(:new).and_return(timer)
- TallyAction.should_receive(:new).and_return(tally)
+ expect(timer).to receive(:register)
+ expect(tally).to receive(:register)
+ expect(tally).to receive(:counter)
+ expect(TimerAction).to receive(:new).and_return(timer)
+ expect(TallyAction).to receive(:new).and_return(tally)
@formatter.register
end
end
-describe DottedFormatter, "#print" do
+RSpec.describe DottedFormatter, "#print" do
before :each do
$stdout = IOStub.new
end
@@ -52,25 +52,25 @@ describe DottedFormatter, "#print" do
it "writes to $stdout by default" do
formatter = DottedFormatter.new
formatter.print "begonias"
- $stdout.should == "begonias"
+ expect($stdout).to eq("begonias")
end
it "writes to the file specified when the formatter was created" do
out = IOStub.new
- File.should_receive(:open).with("some/file", "w").and_return(out)
+ expect(File).to receive(:open).with("some/file", "w").and_return(out)
formatter = DottedFormatter.new "some/file"
formatter.print "begonias"
- out.should == "begonias"
+ expect(out).to eq("begonias")
end
it "flushes the IO output" do
- $stdout.should_receive(:flush)
+ expect($stdout).to receive(:flush)
formatter = DottedFormatter.new
formatter.print "begonias"
end
end
-describe DottedFormatter, "#exception" do
+RSpec.describe DottedFormatter, "#exception" do
before :each do
@formatter = DottedFormatter.new
@failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed")
@@ -79,27 +79,27 @@ describe DottedFormatter, "#exception" do
it "sets the #failure? flag" do
@formatter.exception @failure
- @formatter.failure?.should be_true
+ expect(@formatter.failure?).to be_truthy
@formatter.exception @error
- @formatter.failure?.should be_false
+ expect(@formatter.failure?).to be_falsey
end
it "sets the #exception? flag" do
@formatter.exception @error
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
@formatter.exception @failure
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
end
- it "addes the exception to the list of exceptions" do
- @formatter.exceptions.should == []
+ it "adds the exception to the list of exceptions" do
+ expect(@formatter.exceptions).to eq([])
@formatter.exception @error
@formatter.exception @failure
- @formatter.exceptions.should == [@error, @failure]
+ expect(@formatter.exceptions).to eq([@error, @failure])
end
end
-describe DottedFormatter, "#exception?" do
+RSpec.describe DottedFormatter, "#exception?" do
before :each do
@formatter = DottedFormatter.new
@failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed")
@@ -107,29 +107,29 @@ describe DottedFormatter, "#exception?" do
end
it "returns false if there have been no exceptions" do
- @formatter.exception?.should be_false
+ expect(@formatter.exception?).to be_falsey
end
it "returns true if any exceptions are errors" do
@formatter.exception @failure
@formatter.exception @error
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
end
it "returns true if all exceptions are failures" do
@formatter.exception @failure
@formatter.exception @failure
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
end
it "returns true if all exceptions are errors" do
@formatter.exception @error
@formatter.exception @error
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
end
end
-describe DottedFormatter, "#failure?" do
+RSpec.describe DottedFormatter, "#failure?" do
before :each do
@formatter = DottedFormatter.new
@failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed")
@@ -137,23 +137,23 @@ describe DottedFormatter, "#failure?" do
end
it "returns false if there have been no exceptions" do
- @formatter.failure?.should be_false
+ expect(@formatter.failure?).to be_falsey
end
it "returns false if any exceptions are errors" do
@formatter.exception @failure
@formatter.exception @error
- @formatter.failure?.should be_false
+ expect(@formatter.failure?).to be_falsey
end
it "returns true if all exceptions are failures" do
@formatter.exception @failure
@formatter.exception @failure
- @formatter.failure?.should be_true
+ expect(@formatter.failure?).to be_truthy
end
end
-describe DottedFormatter, "#before" do
+RSpec.describe DottedFormatter, "#before" do
before :each do
@state = ExampleState.new ContextState.new("describe"), "it"
@formatter = DottedFormatter.new
@@ -161,19 +161,19 @@ describe DottedFormatter, "#before" do
end
it "resets the #failure? flag to false" do
- @formatter.failure?.should be_true
+ expect(@formatter.failure?).to be_truthy
@formatter.before @state
- @formatter.failure?.should be_false
+ expect(@formatter.failure?).to be_falsey
end
it "resets the #exception? flag to false" do
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
@formatter.before @state
- @formatter.exception?.should be_false
+ expect(@formatter.exception?).to be_falsey
end
end
-describe DottedFormatter, "#after" do
+RSpec.describe DottedFormatter, "#after" do
before :each do
$stdout = @out = IOStub.new
@formatter = DottedFormatter.new
@@ -186,21 +186,21 @@ describe DottedFormatter, "#after" do
it "prints a '.' if there was no exception raised" do
@formatter.after(@state)
- @out.should == "."
+ expect(@out).to eq(".")
end
it "prints an 'F' if there was an expectation failure" do
exc = SpecExpectationNotMetError.new "failed"
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.after(@state)
- @out.should == "F"
+ expect(@out).to eq("F")
end
it "prints an 'E' if there was an exception other than expectation failure" do
exc = MSpecExampleError.new("boom!")
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.after(@state)
- @out.should == "E"
+ expect(@out).to eq("E")
end
it "prints an 'E' if there are mixed exceptions and exepctation failures" do
@@ -209,21 +209,21 @@ describe DottedFormatter, "#after" do
exc = MSpecExampleError.new("boom!")
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.after(@state)
- @out.should == "E"
+ expect(@out).to eq("E")
end
end
-describe DottedFormatter, "#finish" do
+RSpec.describe DottedFormatter, "#finish" do
before :each do
@tally = double("tally").as_null_object
- TallyAction.stub(:new).and_return(@tally)
+ allow(TallyAction).to receive(:new).and_return(@tally)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
+ allow(TimerAction).to receive(:new).and_return(@timer)
$stdout = @out = IOStub.new
context = ContextState.new "Class#method"
@state = ExampleState.new(context, "runs")
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@formatter = DottedFormatter.new
@formatter.register
end
@@ -237,40 +237,39 @@ describe DottedFormatter, "#finish" do
@formatter.exception exc
@formatter.after @state
@formatter.finish
- @out.should =~ /^1\)\nClass#method runs ERROR$/
+ expect(@out).to match(/^1\)\nClass#method runs ERROR$/)
end
it "prints a backtrace for an exception" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.after @state
@formatter.finish
- @out.should =~ %r[path/to/some/file.rb:35:in method$]
+ expect(@out).to match(%r[path/to/some/file.rb:35:in method$])
end
it "prints a summary of elapsed time" do
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
@formatter.finish
- @out.should =~ /^Finished in 2.0 seconds$/
+ expect(@out).to match(/^Finished in 2.0 seconds$/)
end
it "prints a tally of counts" do
- @tally.should_receive(:format).and_return("1 example, 0 failures")
+ expect(@tally).to receive(:format).and_return("1 example, 0 failures")
@formatter.finish
- @out.should =~ /^1 example, 0 failures$/
+ expect(@out).to match(/^1 example, 0 failures$/)
end
it "prints errors, backtraces, elapsed time, and tallies" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
- @tally.should_receive(:format).and_return("1 example, 1 failure")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@tally).to receive(:format).and_return("1 example, 1 failure")
@formatter.after @state
@formatter.finish
- @out.should ==
-%[E
+ expect(@out).to eq(%[E
1)
Class#method runs ERROR
@@ -280,6 +279,6 @@ path/to/some/file.rb:35:in method
Finished in 2.0 seconds
1 example, 1 failure
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/file_spec.rb b/spec/mspec/spec/runner/formatters/file_spec.rb
index 946683ad58..ae11d60845 100644
--- a/spec/mspec/spec/runner/formatters/file_spec.rb
+++ b/spec/mspec/spec/runner/formatters/file_spec.rb
@@ -3,27 +3,27 @@ require 'mspec/runner/formatters/file'
require 'mspec/runner/mspec'
require 'mspec/runner/example'
-describe FileFormatter, "#register" do
+RSpec.describe FileFormatter, "#register" do
before :each do
@formatter = FileFormatter.new
- MSpec.stub(:register)
- MSpec.stub(:unregister)
+ allow(MSpec).to receive(:register)
+ allow(MSpec).to receive(:unregister)
end
it "registers self with MSpec for :load, :unload actions" do
- MSpec.should_receive(:register).with(:load, @formatter)
- MSpec.should_receive(:register).with(:unload, @formatter)
+ expect(MSpec).to receive(:register).with(:load, @formatter)
+ expect(MSpec).to receive(:register).with(:unload, @formatter)
@formatter.register
end
it "unregisters self with MSpec for :before, :after actions" do
- MSpec.should_receive(:unregister).with(:before, @formatter)
- MSpec.should_receive(:unregister).with(:after, @formatter)
+ expect(MSpec).to receive(:unregister).with(:before, @formatter)
+ expect(MSpec).to receive(:unregister).with(:after, @formatter)
@formatter.register
end
end
-describe FileFormatter, "#load" do
+RSpec.describe FileFormatter, "#load" do
before :each do
@state = ExampleState.new ContextState.new("describe"), "it"
@formatter = FileFormatter.new
@@ -31,19 +31,19 @@ describe FileFormatter, "#load" do
end
it "resets the #failure? flag to false" do
- @formatter.failure?.should be_true
+ expect(@formatter.failure?).to be_truthy
@formatter.load @state
- @formatter.failure?.should be_false
+ expect(@formatter.failure?).to be_falsey
end
it "resets the #exception? flag to false" do
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
@formatter.load @state
- @formatter.exception?.should be_false
+ expect(@formatter.exception?).to be_falsey
end
end
-describe FileFormatter, "#unload" do
+RSpec.describe FileFormatter, "#unload" do
before :each do
$stdout = @out = IOStub.new
@formatter = FileFormatter.new
@@ -56,21 +56,21 @@ describe FileFormatter, "#unload" do
it "prints a '.' if there was no exception raised" do
@formatter.unload(@state)
- @out.should == "."
+ expect(@out).to eq(".")
end
it "prints an 'F' if there was an expectation failure" do
exc = SpecExpectationNotMetError.new "failed"
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.unload(@state)
- @out.should == "F"
+ expect(@out).to eq("F")
end
it "prints an 'E' if there was an exception other than expectation failure" do
exc = MSpecExampleError.new("boom!")
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.unload(@state)
- @out.should == "E"
+ expect(@out).to eq("E")
end
it "prints an 'E' if there are mixed exceptions and exepctation failures" do
@@ -79,6 +79,6 @@ describe FileFormatter, "#unload" do
exc = MSpecExampleError.new("boom!")
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.unload(@state)
- @out.should == "E"
+ expect(@out).to eq("E")
end
end
diff --git a/spec/mspec/spec/runner/formatters/html_spec.rb b/spec/mspec/spec/runner/formatters/html_spec.rb
index 3783ab6a89..ed973ad93f 100644
--- a/spec/mspec/spec/runner/formatters/html_spec.rb
+++ b/spec/mspec/spec/runner/formatters/html_spec.rb
@@ -4,22 +4,23 @@ require 'mspec/runner/formatters/html'
require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/utils/script'
+require 'mspec/helpers'
-describe HtmlFormatter do
+RSpec.describe HtmlFormatter do
before :each do
@formatter = HtmlFormatter.new
end
it "responds to #register by registering itself with MSpec for appropriate actions" do
- MSpec.stub(:register)
- MSpec.should_receive(:register).with(:start, @formatter)
- MSpec.should_receive(:register).with(:enter, @formatter)
- MSpec.should_receive(:register).with(:leave, @formatter)
+ allow(MSpec).to receive(:register)
+ expect(MSpec).to receive(:register).with(:start, @formatter)
+ expect(MSpec).to receive(:register).with(:enter, @formatter)
+ expect(MSpec).to receive(:register).with(:leave, @formatter)
@formatter.register
end
end
-describe HtmlFormatter, "#start" do
+RSpec.describe HtmlFormatter, "#start" do
before :each do
$stdout = @out = IOStub.new
@formatter = HtmlFormatter.new
@@ -32,9 +33,8 @@ describe HtmlFormatter, "#start" do
it "prints the HTML head" do
@formatter.start
ruby_engine = RUBY_ENGINE
- ruby_engine.should =~ /^#{ruby_engine}/
- @out.should ==
-%[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ expect(ruby_engine).to match(/^#{ruby_engine}/)
+ expect(@out).to eq(%[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
@@ -55,11 +55,11 @@ ul {
</style>
</head>
<body>
-]
+])
end
end
-describe HtmlFormatter, "#enter" do
+RSpec.describe HtmlFormatter, "#enter" do
before :each do
$stdout = @out = IOStub.new
@formatter = HtmlFormatter.new
@@ -71,11 +71,11 @@ describe HtmlFormatter, "#enter" do
it "prints the #describe string" do
@formatter.enter "describe"
- @out.should == "<div><p>describe</p>\n<ul>\n"
+ expect(@out).to eq("<div><p>describe</p>\n<ul>\n")
end
end
-describe HtmlFormatter, "#leave" do
+RSpec.describe HtmlFormatter, "#leave" do
before :each do
$stdout = @out = IOStub.new
@formatter = HtmlFormatter.new
@@ -87,11 +87,11 @@ describe HtmlFormatter, "#leave" do
it "prints the closing tags for the #describe string" do
@formatter.leave
- @out.should == "</ul>\n</div>\n"
+ expect(@out).to eq("</ul>\n</div>\n")
end
end
-describe HtmlFormatter, "#exception" do
+RSpec.describe HtmlFormatter, "#exception" do
before :each do
$stdout = @out = IOStub.new
@formatter = HtmlFormatter.new
@@ -108,14 +108,13 @@ describe HtmlFormatter, "#exception" do
@formatter.exception exc
exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful")
@formatter.exception exc
- @out.should ==
-%[<li class="fail">- it (<a href="#details-1">FAILED - 1</a>)</li>
+ expect(@out).to eq(%[<li class="fail">- it (<a href="#details-1">FAILED - 1</a>)</li>
<li class="fail">- it (<a href="#details-2">ERROR - 2</a>)</li>
-]
+])
end
end
-describe HtmlFormatter, "#after" do
+RSpec.describe HtmlFormatter, "#after" do
before :each do
$stdout = @out = IOStub.new
@formatter = HtmlFormatter.new
@@ -129,7 +128,7 @@ describe HtmlFormatter, "#after" do
it "prints the #it once when there are no exceptions raised" do
@formatter.after @state
- @out.should == %[<li class="pass">- it</li>\n]
+ expect(@out).to eq(%[<li class="pass">- it</li>\n])
end
it "does not print any output if an exception is raised" do
@@ -137,68 +136,73 @@ describe HtmlFormatter, "#after" do
@formatter.exception exc
out = @out.dup
@formatter.after @state
- @out.should == out
+ expect(@out).to eq(out)
end
end
-describe HtmlFormatter, "#finish" do
+RSpec.describe HtmlFormatter, "#finish" do
before :each do
@tally = double("tally").as_null_object
- TallyAction.stub(:new).and_return(@tally)
+ allow(TallyAction).to receive(:new).and_return(@tally)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
+ allow(TimerAction).to receive(:new).and_return(@timer)
+
+ @out = tmp("HtmlFormatter")
- $stdout = @out = IOStub.new
context = ContextState.new "describe"
@state = ExampleState.new(context, "it")
- MSpec.stub(:register)
- @formatter = HtmlFormatter.new
+ allow(MSpec).to receive(:register)
+ @formatter = HtmlFormatter.new(@out)
@formatter.register
@exception = MSpecExampleError.new("broken")
- @exception.stub(:backtrace).and_return(["file.rb:1", "file.rb:2"])
+ allow(@exception).to receive(:backtrace).and_return(["file.rb:1", "file.rb:2"])
end
after :each do
- $stdout = STDOUT
+ rm_r @out
end
it "prints a failure message for an exception" do
exc = ExceptionState.new @state, nil, @exception
@formatter.exception exc
@formatter.finish
- @out.should include "<p>describe it ERROR</p>"
+ output = File.read(@out)
+ expect(output).to include "<p>describe it ERROR</p>"
end
it "prints a backtrace for an exception" do
exc = ExceptionState.new @state, nil, @exception
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.finish
- @out.should =~ %r[<pre>.*path/to/some/file.rb:35:in method.*</pre>]m
+ output = File.read(@out)
+ expect(output).to match(%r[<pre>.*path/to/some/file.rb:35:in method.*</pre>]m)
end
it "prints a summary of elapsed time" do
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
@formatter.finish
- @out.should include "<p>Finished in 2.0 seconds</p>\n"
+ output = File.read(@out)
+ expect(output).to include "<p>Finished in 2.0 seconds</p>\n"
end
it "prints a tally of counts" do
- @tally.should_receive(:format).and_return("1 example, 0 failures")
+ expect(@tally).to receive(:format).and_return("1 example, 0 failures")
@formatter.finish
- @out.should include '<p class="pass">1 example, 0 failures</p>'
+ output = File.read(@out)
+ expect(output).to include '<p class="pass">1 example, 0 failures</p>'
end
it "prints errors, backtraces, elapsed time, and tallies" do
exc = ExceptionState.new @state, nil, @exception
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
- @tally.should_receive(:format).and_return("1 example, 1 failures")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@tally).to receive(:format).and_return("1 example, 1 failures")
@formatter.finish
- @out.should ==
-%[<li class=\"fail\">- it (<a href=\"#details-1\">ERROR - 1</a>)</li>
+ output = File.read(@out)
+ expect(output).to eq(%[<li class=\"fail\">- it (<a href=\"#details-1\">ERROR - 1</a>)</li>
<hr>
<ol id="details">
<li id="details-1"><p>describe it ERROR</p>
@@ -211,6 +215,6 @@ path/to/some/file.rb:35:in method</pre>
<p class="fail">1 example, 1 failures</p>
</body>
</html>
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/junit_spec.rb b/spec/mspec/spec/runner/formatters/junit_spec.rb
index 66e7d70e92..3b3da73849 100644
--- a/spec/mspec/spec/runner/formatters/junit_spec.rb
+++ b/spec/mspec/spec/runner/formatters/junit_spec.rb
@@ -2,22 +2,23 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/formatters/junit'
require 'mspec/runner/example'
+require 'mspec/helpers'
-describe JUnitFormatter, "#initialize" do
+RSpec.describe JUnitFormatter, "#initialize" do
it "permits zero arguments" do
- lambda { JUnitFormatter.new }.should_not raise_error
+ expect { JUnitFormatter.new }.not_to raise_error
end
it "accepts one argument" do
- lambda { JUnitFormatter.new nil }.should_not raise_error
+ expect { JUnitFormatter.new nil }.not_to raise_error
end
end
-describe JUnitFormatter, "#print" do
+RSpec.describe JUnitFormatter, "#print" do
before :each do
$stdout = IOStub.new
@out = IOStub.new
- File.stub(:open).and_return(@out)
+ allow(File).to receive(:open).and_return(@out)
@formatter = JUnitFormatter.new "some/file"
end
@@ -27,121 +28,132 @@ describe JUnitFormatter, "#print" do
it "writes to $stdout if #switch has not been called" do
@formatter.print "begonias"
- $stdout.should == "begonias"
- @out.should == ""
+ expect($stdout).to eq("begonias")
+ expect(@out).to eq("")
end
it "writes to the file passed to #initialize once #switch has been called" do
@formatter.switch
@formatter.print "begonias"
- $stdout.should == ""
- @out.should == "begonias"
+ expect($stdout).to eq("")
+ expect(@out).to eq("begonias")
end
it "writes to $stdout once #switch is called if no file was passed to #initialize" do
formatter = JUnitFormatter.new
formatter.switch
formatter.print "begonias"
- $stdout.should == "begonias"
- @out.should == ""
+ expect($stdout).to eq("begonias")
+ expect(@out).to eq("")
end
end
-describe JUnitFormatter, "#finish" do
+RSpec.describe JUnitFormatter, "#finish" do
before :each do
@tally = double("tally").as_null_object
@counter = double("counter").as_null_object
- @tally.stub(:counter).and_return(@counter)
- TallyAction.stub(:new).and_return(@tally)
+ allow(@tally).to receive(:counter).and_return(@counter)
+ allow(TallyAction).to receive(:new).and_return(@tally)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
+ allow(TimerAction).to receive(:new).and_return(@timer)
+
+ @out = tmp("JUnitFormatter")
- $stdout = IOStub.new
context = ContextState.new "describe"
@state = ExampleState.new(context, "it")
- @formatter = JUnitFormatter.new
- @formatter.stub(:backtrace).and_return("")
- MSpec.stub(:register)
+ @formatter = JUnitFormatter.new(@out)
+ allow(@formatter).to receive(:backtrace).and_return("")
+ allow(MSpec).to receive(:register)
@formatter.register
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.after @state
end
after :each do
- $stdout = STDOUT
+ rm_r @out
end
it "calls #switch" do
- @formatter.should_receive(:switch)
+ expect(@formatter).to receive(:switch).and_call_original
@formatter.finish
end
it "outputs a failure message and backtrace" do
@formatter.finish
- $stdout.should include 'message="error in describe it" type="error"'
- $stdout.should include "MSpecExampleError: broken\n"
- $stdout.should include "path/to/some/file.rb:35:in method"
+ output = File.read(@out)
+ expect(output).to include 'message="error in describe it" type="error"'
+ expect(output).to include "MSpecExampleError: broken\n"
+ expect(output).to include "path/to/some/file.rb:35:in method"
end
it "encodes message and backtrace in latin1 for jenkins" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken…")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in methød")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in methød")
@formatter.exception exc
@formatter.finish
- $stdout.should =~ /MSpecExampleError: broken((\.\.\.)|\?)\n/
- $stdout.should =~ /path\/to\/some\/file\.rb:35:in meth(\?|o)d/
+ output = File.binread(@out)
+ expect(output).to match(/MSpecExampleError: broken((\.\.\.)|\?)\n/)
+ expect(output).to match(/path\/to\/some\/file\.rb:35:in meth(\?|o)d/)
end
it "outputs an elapsed time" do
- @timer.should_receive(:elapsed).and_return(4.2)
+ expect(@timer).to receive(:elapsed).and_return(4.2)
@formatter.finish
- $stdout.should include 'time="4.2"'
+ output = File.read(@out)
+ expect(output).to include 'time="4.2"'
end
it "outputs overall elapsed time" do
- @timer.should_receive(:elapsed).and_return(4.2)
+ expect(@timer).to receive(:elapsed).and_return(4.2)
@formatter.finish
- $stdout.should include 'timeCount="4.2"'
+ output = File.read(@out)
+ expect(output).to include 'timeCount="4.2"'
end
it "outputs the number of examples as test count" do
- @counter.should_receive(:examples).and_return(9)
+ expect(@counter).to receive(:examples).and_return(9)
@formatter.finish
- $stdout.should include 'tests="9"'
+ output = File.read(@out)
+ expect(output).to include 'tests="9"'
end
it "outputs overall number of examples as test count" do
- @counter.should_receive(:examples).and_return(9)
+ expect(@counter).to receive(:examples).and_return(9)
@formatter.finish
- $stdout.should include 'testCount="9"'
+ output = File.read(@out)
+ expect(output).to include 'testCount="9"'
end
it "outputs a failure count" do
- @counter.should_receive(:failures).and_return(2)
+ expect(@counter).to receive(:failures).and_return(2)
@formatter.finish
- $stdout.should include 'failureCount="2"'
+ output = File.read(@out)
+ expect(output).to include 'failureCount="2"'
end
it "outputs overall failure count" do
- @counter.should_receive(:failures).and_return(2)
+ expect(@counter).to receive(:failures).and_return(2)
@formatter.finish
- $stdout.should include 'failures="2"'
+ output = File.read(@out)
+ expect(output).to include 'failures="2"'
end
it "outputs an error count" do
- @counter.should_receive(:errors).and_return(1)
+ expect(@counter).to receive(:errors).and_return(1)
@formatter.finish
- $stdout.should include 'errors="1"'
+ output = File.read(@out)
+ expect(output).to include 'errors="1"'
end
it "outputs overall error count" do
- @counter.should_receive(:errors).and_return(1)
+ expect(@counter).to receive(:errors).and_return(1)
@formatter.finish
- $stdout.should include 'errorCount="1"'
+ output = File.read(@out)
+ expect(output).to include 'errorCount="1"'
end
end
diff --git a/spec/mspec/spec/runner/formatters/method_spec.rb b/spec/mspec/spec/runner/formatters/method_spec.rb
index 77204f74c5..02bf47d538 100644
--- a/spec/mspec/spec/runner/formatters/method_spec.rb
+++ b/spec/mspec/spec/runner/formatters/method_spec.rb
@@ -4,29 +4,29 @@ require 'mspec/runner/mspec'
require 'mspec/runner/example'
require 'mspec/utils/script'
-describe MethodFormatter, "#method_type" do
+RSpec.describe MethodFormatter, "#method_type" do
before :each do
@formatter = MethodFormatter.new
end
it "returns 'class' if the separator is '.' or '::'" do
- @formatter.method_type('.').should == "class"
- @formatter.method_type('::').should == "class"
+ expect(@formatter.method_type('.')).to eq("class")
+ expect(@formatter.method_type('::')).to eq("class")
end
it "returns 'instance' if the separator is '#'" do
- @formatter.method_type('#').should == "instance"
+ expect(@formatter.method_type('#')).to eq("instance")
end
it "returns 'unknown' for all other cases" do
- @formatter.method_type(nil).should == "unknown"
+ expect(@formatter.method_type(nil)).to eq("unknown")
end
end
-describe MethodFormatter, "#before" do
+RSpec.describe MethodFormatter, "#before" do
before :each do
@formatter = MethodFormatter.new
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@formatter.register
end
@@ -38,32 +38,32 @@ describe MethodFormatter, "#before" do
state = ExampleState.new ContextState.new("describe"), "it"
@formatter.before state
- @formatter.tally.counter.examples.should == 0
- @formatter.tally.counter.expectations.should == 0
- @formatter.tally.counter.failures.should == 0
- @formatter.tally.counter.errors.should == 0
+ expect(@formatter.tally.counter.examples).to eq(0)
+ expect(@formatter.tally.counter.expectations).to eq(0)
+ expect(@formatter.tally.counter.failures).to eq(0)
+ expect(@formatter.tally.counter.errors).to eq(0)
end
it "records the class, method if available" do
state = ExampleState.new ContextState.new("Some#method"), "it"
@formatter.before state
key = "Some#method"
- @formatter.methods.keys.should include(key)
+ expect(@formatter.methods.keys).to include(key)
h = @formatter.methods[key]
- h[:class].should == "Some"
- h[:method].should == "method"
- h[:description].should == "Some#method it"
+ expect(h[:class]).to eq("Some")
+ expect(h[:method]).to eq("method")
+ expect(h[:description]).to eq("Some#method it")
end
it "does not record class, method unless both are available" do
state = ExampleState.new ContextState.new("Some method"), "it"
@formatter.before state
key = "Some method"
- @formatter.methods.keys.should include(key)
+ expect(@formatter.methods.keys).to include(key)
h = @formatter.methods[key]
- h[:class].should == ""
- h[:method].should == ""
- h[:description].should == "Some method it"
+ expect(h[:class]).to eq("")
+ expect(h[:method]).to eq("")
+ expect(h[:description]).to eq("Some method it")
end
it "sets the method type to unknown if class and method are not available" do
@@ -71,7 +71,7 @@ describe MethodFormatter, "#before" do
@formatter.before state
key = "Some method"
h = @formatter.methods[key]
- h[:type].should == "unknown"
+ expect(h[:type]).to eq("unknown")
end
it "sets the method type based on the class, method separator" do
@@ -79,7 +79,7 @@ describe MethodFormatter, "#before" do
state = ExampleState.new ContextState.new(k), "it"
@formatter.before state
h = @formatter.methods[k]
- h[:type].should == t
+ expect(h[:type]).to eq(t)
end
end
@@ -87,14 +87,14 @@ describe MethodFormatter, "#before" do
state = ExampleState.new ContextState.new("describe"), "it"
@formatter.exceptions << "stuff"
@formatter.before state
- @formatter.exceptions.should be_empty
+ expect(@formatter.exceptions).to be_empty
end
end
-describe MethodFormatter, "#after" do
+RSpec.describe MethodFormatter, "#after" do
before :each do
@formatter = MethodFormatter.new
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@formatter.register
end
@@ -109,10 +109,10 @@ describe MethodFormatter, "#after" do
@formatter.after state
h = @formatter.methods["Some#method"]
- h[:examples].should == 3
- h[:expectations].should == 4
- h[:failures].should == 2
- h[:errors].should == 1
+ expect(h[:examples]).to eq(3)
+ expect(h[:expectations]).to eq(4)
+ expect(h[:failures]).to eq(2)
+ expect(h[:errors]).to eq(1)
end
it "renders the list of exceptions" do
@@ -125,20 +125,20 @@ describe MethodFormatter, "#after" do
@formatter.after state
h = @formatter.methods["Some#method"]
- h[:exceptions].should == [
+ expect(h[:exceptions]).to eq([
%[failed\n\n],
%[failed\n\n]
- ]
+ ])
end
end
-describe MethodFormatter, "#after" do
+RSpec.describe MethodFormatter, "#after" do
before :each do
$stdout = IOStub.new
context = ContextState.new "Class#method"
@state = ExampleState.new(context, "runs")
@formatter = MethodFormatter.new
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@formatter.register
end
@@ -159,8 +159,7 @@ describe MethodFormatter, "#after" do
@formatter.after @state
@formatter.finish
- $stdout.should ==
-%[---
+ expect($stdout).to eq(%[---
"Class#method":
class: "Class"
method: "method"
@@ -173,6 +172,6 @@ describe MethodFormatter, "#after" do
exceptions:
- "failed\\n\\n"
- "failed\\n\\n"
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/multi_spec.rb b/spec/mspec/spec/runner/formatters/multi_spec.rb
index 72bf629f71..2d13c05836 100644
--- a/spec/mspec/spec/runner/formatters/multi_spec.rb
+++ b/spec/mspec/spec/runner/formatters/multi_spec.rb
@@ -1,21 +1,23 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'mspec/runner/formatters/dotted'
require 'mspec/runner/formatters/multi'
require 'mspec/runner/example'
+require 'yaml'
-describe MultiFormatter, "#aggregate_results" do
+RSpec.describe MultiFormatter, "#aggregate_results" do
before :each do
@stdout, $stdout = $stdout, IOStub.new
@file = double("file").as_null_object
- File.stub(:delete)
- File.stub(:read)
+ allow(File).to receive(:delete)
+ allow(File).to receive(:read)
@hash = { "files"=>1, "examples"=>1, "expectations"=>2, "failures"=>0, "errors"=>0 }
- YAML.stub(:load).and_return(@hash)
+ allow(YAML).to receive(:load).and_return(@hash)
- @formatter = MultiFormatter.new
- @formatter.timer.stub(:format).and_return("Finished in 42 seconds")
+ @formatter = DottedFormatter.new.extend(MultiFormatter)
+ allow(@formatter.timer).to receive(:format).and_return("Finished in 42 seconds")
end
after :each do
@@ -25,13 +27,12 @@ describe MultiFormatter, "#aggregate_results" do
it "outputs a summary without errors" do
@formatter.aggregate_results(["a", "b"])
@formatter.finish
- $stdout.should ==
-%[
+ expect($stdout).to eq(%[
Finished in 42 seconds
2 files, 2 examples, 4 expectations, 0 failures, 0 errors, 0 tagged
-]
+])
end
it "outputs a summary with errors" do
@@ -41,8 +42,7 @@ Finished in 42 seconds
]
@formatter.aggregate_results(["a"])
@formatter.finish
- $stdout.should ==
-%[
+ expect($stdout).to eq(%[
1)
Some#method works real good FAILED
@@ -63,6 +63,6 @@ foo.rb:2
Finished in 42 seconds
1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/specdoc_spec.rb b/spec/mspec/spec/runner/formatters/specdoc_spec.rb
index edb439fc11..54b5e2cf0d 100644
--- a/spec/mspec/spec/runner/formatters/specdoc_spec.rb
+++ b/spec/mspec/spec/runner/formatters/specdoc_spec.rb
@@ -2,19 +2,19 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/formatters/specdoc'
require 'mspec/runner/example'
-describe SpecdocFormatter do
+RSpec.describe SpecdocFormatter do
before :each do
@formatter = SpecdocFormatter.new
end
it "responds to #register by registering itself with MSpec for appropriate actions" do
- MSpec.stub(:register)
- MSpec.should_receive(:register).with(:enter, @formatter)
+ allow(MSpec).to receive(:register)
+ expect(MSpec).to receive(:register).with(:enter, @formatter)
@formatter.register
end
end
-describe SpecdocFormatter, "#enter" do
+RSpec.describe SpecdocFormatter, "#enter" do
before :each do
$stdout = @out = IOStub.new
@formatter = SpecdocFormatter.new
@@ -26,11 +26,11 @@ describe SpecdocFormatter, "#enter" do
it "prints the #describe string" do
@formatter.enter("describe")
- @out.should == "\ndescribe\n"
+ expect(@out).to eq("\ndescribe\n")
end
end
-describe SpecdocFormatter, "#before" do
+RSpec.describe SpecdocFormatter, "#before" do
before :each do
$stdout = @out = IOStub.new
@formatter = SpecdocFormatter.new
@@ -43,19 +43,19 @@ describe SpecdocFormatter, "#before" do
it "prints the #it string" do
@formatter.before @state
- @out.should == "- it"
+ expect(@out).to eq("- it")
end
it "resets the #exception? flag" do
exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing")
@formatter.exception exc
- @formatter.exception?.should be_true
+ expect(@formatter.exception?).to be_truthy
@formatter.before @state
- @formatter.exception?.should be_false
+ expect(@formatter.exception?).to be_falsey
end
end
-describe SpecdocFormatter, "#exception" do
+RSpec.describe SpecdocFormatter, "#exception" do
before :each do
$stdout = @out = IOStub.new
@formatter = SpecdocFormatter.new
@@ -70,13 +70,13 @@ describe SpecdocFormatter, "#exception" do
it "prints 'ERROR' if an exception is not an SpecExpectationNotMetError" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful")
@formatter.exception exc
- @out.should == " (ERROR - 1)"
+ expect(@out).to eq(" (ERROR - 1)")
end
it "prints 'FAILED' if an exception is an SpecExpectationNotMetError" do
exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing")
@formatter.exception exc
- @out.should == " (FAILED - 1)"
+ expect(@out).to eq(" (FAILED - 1)")
end
it "prints the #it string if an exception has already been raised" do
@@ -84,11 +84,11 @@ describe SpecdocFormatter, "#exception" do
@formatter.exception exc
exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful")
@formatter.exception exc
- @out.should == " (FAILED - 1)\n- it (ERROR - 2)"
+ expect(@out).to eq(" (FAILED - 1)\n- it (ERROR - 2)")
end
end
-describe SpecdocFormatter, "#after" do
+RSpec.describe SpecdocFormatter, "#after" do
before :each do
$stdout = @out = IOStub.new
@formatter = SpecdocFormatter.new
@@ -101,6 +101,6 @@ describe SpecdocFormatter, "#after" do
it "prints a newline character" do
@formatter.after @state
- @out.should == "\n"
+ expect(@out).to eq("\n")
end
end
diff --git a/spec/mspec/spec/runner/formatters/spinner_spec.rb b/spec/mspec/spec/runner/formatters/spinner_spec.rb
index a122620e39..5c93d38822 100644
--- a/spec/mspec/spec/runner/formatters/spinner_spec.rb
+++ b/spec/mspec/spec/runner/formatters/spinner_spec.rb
@@ -3,7 +3,7 @@ require 'mspec/runner/formatters/spinner'
require 'mspec/runner/mspec'
require 'mspec/runner/example'
-describe SpinnerFormatter, "#initialize" do
+RSpec.describe SpinnerFormatter, "#initialize" do
it "permits zero arguments" do
SpinnerFormatter.new
end
@@ -13,33 +13,33 @@ describe SpinnerFormatter, "#initialize" do
end
end
-describe SpinnerFormatter, "#register" do
+RSpec.describe SpinnerFormatter, "#register" do
before :each do
@formatter = SpinnerFormatter.new
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
end
it "registers self with MSpec for appropriate actions" do
- MSpec.should_receive(:register).with(:start, @formatter)
- MSpec.should_receive(:register).with(:unload, @formatter)
- MSpec.should_receive(:register).with(:after, @formatter)
- MSpec.should_receive(:register).with(:finish, @formatter)
+ expect(MSpec).to receive(:register).with(:start, @formatter)
+ expect(MSpec).to receive(:register).with(:unload, @formatter)
+ expect(MSpec).to receive(:register).with(:after, @formatter)
+ expect(MSpec).to receive(:register).with(:finish, @formatter)
@formatter.register
end
it "creates TimerAction and TallyAction" do
timer = double("timer")
tally = double("tally")
- timer.should_receive(:register)
- tally.should_receive(:register)
- tally.should_receive(:counter)
- TimerAction.should_receive(:new).and_return(timer)
- TallyAction.should_receive(:new).and_return(tally)
+ expect(timer).to receive(:register)
+ expect(tally).to receive(:register)
+ expect(tally).to receive(:counter)
+ expect(TimerAction).to receive(:new).and_return(timer)
+ expect(TallyAction).to receive(:new).and_return(tally)
@formatter.register
end
end
-describe SpinnerFormatter, "#print" do
+RSpec.describe SpinnerFormatter, "#print" do
after :each do
$stdout = STDOUT
end
@@ -48,11 +48,11 @@ describe SpinnerFormatter, "#print" do
$stdout = IOStub.new
formatter = SpinnerFormatter.new "some/file"
formatter.print "begonias"
- $stdout.should == "begonias"
+ expect($stdout).to eq("begonias")
end
end
-describe SpinnerFormatter, "#after" do
+RSpec.describe SpinnerFormatter, "#after" do
before :each do
$stdout = IOStub.new
MSpec.store(:files, ["a", "b", "c", "d"])
@@ -78,6 +78,6 @@ describe SpinnerFormatter, "#after" do
output = "\r[/ | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \
"\r[- | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \
"\r[\\ | ========== 25% | 00:00:00] #{green} 0F #{green} 0E#{reset} "
- $stdout.should == output
+ expect($stdout).to eq(output)
end
end
diff --git a/spec/mspec/spec/runner/formatters/summary_spec.rb b/spec/mspec/spec/runner/formatters/summary_spec.rb
index 16a156b695..c87d940042 100644
--- a/spec/mspec/spec/runner/formatters/summary_spec.rb
+++ b/spec/mspec/spec/runner/formatters/summary_spec.rb
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/formatters/summary'
require 'mspec/runner/example'
-describe SummaryFormatter, "#after" do
+RSpec.describe SummaryFormatter, "#after" do
before :each do
$stdout = @out = IOStub.new
@formatter = SummaryFormatter.new
@@ -21,6 +21,6 @@ describe SummaryFormatter, "#after" do
exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful")
@formatter.exception exc
@formatter.after(@state)
- @out.should == ""
+ expect(@out).to eq("")
end
end
diff --git a/spec/mspec/spec/runner/formatters/unit_spec.rb b/spec/mspec/spec/runner/formatters/unit_spec.rb
index 18167a32b8..d349e6871d 100644
--- a/spec/mspec/spec/runner/formatters/unit_spec.rb
+++ b/spec/mspec/spec/runner/formatters/unit_spec.rb
@@ -3,17 +3,17 @@ require 'mspec/runner/formatters/unit'
require 'mspec/runner/example'
require 'mspec/utils/script'
-describe UnitdiffFormatter, "#finish" do
+RSpec.describe UnitdiffFormatter, "#finish" do
before :each do
@tally = double("tally").as_null_object
- TallyAction.stub(:new).and_return(@tally)
+ allow(TallyAction).to receive(:new).and_return(@tally)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
+ allow(TimerAction).to receive(:new).and_return(@timer)
$stdout = @out = IOStub.new
context = ContextState.new "describe"
@state = ExampleState.new(context, "it")
- MSpec.stub(:register)
+ allow(MSpec).to receive(:register)
@formatter = UnitdiffFormatter.new
@formatter.register
end
@@ -27,39 +27,38 @@ describe UnitdiffFormatter, "#finish" do
@formatter.exception exc
@formatter.after @state
@formatter.finish
- @out.should =~ /^1\)\ndescribe it ERROR$/
+ expect(@out).to match(/^1\)\ndescribe it ERROR$/)
end
it "prints a backtrace for an exception" do
exc = ExceptionState.new @state, nil, Exception.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.finish
- @out.should =~ %r[path/to/some/file.rb:35:in method$]
+ expect(@out).to match(%r[path/to/some/file.rb:35:in method$])
end
it "prints a summary of elapsed time" do
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
@formatter.finish
- @out.should =~ /^Finished in 2.0 seconds$/
+ expect(@out).to match(/^Finished in 2.0 seconds$/)
end
it "prints a tally of counts" do
- @tally.should_receive(:format).and_return("1 example, 0 failures")
+ expect(@tally).to receive(:format).and_return("1 example, 0 failures")
@formatter.finish
- @out.should =~ /^1 example, 0 failures$/
+ expect(@out).to match(/^1 example, 0 failures$/)
end
it "prints errors, backtraces, elapsed time, and tallies" do
exc = ExceptionState.new @state, nil, Exception.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.after @state
- @timer.should_receive(:format).and_return("Finished in 2.0 seconds")
- @tally.should_receive(:format).and_return("1 example, 0 failures")
+ expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds")
+ expect(@tally).to receive(:format).and_return("1 example, 0 failures")
@formatter.finish
- @out.should ==
-%[E
+ expect(@out).to eq(%[E
Finished in 2.0 seconds
@@ -69,6 +68,6 @@ Exception: broken:
path/to/some/file.rb:35:in method
1 example, 0 failures
-]
+])
end
end
diff --git a/spec/mspec/spec/runner/formatters/yaml_spec.rb b/spec/mspec/spec/runner/formatters/yaml_spec.rb
index eb4d99f74c..2e334fdbb9 100644
--- a/spec/mspec/spec/runner/formatters/yaml_spec.rb
+++ b/spec/mspec/spec/runner/formatters/yaml_spec.rb
@@ -1,8 +1,9 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'mspec/runner/formatters/yaml'
require 'mspec/runner/example'
+require 'mspec/helpers'
-describe YamlFormatter, "#initialize" do
+RSpec.describe YamlFormatter, "#initialize" do
it "permits zero arguments" do
YamlFormatter.new
end
@@ -12,11 +13,11 @@ describe YamlFormatter, "#initialize" do
end
end
-describe YamlFormatter, "#print" do
+RSpec.describe YamlFormatter, "#print" do
before :each do
$stdout = IOStub.new
@out = IOStub.new
- File.stub(:open).and_return(@out)
+ allow(File).to receive(:open).and_return(@out)
@formatter = YamlFormatter.new "some/file"
end
@@ -26,100 +27,108 @@ describe YamlFormatter, "#print" do
it "writes to $stdout if #switch has not been called" do
@formatter.print "begonias"
- $stdout.should == "begonias"
- @out.should == ""
+ expect($stdout).to eq("begonias")
+ expect(@out).to eq("")
end
it "writes to the file passed to #initialize once #switch has been called" do
@formatter.switch
@formatter.print "begonias"
- $stdout.should == ""
- @out.should == "begonias"
+ expect($stdout).to eq("")
+ expect(@out).to eq("begonias")
end
it "writes to $stdout once #switch is called if no file was passed to #initialize" do
formatter = YamlFormatter.new
formatter.switch
formatter.print "begonias"
- $stdout.should == "begonias"
- @out.should == ""
+ expect($stdout).to eq("begonias")
+ expect(@out).to eq("")
end
end
-describe YamlFormatter, "#finish" do
+RSpec.describe YamlFormatter, "#finish" do
before :each do
@tally = double("tally").as_null_object
@counter = double("counter").as_null_object
- @tally.stub(:counter).and_return(@counter)
- TallyAction.stub(:new).and_return(@tally)
+ allow(@tally).to receive(:counter).and_return(@counter)
+ allow(TallyAction).to receive(:new).and_return(@tally)
@timer = double("timer").as_null_object
- TimerAction.stub(:new).and_return(@timer)
+ allow(TimerAction).to receive(:new).and_return(@timer)
+
+ @out = tmp("YamlFormatter")
- $stdout = IOStub.new
context = ContextState.new "describe"
@state = ExampleState.new(context, "it")
- @formatter = YamlFormatter.new
- @formatter.stub(:backtrace).and_return("")
- MSpec.stub(:register)
+ @formatter = YamlFormatter.new(@out)
+ allow(@formatter).to receive(:backtrace).and_return("")
+ allow(MSpec).to receive(:register)
@formatter.register
exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
- exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method")
+ allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method")
@formatter.exception exc
@formatter.after @state
end
after :each do
- $stdout = STDOUT
+ rm_r @out
end
it "calls #switch" do
- @formatter.should_receive(:switch)
+ expect(@formatter).to receive(:switch).and_call_original
@formatter.finish
end
it "outputs a failure message and backtrace" do
@formatter.finish
- $stdout.should include "describe it ERROR"
- $stdout.should include "MSpecExampleError: broken\\n"
- $stdout.should include "path/to/some/file.rb:35:in method"
+ output = File.read(@out)
+ expect(output).to include "describe it ERROR"
+ expect(output).to include "MSpecExampleError: broken\\n"
+ expect(output).to include "path/to/some/file.rb:35:in method"
end
it "outputs an elapsed time" do
- @timer.should_receive(:elapsed).and_return(4.2)
+ expect(@timer).to receive(:elapsed).and_return(4.2)
@formatter.finish
- $stdout.should include "time: 4.2"
+ output = File.read(@out)
+ expect(output).to include "time: 4.2"
end
it "outputs a file count" do
- @counter.should_receive(:files).and_return(3)
+ expect(@counter).to receive(:files).and_return(3)
@formatter.finish
- $stdout.should include "files: 3"
+ output = File.read(@out)
+ expect(output).to include "files: 3"
end
it "outputs an example count" do
- @counter.should_receive(:examples).and_return(3)
+ expect(@counter).to receive(:examples).and_return(3)
@formatter.finish
- $stdout.should include "examples: 3"
+ output = File.read(@out)
+ expect(output).to include "examples: 3"
end
it "outputs an expectation count" do
- @counter.should_receive(:expectations).and_return(9)
+ expect(@counter).to receive(:expectations).and_return(9)
@formatter.finish
- $stdout.should include "expectations: 9"
+ output = File.read(@out)
+ expect(output).to include "expectations: 9"
end
it "outputs a failure count" do
- @counter.should_receive(:failures).and_return(2)
+ expect(@counter).to receive(:failures).and_return(2)
@formatter.finish
- $stdout.should include "failures: 2"
+ output = File.read(@out)
+ expect(output).to include "failures: 2"
end
it "outputs an error count" do
- @counter.should_receive(:errors).and_return(1)
+ expect(@counter).to receive(:errors).and_return(1)
@formatter.finish
- $stdout.should include "errors: 1"
+ output = File.read(@out)
+ expect(output).to include "errors: 1"
end
end
diff --git a/spec/mspec/spec/runner/mspec_spec.rb b/spec/mspec/spec/runner/mspec_spec.rb
index 91338c6ddb..4af01806c0 100644
--- a/spec/mspec/spec/runner/mspec_spec.rb
+++ b/spec/mspec/spec/runner/mspec_spec.rb
@@ -1,97 +1,98 @@
require 'spec_helper'
+require 'mspec/expectations/expectations'
require 'mspec/helpers/tmp'
require 'mspec/helpers/fs'
require 'mspec/matchers/base'
require 'mspec/runner/mspec'
require 'mspec/runner/example'
-describe MSpec, ".register_files" do
+RSpec.describe MSpec, ".register_files" do
it "records which spec files to run" do
MSpec.register_files [:one, :two, :three]
- MSpec.retrieve(:files).should == [:one, :two, :three]
+ expect(MSpec.files_array).to eq([:one, :two, :three])
end
end
-describe MSpec, ".register_mode" do
+RSpec.describe MSpec, ".register_mode" do
before :each do
MSpec.clear_modes
end
it "sets execution mode flags" do
MSpec.register_mode :verify
- MSpec.retrieve(:modes).should == [:verify]
+ expect(MSpec.retrieve(:modes)).to eq([:verify])
end
end
-describe MSpec, ".register_tags_patterns" do
+RSpec.describe MSpec, ".register_tags_patterns" do
it "records the patterns for generating a tag file from a spec file" do
MSpec.register_tags_patterns [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]]
- MSpec.retrieve(:tags_patterns).should == [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]]
+ expect(MSpec.retrieve(:tags_patterns)).to eq([[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]])
end
end
-describe MSpec, ".register_exit" do
+RSpec.describe MSpec, ".register_exit" do
before :each do
MSpec.store :exit, 0
end
it "records the exit code" do
- MSpec.exit_code.should == 0
+ expect(MSpec.exit_code).to eq(0)
MSpec.register_exit 1
- MSpec.exit_code.should == 1
+ expect(MSpec.exit_code).to eq(1)
end
end
-describe MSpec, ".exit_code" do
+RSpec.describe MSpec, ".exit_code" do
it "retrieves the code set with .register_exit" do
MSpec.register_exit 99
- MSpec.exit_code.should == 99
+ expect(MSpec.exit_code).to eq(99)
end
end
-describe MSpec, ".store" do
+RSpec.describe MSpec, ".store" do
it "records data for MSpec settings" do
MSpec.store :anything, :value
- MSpec.retrieve(:anything).should == :value
+ expect(MSpec.retrieve(:anything)).to eq(:value)
end
end
-describe MSpec, ".retrieve" do
+RSpec.describe MSpec, ".retrieve" do
it "accesses .store'd data" do
MSpec.register :retrieve, :first
- MSpec.retrieve(:retrieve).should == [:first]
+ expect(MSpec.retrieve(:retrieve)).to eq([:first])
end
end
-describe MSpec, ".randomize" do
+RSpec.describe MSpec, ".randomize" do
it "sets the flag to randomize spec execution order" do
- MSpec.randomize?.should == false
- MSpec.randomize
- MSpec.randomize?.should == true
- MSpec.randomize false
- MSpec.randomize?.should == false
+ expect(MSpec.randomize?).to eq(false)
+ MSpec.randomize = true
+ expect(MSpec.randomize?).to eq(true)
+ MSpec.randomize = false
+ expect(MSpec.randomize?).to eq(false)
end
end
-describe MSpec, ".register" do
+RSpec.describe MSpec, ".register" do
it "is the gateway behind the register(symbol, action) facility" do
MSpec.register :bonus, :first
MSpec.register :bonus, :second
MSpec.register :bonus, :second
- MSpec.retrieve(:bonus).should == [:first, :second]
+ expect(MSpec.retrieve(:bonus)).to eq([:first, :second])
end
end
-describe MSpec, ".unregister" do
+RSpec.describe MSpec, ".unregister" do
it "is the gateway behind the unregister(symbol, actions) facility" do
MSpec.register :unregister, :first
MSpec.register :unregister, :second
MSpec.unregister :unregister, :second
- MSpec.retrieve(:unregister).should == [:first]
+ expect(MSpec.retrieve(:unregister)).to eq([:first])
end
end
-describe MSpec, ".protect" do
+RSpec.describe MSpec, ".protect" do
before :each do
MSpec.clear_current
@cs = ContextState.new "C#m"
@@ -102,11 +103,11 @@ describe MSpec, ".protect" do
end
it "returns true if no exception is raised" do
- MSpec.protect("passed") { 1 }.should be_true
+ expect(MSpec.protect("passed") { 1 }).to be_truthy
end
it "returns false if an exception is raised" do
- MSpec.protect("testing") { raise ScratchPad.recorded }.should be_false
+ expect(MSpec.protect("testing") { raise ScratchPad.recorded }).to be_falsey
end
it "rescues any exceptions raised when evaluating the block argument" do
@@ -119,244 +120,245 @@ describe MSpec, ".protect" do
rescue SystemExit
ScratchPad.record :system_exit
end
- ScratchPad.recorded.should == :system_exit
+ expect(ScratchPad.recorded).to eq(:system_exit)
end
it "calls all the exception actions" do
exc = ExceptionState.new @es, "testing", ScratchPad.recorded
- ExceptionState.stub(:new).and_return(exc)
+ allow(ExceptionState).to receive(:new).and_return(exc)
action = double("exception")
- action.should_receive(:exception).with(exc)
+ expect(action).to receive(:exception).with(exc)
MSpec.register :exception, action
MSpec.protect("testing") { raise ScratchPad.recorded }
MSpec.unregister :exception, action
end
it "registers a non-zero exit code when an exception is raised" do
- MSpec.should_receive(:register_exit).with(1)
+ expect(MSpec).to receive(:register_exit).with(1)
MSpec.protect("testing") { raise ScratchPad.recorded }
end
end
-describe MSpec, ".register_current" do
+RSpec.describe MSpec, ".register_current" do
before :each do
MSpec.clear_current
end
it "sets the value returned by MSpec.current" do
- MSpec.current.should be_nil
+ expect(MSpec.current).to be_nil
MSpec.register_current :a
- MSpec.current.should == :a
+ expect(MSpec.current).to eq(:a)
end
end
-describe MSpec, ".clear_current" do
+RSpec.describe MSpec, ".clear_current" do
it "sets the value returned by MSpec.current to nil" do
MSpec.register_current :a
- MSpec.current.should_not be_nil
+ expect(MSpec.current).not_to be_nil
MSpec.clear_current
- MSpec.current.should be_nil
+ expect(MSpec.current).to be_nil
end
end
-describe MSpec, ".current" do
+RSpec.describe MSpec, ".current" do
before :each do
MSpec.clear_current
end
it "returns nil if no ContextState has been registered" do
- MSpec.current.should be_nil
+ expect(MSpec.current).to be_nil
end
it "returns the most recently registered ContextState" do
first = ContextState.new ""
second = ContextState.new ""
MSpec.register_current first
- MSpec.current.should == first
+ expect(MSpec.current).to eq(first)
MSpec.register_current second
- MSpec.current.should == second
+ expect(MSpec.current).to eq(second)
end
end
-describe MSpec, ".actions" do
+RSpec.describe MSpec, ".actions" do
before :each do
MSpec.store :start, []
ScratchPad.record []
start_one = double("one")
- start_one.stub(:start).and_return { ScratchPad << :one }
+ allow(start_one).to receive(:start) { ScratchPad << :one }
start_two = double("two")
- start_two.stub(:start).and_return { ScratchPad << :two }
+ allow(start_two).to receive(:start) { ScratchPad << :two }
MSpec.register :start, start_one
MSpec.register :start, start_two
end
it "does not attempt to run any actions if none have been registered" do
MSpec.store :finish, nil
- lambda { MSpec.actions :finish }.should_not raise_error
+ expect { MSpec.actions :finish }.not_to raise_error
end
it "runs each action registered as a start action" do
MSpec.actions :start
- ScratchPad.recorded.should == [:one, :two]
+ expect(ScratchPad.recorded).to eq([:one, :two])
end
end
-describe MSpec, ".mode?" do
+RSpec.describe MSpec, ".mode?" do
before :each do
MSpec.clear_modes
end
it "returns true if the mode has been set" do
- MSpec.mode?(:verify).should == false
+ expect(MSpec.mode?(:verify)).to eq(false)
MSpec.register_mode :verify
- MSpec.mode?(:verify).should == true
+ expect(MSpec.mode?(:verify)).to eq(true)
end
end
-describe MSpec, ".clear_modes" do
+RSpec.describe MSpec, ".clear_modes" do
it "clears all registered modes" do
MSpec.register_mode(:pretend)
MSpec.register_mode(:verify)
- MSpec.mode?(:pretend).should == true
- MSpec.mode?(:verify).should == true
+ expect(MSpec.mode?(:pretend)).to eq(true)
+ expect(MSpec.mode?(:verify)).to eq(true)
MSpec.clear_modes
- MSpec.mode?(:pretend).should == false
- MSpec.mode?(:verify).should == false
+ expect(MSpec.mode?(:pretend)).to eq(false)
+ expect(MSpec.mode?(:verify)).to eq(false)
end
end
-describe MSpec, ".guarded?" do
+RSpec.describe MSpec, ".guarded?" do
before :each do
MSpec.instance_variable_set :@guarded, []
end
it "returns false if no guard has run" do
- MSpec.guarded?.should == false
+ expect(MSpec.guarded?).to eq(false)
end
it "returns true if a single guard has run" do
MSpec.guard
- MSpec.guarded?.should == true
+ expect(MSpec.guarded?).to eq(true)
end
it "returns true if more than one guard has run" do
MSpec.guard
MSpec.guard
- MSpec.guarded?.should == true
+ expect(MSpec.guarded?).to eq(true)
end
it "returns true until all guards have finished" do
MSpec.guard
MSpec.guard
- MSpec.guarded?.should == true
+ expect(MSpec.guarded?).to eq(true)
MSpec.unguard
- MSpec.guarded?.should == true
+ expect(MSpec.guarded?).to eq(true)
MSpec.unguard
- MSpec.guarded?.should == false
+ expect(MSpec.guarded?).to eq(false)
end
end
-describe MSpec, ".describe" do
+RSpec.describe MSpec, ".describe" do
before :each do
MSpec.clear_current
@cs = ContextState.new ""
- ContextState.stub(:new).and_return(@cs)
- MSpec.stub(:current).and_return(nil)
- MSpec.stub(:register_current)
+ allow(ContextState).to receive(:new).and_return(@cs)
+ allow(MSpec).to receive(:current).and_return(nil)
+ allow(MSpec).to receive(:register_current)
end
it "creates a new ContextState for the block" do
- ContextState.should_receive(:new).and_return(@cs)
+ expect(ContextState).to receive(:new).and_return(@cs)
MSpec.describe(Object) { }
end
it "accepts an optional second argument" do
- ContextState.should_receive(:new).and_return(@cs)
+ expect(ContextState).to receive(:new).and_return(@cs)
MSpec.describe(Object, "msg") { }
end
it "registers the newly created ContextState" do
- MSpec.should_receive(:register_current).with(@cs).twice
+ expect(MSpec).to receive(:register_current).with(@cs).twice
MSpec.describe(Object) { }
end
it "invokes the ContextState#describe method" do
- prc = lambda { }
- @cs.should_receive(:describe).with(&prc)
- MSpec.describe(Object, "msg", &prc)
+ expect(@cs).to receive(:describe)
+ MSpec.describe(Object, "msg") {}
end
end
-describe MSpec, ".process" do
+RSpec.describe MSpec, ".process" do
before :each do
- MSpec.stub(:files)
+ allow(MSpec).to receive(:files)
MSpec.store :start, []
MSpec.store :finish, []
- STDOUT.stub(:puts)
+ allow(STDOUT).to receive(:puts)
end
it "prints the RUBY_DESCRIPTION" do
- STDOUT.should_receive(:puts).with(RUBY_DESCRIPTION)
+ expect(STDOUT).to receive(:puts).with(RUBY_DESCRIPTION)
MSpec.process
end
it "calls all start actions" do
start = double("start")
- start.stub(:start).and_return { ScratchPad.record :start }
+ allow(start).to receive(:start) { ScratchPad.record :start }
MSpec.register :start, start
MSpec.process
- ScratchPad.recorded.should == :start
+ expect(ScratchPad.recorded).to eq(:start)
end
it "calls all finish actions" do
finish = double("finish")
- finish.stub(:finish).and_return { ScratchPad.record :finish }
+ allow(finish).to receive(:finish) { ScratchPad.record :finish }
MSpec.register :finish, finish
MSpec.process
- ScratchPad.recorded.should == :finish
+ expect(ScratchPad.recorded).to eq(:finish)
end
it "calls the files method" do
- MSpec.should_receive(:files)
+ expect(MSpec).to receive(:files)
MSpec.process
end
end
-describe MSpec, ".files" do
+RSpec.describe MSpec, ".files" do
before :each do
MSpec.store :load, []
MSpec.store :unload, []
MSpec.register_files [:one, :two, :three]
- Kernel.stub(:load)
+ allow(Kernel).to receive(:load)
end
it "calls load actions before each file" do
load = double("load")
- load.stub(:load).and_return { ScratchPad.record :load }
+ allow(load).to receive(:load) { ScratchPad.record :load }
MSpec.register :load, load
MSpec.files
- ScratchPad.recorded.should == :load
+ expect(ScratchPad.recorded).to eq(:load)
end
it "shuffles the file list if .randomize? is true" do
- MSpec.randomize
- MSpec.should_receive(:shuffle)
+ MSpec.randomize = true
+ expect(MSpec).to receive(:shuffle)
MSpec.files
- MSpec.randomize false
+ MSpec.randomize = false
end
it "registers the current file" do
- MSpec.should_receive(:store).with(:file, :one)
- MSpec.should_receive(:store).with(:file, :two)
- MSpec.should_receive(:store).with(:file, :three)
+ load = double("load")
+ files = []
+ allow(load).to receive(:load) { files << MSpec.file }
+ MSpec.register :load, load
MSpec.files
+ expect(files).to eq([:one, :two, :three])
end
end
-describe MSpec, ".shuffle" do
+RSpec.describe MSpec, ".shuffle" do
before :each do
@base = (0..100).to_a
@list = @base.clone
@@ -365,30 +367,30 @@ describe MSpec, ".shuffle" do
it "does not alter the elements in the list" do
@base.each do |elt|
- @list.should include(elt)
+ expect(@list).to include(elt)
end
end
it "changes the order of the list" do
# obviously, this spec has a certain probability
# of failing. If it fails, run it again.
- @list.should_not == @base
+ expect(@list).not_to eq(@base)
end
end
-describe MSpec, ".tags_file" do
+RSpec.describe MSpec, ".tags_file" do
before :each do
MSpec.store :file, "path/to/spec/something/some_spec.rb"
MSpec.store :tags_patterns, nil
end
it "returns the default tags file for the current spec file" do
- MSpec.tags_file.should == "path/to/spec/tags/something/some_tags.txt"
+ expect(MSpec.tags_file).to eq("path/to/spec/tags/something/some_tags.txt")
end
it "returns the tags file for the current spec file with custom tags_patterns" do
MSpec.register_tags_patterns [[/^(.*)\/spec/, '\1/tags'], [/_spec.rb/, "_tags.txt"]]
- MSpec.tags_file.should == "path/to/tags/something/some_tags.txt"
+ expect(MSpec.tags_file).to eq("path/to/tags/something/some_tags.txt")
end
it "performs multiple substitutions" do
@@ -397,31 +399,31 @@ describe MSpec, ".tags_file" do
[%r(/spec/), "/spec/tags/"],
[/_spec.rb/, "_tags.txt"]
]
- MSpec.tags_file.should == "path/to/spec/tags/other/some_tags.txt"
+ expect(MSpec.tags_file).to eq("path/to/spec/tags/other/some_tags.txt")
end
it "handles cases where no substitution is performed" do
MSpec.register_tags_patterns [[/nothing/, "something"]]
- MSpec.tags_file.should == "path/to/spec/something/some_spec.rb"
+ expect(MSpec.tags_file).to eq("path/to/spec/something/some_spec.rb")
end
end
-describe MSpec, ".read_tags" do
+RSpec.describe MSpec, ".read_tags" do
before :each do
- MSpec.stub(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt')
+ allow(MSpec).to receive(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt')
end
it "returns a list of tag instances for matching tag names found" do
one = SpecTag.new "fail(broken):Some#method? works"
- MSpec.read_tags(["fail", "pass"]).should == [one]
+ expect(MSpec.read_tags(["fail", "pass"])).to eq([one])
end
it "returns [] if no tags names match" do
- MSpec.read_tags("super").should == []
+ expect(MSpec.read_tags("super")).to eq([])
end
end
-describe MSpec, ".read_tags" do
+RSpec.describe MSpec, ".read_tags" do
before :each do
@tag = SpecTag.new "fails:Some#method"
File.open(tmp("tags.txt", false), "w") do |f|
@@ -429,18 +431,18 @@ describe MSpec, ".read_tags" do
f.puts @tag
f.puts ""
end
- MSpec.stub(:tags_file).and_return(tmp("tags.txt", false))
+ allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false))
end
it "does not return a tag object for empty lines" do
- MSpec.read_tags(["fails"]).should == [@tag]
+ expect(MSpec.read_tags(["fails"])).to eq([@tag])
end
end
-describe MSpec, ".write_tags" do
+RSpec.describe MSpec, ".write_tags" do
before :each do
FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false)
- MSpec.stub(:tags_file).and_return(tmp("tags.txt", false))
+ allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false))
@tag1 = SpecTag.new "check(broken):Tag#rewrite works"
@tag2 = SpecTag.new "broken:Tag#write_tags fails"
end
@@ -450,22 +452,22 @@ describe MSpec, ".write_tags" do
end
it "overwrites the tags in the tag file" do
- IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works
+ expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works
incomplete(20%):The#best method ever
benchmark(0.01825):The#fastest method today
extended():\"Multi-line\\ntext\\ntag\"
-]
+])
MSpec.write_tags [@tag1, @tag2]
- IO.read(tmp("tags.txt", false)).should == %[check(broken):Tag#rewrite works
+ expect(IO.read(tmp("tags.txt", false))).to eq(%[check(broken):Tag#rewrite works
broken:Tag#write_tags fails
-]
+])
end
end
-describe MSpec, ".write_tag" do
+RSpec.describe MSpec, ".write_tag" do
before :each do
- FileUtils.stub(:mkdir_p)
- MSpec.stub(:tags_file).and_return(tmp("tags.txt", false))
+ allow(FileUtils).to receive(:mkdir_p)
+ allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false))
@tag = SpecTag.new "fail(broken):Some#method works"
end
@@ -475,20 +477,20 @@ describe MSpec, ".write_tag" do
it "writes a tag to the tags file for the current spec file" do
MSpec.write_tag @tag
- IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n"
+ expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n")
end
it "does not write a duplicate tag" do
File.open(tmp("tags.txt", false), "w") { |f| f.puts @tag }
MSpec.write_tag @tag
- IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n"
+ expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n")
end
end
-describe MSpec, ".delete_tag" do
+RSpec.describe MSpec, ".delete_tag" do
before :each do
FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false)
- MSpec.stub(:tags_file).and_return(tmp("tags.txt", false))
+ allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false))
@tag = SpecTag.new "fail(Comments don't matter):Some#method? works"
end
@@ -497,84 +499,84 @@ describe MSpec, ".delete_tag" do
end
it "deletes the tag if it exists" do
- MSpec.delete_tag(@tag).should == true
- IO.read(tmp("tags.txt", false)).should == %[incomplete(20%):The#best method ever
+ expect(MSpec.delete_tag(@tag)).to eq(true)
+ expect(IO.read(tmp("tags.txt", false))).to eq(%[incomplete(20%):The#best method ever
benchmark(0.01825):The#fastest method today
extended():\"Multi-line\\ntext\\ntag\"
-]
+])
end
it "deletes a tag with escaped newlines" do
- MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true
- IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works
+ expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true)
+ expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works
incomplete(20%):The#best method ever
benchmark(0.01825):The#fastest method today
-]
+])
end
it "does not change the tags file contents if the tag doesn't exist" do
@tag.tag = "failed"
- MSpec.delete_tag(@tag).should == false
- IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works
+ expect(MSpec.delete_tag(@tag)).to eq(false)
+ expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works
incomplete(20%):The#best method ever
benchmark(0.01825):The#fastest method today
extended():\"Multi-line\\ntext\\ntag\"
-]
+])
end
it "deletes the tag file if it is empty" do
- MSpec.delete_tag(@tag).should == true
- MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever")).should == true
- MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today")).should == true
- MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true
- File.exist?(tmp("tags.txt", false)).should == false
+ expect(MSpec.delete_tag(@tag)).to eq(true)
+ expect(MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever"))).to eq(true)
+ expect(MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today"))).to eq(true)
+ expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true)
+ expect(File.exist?(tmp("tags.txt", false))).to eq(false)
end
end
-describe MSpec, ".delete_tags" do
+RSpec.describe MSpec, ".delete_tags" do
before :each do
@tags = tmp("tags.txt", false)
FileUtils.cp File.dirname(__FILE__) + "/tags.txt", @tags
- MSpec.stub(:tags_file).and_return(@tags)
+ allow(MSpec).to receive(:tags_file).and_return(@tags)
end
it "deletes the tag file" do
MSpec.delete_tags
- File.exist?(@tags).should be_false
+ expect(File.exist?(@tags)).to be_falsey
end
end
-describe MSpec, ".expectation" do
+RSpec.describe MSpec, ".expectation" do
it "sets the flag that an expectation has been reported" do
MSpec.clear_expectations
- MSpec.expectation?.should be_false
+ expect(MSpec.expectation?).to be_falsey
MSpec.expectation
- MSpec.expectation?.should be_true
+ expect(MSpec.expectation?).to be_truthy
end
end
-describe MSpec, ".expectation?" do
+RSpec.describe MSpec, ".expectation?" do
it "returns true if an expectation has been reported" do
MSpec.expectation
- MSpec.expectation?.should be_true
+ expect(MSpec.expectation?).to be_truthy
end
it "returns false if an expectation has not been reported" do
MSpec.clear_expectations
- MSpec.expectation?.should be_false
+ expect(MSpec.expectation?).to be_falsey
end
end
-describe MSpec, ".clear_expectations" do
+RSpec.describe MSpec, ".clear_expectations" do
it "clears the flag that an expectation has been reported" do
MSpec.expectation
- MSpec.expectation?.should be_true
+ expect(MSpec.expectation?).to be_truthy
MSpec.clear_expectations
- MSpec.expectation?.should be_false
+ expect(MSpec.expectation?).to be_falsey
end
end
-describe MSpec, ".register_shared" do
+RSpec.describe MSpec, ".register_shared" do
it "stores a shared ContextState by description" do
parent = ContextState.new "container"
state = ContextState.new "shared"
@@ -582,14 +584,14 @@ describe MSpec, ".register_shared" do
prc = lambda { }
state.describe(&prc)
MSpec.register_shared(state)
- MSpec.retrieve(:shared)["shared"].should == state
+ expect(MSpec.retrieve(:shared)["shared"]).to eq(state)
end
end
-describe MSpec, ".retrieve_shared" do
+RSpec.describe MSpec, ".retrieve_shared" do
it "retrieves the shared ContextState matching description" do
state = ContextState.new ""
MSpec.retrieve(:shared)["shared"] = state
- MSpec.retrieve_shared(:shared).should == state
+ expect(MSpec.retrieve_shared(:shared)).to eq(state)
end
end
diff --git a/spec/mspec/spec/runner/shared_spec.rb b/spec/mspec/spec/runner/shared_spec.rb
index b91800b7db..153b8f0698 100644
--- a/spec/mspec/spec/runner/shared_spec.rb
+++ b/spec/mspec/spec/runner/shared_spec.rb
@@ -3,7 +3,7 @@ require 'mspec/runner/shared'
require 'mspec/runner/context'
require 'mspec/runner/example'
-describe Object, "#it_behaves_like" do
+RSpec.describe Object, "#it_behaves_like" do
before :each do
ScratchPad.clear
@@ -14,14 +14,14 @@ describe Object, "#it_behaves_like" do
@state.singleton_class.send(:public, :it_behaves_like)
@shared = ContextState.new :shared_spec, :shared => true
- MSpec.stub(:retrieve_shared).and_return(@shared)
+ allow(MSpec).to receive(:retrieve_shared).and_return(@shared)
end
it "creates @method set to the name of the aliased method" do
@shared.it("an example") { ScratchPad.record @method }
@state.it_behaves_like :shared_spec, :some_method
@state.process
- ScratchPad.recorded.should == :some_method
+ expect(ScratchPad.recorded).to eq(:some_method)
end
it "creates @object if the passed object" do
@@ -29,7 +29,7 @@ describe Object, "#it_behaves_like" do
@shared.it("an example") { ScratchPad.record @object }
@state.it_behaves_like :shared_spec, :some_method, object
@state.process
- ScratchPad.recorded.should == object
+ expect(ScratchPad.recorded).to eq(object)
end
it "creates @object if the passed false" do
@@ -37,11 +37,11 @@ describe Object, "#it_behaves_like" do
@shared.it("an example") { ScratchPad.record @object }
@state.it_behaves_like :shared_spec, :some_method, object
@state.process
- ScratchPad.recorded.should == object
+ expect(ScratchPad.recorded).to eq(object)
end
it "sends :it_should_behave_like" do
- @state.should_receive(:it_should_behave_like)
+ expect(@state).to receive(:it_should_behave_like)
@state.it_behaves_like :shared_spec, :some_method
end
@@ -61,12 +61,12 @@ describe Object, "#it_behaves_like" do
@state.it_behaves_like :shared_spec, :some_method, @obj
@state.process
- ScratchPad.recorded.should == [:some_method, @obj]
+ expect(ScratchPad.recorded).to eq([:some_method, @obj])
@state2.it_behaves_like :shared_spec, :another_method, @obj2
@state2.process
- ScratchPad.recorded.should == [:another_method, @obj2]
+ expect(ScratchPad.recorded).to eq([:another_method, @obj2])
end
it "ensures the shared spec state is distinct for nested shared specs" do
@@ -79,12 +79,12 @@ describe Object, "#it_behaves_like" do
@state.it_behaves_like :shared_spec, :some_method, @obj
@state.process
- ScratchPad.recorded.should == [:shared, :some_method, @obj]
+ expect(ScratchPad.recorded).to eq([:shared, :some_method, @obj])
@state2.it_behaves_like :shared_spec, :another_method, @obj2
@state2.process
- ScratchPad.recorded.should == [:shared, :another_method, @obj2]
+ expect(ScratchPad.recorded).to eq([:shared, :another_method, @obj2])
end
end
end
diff --git a/spec/mspec/spec/runner/tag_spec.rb b/spec/mspec/spec/runner/tag_spec.rb
index db55a1b186..bda9ac4280 100644
--- a/spec/mspec/spec/runner/tag_spec.rb
+++ b/spec/mspec/spec/runner/tag_spec.rb
@@ -1,123 +1,123 @@
require 'spec_helper'
require 'mspec/runner/tag'
-describe SpecTag do
+RSpec.describe SpecTag do
it "accepts an optional string to parse into fields" do
tag = SpecTag.new "tag(comment):description"
- tag.tag.should == "tag"
- tag.comment.should == "comment"
- tag.description.should == "description"
+ expect(tag.tag).to eq("tag")
+ expect(tag.comment).to eq("comment")
+ expect(tag.description).to eq("description")
end
end
-describe SpecTag, "#parse" do
+RSpec.describe SpecTag, "#parse" do
before :each do
@tag = SpecTag.new
end
it "accepts 'tag(comment):description'" do
@tag.parse "tag(I'm real):Some#method returns a value"
- @tag.tag.should == "tag"
- @tag.comment.should == "I'm real"
- @tag.description.should == "Some#method returns a value"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq("I'm real")
+ expect(@tag.description).to eq("Some#method returns a value")
end
it "accepts 'tag:description'" do
@tag.parse "tag:Another#method"
- @tag.tag.should == "tag"
- @tag.comment.should == nil
- @tag.description.should == "Another#method"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq(nil)
+ expect(@tag.description).to eq("Another#method")
end
it "accepts 'tag():description'" do
@tag.parse "tag():Another#method"
- @tag.tag.should == "tag"
- @tag.comment.should == nil
- @tag.description.should == "Another#method"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq(nil)
+ expect(@tag.description).to eq("Another#method")
end
it "accepts 'tag:'" do
@tag.parse "tag:"
- @tag.tag.should == "tag"
- @tag.comment.should == nil
- @tag.description.should == ""
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq(nil)
+ expect(@tag.description).to eq("")
end
it "accepts 'tag(bug:555):Another#method'" do
@tag.parse "tag(bug:555):Another#method"
- @tag.tag.should == "tag"
- @tag.comment.should == "bug:555"
- @tag.description.should == "Another#method"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq("bug:555")
+ expect(@tag.description).to eq("Another#method")
end
it "accepts 'tag(http://someplace.com/neato):Another#method'" do
@tag.parse "tag(http://someplace.com/neato):Another#method"
- @tag.tag.should == "tag"
- @tag.comment.should == "http://someplace.com/neato"
- @tag.description.should == "Another#method"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq("http://someplace.com/neato")
+ expect(@tag.description).to eq("Another#method")
end
it "accepts 'tag(comment):\"Multi-line\\ntext\"'" do
@tag.parse 'tag(comment):"Multi-line\ntext"'
- @tag.tag.should == "tag"
- @tag.comment.should == "comment"
- @tag.description.should == "Multi-line\ntext"
+ expect(@tag.tag).to eq("tag")
+ expect(@tag.comment).to eq("comment")
+ expect(@tag.description).to eq("Multi-line\ntext")
end
it "ignores '#anything'" do
@tag.parse "# this could be a comment"
- @tag.tag.should == nil
- @tag.comment.should == nil
- @tag.description.should == nil
+ expect(@tag.tag).to eq(nil)
+ expect(@tag.comment).to eq(nil)
+ expect(@tag.description).to eq(nil)
end
end
-describe SpecTag, "#to_s" do
+RSpec.describe SpecTag, "#to_s" do
it "formats itself as 'tag(comment):description'" do
txt = "tag(comment):description"
tag = SpecTag.new txt
- tag.tag.should == "tag"
- tag.comment.should == "comment"
- tag.description.should == "description"
- tag.to_s.should == txt
+ expect(tag.tag).to eq("tag")
+ expect(tag.comment).to eq("comment")
+ expect(tag.description).to eq("description")
+ expect(tag.to_s).to eq(txt)
end
it "formats itself as 'tag:description" do
txt = "tag:description"
tag = SpecTag.new txt
- tag.tag.should == "tag"
- tag.comment.should == nil
- tag.description.should == "description"
- tag.to_s.should == txt
+ expect(tag.tag).to eq("tag")
+ expect(tag.comment).to eq(nil)
+ expect(tag.description).to eq("description")
+ expect(tag.to_s).to eq(txt)
end
it "formats itself as 'tag(comment):\"multi-line\\ntext\\ntag\"'" do
txt = 'tag(comment):"multi-line\ntext\ntag"'
tag = SpecTag.new txt
- tag.tag.should == "tag"
- tag.comment.should == "comment"
- tag.description.should == "multi-line\ntext\ntag"
- tag.to_s.should == txt
+ expect(tag.tag).to eq("tag")
+ expect(tag.comment).to eq("comment")
+ expect(tag.description).to eq("multi-line\ntext\ntag")
+ expect(tag.to_s).to eq(txt)
end
end
-describe SpecTag, "#==" do
+RSpec.describe SpecTag, "#==" do
it "returns true if the tags have the same fields" do
one = SpecTag.new "tag(this):unicorn"
two = SpecTag.new "tag(this):unicorn"
- one.==(two).should == true
- [one].==([two]).should == true
+ expect(one.==(two)).to eq(true)
+ expect([one].==([two])).to eq(true)
end
end
-describe SpecTag, "#unescape" do
+RSpec.describe SpecTag, "#unescape" do
it "replaces \\n by LF when the description is quoted" do
tag = SpecTag.new 'tag:"desc with\nnew line"'
- tag.description.should == "desc with\nnew line"
+ expect(tag.description).to eq("desc with\nnew line")
end
it "does not replaces \\n by LF when the description is not quoted " do
tag = SpecTag.new 'tag:desc with\nnew line'
- tag.description.should == "desc with\\nnew line"
+ expect(tag.description).to eq("desc with\\nnew line")
end
end
diff --git a/spec/mspec/spec/spec_helper.rb b/spec/mspec/spec/spec_helper.rb
index 0d497f6627..5cabfe5626 100644
--- a/spec/mspec/spec/spec_helper.rb
+++ b/spec/mspec/spec/spec_helper.rb
@@ -1,6 +1,9 @@
-require 'pp'
-require 'mspec/helpers/io'
-require 'mspec/helpers/scratch'
+RSpec.configure do |config|
+ config.disable_monkey_patching!
+ config.raise_errors_for_deprecations!
+end
+
+require 'mspec'
# Remove this when MRI has intelligent warnings
$VERBOSE = nil unless $VERBOSE
@@ -37,7 +40,7 @@ class MSpecExampleError < Exception
end
def hide_deprecation_warnings
- MSpec.stub(:deprecate)
+ allow(MSpec).to receive(:deprecate)
end
def run_mspec(command, args)
@@ -53,3 +56,15 @@ def run_mspec(command, args)
out = out.gsub(cwd, "CWD")
return out, ret
end
+
+def ensure_mspec_method(method)
+ file, _line = method.source_location
+ expect(file).to start_with(File.expand_path('../../lib/mspec', __FILE__ ))
+end
+
+PublicMSpecMatchers = Class.new {
+ include MSpecMatchers
+ public :raise_error
+}.new
+
+BACKTRACE_QUOTE = RUBY_VERSION >= "3.4" ? "'" : "`"
diff --git a/spec/mspec/spec/utils/deprecate_spec.rb b/spec/mspec/spec/utils/deprecate_spec.rb
index 7fa60df26a..73eaf7d04e 100644
--- a/spec/mspec/spec/utils/deprecate_spec.rb
+++ b/spec/mspec/spec/utils/deprecate_spec.rb
@@ -1,17 +1,17 @@
require 'spec_helper'
require 'mspec/utils/deprecate'
-describe MSpec, "#deprecate" do
+RSpec.describe MSpec, "#deprecate" do
it "warns when using a deprecated method" do
warning = nil
- $stderr.stub(:puts) { |str| warning = str }
+ allow($stderr).to receive(:puts) { |str| warning = str }
MSpec.deprecate(:some_method, :other_method)
- warning.should start_with(<<-EOS.chomp)
+ expect(warning).to start_with(<<-EOS.chomp)
some_method is deprecated, use other_method instead.
from
EOS
- warning.should include(__FILE__)
- warning.should include('8')
+ expect(warning).to include(__FILE__)
+ expect(warning).to include('8')
end
end
diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises.rb b/spec/mspec/spec/utils/fixtures/this_file_raises.rb
new file mode 100644
index 0000000000..8e37a587bf
--- /dev/null
+++ b/spec/mspec/spec/utils/fixtures/this_file_raises.rb
@@ -0,0 +1 @@
+raise "This is a BAD file"
diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises2.rb b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb
new file mode 100644
index 0000000000..8efc10199a
--- /dev/null
+++ b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb
@@ -0,0 +1 @@
+raise "This is a BAD file 2"
diff --git a/spec/mspec/spec/utils/name_map_spec.rb b/spec/mspec/spec/utils/name_map_spec.rb
index d5d2cca84a..a42dc9ffec 100644
--- a/spec/mspec/spec/utils/name_map_spec.rb
+++ b/spec/mspec/spec/utils/name_map_spec.rb
@@ -21,50 +21,53 @@ module NameMapSpecs
def f; end
end
+ autoload :BadFile, "#{__dir__}/fixtures/this_file_raises.rb"
+ autoload :BadFile2, "#{__dir__}/fixtures/this_file_raises2.rb"
+
def self.n; end
def n; end
end
-describe NameMap, "#exception?" do
+RSpec.describe NameMap, "#exception?" do
before :each do
@map = NameMap.new
end
it "returns true if the constant is Errno" do
- @map.exception?("Errno").should == true
+ expect(@map.exception?("Errno")).to eq(true)
end
it "returns true if the constant is a kind of Exception" do
- @map.exception?("Errno::EBADF").should == true
- @map.exception?("LoadError").should == true
- @map.exception?("SystemExit").should == true
+ expect(@map.exception?("Errno::EBADF")).to eq(true)
+ expect(@map.exception?("LoadError")).to eq(true)
+ expect(@map.exception?("SystemExit")).to eq(true)
end
it "returns false if the constant is not a kind of Exception" do
- @map.exception?("NameMapSpecs::Error").should == false
- @map.exception?("NameMapSpecs").should == false
+ expect(@map.exception?("NameMapSpecs::Error")).to eq(false)
+ expect(@map.exception?("NameMapSpecs")).to eq(false)
end
it "returns false if the constant does not exist" do
- @map.exception?("Nonexistent").should == false
+ expect(@map.exception?("Nonexistent")).to eq(false)
end
end
-describe NameMap, "#class_or_module" do
+RSpec.describe NameMap, "#class_or_module" do
before :each do
@map = NameMap.new true
end
it "returns the constant specified by the string" do
- @map.class_or_module("NameMapSpecs").should == NameMapSpecs
+ expect(@map.class_or_module("NameMapSpecs")).to eq(NameMapSpecs)
end
it "returns the constant specified by the 'A::B' string" do
- @map.class_or_module("NameMapSpecs::A").should == NameMapSpecs::A
+ expect(@map.class_or_module("NameMapSpecs::A")).to eq(NameMapSpecs::A)
end
it "returns nil if the constant is not a class or module" do
- @map.class_or_module("Float::MAX").should == nil
+ expect(@map.class_or_module("Float::MAX")).to eq(nil)
end
it "returns nil if the constant is in the set of excluded constants" do
@@ -75,101 +78,110 @@ describe NameMap, "#class_or_module" do
]
excluded.each do |const|
- @map.class_or_module(const).should == nil
+ expect(@map.class_or_module(const)).to eq(nil)
end
end
it "returns nil if the constant does not exist" do
- @map.class_or_module("Heaven").should == nil
- @map.class_or_module("Hell").should == nil
- @map.class_or_module("Bush::Brain").should == nil
+ expect(@map.class_or_module("Heaven")).to eq(nil)
+ expect(@map.class_or_module("Hell")).to eq(nil)
+ expect(@map.class_or_module("Bush::Brain")).to eq(nil)
+ end
+
+ it "returns nil if accessing the constant raises RuntimeError" do
+ expect { NameMapSpecs::BadFile }.to raise_error(RuntimeError)
+ expect(@map.class_or_module("NameMapSpecs::BadFile")).to eq(nil)
+ end
+
+ it "returns nil if accessing the constant raises RuntimeError when not triggering the autoload before" do
+ expect(@map.class_or_module("NameMapSpecs::BadFile2")).to eq(nil)
end
end
-describe NameMap, "#dir_name" do
+RSpec.describe NameMap, "#dir_name" do
before :each do
@map = NameMap.new
end
it "returns a directory name from the base name and constant" do
- @map.dir_name("NameMapSpecs", 'spec/core').should == 'spec/core/namemapspecs'
+ expect(@map.dir_name("NameMapSpecs", 'spec/core')).to eq('spec/core/namemapspecs')
end
it "returns a directory name from the components in the constants name" do
- @map.dir_name("NameMapSpecs::A", 'spec').should == 'spec/namemapspecs/a'
- @map.dir_name("NameMapSpecs::A::B", 'spec').should == 'spec/namemapspecs/a/b'
+ expect(@map.dir_name("NameMapSpecs::A", 'spec')).to eq('spec/namemapspecs/a')
+ expect(@map.dir_name("NameMapSpecs::A::B", 'spec')).to eq('spec/namemapspecs/a/b')
end
it "returns a directory name without 'class' for constants like TrueClass" do
- @map.dir_name("TrueClass", 'spec').should == 'spec/true'
- @map.dir_name("FalseClass", 'spec').should == 'spec/false'
+ expect(@map.dir_name("TrueClass", 'spec')).to eq('spec/true')
+ expect(@map.dir_name("FalseClass", 'spec')).to eq('spec/false')
end
it "returns 'exception' for the directory name of any Exception subclass" do
- @map.dir_name("SystemExit", 'spec').should == 'spec/exception'
- @map.dir_name("Errno::EBADF", 'spec').should == 'spec/exception'
+ expect(@map.dir_name("SystemExit", 'spec')).to eq('spec/exception')
+ expect(@map.dir_name("Errno::EBADF", 'spec')).to eq('spec/exception')
end
it "returns 'class' for Class" do
- @map.dir_name("Class", 'spec').should == 'spec/class'
+ expect(@map.dir_name("Class", 'spec')).to eq('spec/class')
end
end
# These specs do not cover all the mappings, but only describe how the
# name is derived when the hash item maps to a single value, a hash with
# a specific item, or a hash with a :default item.
-describe NameMap, "#file_name" do
+RSpec.describe NameMap, "#file_name" do
before :each do
@map = NameMap.new
end
it "returns the name of the spec file based on the constant and method" do
- @map.file_name("[]=", "Array").should == "element_set_spec.rb"
+ expect(@map.file_name("[]=", "Array")).to eq("element_set_spec.rb")
end
it "returns the name of the spec file based on the special entry for the method" do
- @map.file_name("~", "Regexp").should == "match_spec.rb"
- @map.file_name("~", "Integer").should == "complement_spec.rb"
+ expect(@map.file_name("~", "Regexp")).to eq("match_spec.rb")
+ expect(@map.file_name("~", "Integer")).to eq("complement_spec.rb")
end
it "returns the name of the spec file based on the default entry for the method" do
- @map.file_name("<<", "NameMapSpecs").should == "append_spec.rb"
+ expect(@map.file_name("<<", "NameMapSpecs")).to eq("append_spec.rb")
end
it "uses the last component of the constant to look up the method name" do
- @map.file_name("^", "NameMapSpecs::Integer").should == "bit_xor_spec.rb"
+ expect(@map.file_name("^", "NameMapSpecs::Integer")).to eq("bit_xor_spec.rb")
end
end
-describe NameMap, "#namespace" do
+RSpec.describe NameMap, "#namespace" do
before :each do
@map = NameMap.new
end
it "prepends the module to the constant name" do
- @map.namespace("SubModule", Integer).should == "SubModule::Integer"
+ expect(@map.namespace("SubModule", Integer)).to eq("SubModule::Integer")
end
it "does not prepend Object, Class, or Module to the constant name" do
- @map.namespace("Object", String).should == "String"
- @map.namespace("Module", Integer).should == "Integer"
- @map.namespace("Class", Float).should == "Float"
+ expect(@map.namespace("Object", String)).to eq("String")
+ expect(@map.namespace("Module", Integer)).to eq("Integer")
+ expect(@map.namespace("Class", Float)).to eq("Float")
end
end
-describe NameMap, "#map" do
+RSpec.describe NameMap, "#map" do
before :each do
@map = NameMap.new
end
it "flattens an object hierarchy into a single Hash" do
- @map.map({}, [NameMapSpecs]).should == {
+ expect(@map.map({}, [NameMapSpecs])).to eq({
"NameMapSpecs." => ["n"],
"NameMapSpecs#" => ["n"],
"NameMapSpecs::A." => ["a"],
"NameMapSpecs::A#" => ["a", "c"],
"NameMapSpecs::A::B#" => ["b"],
"NameMapSpecs::Fixnum#" => ["f"]
- }
+ })
end
end
diff --git a/spec/mspec/spec/utils/options_spec.rb b/spec/mspec/spec/utils/options_spec.rb
index face909286..2e3925f579 100644
--- a/spec/mspec/spec/utils/options_spec.rb
+++ b/spec/mspec/spec/utils/options_spec.rb
@@ -5,155 +5,155 @@ require 'mspec/guards/guard'
require 'mspec/runner/mspec'
require 'mspec/runner/formatters'
-describe MSpecOption, ".new" do
+RSpec.describe MSpecOption, ".new" do
before :each do
@opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block)
end
it "sets the short attribute" do
- @opt.short.should == "-a"
+ expect(@opt.short).to eq("-a")
end
it "sets the long attribute" do
- @opt.long.should == "--bdc"
+ expect(@opt.long).to eq("--bdc")
end
it "sets the arg attribute" do
- @opt.arg.should == "ARG"
+ expect(@opt.arg).to eq("ARG")
end
it "sets the description attribute" do
- @opt.description.should == "desc"
+ expect(@opt.description).to eq("desc")
end
it "sets the block attribute" do
- @opt.block.should == :block
+ expect(@opt.block).to eq(:block)
end
end
-describe MSpecOption, "#arg?" do
+RSpec.describe MSpecOption, "#arg?" do
it "returns true if arg attribute is not nil" do
- MSpecOption.new(nil, nil, "ARG", nil, nil).arg?.should be_true
+ expect(MSpecOption.new(nil, nil, "ARG", nil, nil).arg?).to be_truthy
end
it "returns false if arg attribute is nil" do
- MSpecOption.new(nil, nil, nil, nil, nil).arg?.should be_false
+ expect(MSpecOption.new(nil, nil, nil, nil, nil).arg?).to be_falsey
end
end
-describe MSpecOption, "#match?" do
+RSpec.describe MSpecOption, "#match?" do
before :each do
@opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block)
end
it "returns true if the argument matches the short option" do
- @opt.match?("-a").should be_true
+ expect(@opt.match?("-a")).to be_truthy
end
it "returns true if the argument matches the long option" do
- @opt.match?("--bdc").should be_true
+ expect(@opt.match?("--bdc")).to be_truthy
end
it "returns false if the argument matches neither the short nor long option" do
- @opt.match?("-b").should be_false
- @opt.match?("-abdc").should be_false
+ expect(@opt.match?("-b")).to be_falsey
+ expect(@opt.match?("-abdc")).to be_falsey
end
end
-describe MSpecOptions, ".new" do
+RSpec.describe MSpecOptions, ".new" do
before :each do
@opt = MSpecOptions.new("cmd", 20, :config)
end
it "sets the banner attribute" do
- @opt.banner.should == "cmd"
+ expect(@opt.banner).to eq("cmd")
end
it "sets the config attribute" do
- @opt.config.should == :config
+ expect(@opt.config).to eq(:config)
end
it "sets the width attribute" do
- @opt.width.should == 20
+ expect(@opt.width).to eq(20)
end
it "sets the default width attribute" do
- MSpecOptions.new.width.should == 30
+ expect(MSpecOptions.new.width).to eq(30)
end
end
-describe MSpecOptions, "#on" do
+RSpec.describe MSpecOptions, "#on" do
before :each do
@opt = MSpecOptions.new
end
it "adds a short option" do
- @opt.should_receive(:add).with("-a", nil, nil, "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil)
@opt.on("-a", "desc")
end
it "adds a short option taking an argument" do
- @opt.should_receive(:add).with("-a", nil, "ARG", "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, "ARG", "desc", nil)
@opt.on("-a", "ARG", "desc")
end
it "adds a long option" do
- @opt.should_receive(:add).with("-a", nil, nil, "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil)
@opt.on("-a", "desc")
end
it "adds a long option taking an argument" do
- @opt.should_receive(:add).with("-a", nil, nil, "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil)
@opt.on("-a", "desc")
end
it "adds a short and long option" do
- @opt.should_receive(:add).with("-a", nil, nil, "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil)
@opt.on("-a", "desc")
end
it "adds a short and long option taking an argument" do
- @opt.should_receive(:add).with("-a", nil, nil, "desc", nil)
+ expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil)
@opt.on("-a", "desc")
end
it "raises MSpecOptions::OptionError if pass less than 2 arguments" do
- lambda { @opt.on }.should raise_error(MSpecOptions::OptionError)
- lambda { @opt.on "" }.should raise_error(MSpecOptions::OptionError)
+ expect { @opt.on }.to raise_error(MSpecOptions::OptionError)
+ expect { @opt.on "" }.to raise_error(MSpecOptions::OptionError)
end
end
-describe MSpecOptions, "#add" do
+RSpec.describe MSpecOptions, "#add" do
before :each do
@opt = MSpecOptions.new "cmd", 20
@prc = lambda { }
end
it "adds documentation for an option" do
- @opt.should_receive(:doc).with(" -t, --typo ARG Correct typo ARG")
+ expect(@opt).to receive(:doc).with(" -t, --typo ARG Correct typo ARG")
@opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc)
end
it "leaves spaces in the documentation for a missing short option" do
- @opt.should_receive(:doc).with(" --typo ARG Correct typo ARG")
+ expect(@opt).to receive(:doc).with(" --typo ARG Correct typo ARG")
@opt.add(nil, "--typo", "ARG", "Correct typo ARG", @prc)
end
it "handles a short option with argument but no long argument" do
- @opt.should_receive(:doc).with(" -t ARG Correct typo ARG")
+ expect(@opt).to receive(:doc).with(" -t ARG Correct typo ARG")
@opt.add("-t", nil, "ARG", "Correct typo ARG", @prc)
end
it "registers an option" do
option = MSpecOption.new "-t", "--typo", "ARG", "Correct typo ARG", @prc
- MSpecOption.should_receive(:new).with(
+ expect(MSpecOption).to receive(:new).with(
"-t", "--typo", "ARG", "Correct typo ARG", @prc).and_return(option)
@opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc)
- @opt.options.should == [option]
+ expect(@opt.options).to eq([option])
end
end
-describe MSpecOptions, "#match?" do
+RSpec.describe MSpecOptions, "#match?" do
before :each do
@opt = MSpecOptions.new
end
@@ -161,15 +161,15 @@ describe MSpecOptions, "#match?" do
it "returns the MSpecOption instance matching the argument" do
@opt.on "-a", "--abdc", "desc"
option = @opt.match? "-a"
- @opt.match?("--abdc").should be(option)
- option.should be_kind_of(MSpecOption)
- option.short.should == "-a"
- option.long.should == "--abdc"
- option.description.should == "desc"
+ expect(@opt.match?("--abdc")).to be(option)
+ expect(option).to be_kind_of(MSpecOption)
+ expect(option.short).to eq("-a")
+ expect(option.long).to eq("--abdc")
+ expect(option.description).to eq("desc")
end
end
-describe MSpecOptions, "#process" do
+RSpec.describe MSpecOptions, "#process" do
before :each do
@opt = MSpecOptions.new
ScratchPad.clear
@@ -178,62 +178,62 @@ describe MSpecOptions, "#process" do
it "calls the on_extra block if the argument does not match any option" do
@opt.on_extra { ScratchPad.record :extra }
@opt.process ["-a"], "-a", "-a", nil
- ScratchPad.recorded.should == :extra
+ expect(ScratchPad.recorded).to eq(:extra)
end
it "returns the matching option" do
@opt.on "-a", "ARG", "desc"
option = @opt.process [], "-a", "-a", "ARG"
- option.should be_kind_of(MSpecOption)
- option.short.should == "-a"
- option.arg.should == "ARG"
- option.description.should == "desc"
+ expect(option).to be_kind_of(MSpecOption)
+ expect(option.short).to eq("-a")
+ expect(option.arg).to eq("ARG")
+ expect(option.description).to eq("desc")
end
it "raises an MSpecOptions::ParseError if arg is nil and there are no more entries in argv" do
@opt.on "-a", "ARG", "desc"
- lambda { @opt.process [], "-a", "-a", nil }.should raise_error(MSpecOptions::ParseError)
+ expect { @opt.process [], "-a", "-a", nil }.to raise_error(MSpecOptions::ParseError)
end
it "fetches the argument for the option from argv if arg is nil" do
@opt.on("-a", "ARG", "desc") { |o| ScratchPad.record o }
@opt.process ["ARG"], "-a", "-a", nil
- ScratchPad.recorded.should == "ARG"
+ expect(ScratchPad.recorded).to eq("ARG")
end
it "calls the option's block" do
@opt.on("-a", "ARG", "desc") { ScratchPad.record :option }
@opt.process [], "-a", "-a", "ARG"
- ScratchPad.recorded.should == :option
+ expect(ScratchPad.recorded).to eq(:option)
end
it "does not call the option's block if it is nil" do
@opt.on "-a", "ARG", "desc"
- lambda { @opt.process [], "-a", "-a", "ARG" }.should_not raise_error
+ expect { @opt.process [], "-a", "-a", "ARG" }.not_to raise_error
end
end
-describe MSpecOptions, "#split" do
+RSpec.describe MSpecOptions, "#split" do
before :each do
@opt = MSpecOptions.new
end
it "breaks a string at the nth character" do
opt, arg, rest = @opt.split "-bdc", 2
- opt.should == "-b"
- arg.should == "dc"
- rest.should == "dc"
+ expect(opt).to eq("-b")
+ expect(arg).to eq("dc")
+ expect(rest).to eq("dc")
end
it "returns nil for arg if there are no characters left" do
opt, arg, rest = @opt.split "-b", 2
- opt.should == "-b"
- arg.should == nil
- rest.should == ""
+ expect(opt).to eq("-b")
+ expect(arg).to eq(nil)
+ expect(rest).to eq("")
end
end
-describe MSpecOptions, "#parse" do
+RSpec.describe MSpecOptions, "#parse" do
before :each do
@opt = MSpecOptions.new
@prc = lambda { ScratchPad.record :parsed }
@@ -244,43 +244,43 @@ describe MSpecOptions, "#parse" do
it "parses a short option" do
@opt.on "-a", "desc", &@prc
@opt.parse ["-a"]
- ScratchPad.recorded.should == :parsed
+ expect(ScratchPad.recorded).to eq(:parsed)
end
it "parse a long option" do
@opt.on "--abdc", "desc", &@prc
@opt.parse ["--abdc"]
- ScratchPad.recorded.should == :parsed
+ expect(ScratchPad.recorded).to eq(:parsed)
end
it "parses a short option group" do
@opt.on "-a", "ARG", "desc", &@arg_prc
@opt.parse ["-a", "ARG"]
- ScratchPad.recorded.should == [:parsed, "ARG"]
+ expect(ScratchPad.recorded).to eq([:parsed, "ARG"])
end
it "parses a short option with an argument" do
@opt.on "-a", "ARG", "desc", &@arg_prc
@opt.parse ["-a", "ARG"]
- ScratchPad.recorded.should == [:parsed, "ARG"]
+ expect(ScratchPad.recorded).to eq([:parsed, "ARG"])
end
it "parses a short option with connected argument" do
@opt.on "-a", "ARG", "desc", &@arg_prc
@opt.parse ["-aARG"]
- ScratchPad.recorded.should == [:parsed, "ARG"]
+ expect(ScratchPad.recorded).to eq([:parsed, "ARG"])
end
it "parses a long option with an argument" do
@opt.on "--abdc", "ARG", "desc", &@arg_prc
@opt.parse ["--abdc", "ARG"]
- ScratchPad.recorded.should == [:parsed, "ARG"]
+ expect(ScratchPad.recorded).to eq([:parsed, "ARG"])
end
it "parses a long option with an '=' argument" do
@opt.on "--abdc", "ARG", "desc", &@arg_prc
@opt.parse ["--abdc=ARG"]
- ScratchPad.recorded.should == [:parsed, "ARG"]
+ expect(ScratchPad.recorded).to eq([:parsed, "ARG"])
end
it "parses a short option group with the final option taking an argument" do
@@ -288,7 +288,7 @@ describe MSpecOptions, "#parse" do
@opt.on("-a", "desc") { |o| ScratchPad << :a }
@opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] }
@opt.parse ["-ab", "ARG"]
- ScratchPad.recorded.should == [:a, [:b, "ARG"]]
+ expect(ScratchPad.recorded).to eq([:a, [:b, "ARG"]])
end
it "parses a short option group with a connected argument" do
@@ -297,12 +297,12 @@ describe MSpecOptions, "#parse" do
@opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] }
@opt.on("-c", "desc") { |o| ScratchPad << :c }
@opt.parse ["-acbARG"]
- ScratchPad.recorded.should == [:a, :c, [:b, "ARG"]]
+ expect(ScratchPad.recorded).to eq([:a, :c, [:b, "ARG"]])
end
it "returns the unprocessed entries" do
@opt.on "-a", "ARG", "desc", &@arg_prc
- @opt.parse(["abdc", "-a", "ilny"]).should == ["abdc"]
+ expect(@opt.parse(["abdc", "-a", "ilny"])).to eq(["abdc"])
end
it "calls the on_extra handler with unrecognized options" do
@@ -310,59 +310,59 @@ describe MSpecOptions, "#parse" do
@opt.on_extra { |o| ScratchPad << o }
@opt.on "-a", "desc"
@opt.parse ["-a", "-b"]
- ScratchPad.recorded.should == ["-b"]
+ expect(ScratchPad.recorded).to eq(["-b"])
end
it "does not attempt to call the block if it is nil" do
@opt.on "-a", "ARG", "desc"
- @opt.parse(["-a", "ARG"]).should == []
+ expect(@opt.parse(["-a", "ARG"])).to eq([])
end
it "raises MSpecOptions::ParseError if passed an unrecognized option" do
- @opt.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String))
- @opt.stub(:puts)
- @opt.stub(:exit)
+ expect(@opt).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String))
+ allow(@opt).to receive(:puts)
+ allow(@opt).to receive(:exit)
@opt.parse "-u"
end
end
-describe MSpecOptions, "#banner=" do
+RSpec.describe MSpecOptions, "#banner=" do
before :each do
@opt = MSpecOptions.new
end
it "sets the banner attribute" do
- @opt.banner.should == ""
+ expect(@opt.banner).to eq("")
@opt.banner = "banner"
- @opt.banner.should == "banner"
+ expect(@opt.banner).to eq("banner")
end
end
-describe MSpecOptions, "#width=" do
+RSpec.describe MSpecOptions, "#width=" do
before :each do
@opt = MSpecOptions.new
end
it "sets the width attribute" do
- @opt.width.should == 30
+ expect(@opt.width).to eq(30)
@opt.width = 20
- @opt.width.should == 20
+ expect(@opt.width).to eq(20)
end
end
-describe MSpecOptions, "#config=" do
+RSpec.describe MSpecOptions, "#config=" do
before :each do
@opt = MSpecOptions.new
end
it "sets the config attribute" do
- @opt.config.should be_nil
+ expect(@opt.config).to be_nil
@opt.config = :config
- @opt.config.should == :config
+ expect(@opt.config).to eq(:config)
end
end
-describe MSpecOptions, "#doc" do
+RSpec.describe MSpecOptions, "#doc" do
before :each do
@opt = MSpecOptions.new "command"
end
@@ -370,7 +370,7 @@ describe MSpecOptions, "#doc" do
it "adds text to be displayed with #to_s" do
@opt.doc "Some message"
@opt.doc "Another message"
- @opt.to_s.should == <<-EOD
+ expect(@opt.to_s).to eq <<-EOD
command
Some message
@@ -379,15 +379,15 @@ EOD
end
end
-describe MSpecOptions, "#version" do
+RSpec.describe MSpecOptions, "#version" do
before :each do
@opt = MSpecOptions.new
ScratchPad.clear
end
it "installs a basic -v, --version option" do
- @opt.should_receive(:puts)
- @opt.should_receive(:exit)
+ expect(@opt).to receive(:puts)
+ expect(@opt).to receive(:exit)
@opt.version "1.0.0"
@opt.parse "-v"
end
@@ -395,19 +395,19 @@ describe MSpecOptions, "#version" do
it "accepts a block instead of using the default block" do
@opt.version("1.0.0") { |o| ScratchPad.record :version }
@opt.parse "-v"
- ScratchPad.recorded.should == :version
+ expect(ScratchPad.recorded).to eq(:version)
end
end
-describe MSpecOptions, "#help" do
+RSpec.describe MSpecOptions, "#help" do
before :each do
@opt = MSpecOptions.new
ScratchPad.clear
end
it "installs a basic -h, --help option" do
- @opt.should_receive(:puts)
- @opt.should_receive(:exit).with(1)
+ expect(@opt).to receive(:puts)
+ expect(@opt).to receive(:exit).with(1)
@opt.help
@opt.parse "-h"
end
@@ -415,11 +415,11 @@ describe MSpecOptions, "#help" do
it "accepts a block instead of using the default block" do
@opt.help { |o| ScratchPad.record :help }
@opt.parse "-h"
- ScratchPad.recorded.should == :help
+ expect(ScratchPad.recorded).to eq(:help)
end
end
-describe MSpecOptions, "#on_extra" do
+RSpec.describe MSpecOptions, "#on_extra" do
before :each do
@opt = MSpecOptions.new
ScratchPad.clear
@@ -428,18 +428,18 @@ describe MSpecOptions, "#on_extra" do
it "registers a block to be called when an option is not recognized" do
@opt.on_extra { ScratchPad.record :extra }
@opt.parse "-g"
- ScratchPad.recorded.should == :extra
+ expect(ScratchPad.recorded).to eq(:extra)
end
end
-describe MSpecOptions, "#to_s" do
+RSpec.describe MSpecOptions, "#to_s" do
before :each do
@opt = MSpecOptions.new "command"
end
it "returns the banner and descriptive strings for all registered options" do
@opt.on "-t", "--this ARG", "Adds this ARG to the list"
- @opt.to_s.should == <<-EOD
+ expect(@opt.to_s).to eq <<-EOD
command
-t, --this ARG Adds this ARG to the list
@@ -447,13 +447,13 @@ EOD
end
end
-describe "The -B, --config FILE option" do
+RSpec.describe "The -B, --config FILE option" do
before :each do
@options, @config = new_option
end
it "is enabled with #configure { }" do
- @options.should_receive(:on).with("-B", "--config", "FILE",
+ expect(@options).to receive(:on).with("-B", "--config", "FILE",
an_instance_of(String))
@options.configure {}
end
@@ -464,38 +464,38 @@ describe "The -B, --config FILE option" do
@options.configure { |x| ScratchPad.record x }
@options.parse [opt, "file"]
- ScratchPad.recorded.should == "file"
+ expect(ScratchPad.recorded).to eq("file")
end
end
end
-describe "The -C, --chdir DIR option" do
+RSpec.describe "The -C, --chdir DIR option" do
before :each do
@options, @config = new_option
@options.chdir
end
it "is enabled with #chdir" do
- @options.should_receive(:on).with("-C", "--chdir", "DIR",
+ expect(@options).to receive(:on).with("-C", "--chdir", "DIR",
an_instance_of(String))
@options.chdir
end
it "changes the working directory to DIR" do
- Dir.should_receive(:chdir).with("dir").twice
+ expect(Dir).to receive(:chdir).with("dir").twice
["-C", "--chdir"].each do |opt|
@options.parse [opt, "dir"]
end
end
end
-describe "The --prefix STR option" do
+RSpec.describe "The --prefix STR option" do
before :each do
@options, @config = new_option
end
it "is enabled with #prefix" do
- @options.should_receive(:on).with("--prefix", "STR",
+ expect(@options).to receive(:on).with("--prefix", "STR",
an_instance_of(String))
@options.prefix
end
@@ -503,19 +503,19 @@ describe "The --prefix STR option" do
it "sets the prefix config value" do
@options.prefix
@options.parse ["--prefix", "some/dir"]
- @config[:prefix].should == "some/dir"
+ expect(@config[:prefix]).to eq("some/dir")
end
end
-describe "The -t, --target TARGET option" do
+RSpec.describe "The -t, --target TARGET option" do
before :each do
@options, @config = new_option
@options.targets
end
it "is enabled with #targets" do
- @options.stub(:on)
- @options.should_receive(:on).with("-t", "--target", "TARGET",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-t", "--target", "TARGET",
an_instance_of(String))
@options.targets
end
@@ -525,7 +525,7 @@ describe "The -t, --target TARGET option" do
["r", "ruby"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "ruby"
+ expect(@config[:target]).to eq("ruby")
end
end
end
@@ -535,7 +535,7 @@ describe "The -t, --target TARGET option" do
["j", "jruby"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "jruby"
+ expect(@config[:target]).to eq("jruby")
end
end
end
@@ -545,7 +545,7 @@ describe "The -t, --target TARGET option" do
["x", "rubinius"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "./bin/rbx"
+ expect(@config[:target]).to eq("./bin/rbx")
end
end
end
@@ -555,7 +555,7 @@ describe "The -t, --target TARGET option" do
["X", "rbx"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "rbx"
+ expect(@config[:target]).to eq("rbx")
end
end
end
@@ -565,7 +565,7 @@ describe "The -t, --target TARGET option" do
["m", "maglev"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "maglev-ruby"
+ expect(@config[:target]).to eq("maglev-ruby")
end
end
end
@@ -575,7 +575,7 @@ describe "The -t, --target TARGET option" do
["t", "topaz"].each do |t|
@config[:target] = nil
@options.parse [opt, t]
- @config[:target].should == "topaz"
+ expect(@config[:target]).to eq("topaz")
end
end
end
@@ -584,20 +584,20 @@ describe "The -t, --target TARGET option" do
["-t", "--target"].each do |opt|
@config[:target] = nil
@options.parse [opt, "whateva"]
- @config[:target].should == "whateva"
+ expect(@config[:target]).to eq("whateva")
end
end
end
-describe "The -T, --target-opt OPT option" do
+RSpec.describe "The -T, --target-opt OPT option" do
before :each do
@options, @config = new_option
@options.targets
end
it "is enabled with #targets" do
- @options.stub(:on)
- @options.should_receive(:on).with("-T", "--target-opt", "OPT",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-T", "--target-opt", "OPT",
an_instance_of(String))
@options.targets
end
@@ -606,20 +606,20 @@ describe "The -T, --target-opt OPT option" do
["-T", "--target-opt"].each do |opt|
@config[:flags].delete "--whateva"
@options.parse [opt, "--whateva"]
- @config[:flags].should include("--whateva")
+ expect(@config[:flags]).to include("--whateva")
end
end
end
-describe "The -I, --include DIR option" do
+RSpec.describe "The -I, --include DIR option" do
before :each do
@options, @config = new_option
@options.targets
end
it "is enabled with #targets" do
- @options.stub(:on)
- @options.should_receive(:on).with("-I", "--include", "DIR",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-I", "--include", "DIR",
an_instance_of(String))
@options.targets
end
@@ -628,20 +628,20 @@ describe "The -I, --include DIR option" do
["-I", "--include"].each do |opt|
@config[:loadpath].delete "-Ipackage"
@options.parse [opt, "package"]
- @config[:loadpath].should include("-Ipackage")
+ expect(@config[:loadpath]).to include("-Ipackage")
end
end
end
-describe "The -r, --require LIBRARY option" do
+RSpec.describe "The -r, --require LIBRARY option" do
before :each do
@options, @config = new_option
@options.targets
end
it "is enabled with #targets" do
- @options.stub(:on)
- @options.should_receive(:on).with("-r", "--require", "LIBRARY",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-r", "--require", "LIBRARY",
an_instance_of(String))
@options.targets
end
@@ -650,20 +650,20 @@ describe "The -r, --require LIBRARY option" do
["-r", "--require"].each do |opt|
@config[:requires].delete "-rlibrick"
@options.parse [opt, "librick"]
- @config[:requires].should include("-rlibrick")
+ expect(@config[:requires]).to include("-rlibrick")
end
end
end
-describe "The -f, --format FORMAT option" do
+RSpec.describe "The -f, --format FORMAT option" do
before :each do
@options, @config = new_option
@options.formatters
end
it "is enabled with #formatters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-f", "--format", "FORMAT",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-f", "--format", "FORMAT",
an_instance_of(String))
@options.formatters
end
@@ -673,7 +673,7 @@ describe "The -f, --format FORMAT option" do
["s", "specdoc"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == SpecdocFormatter
+ expect(@config[:formatter]).to eq(SpecdocFormatter)
end
end
end
@@ -683,7 +683,7 @@ describe "The -f, --format FORMAT option" do
["h", "html"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == HtmlFormatter
+ expect(@config[:formatter]).to eq(HtmlFormatter)
end
end
end
@@ -693,7 +693,7 @@ describe "The -f, --format FORMAT option" do
["d", "dot", "dotted"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == DottedFormatter
+ expect(@config[:formatter]).to eq(DottedFormatter)
end
end
end
@@ -703,7 +703,7 @@ describe "The -f, --format FORMAT option" do
["b", "describe"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == DescribeFormatter
+ expect(@config[:formatter]).to eq(DescribeFormatter)
end
end
end
@@ -713,7 +713,7 @@ describe "The -f, --format FORMAT option" do
["f", "file"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == FileFormatter
+ expect(@config[:formatter]).to eq(FileFormatter)
end
end
end
@@ -723,7 +723,7 @@ describe "The -f, --format FORMAT option" do
["u", "unit", "unitdiff"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == UnitdiffFormatter
+ expect(@config[:formatter]).to eq(UnitdiffFormatter)
end
end
end
@@ -733,7 +733,7 @@ describe "The -f, --format FORMAT option" do
["m", "summary"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == SummaryFormatter
+ expect(@config[:formatter]).to eq(SummaryFormatter)
end
end
end
@@ -743,7 +743,7 @@ describe "The -f, --format FORMAT option" do
["a", "*", "spin"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == SpinnerFormatter
+ expect(@config[:formatter]).to eq(SpinnerFormatter)
end
end
end
@@ -753,7 +753,7 @@ describe "The -f, --format FORMAT option" do
["t", "method"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == MethodFormatter
+ expect(@config[:formatter]).to eq(MethodFormatter)
end
end
end
@@ -763,7 +763,7 @@ describe "The -f, --format FORMAT option" do
["y", "yaml"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == YamlFormatter
+ expect(@config[:formatter]).to eq(YamlFormatter)
end
end
end
@@ -773,21 +773,21 @@ describe "The -f, --format FORMAT option" do
["j", "junit"].each do |f|
@config[:formatter] = nil
@options.parse [opt, f]
- @config[:formatter].should == JUnitFormatter
+ expect(@config[:formatter]).to eq(JUnitFormatter)
end
end
end
end
-describe "The -o, --output FILE option" do
+RSpec.describe "The -o, --output FILE option" do
before :each do
@options, @config = new_option
@options.formatters
end
it "is enabled with #formatters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-o", "--output", "FILE",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-o", "--output", "FILE",
an_instance_of(String))
@options.formatters
end
@@ -796,20 +796,20 @@ describe "The -o, --output FILE option" do
["-o", "--output"].each do |opt|
@config[:output] = nil
@options.parse [opt, "some/file"]
- @config[:output].should == "some/file"
+ expect(@config[:output]).to eq("some/file")
end
end
end
-describe "The -e, --example STR" do
+RSpec.describe "The -e, --example STR" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-e", "--example", "STR",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-e", "--example", "STR",
an_instance_of(String))
@options.filters
end
@@ -818,20 +818,20 @@ describe "The -e, --example STR" do
["-e", "--example"].each do |opt|
@config[:includes] = []
@options.parse [opt, "this spec"]
- @config[:includes].should include("this spec")
+ expect(@config[:includes]).to include("this spec")
end
end
end
-describe "The -E, --exclude STR" do
+RSpec.describe "The -E, --exclude STR" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-E", "--exclude", "STR",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-E", "--exclude", "STR",
an_instance_of(String))
@options.filters
end
@@ -840,20 +840,20 @@ describe "The -E, --exclude STR" do
["-E", "--exclude"].each do |opt|
@config[:excludes] = []
@options.parse [opt, "this spec"]
- @config[:excludes].should include("this spec")
+ expect(@config[:excludes]).to include("this spec")
end
end
end
-describe "The -p, --pattern PATTERN" do
+RSpec.describe "The -p, --pattern PATTERN" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-p", "--pattern", "PATTERN",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-p", "--pattern", "PATTERN",
an_instance_of(String))
@options.filters
end
@@ -862,20 +862,20 @@ describe "The -p, --pattern PATTERN" do
["-p", "--pattern"].each do |opt|
@config[:patterns] = []
@options.parse [opt, "this spec"]
- @config[:patterns].should include(/this spec/)
+ expect(@config[:patterns]).to include(/this spec/)
end
end
end
-describe "The -P, --excl-pattern PATTERN" do
+RSpec.describe "The -P, --excl-pattern PATTERN" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-P", "--excl-pattern", "PATTERN",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-P", "--excl-pattern", "PATTERN",
an_instance_of(String))
@options.filters
end
@@ -884,20 +884,20 @@ describe "The -P, --excl-pattern PATTERN" do
["-P", "--excl-pattern"].each do |opt|
@config[:xpatterns] = []
@options.parse [opt, "this spec"]
- @config[:xpatterns].should include(/this spec/)
+ expect(@config[:xpatterns]).to include(/this spec/)
end
end
end
-describe "The -g, --tag TAG" do
+RSpec.describe "The -g, --tag TAG" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-g", "--tag", "TAG",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-g", "--tag", "TAG",
an_instance_of(String))
@options.filters
end
@@ -906,20 +906,20 @@ describe "The -g, --tag TAG" do
["-g", "--tag"].each do |opt|
@config[:tags] = []
@options.parse [opt, "this spec"]
- @config[:tags].should include("this spec")
+ expect(@config[:tags]).to include("this spec")
end
end
end
-describe "The -G, --excl-tag TAG" do
+RSpec.describe "The -G, --excl-tag TAG" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-G", "--excl-tag", "TAG",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-G", "--excl-tag", "TAG",
an_instance_of(String))
@options.filters
end
@@ -928,20 +928,20 @@ describe "The -G, --excl-tag TAG" do
["-G", "--excl-tag"].each do |opt|
@config[:xtags] = []
@options.parse [opt, "this spec"]
- @config[:xtags].should include("this spec")
+ expect(@config[:xtags]).to include("this spec")
end
end
end
-describe "The -w, --profile FILE option" do
+RSpec.describe "The -w, --profile FILE option" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-w", "--profile", "FILE",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-w", "--profile", "FILE",
an_instance_of(String))
@options.filters
end
@@ -950,20 +950,20 @@ describe "The -w, --profile FILE option" do
["-w", "--profile"].each do |opt|
@config[:profiles] = []
@options.parse [opt, "spec/profiles/rails.yaml"]
- @config[:profiles].should include("spec/profiles/rails.yaml")
+ expect(@config[:profiles]).to include("spec/profiles/rails.yaml")
end
end
end
-describe "The -W, --excl-profile FILE option" do
+RSpec.describe "The -W, --excl-profile FILE option" do
before :each do
@options, @config = new_option
@options.filters
end
it "is enabled with #filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-W", "--excl-profile", "FILE",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-W", "--excl-profile", "FILE",
an_instance_of(String))
@options.filters
end
@@ -972,93 +972,93 @@ describe "The -W, --excl-profile FILE option" do
["-W", "--excl-profile"].each do |opt|
@config[:xprofiles] = []
@options.parse [opt, "spec/profiles/rails.yaml"]
- @config[:xprofiles].should include("spec/profiles/rails.yaml")
+ expect(@config[:xprofiles]).to include("spec/profiles/rails.yaml")
end
end
end
-describe "The -Z, --dry-run option" do
+RSpec.describe "The -Z, --dry-run option" do
before :each do
@options, @config = new_option
@options.pretend
end
it "is enabled with #pretend" do
- @options.should_receive(:on).with("-Z", "--dry-run", an_instance_of(String))
+ expect(@options).to receive(:on).with("-Z", "--dry-run", an_instance_of(String))
@options.pretend
end
it "registers the MSpec pretend mode" do
- MSpec.should_receive(:register_mode).with(:pretend).twice
+ expect(MSpec).to receive(:register_mode).with(:pretend).twice
["-Z", "--dry-run"].each do |opt|
@options.parse opt
end
end
end
-describe "The --unguarded option" do
+RSpec.describe "The --unguarded option" do
before :each do
@options, @config = new_option
@options.unguarded
end
it "is enabled with #unguarded" do
- @options.stub(:on)
- @options.should_receive(:on).with("--unguarded", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--unguarded", an_instance_of(String))
@options.unguarded
end
it "registers the MSpec unguarded mode" do
- MSpec.should_receive(:register_mode).with(:unguarded)
+ expect(MSpec).to receive(:register_mode).with(:unguarded)
@options.parse "--unguarded"
end
end
-describe "The --no-ruby_guard option" do
+RSpec.describe "The --no-ruby_guard option" do
before :each do
@options, @config = new_option
@options.unguarded
end
it "is enabled with #unguarded" do
- @options.stub(:on)
- @options.should_receive(:on).with("--no-ruby_bug", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--no-ruby_bug", an_instance_of(String))
@options.unguarded
end
it "registers the MSpec no_ruby_bug mode" do
- MSpec.should_receive(:register_mode).with(:no_ruby_bug)
+ expect(MSpec).to receive(:register_mode).with(:no_ruby_bug)
@options.parse "--no-ruby_bug"
end
end
-describe "The -H, --random option" do
+RSpec.describe "The -H, --random option" do
before :each do
@options, @config = new_option
@options.randomize
end
it "is enabled with #randomize" do
- @options.should_receive(:on).with("-H", "--random", an_instance_of(String))
+ expect(@options).to receive(:on).with("-H", "--random", an_instance_of(String))
@options.randomize
end
it "registers the MSpec randomize mode" do
- MSpec.should_receive(:randomize).twice
+ expect(MSpec).to receive(:randomize=).twice
["-H", "--random"].each do |opt|
@options.parse opt
end
end
end
-describe "The -R, --repeat option" do
+RSpec.describe "The -R, --repeat option" do
before :each do
@options, @config = new_option
@options.repeat
end
it "is enabled with #repeat" do
- @options.should_receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String))
+ expect(@options).to receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String))
@options.repeat
end
@@ -1070,117 +1070,115 @@ describe "The -R, --repeat option" do
MSpec.repeat do
repeat_count += 1
end
- repeat_count.should == 10
+ expect(repeat_count).to eq(10)
end
end
end
-describe "The -V, --verbose option" do
+RSpec.describe "The -V, --verbose option" do
before :each do
@options, @config = new_option
@options.verbose
end
it "is enabled with #verbose" do
- @options.stub(:on)
- @options.should_receive(:on).with("-V", "--verbose", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-V", "--verbose", an_instance_of(String))
@options.verbose
end
it "registers a verbose output object with MSpec" do
- MSpec.should_receive(:register).with(:start, anything()).twice
- MSpec.should_receive(:register).with(:load, anything()).twice
+ expect(MSpec).to receive(:register).with(:start, anything()).twice
+ expect(MSpec).to receive(:register).with(:load, anything()).twice
["-V", "--verbose"].each do |opt|
@options.parse opt
end
end
end
-describe "The -m, --marker MARKER option" do
+RSpec.describe "The -m, --marker MARKER option" do
before :each do
@options, @config = new_option
@options.verbose
end
it "is enabled with #verbose" do
- @options.stub(:on)
- @options.should_receive(:on).with("-m", "--marker", "MARKER",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-m", "--marker", "MARKER",
an_instance_of(String))
@options.verbose
end
it "registers a marker output object with MSpec" do
- MSpec.should_receive(:register).with(:load, anything()).twice
+ expect(MSpec).to receive(:register).with(:load, anything()).twice
["-m", "--marker"].each do |opt|
@options.parse [opt, ","]
end
end
end
-describe "The --int-spec option" do
+RSpec.describe "The --int-spec option" do
before :each do
@options, @config = new_option
@options.interrupt
end
it "is enabled with #interrupt" do
- @options.should_receive(:on).with("--int-spec", an_instance_of(String))
+ expect(@options).to receive(:on).with("--int-spec", an_instance_of(String))
@options.interrupt
end
it "sets the abort config option to false to only abort the running spec with ^C" do
@config[:abort] = true
@options.parse "--int-spec"
- @config[:abort].should == false
+ expect(@config[:abort]).to eq(false)
end
end
-describe "The -Y, --verify option" do
+RSpec.describe "The -Y, --verify option" do
before :each do
@options, @config = new_option
@options.verify
end
it "is enabled with #interrupt" do
- @options.stub(:on)
- @options.should_receive(:on).with("-Y", "--verify", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-Y", "--verify", an_instance_of(String))
@options.verify
end
it "sets the MSpec mode to :verify" do
- MSpec.should_receive(:register_mode).with(:verify).twice
+ expect(MSpec).to receive(:register_mode).with(:verify).twice
["-Y", "--verify"].each do |m|
@options.parse m
end
end
end
-describe "The -O, --report option" do
+RSpec.describe "The -O, --report option" do
before :each do
@options, @config = new_option
@options.verify
end
it "is enabled with #interrupt" do
- @options.stub(:on)
- @options.should_receive(:on).with("-O", "--report", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-O", "--report", an_instance_of(String))
@options.verify
end
it "sets the MSpec mode to :report" do
- MSpec.should_receive(:register_mode).with(:report).twice
+ expect(MSpec).to receive(:register_mode).with(:report).twice
["-O", "--report"].each do |m|
@options.parse m
end
end
end
-describe "The --report-on GUARD option" do
- before :all do
- MSpec.stub(:register_mode)
- end
-
+RSpec.describe "The --report-on GUARD option" do
before :each do
+ allow(MSpec).to receive(:register_mode)
+
@options, @config = new_option
@options.verify
@@ -1192,37 +1190,37 @@ describe "The --report-on GUARD option" do
end
it "is enabled with #interrupt" do
- @options.stub(:on)
- @options.should_receive(:on).with("--report-on", "GUARD", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("--report-on", "GUARD", an_instance_of(String))
@options.verify
end
it "sets the MSpec mode to :report_on" do
- MSpec.should_receive(:register_mode).with(:report_on)
+ expect(MSpec).to receive(:register_mode).with(:report_on)
@options.parse ["--report-on", "ruby_bug"]
end
it "converts the guard name to a symbol" do
name = double("ruby_bug")
- name.should_receive(:to_sym)
+ expect(name).to receive(:to_sym)
@options.parse ["--report-on", name]
end
it "saves the name of the guard" do
@options.parse ["--report-on", "ruby_bug"]
- SpecGuard.guards.should == [:ruby_bug]
+ expect(SpecGuard.guards).to eq([:ruby_bug])
end
end
-describe "The -K, --action-tag TAG option" do
+RSpec.describe "The -K, --action-tag TAG option" do
before :each do
@options, @config = new_option
@options.action_filters
end
it "is enabled with #action_filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-K", "--action-tag", "TAG",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-K", "--action-tag", "TAG",
an_instance_of(String))
@options.action_filters
end
@@ -1231,20 +1229,20 @@ describe "The -K, --action-tag TAG option" do
["-K", "--action-tag"].each do |opt|
@config[:atags] = []
@options.parse [opt, "action-tag"]
- @config[:atags].should include("action-tag")
+ expect(@config[:atags]).to include("action-tag")
end
end
end
-describe "The -S, --action-string STR option" do
+RSpec.describe "The -S, --action-string STR option" do
before :each do
@options, @config = new_option
@options.action_filters
end
it "is enabled with #action_filters" do
- @options.stub(:on)
- @options.should_receive(:on).with("-S", "--action-string", "STR",
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-S", "--action-string", "STR",
an_instance_of(String))
@options.action_filters
end
@@ -1253,12 +1251,12 @@ describe "The -S, --action-string STR option" do
["-S", "--action-string"].each do |opt|
@config[:astrings] = []
@options.parse [opt, "action-str"]
- @config[:astrings].should include("action-str")
+ expect(@config[:astrings]).to include("action-str")
end
end
end
-describe "The -d, --debug option" do
+RSpec.describe "The -d, --debug option" do
before :each do
@options, @config = new_option
@options.debug
@@ -1269,17 +1267,36 @@ describe "The -d, --debug option" do
end
it "is enabled with #debug" do
- @options.stub(:on)
- @options.should_receive(:on).with("-d", "--debug", an_instance_of(String))
+ allow(@options).to receive(:on)
+ expect(@options).to receive(:on).with("-d", "--debug", an_instance_of(String))
@options.debug
end
it "sets $MSPEC_DEBUG to true" do
["-d", "--debug"].each do |opt|
- $MSPEC_DEBUG.should_not be_true
+ expect($MSPEC_DEBUG).not_to be_truthy
@options.parse opt
- $MSPEC_DEBUG.should be_true
+ expect($MSPEC_DEBUG).to be_truthy
$MSPEC_DEBUG = nil
end
end
end
+
+RSpec.describe "MSpecOptions#all" do
+ it "includes all options" do
+ meth = MSpecOptions.instance_method(:all)
+ file, line = meth.source_location
+ contents = File.read(file)
+ lines = contents.lines
+
+ from = line
+ to = from
+ to += 1 until /^\s*end\s*$/ =~ lines[to]
+ calls = lines[from...to].map(&:strip)
+
+ option_methods = contents.scan(/def (\w+).*\n\s*on\(/).map(&:first)
+ option_methods[0].sub!("configure", "configure {}")
+
+ expect(calls).to eq(option_methods)
+ end
+end
diff --git a/spec/mspec/spec/utils/script_spec.rb b/spec/mspec/spec/utils/script_spec.rb
index e3188ab5ff..c35bda8b47 100644
--- a/spec/mspec/spec/utils/script_spec.rb
+++ b/spec/mspec/spec/utils/script_spec.rb
@@ -4,40 +4,40 @@ require 'mspec/runner/mspec'
require 'mspec/runner/filters'
require 'mspec/runner/actions/filter'
-describe MSpecScript, ".config" do
+RSpec.describe MSpecScript, ".config" do
it "returns a Hash" do
- MSpecScript.config.should be_kind_of(Hash)
+ expect(MSpecScript.config).to be_kind_of(Hash)
end
end
-describe MSpecScript, ".set" do
+RSpec.describe MSpecScript, ".set" do
it "sets the config hash key, value" do
MSpecScript.set :a, 10
- MSpecScript.config[:a].should == 10
+ expect(MSpecScript.config[:a]).to eq(10)
end
end
-describe MSpecScript, ".get" do
+RSpec.describe MSpecScript, ".get" do
it "gets the config hash value for a key" do
MSpecScript.set :a, 10
- MSpecScript.get(:a).should == 10
+ expect(MSpecScript.get(:a)).to eq(10)
end
end
-describe MSpecScript, "#config" do
+RSpec.describe MSpecScript, "#config" do
it "returns the MSpecScript config hash" do
MSpecScript.set :b, 5
- MSpecScript.new.config[:b].should == 5
+ expect(MSpecScript.new.config[:b]).to eq(5)
end
it "returns the MSpecScript config hash from subclasses" do
class MSSClass < MSpecScript; end
MSpecScript.set :b, 5
- MSSClass.new.config[:b].should == 5
+ expect(MSSClass.new.config[:b]).to eq(5)
end
end
-describe MSpecScript, "#load_default" do
+RSpec.describe MSpecScript, "#load_default" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@@ -53,7 +53,7 @@ describe MSpecScript, "#load_default" do
@engine = Object.const_get :RUBY_ENGINE
end
@script = MSpecScript.new
- MSpecScript.stub(:new).and_return(@script)
+ allow(MSpecScript).to receive(:new).and_return(@script)
end
after :each do
@@ -62,8 +62,8 @@ describe MSpecScript, "#load_default" do
end
it "attempts to load 'default.mspec'" do
- @script.stub(:try_load)
- @script.should_receive(:try_load).with('default.mspec').and_return(true)
+ allow(@script).to receive(:try_load)
+ expect(@script).to receive(:try_load).with('default.mspec').and_return(true)
@script.load_default
end
@@ -71,145 +71,140 @@ describe MSpecScript, "#load_default" do
Object.const_set :RUBY_ENGINE, "ybur"
Object.const_set :RUBY_VERSION, "1.8.9"
default = "ybur.1.8.mspec"
- @script.should_receive(:try_load).with('default.mspec').and_return(false)
- @script.should_receive(:try_load).with(default)
- @script.should_receive(:try_load).with('ybur.mspec')
+ expect(@script).to receive(:try_load).with('default.mspec').and_return(false)
+ expect(@script).to receive(:try_load).with(default)
+ expect(@script).to receive(:try_load).with('ybur.mspec')
@script.load_default
end
end
-describe MSpecScript, ".main" do
+RSpec.describe MSpecScript, ".main" do
before :each do
@script = double("MSpecScript").as_null_object
- MSpecScript.stub(:new).and_return(@script)
+ allow(MSpecScript).to receive(:new).and_return(@script)
# Do not require full mspec as it would conflict with RSpec
- MSpecScript.should_receive(:require).with('mspec')
+ expect(MSpecScript).to receive(:require).with('mspec')
end
it "creates an instance of MSpecScript" do
- MSpecScript.should_receive(:new).and_return(@script)
+ expect(MSpecScript).to receive(:new).and_return(@script)
MSpecScript.main
end
it "attempts to load the default config" do
- @script.should_receive(:load_default)
- MSpecScript.main
- end
-
- it "attempts to load the '~/.mspecrc' script" do
- @script.should_receive(:try_load).with('~/.mspecrc')
+ expect(@script).to receive(:load_default)
MSpecScript.main
end
it "calls the #options method on the script" do
- @script.should_receive(:options)
+ expect(@script).to receive(:options)
MSpecScript.main
end
it "calls the #signals method on the script" do
- @script.should_receive(:signals)
+ expect(@script).to receive(:signals)
MSpecScript.main
end
it "calls the #register method on the script" do
- @script.should_receive(:register)
+ expect(@script).to receive(:register)
MSpecScript.main
end
it "calls the #setup_env method on the script" do
- @script.should_receive(:setup_env)
+ expect(@script).to receive(:setup_env)
MSpecScript.main
end
it "calls the #run method on the script" do
- @script.should_receive(:run)
+ expect(@script).to receive(:run)
MSpecScript.main
end
end
-describe MSpecScript, "#initialize" do
+RSpec.describe MSpecScript, "#initialize" do
before :each do
@config = MSpecScript.new.config
end
it "sets the default config values" do
- @config[:formatter].should == nil
- @config[:includes].should == []
- @config[:excludes].should == []
- @config[:patterns].should == []
- @config[:xpatterns].should == []
- @config[:tags].should == []
- @config[:xtags].should == []
- @config[:atags].should == []
- @config[:astrings].should == []
- @config[:abort].should == true
- @config[:config_ext].should == '.mspec'
+ expect(@config[:formatter]).to eq(nil)
+ expect(@config[:includes]).to eq([])
+ expect(@config[:excludes]).to eq([])
+ expect(@config[:patterns]).to eq([])
+ expect(@config[:xpatterns]).to eq([])
+ expect(@config[:tags]).to eq([])
+ expect(@config[:xtags]).to eq([])
+ expect(@config[:atags]).to eq([])
+ expect(@config[:astrings]).to eq([])
+ expect(@config[:abort]).to eq(true)
+ expect(@config[:config_ext]).to eq('.mspec')
end
end
-describe MSpecScript, "#load" do
+RSpec.describe MSpecScript, "#load" do
before :each do
- File.stub(:exist?).and_return(false)
+ allow(File).to receive(:exist?).and_return(false)
@script = MSpecScript.new
@file = "default.mspec"
@base = "default"
end
it "attempts to locate the file through the expanded path name" do
- File.should_receive(:expand_path).with(@file, ".").and_return(@file)
- File.should_receive(:exist?).with(@file).and_return(true)
- Kernel.should_receive(:load).with(@file).and_return(:loaded)
- @script.load(@file).should == :loaded
+ expect(File).to receive(:expand_path).with(@file, ".").and_return(@file)
+ expect(File).to receive(:exist?).with(@file).and_return(true)
+ expect(Kernel).to receive(:load).with(@file).and_return(:loaded)
+ expect(@script.load(@file)).to eq(:loaded)
end
it "appends config[:config_ext] to the name and attempts to locate the file through the expanded path name" do
- File.should_receive(:expand_path).with(@base, ".").and_return(@base)
- File.should_receive(:expand_path).with(@base, "spec").and_return(@base)
- File.should_receive(:expand_path).with(@file, ".").and_return(@file)
- File.should_receive(:exist?).with(@base).and_return(false)
- File.should_receive(:exist?).with(@file).and_return(true)
- Kernel.should_receive(:load).with(@file).and_return(:loaded)
- @script.load(@base).should == :loaded
+ expect(File).to receive(:expand_path).with(@base, ".").and_return(@base)
+ expect(File).to receive(:expand_path).with(@base, "spec").and_return(@base)
+ expect(File).to receive(:expand_path).with(@file, ".").and_return(@file)
+ expect(File).to receive(:exist?).with(@base).and_return(false)
+ expect(File).to receive(:exist?).with(@file).and_return(true)
+ expect(Kernel).to receive(:load).with(@file).and_return(:loaded)
+ expect(@script.load(@base)).to eq(:loaded)
end
it "attempts to locate the file in '.'" do
path = File.expand_path @file, "."
- File.should_receive(:exist?).with(path).and_return(true)
- Kernel.should_receive(:load).with(path).and_return(:loaded)
- @script.load(@file).should == :loaded
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(Kernel).to receive(:load).with(path).and_return(:loaded)
+ expect(@script.load(@file)).to eq(:loaded)
end
it "appends config[:config_ext] to the name and attempts to locate the file in '.'" do
path = File.expand_path @file, "."
- File.should_receive(:exist?).with(path).and_return(true)
- Kernel.should_receive(:load).with(path).and_return(:loaded)
- @script.load(@base).should == :loaded
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(Kernel).to receive(:load).with(path).and_return(:loaded)
+ expect(@script.load(@base)).to eq(:loaded)
end
it "attempts to locate the file in 'spec'" do
path = File.expand_path @file, "spec"
- File.should_receive(:exist?).with(path).and_return(true)
- Kernel.should_receive(:load).with(path).and_return(:loaded)
- @script.load(@file).should == :loaded
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(Kernel).to receive(:load).with(path).and_return(:loaded)
+ expect(@script.load(@file)).to eq(:loaded)
end
it "appends config[:config_ext] to the name and attempts to locate the file in 'spec'" do
path = File.expand_path @file, "spec"
- File.should_receive(:exist?).with(path).and_return(true)
- Kernel.should_receive(:load).with(path).and_return(:loaded)
- @script.load(@base).should == :loaded
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(Kernel).to receive(:load).with(path).and_return(:loaded)
+ expect(@script.load(@base)).to eq(:loaded)
end
it "loads a given file only once" do
path = File.expand_path @file, "spec"
- File.should_receive(:exist?).with(path).and_return(true)
- Kernel.should_receive(:load).once.with(path).and_return(:loaded)
- @script.load(@base).should == :loaded
- @script.load(@base).should == true
+ expect(File).to receive(:exist?).with(path).and_return(true)
+ expect(Kernel).to receive(:load).once.with(path).and_return(:loaded)
+ expect(@script.load(@base)).to eq(:loaded)
+ expect(@script.load(@base)).to eq(true)
end
end
-describe MSpecScript, "#custom_options" do
+RSpec.describe MSpecScript, "#custom_options" do
before :each do
@script = MSpecScript.new
end
@@ -219,12 +214,12 @@ describe MSpecScript, "#custom_options" do
it "prints 'None'" do
options = double("options")
- options.should_receive(:doc).with(" No custom options registered")
+ expect(options).to receive(:doc).with(" No custom options registered")
@script.custom_options options
end
end
-describe MSpecScript, "#register" do
+RSpec.describe MSpecScript, "#register" do
before :each do
@script = MSpecScript.new
@@ -233,8 +228,8 @@ describe MSpecScript, "#register" do
end
it "creates and registers the formatter" do
- @formatter.should_receive(:new).and_return(@formatter)
- @formatter.should_receive(:register)
+ expect(@formatter).to receive(:new).and_return(@formatter)
+ expect(@formatter).to receive(:register)
@script.register
end
@@ -244,24 +239,24 @@ describe MSpecScript, "#register" do
end
it "calls #custom_register" do
- @script.should_receive(:custom_register)
+ expect(@script).to receive(:custom_register)
@script.register
end
it "registers :formatter with the formatter instance" do
- @formatter.stub(:new).and_return(@formatter)
- MSpec.should_receive(:store).with(:formatter, @formatter)
+ allow(@formatter).to receive(:new).and_return(@formatter)
@script.register
+ expect(MSpec.formatter).to be(@formatter)
end
it "does not register :formatter if config[:formatter] is false" do
@script.config[:formatter] = false
- MSpec.should_not_receive(:store)
+ expect(MSpec).not_to receive(:store)
@script.register
end
end
-describe MSpecScript, "#register" do
+RSpec.describe MSpecScript, "#register" do
before :each do
@script = MSpecScript.new
@@ -269,61 +264,61 @@ describe MSpecScript, "#register" do
@script.config[:formatter] = @formatter
@filter = double("filter")
- @filter.should_receive(:register)
+ expect(@filter).to receive(:register)
@ary = ["some", "spec"]
end
it "creates and registers a MatchFilter for include specs" do
- MatchFilter.should_receive(:new).with(:include, *@ary).and_return(@filter)
+ expect(MatchFilter).to receive(:new).with(:include, *@ary).and_return(@filter)
@script.config[:includes] = @ary
@script.register
end
it "creates and registers a MatchFilter for excluded specs" do
- MatchFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter)
+ expect(MatchFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter)
@script.config[:excludes] = @ary
@script.register
end
it "creates and registers a RegexpFilter for include specs" do
- RegexpFilter.should_receive(:new).with(:include, *@ary).and_return(@filter)
+ expect(RegexpFilter).to receive(:new).with(:include, *@ary).and_return(@filter)
@script.config[:patterns] = @ary
@script.register
end
it "creates and registers a RegexpFilter for excluded specs" do
- RegexpFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter)
+ expect(RegexpFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter)
@script.config[:xpatterns] = @ary
@script.register
end
it "creates and registers a TagFilter for include specs" do
- TagFilter.should_receive(:new).with(:include, *@ary).and_return(@filter)
+ expect(TagFilter).to receive(:new).with(:include, *@ary).and_return(@filter)
@script.config[:tags] = @ary
@script.register
end
it "creates and registers a TagFilter for excluded specs" do
- TagFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter)
+ expect(TagFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter)
@script.config[:xtags] = @ary
@script.register
end
it "creates and registers a ProfileFilter for include specs" do
- ProfileFilter.should_receive(:new).with(:include, *@ary).and_return(@filter)
+ expect(ProfileFilter).to receive(:new).with(:include, *@ary).and_return(@filter)
@script.config[:profiles] = @ary
@script.register
end
it "creates and registers a ProfileFilter for excluded specs" do
- ProfileFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter)
+ expect(ProfileFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter)
@script.config[:xprofiles] = @ary
@script.register
end
end
-describe MSpecScript, "#signals" do
+RSpec.describe MSpecScript, "#signals" do
before :each do
@script = MSpecScript.new
@abort = @script.config[:abort]
@@ -334,42 +329,42 @@ describe MSpecScript, "#signals" do
end
it "traps the INT signal if config[:abort] is true" do
- Signal.should_receive(:trap).with("INT")
+ expect(Signal).to receive(:trap).with("INT")
@script.config[:abort] = true
@script.signals
end
it "does not trap the INT signal if config[:abort] is not true" do
- Signal.should_not_receive(:trap).with("INT")
+ expect(Signal).not_to receive(:trap).with("INT")
@script.config[:abort] = false
@script.signals
end
end
-describe MSpecScript, "#entries" do
+RSpec.describe MSpecScript, "#entries" do
before :each do
@script = MSpecScript.new
- File.stub(:realpath).and_return("name")
- File.stub(:file?).and_return(false)
- File.stub(:directory?).and_return(false)
+ allow(File).to receive(:realpath).and_return("name")
+ allow(File).to receive(:file?).and_return(false)
+ allow(File).to receive(:directory?).and_return(false)
end
it "returns the pattern in an array if it is a file" do
- File.should_receive(:realpath).with("file").and_return("file/expanded.rb")
- File.should_receive(:file?).with("file/expanded.rb").and_return(true)
- @script.entries("file").should == ["file/expanded.rb"]
+ expect(File).to receive(:realpath).with("file").and_return("file/expanded.rb")
+ expect(File).to receive(:file?).with("file/expanded.rb").and_return(true)
+ expect(@script.entries("file")).to eq(["file/expanded.rb"])
end
it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do
- File.should_receive(:directory?).with("name").and_return(true)
- File.stub(:realpath).and_return("name", "name/**/*_spec.rb")
- Dir.should_receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"])
- @script.entries("name").should == ["dir1", "dir2"]
+ expect(File).to receive(:directory?).with("name").and_return(true)
+ allow(File).to receive(:realpath).and_return("name", "name/**/*_spec.rb")
+ expect(Dir).to receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"])
+ expect(@script.entries("name")).to eq(["dir1", "dir2"])
end
it "aborts if pattern cannot be resolved to a file nor a directory" do
- @script.should_receive(:abort)
+ expect(@script).to receive(:abort)
@script.entries("pattern")
end
@@ -382,47 +377,47 @@ describe MSpecScript, "#entries" do
it "returns the pattern in an array if it is a file" do
name = "#{@name}.rb"
- File.should_receive(:realpath).with(name).and_return(name)
- File.should_receive(:file?).with(name).and_return(true)
- @script.entries("name.rb").should == [name]
+ expect(File).to receive(:realpath).with(name).and_return(name)
+ expect(File).to receive(:file?).with(name).and_return(true)
+ expect(@script.entries("name.rb")).to eq([name])
end
it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do
- File.stub(:realpath).and_return(@name, @name+"/**/*_spec.rb")
- File.should_receive(:directory?).with(@name).and_return(true)
- Dir.should_receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"])
- @script.entries("name").should == ["dir1", "dir2"]
+ allow(File).to receive(:realpath).and_return(@name, @name+"/**/*_spec.rb")
+ expect(File).to receive(:directory?).with(@name).and_return(true)
+ expect(Dir).to receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"])
+ expect(@script.entries("name")).to eq(["dir1", "dir2"])
end
it "aborts if pattern cannot be resolved to a file nor a directory" do
- @script.should_receive(:abort)
+ expect(@script).to receive(:abort)
@script.entries("pattern")
end
end
end
-describe MSpecScript, "#files" do
+RSpec.describe MSpecScript, "#files" do
before :each do
@script = MSpecScript.new
end
- it "accumlates the values returned by #entries" do
- @script.should_receive(:entries).and_return(["file1"], ["file2"])
- @script.files(["a", "b"]).should == ["file1", "file2"]
+ it "accumulates the values returned by #entries" do
+ expect(@script).to receive(:entries).and_return(["file1"], ["file2"])
+ expect(@script.files(["a", "b"])).to eq(["file1", "file2"])
end
it "strips a leading '^' and removes the values returned by #entries" do
- @script.should_receive(:entries).and_return(["file1"], ["file2"], ["file1"])
- @script.files(["a", "b", "^a"]).should == ["file2"]
+ expect(@script).to receive(:entries).and_return(["file1"], ["file2"], ["file1"])
+ expect(@script.files(["a", "b", "^a"])).to eq(["file2"])
end
it "processes the array elements in order" do
- @script.should_receive(:entries).and_return(["file1"], ["file1"], ["file2"])
- @script.files(["^a", "a", "b"]).should == ["file1", "file2"]
+ expect(@script).to receive(:entries).and_return(["file1"], ["file1"], ["file2"])
+ expect(@script.files(["^a", "a", "b"])).to eq(["file1", "file2"])
end
end
-describe MSpecScript, "#files" do
+RSpec.describe MSpecScript, "#files" do
before :each do
MSpecScript.set :files, ["file1", "file2"]
@@ -434,21 +429,21 @@ describe MSpecScript, "#files" do
end
it "looks up items with leading ':' in the config object" do
- @script.should_receive(:entries).and_return(["file1"], ["file2"])
- @script.files([":files"]).should == ["file1", "file2"]
+ expect(@script).to receive(:entries).and_return(["file1"], ["file2"])
+ expect(@script.files([":files"])).to eq(["file1", "file2"])
end
it "aborts if the config key is not set" do
- @script.should_receive(:abort).with("Key :all_files not found in mspec config.")
+ expect(@script).to receive(:abort).with("Key :all_files not found in mspec config.")
@script.files([":all_files"])
end
end
-describe MSpecScript, "#setup_env" do
+RSpec.describe MSpecScript, "#setup_env" do
before :each do
@script = MSpecScript.new
@options, @config = new_option
- @script.stub(:config).and_return(@config)
+ allow(@script).to receive(:config).and_return(@config)
end
after :each do
@@ -457,19 +452,19 @@ describe MSpecScript, "#setup_env" do
it "sets MSPEC_RUNNER = '1' in the environment" do
ENV["MSPEC_RUNNER"] = "0"
@script.setup_env
- ENV["MSPEC_RUNNER"].should == "1"
+ expect(ENV["MSPEC_RUNNER"]).to eq("1")
end
it "sets RUBY_EXE = config[:target] in the environment" do
ENV["RUBY_EXE"] = nil
@script.setup_env
- ENV["RUBY_EXE"].should == @config[:target]
+ expect(ENV["RUBY_EXE"]).to eq(@config[:target])
end
it "sets RUBY_FLAGS = config[:flags] in the environment" do
ENV["RUBY_FLAGS"] = nil
@config[:flags] = ["-w", "-Q"]
@script.setup_env
- ENV["RUBY_FLAGS"].should == "-w -Q"
+ expect(ENV["RUBY_FLAGS"]).to eq("-w -Q")
end
end
diff --git a/spec/mspec/spec/utils/version_spec.rb b/spec/mspec/spec/utils/version_spec.rb
index 0b2d383c6d..ec367d2a1e 100644
--- a/spec/mspec/spec/utils/version_spec.rb
+++ b/spec/mspec/spec/utils/version_spec.rb
@@ -1,45 +1,45 @@
require 'spec_helper'
require 'mspec/utils/version'
-describe SpecVersion, "#to_s" do
+RSpec.describe SpecVersion, "#to_s" do
it "returns the string with which it was initialized" do
- SpecVersion.new("1.8").to_s.should == "1.8"
- SpecVersion.new("2.118.9").to_s.should == "2.118.9"
+ expect(SpecVersion.new("1.8").to_s).to eq("1.8")
+ expect(SpecVersion.new("2.118.9").to_s).to eq("2.118.9")
end
end
-describe SpecVersion, "#to_str" do
+RSpec.describe SpecVersion, "#to_str" do
it "returns the same string as #to_s" do
version = SpecVersion.new("2.118.9")
- version.to_str.should == version.to_s
+ expect(version.to_str).to eq(version.to_s)
end
end
-describe SpecVersion, "#to_i with ceil = false" do
+RSpec.describe SpecVersion, "#to_i with ceil = false" do
it "returns an integer representation of the version string" do
- SpecVersion.new("2.23.10").to_i.should == 1022310
+ expect(SpecVersion.new("2.23.10").to_i).to eq(1022310)
end
it "replaces missing version parts with zeros" do
- SpecVersion.new("1.8").to_i.should == 1010800
- SpecVersion.new("1.8.6").to_i.should == 1010806
+ expect(SpecVersion.new("1.8").to_i).to eq(1010800)
+ expect(SpecVersion.new("1.8.6").to_i).to eq(1010806)
end
end
-describe SpecVersion, "#to_i with ceil = true" do
+RSpec.describe SpecVersion, "#to_i with ceil = true" do
it "returns an integer representation of the version string" do
- SpecVersion.new("1.8.6", true).to_i.should == 1010806
+ expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806)
end
it "fills in 9s for missing tiny values" do
- SpecVersion.new("1.8", true).to_i.should == 1010899
- SpecVersion.new("1.8.6", true).to_i.should == 1010806
+ expect(SpecVersion.new("1.8", true).to_i).to eq(1010899)
+ expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806)
end
end
-describe SpecVersion, "#to_int" do
+RSpec.describe SpecVersion, "#to_int" do
it "returns the same value as #to_i" do
version = SpecVersion.new("4.16.87")
- version.to_int.should == version.to_i
+ expect(version.to_int).to eq(version.to_i)
end
end
diff --git a/spec/mspec/tool/check_require_spec_helper.rb b/spec/mspec/tool/check_require_spec_helper.rb
new file mode 100755
index 0000000000..07126e68dc
--- /dev/null
+++ b/spec/mspec/tool/check_require_spec_helper.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+
+# This script is used to check that each *_spec.rb file has
+# a relative_require for spec_helper which should live higher
+# up in the ruby/spec repo directory tree.
+#
+# Prints errors to $stderr and returns a non-zero exit code when
+# errors are found.
+#
+# Related to https://github.com/ruby/spec/pull/992
+
+def check_file(fn)
+ File.foreach(fn) do |line|
+ return $1 if line =~ /^\s*require_relative\s*['"](.*spec_helper)['"]/
+ end
+ nil
+end
+
+rootdir = ARGV[0] || "."
+fglob = File.join(rootdir, "**", "*_spec.rb")
+specfiles = Dir.glob(fglob)
+raise "No spec files found in #{fglob.inspect}. Give an argument to specify the root-directory of ruby/spec" if specfiles.empty?
+
+errors = 0
+specfiles.sort.each do |fn|
+ result = check_file(fn)
+ if result.nil?
+ warn "Missing require_relative for *spec_helper for file: #{fn}"
+ errors += 1
+ end
+end
+
+puts "# Found #{errors} files with require_relative spec_helper issues."
+exit 1 if errors > 0
diff --git a/spec/mspec/tool/pull-latest-mspec-spec b/spec/mspec/tool/pull-latest-mspec-spec
index 62c1f8fefa..154a353e64 100755
--- a/spec/mspec/tool/pull-latest-mspec-spec
+++ b/spec/mspec/tool/pull-latest-mspec-spec
@@ -3,17 +3,24 @@
# Assumes all commits have been synchronized to https://github.com/ruby/spec
# See spec/mspec/tool/sync/sync-rubyspec.rb
-rm -rf spec/mspec
-git clone --depth 1 https://github.com/ruby/mspec.git spec/mspec
-commit=$(git -C spec/mspec log -n 1 --format='%h')
-rm -rf spec/mspec/.git
-rm -f spec/mspec/.travis.yml
-git add spec/mspec
-git commit -m "Update to ruby/mspec@${commit}"
+function sync {
+ dir="$1"
+ repo="$2"
+ short_repo_name="ruby/$(basename "$repo" .git)"
-rm -rf spec/ruby
-git clone --depth 1 https://github.com/ruby/spec.git spec/ruby
-commit=$(git -C spec/ruby log -n 1 --format='%h')
-rm -rf spec/ruby/.git
-git add spec/ruby
-git commit -m "Update to ruby/spec@${commit}"
+ rm -rf "$dir"
+ git clone --depth 1 "$repo" "$dir"
+ commit=$(git -C "$dir" log -n 1 --format='%h')
+ rm -rf "$dir/.git"
+
+ # Remove CI files to avoid confusion
+ rm -f "$dir/appveyor.yml"
+ rm -f "$dir/.travis.yml"
+ rm -rf "$dir/.github"
+
+ git add "$dir"
+ git commit -m "Update to ${short_repo_name}@${commit}"
+}
+
+sync spec/mspec https://github.com/ruby/mspec.git
+sync spec/ruby https://github.com/ruby/spec.git
diff --git a/spec/mspec/tool/remove_old_guards.rb b/spec/mspec/tool/remove_old_guards.rb
index 8b036d07f5..bc5612c78d 100644..100755
--- a/spec/mspec/tool/remove_old_guards.rb
+++ b/spec/mspec/tool/remove_old_guards.rb
@@ -1,4 +1,23 @@
-# Remove old version guards in ruby/spec
+#!/usr/bin/env ruby
+
+# Removes old version guards in ruby/spec.
+# Run it from the ruby/spec repository root.
+# The argument is the new minimum supported version.
+#
+# cd spec
+# ../mspec/tool/remove_old_guards.rb <ruby-version>
+#
+# where <ruby-version> is a version guard with which should be removed
+#
+# Example:
+# tool/remove_old_guards.rb 3.1
+#
+# As a result guards like
+# ruby_version_is "3.1" do
+# # ...
+# end
+#
+# will be removed.
def dedent(line)
if line.start_with?(" ")
@@ -8,34 +27,119 @@ def dedent(line)
end
end
+def each_spec_file(&block)
+ Dir["*/**/*.rb"].each(&block)
+end
+
+def each_file(&block)
+ Dir["**/*"].each { |path|
+ yield path if File.file?(path)
+ }
+end
+
def remove_guards(guard, keep)
- Dir["*/**/*.rb"].each do |file|
- contents = File.read(file)
+ each_spec_file do |file|
+ contents = File.binread(file)
if contents =~ guard
puts file
lines = contents.lines.to_a
while first = lines.find_index { |line| line =~ guard }
+ comment = first
+ while comment > 0 and lines[comment-1] =~ /^(\s*)#/
+ comment -= 1
+ end
indent = lines[first][/^(\s*)/, 1].length
last = (first+1...lines.size).find { |i|
space = lines[i][/^(\s*)end$/, 1] and space.length == indent
}
raise file unless last
if keep
- lines[first..last] = lines[first+1..last-1].map { |l| dedent(l) }
+ lines[comment..last] = lines[first+1..last-1].map { |l| dedent(l) }
else
- if first > 0 and lines[first-1] == "\n"
- first -= 1
+ if comment > 0 and lines[comment-1] == "\n"
+ comment -= 1
elsif lines[last+1] == "\n"
last += 1
end
- lines[first..last] = []
+ lines[comment..last] = []
end
end
- File.write file, lines.join
+ File.binwrite file, lines.join
+ end
+ end
+end
+
+def remove_empty_files
+ each_spec_file do |file|
+ unless file.include?("fixtures/")
+ lines = File.readlines(file)
+ if lines.all? { |line| line.chomp.empty? or line.start_with?('require', '#') }
+ puts "Removing empty file #{file}"
+ File.delete(file)
+ end
end
end
end
-version = (ARGV[0] || "2.3")
-remove_guards(/ruby_version_is ["']#{version}["'] do/, true)
-remove_guards(/ruby_version_is ["'][0-9.]*["']...["']#{version}["'] do/, false)
+def remove_unused_shared_specs
+ shared_groups = {}
+ # Dir["**/shared/**/*.rb"].each do |shared|
+ each_spec_file do |shared|
+ next if File.basename(shared) == 'constants.rb'
+ contents = File.binread(shared)
+ found = false
+ contents.scan(/^\s*describe (:[\w_?]+), shared: true do$/) {
+ shared_groups[$1] = 0
+ found = true
+ }
+ if !found and shared.include?('shared/') and !shared.include?('fixtures/') and !shared.end_with?('/constants.rb')
+ puts "no shared describe in #{shared} ?"
+ end
+ end
+
+ each_spec_file do |file|
+ contents = File.binread(file)
+ contents.scan(/(?:it_behaves_like|it_should_behave_like) (:[\w_?]+)[,\s]/) do
+ puts $1 unless shared_groups.key?($1)
+ shared_groups[$1] += 1
+ end
+ end
+
+ shared_groups.each_pair do |group, value|
+ if value == 0
+ puts "Shared describe #{group} seems unused"
+ elsif value == 1
+ puts "Shared describe #{group} seems used only once" if $VERBOSE
+ end
+ end
+end
+
+def search(regexp)
+ each_file do |file|
+ contents = File.binread(file)
+ if contents =~ regexp
+ puts file
+ contents.each_line do |line|
+ if line =~ regexp
+ puts line
+ end
+ end
+ end
+ end
+end
+
+abort "usage: #{$0} <ruby-version>" if ARGV.empty?
+
+version = Regexp.escape(ARGV.fetch(0))
+version += "(?:\\.0)?" if version.count(".") < 2
+remove_guards(/ruby_version_is (["'])#{version}\1 do/, true)
+remove_guards(/ruby_version_is (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, false)
+remove_guards(/ruby_bug ["']#\d+["'], (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, true)
+
+remove_empty_files
+remove_unused_shared_specs
+
+puts "Search:"
+search(/(["'])#{version}\1/)
+search(/^\s*#.+#{version}/)
+search(/RUBY_VERSION_IS_#{version.tr('.', '_')}/)
diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb
index 120a4ad64c..86c43d0dc8 100644
--- a/spec/mspec/tool/sync/sync-rubyspec.rb
+++ b/spec/mspec/tool/sync/sync-rubyspec.rb
@@ -1,6 +1,9 @@
+# This script is based on commands from the wiki:
+# https://github.com/ruby/spec/wiki/Merging-specs-from-JRuby-and-other-sources
+
IMPLS = {
truffleruby: {
- git: "https://github.com/oracle/truffleruby.git",
+ git: "https://github.com/truffleruby/truffleruby.git",
from_commit: "f10ab6988d",
},
jruby: {
@@ -12,12 +15,16 @@ IMPLS = {
},
mri: {
git: "https://github.com/ruby/ruby.git",
- master: "trunk",
},
}
MSPEC = ARGV.delete('--mspec')
+CHECK_LAST_MERGE = !MSPEC && ENV['CHECK_LAST_MERGE'] != 'false'
+TEST_MASTER = ENV['TEST_MASTER'] != 'false'
+
+ONLY_FILTER = ENV['ONLY_FILTER'] == 'true'
+
MSPEC_REPO = File.expand_path("../../..", __FILE__)
raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git")
@@ -27,12 +34,22 @@ raise RUBYSPEC_REPO unless Dir.exist?(RUBYSPEC_REPO)
SOURCE_REPO = MSPEC ? MSPEC_REPO : RUBYSPEC_REPO
+# LAST_MERGE is a commit of ruby/spec or ruby/mspec
+# which is the spec/mspec commit that was last imported in the Ruby implementation
+# (i.e. the commit in "Update to ruby/spec@commit").
+# It is normally automatically computed, but can be manually set when
+# e.g. the last update of specs wasn't merged in the Ruby implementation.
+LAST_MERGE = ENV["LAST_MERGE"]
+
NOW = Time.now
BRIGHT_RED = "\e[31;1m"
BRIGHT_YELLOW = "\e[33;1m"
RESET = "\e[0m"
+# git filter-branch --subdirectory-filter works fine for our use case
+ENV['FILTER_BRANCH_SQUELCH_WARNING'] = '1'
+
class RubyImplementation
attr_reader :name
@@ -45,14 +62,14 @@ class RubyImplementation
@data[:git]
end
- def default_branch
- @data[:master] || "master"
- end
-
def repo_name
File.basename(git_url, ".git")
end
+ def repo_path
+ "#{__dir__}/#{repo_name}"
+ end
+
def repo_org
File.basename(File.dirname(git_url))
end
@@ -96,7 +113,7 @@ def update_repo(impl)
Dir.chdir(impl.repo_name) do
puts Dir.pwd
- sh "git", "checkout", impl.default_branch
+ sh "git", "checkout", "master"
sh "git", "pull"
end
end
@@ -132,22 +149,27 @@ def rebase_commits(impl)
else
sh "git", "checkout", impl.name
- if ENV["LAST_MERGE"]
- last_merge = `git log -n 1 --format='%H %ct' #{ENV["LAST_MERGE"]}`
+ if LAST_MERGE
+ last_merge = `git log -n 1 --format='%H %ct' #{LAST_MERGE}`
else
last_merge = `git log --grep='^#{impl.last_merge_message}' -n 1 --format='%H %ct'`
end
- last_merge, commit_timestamp = last_merge.chomp.split(' ')
+ last_merge, commit_timestamp = last_merge.split(' ')
raise "Could not find last merge" unless last_merge
puts "Last merge is #{last_merge}"
commit_date = Time.at(Integer(commit_timestamp))
days_since_last_merge = (NOW-commit_date) / 86400
- if days_since_last_merge > 60
+ if CHECK_LAST_MERGE and days_since_last_merge > 60
raise "#{days_since_last_merge.floor} days since last merge, probably wrong commit"
end
+ puts "Checking if the last merge is consistent with upstream files"
+ rubyspec_commit = `git log -n 1 --format='%s' #{last_merge}`.chomp.split('@', 2)[-1]
+ sh "git", "checkout", last_merge
+ sh "git", "diff", "--exit-code", rubyspec_commit, "--", ":!.github"
+
puts "Rebasing..."
sh "git", "branch", "-D", rebased if branch?(rebased)
sh "git", "checkout", "-b", rebased, impl.name
@@ -156,43 +178,40 @@ def rebase_commits(impl)
end
end
+def new_commits?(impl)
+ Dir.chdir(SOURCE_REPO) do
+ diff = `git diff master #{impl.rebased_branch}`
+ !diff.empty?
+ end
+end
+
def test_new_specs
require "yaml"
Dir.chdir(SOURCE_REPO) do
- versions = YAML.load_file(".travis.yml")
- versions = versions["matrix"]["include"].map { |job| job["rvm"] }
- versions.delete "ruby-head"
- versions.delete "system"
+ workflow = YAML.load_file(".github/workflows/ci.yml")
+ job_name = MSPEC ? "test" : "specs"
+ versions = workflow.dig("jobs", job_name, "strategy", "matrix", "ruby").map(&:to_s)
+ versions = versions.grep(/^\d+\./) # Test on MRI
min_version, max_version = versions.minmax
- test_command = MSPEC ? "bundle exec rspec" : "../mspec/bin/mspec -j"
+ test_command = MSPEC ? "bundle install && bundle exec rspec" : "../mspec/bin/mspec -j"
run_test = -> version {
- command = "chruby #{version} && #{test_command}"
+ command = "chruby ruby-#{version} && #{test_command}"
sh ENV["SHELL"], "-c", command
}
run_test[min_version]
run_test[max_version]
- run_test["trunk"]
- end
-end
-
-def verify_commits(impl)
- puts
- Dir.chdir(SOURCE_REPO) do
- puts "Manually check commit messages:"
- print "Press enter >"
- STDIN.gets
- sh "git", "log", "master..."
+ run_test["master"] if TEST_MASTER
end
end
def fast_forward_master(impl)
Dir.chdir(SOURCE_REPO) do
sh "git", "checkout", "master"
- sh "git", "merge", "--ff-only", "#{impl.name}-rebased"
- sh "git", "branch", "--delete", "#{impl.name}-rebased"
+ sh "git", "merge", "--ff-only", impl.rebased_branch
+ sh "git", "branch", "--delete", impl.rebased_branch
end
end
@@ -210,11 +229,17 @@ def main(impls)
impl = RubyImplementation.new(impl, data)
update_repo(impl)
filter_commits(impl)
- rebase_commits(impl)
- test_new_specs
- verify_commits(impl)
- fast_forward_master(impl)
- check_ci
+ unless ONLY_FILTER
+ rebase_commits(impl)
+ if new_commits?(impl)
+ test_new_specs
+ fast_forward_master(impl)
+ check_ci
+ else
+ STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}"
+ fast_forward_master(impl)
+ end
+ end
end
end
diff --git a/spec/mspec/tool/tag_from_output.rb b/spec/mspec/tool/tag_from_output.rb
new file mode 100755
index 0000000000..41aa70f932
--- /dev/null
+++ b/spec/mspec/tool/tag_from_output.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+
+# Adds tags based on error and failures output (e.g., from a CI log),
+# without running any spec code.
+
+tag = ENV["TAG"] || "fails"
+
+tags_dir = %w[
+ spec/tags
+ spec/tags/ruby
+].find { |dir| Dir.exist?("#{dir}/language") }
+abort 'Could not find tags directory' unless tags_dir
+
+output = ARGF.readlines
+
+# Automatically strip datetime of GitHub Actions
+if output.first =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z /
+ output = output.map { |line| line.split(' ', 2).last }
+end
+
+NUMBER = /^\d+\)$/
+ERROR_OR_FAILED = / (ERROR|FAILED)$/
+SPEC_FILE = /^((?:\/|[CD]:\/).+_spec\.rb)\:\d+/
+
+output.slice_before(NUMBER).select { |number, *rest|
+ number =~ NUMBER and rest.any? { |line| line =~ ERROR_OR_FAILED }
+}.each { |number, *rest|
+ error_line = rest.find { |line| line =~ ERROR_OR_FAILED }
+ description = error_line.match(ERROR_OR_FAILED).pre_match
+
+ spec_file = rest.find { |line| line =~ SPEC_FILE }
+ if spec_file
+ spec_file = spec_file[SPEC_FILE, 1] or raise
+ else
+ if error_line =~ /^([\w:]+)[#\.](\w+) /
+ mod, method = $1, $2
+ file = "#{mod.downcase.gsub('::', '/')}/#{method}_spec.rb"
+ spec_file = ['spec/ruby/core', 'spec/ruby/library', *Dir.glob('spec/ruby/library/*')].find { |dir|
+ path = "#{dir}/#{file}"
+ break path if File.exist?(path)
+ }
+ end
+
+ unless spec_file
+ warn "Could not find file for:\n#{error_line}"
+ next
+ end
+ end
+
+ prefix = spec_file.index('spec/ruby/') || spec_file.index('spec/truffle/')
+ spec_file = spec_file[prefix..-1]
+
+ tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub('spec/truffle/', "#{tags_dir}/truffle/")
+ tags_file = tags_file.sub(/_spec\.rb$/, '_tags.txt')
+
+ dir = File.dirname(tags_file)
+ Dir.mkdir(dir) unless Dir.exist?(dir)
+
+ tag_line = "#{tag}:#{description}"
+ lines = File.exist?(tags_file) ? File.readlines(tags_file, chomp: true) : []
+ unless lines.include?(tag_line)
+ puts tags_file
+ File.write(tags_file, (lines + [tag_line]).join("\n") + "\n")
+ end
+}
diff --git a/spec/mspec/tool/wrap_with_guard.rb b/spec/mspec/tool/wrap_with_guard.rb
new file mode 100755
index 0000000000..5b1bf4d7f7
--- /dev/null
+++ b/spec/mspec/tool/wrap_with_guard.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+# Wrap the passed the files with a guard (e.g., `ruby_version_is ""..."3.0"`).
+# Notably if some methods are removed, this is a convenient way to skip such file from a given version.
+# Example usage:
+# $ spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.0"' spec/ruby/library/set/sortedset/**/*_spec.rb
+
+guard, *files = ARGV
+abort "Usage: #{$0} GUARD FILES..." if files.empty?
+
+files.each do |file|
+ contents = File.binread(file)
+ lines = contents.lines.to_a
+
+ lines = lines.map { |line| line.chomp.empty? ? line : " #{line}" }
+
+ version_line = "#{guard} do\n"
+ if lines[0] =~ /^\s*require.+spec_helper/
+ lines[0] = lines[0].sub(/^ /, '')
+ lines.insert 1, "\n", version_line
+ else
+ warn "Could not find 'require spec_helper' line in #{file}"
+ lines.insert 0, version_line
+ end
+
+ lines << "end\n"
+
+ File.binwrite file, lines.join
+end
diff --git a/spec/ruby/.mspec.constants b/spec/ruby/.mspec.constants
new file mode 100644
index 0000000000..4da3633715
--- /dev/null
+++ b/spec/ruby/.mspec.constants
@@ -0,0 +1,236 @@
+Abbrev
+Addrinfo
+AliasObject
+AliasObject2
+AnonWithConstant
+ArbitraryException
+ArraySub
+ArraySubPush
+AryChild
+Base64
+BaseClass
+BasicSocket
+BeCloseToMatrixMatcher
+BigDecimal
+BigMath
+BitwiseAndTest
+BreakTest
+BreakTest2
+CAPI_SIZEOF_LONG
+CApiModuleSpecsAutoload
+CApiModuleSpecsModuleA
+CGI
+CMath
+CODE_LOADING_DIR
+CSAutoloadA
+CSAutoloadB
+CSAutoloadC
+CSAutoloadD
+CSV
+ChainedNextTest
+ChildClass
+ClassIdUnderAutoload
+ClassSpecDefineClass
+ClassSpecsKeywordWithSemicolon
+ClassSpecsKeywordWithoutSemicolon
+ClassSpecsNumber
+ClassUnderAutoload
+CodingUS_ASCII
+CodingUTF_8
+ComparisonTest
+ConstantSpecsIncludedModule
+ConstantSpecsTwo
+ConstantSpecsThree
+ConstantVisibility
+Coverage
+CoverageSpecs
+CustomArgumentError
+DRb
+DRbIdConv
+DRbObject
+DRbUndumped
+Date
+DateTime
+DefSpecNested
+DefSpecNestedB
+DefSpecSingleton
+DefSpecsLambdaVisibility
+DefineMethodByProcClass
+DefineMethodSpecClass
+DefineSingletonMethodSpecClass
+Delegator
+DescArray
+DescObjectTest
+Digest
+DumpableDir
+ERB
+EnsureInClassExample
+EnumerableSpecGrep
+EnumerableSpecGrep2
+EnumerableSpecIncludeP
+EnumerableSpecIncludeP11
+Etc
+EvalBindingA
+EvalBindingProcA
+Exception2MessageMapper
+ExceptionForMatrix
+Fcntl
+Fiddle
+FileStat
+FileUtils
+Find
+Forwardable
+GetoptLong
+HMACConstants
+HashStringsBinary
+HashStringsUSASCII
+HashStringsUTF8
+IPAddr
+IPSocket
+Importer
+IncludeSpecsClass
+IncludeSpecsMiddle
+IncludeSpecsTop
+IncludesMath
+JSON
+KSAutoloadA
+KSAutoloadB
+KSAutoloadBB
+KSAutoloadCallsRequire
+KSAutoloadD
+Logger
+MD5Constants
+MY_INPUT4_FOR_ERB
+Matrix
+MatrixSub
+MethodArity
+Meths
+MethsMore
+Mixin
+ModuleSpecsKeywordWithoutSemicolon
+ModuleSpecsToplevel
+ModuleSpecs_CS1
+ModuleSpecs_CS2
+ModuleSpecs_CS3
+MyClass
+MyClass0ForErb
+MyClass1ForErb
+MyClass1ForErb_
+MyClass2ForErb
+MyClass4ForErb
+MyFiber
+MyModule2ForErb
+MyString
+NamespaceTest
+Net
+OBJDIR
+OBJECT_SPACE_TOP_LEVEL_CONSTANT
+OFor
+ObjectSpaceFixtures
+ObjectSpecDup
+ObjectSpecDupInitCopy
+ObjectTest
+Observable
+Open3
+OpenSSL
+OpenStruct
+OperatorImplementor
+OptParse
+OptionParser
+OrAndXorTest
+OtherCustomException
+ParentClass
+Pathname
+Person
+Prime
+Private
+ProcFromMethod
+Psych
+RactorLocalSingleton
+REXML
+RUBY_SIGNALS
+RbReadline
+Readline
+ReceiverClass
+RegexpSpecsSubclass
+RegexpSpecsSubclassTwo
+Reline
+RescueInClassExample
+Resolv
+Ripper
+SHA1Constants
+SHA256Constants
+SHA384Constants
+SHA512Constants
+SameName
+ScanError
+Scanf
+SecondClass
+SecureRandom
+Set
+Shellwords
+SimpleDelegator
+SingleForwardable
+Singleton
+Socket
+SocketError
+SomeClass
+SortedSet
+SpecificExampleException
+Specs
+StrChild
+StrangeEach
+StringIO
+StringRefinement
+StringScanner
+StringSubclass
+StructClasses
+Syck
+Syslog
+TCPServer
+TCPSocket
+TSort
+Tempfile
+TestServer
+Timeout
+TimeoutError
+UDPSocket
+UNIXServer
+UNIXSocket
+URI
+UnaryMinusTest
+UnicodeNormalize
+UnloadableDumpableDir
+UserArray
+UserCustomConstructorString
+UserDefined
+UserDefinedImmediate
+UserDefinedString
+UserDefinedWithIvar
+UserHash
+UserHashInitParams
+UserMarshal
+UserMarshalWithClassName
+UserMarshalWithIvar
+UserObject
+UserPreviouslyDefinedWithInitializedIvar
+UserRegexp
+UserString
+Vector
+WEBrick
+WIN32OLE
+WIN32OLEQueryInterfaceError
+WIN32OLERuntimeError
+WIN32OLE_EVENT
+WIN32OLE_METHOD
+WIN32OLE_PARAM
+WIN32OLE_RECORD
+WIN32OLE_RUBYSPEC
+WIN32OLE_TYPE
+WIN32OLE_TYPELIB
+WIN32OLE_VARIABLE
+WIN32OLE_VARIANT
+WeakRef
+Win32
+YAML
+Zlib
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index 58529f15b2..0b5dcb80a2 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,20 +1,29 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 2.4
+ TargetRubyVersion: 3.2
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
+ - core/exception/fixtures/syntax_error.rb
DisabledByDefault: true
+ NewCops: disable
+
+Layout/IndentationConsistency:
+ Enabled: true
Layout/TrailingWhitespace:
Enabled: true
-Layout/TrailingBlankLines:
+Layout/TrailingEmptyLines:
Enabled: true
Exclude:
- library/coverage/fixtures/some_class.rb
+Layout/SpaceInLambdaLiteral:
+ Enabled: true
+ EnforcedStyle: require_space
+
Lint:
Enabled: true
@@ -28,16 +37,27 @@ Lint/AssignmentInCondition:
Lint/BooleanSymbol:
Enabled: false
+Lint/DeprecatedOpenSSLConstant:
+ Exclude:
+ - library/openssl/digest/**/*.rb
+
Lint/InterpolationCheck:
Enabled: false
Lint/LiteralAsCondition:
Enabled: false
-Lint/UnneededRequireStatement:
+# Required to support Ruby 3.0
+Lint/RedundantRequireStatement:
+ Exclude:
+ - core/fiber/**/*.rb
+ - library/fiber/**/*.rb
+ - optional/capi/fiber_spec.rb
+
+Lint/RedundantSplatExpansion:
Enabled: false
-Lint/UnneededSplatExpansion:
+Lint/RescueException:
Enabled: false
Lint/UnifiedInteger:
@@ -52,12 +72,58 @@ Lint/UnusedMethodArgument:
Lint/UselessAssignment:
Enabled: false
-Lint/UselessComparison:
+Lint/BinaryOperatorWithIdenticalOperands:
Enabled: false
+Lint/EmptyConditionalBody:
+ Enabled: false # buggy
+
Lint/Void:
Enabled: false
+Lint/ConstantDefinitionInBlock:
+ Enabled: false
+
+Lint/RaiseException:
+ Enabled: false
+
+Lint/FloatComparison:
+ Enabled: false
+
+Lint/DeprecatedClassMethods:
+ Enabled: false
+
+Lint/UnreachableLoop:
+ Enabled: false
+
+Lint/MissingSuper:
+ Enabled: false
+
+Lint/UselessMethodDefinition:
+ Enabled: false
+
+Lint/UselessTimes:
+ Enabled: false
+
+Lint/MixedRegexpCaptureTypes:
+ Enabled: false
+
+Lint/DuplicateElsifCondition:
+ Enabled: false
+
+Lint/OutOfRangeRegexpRef:
+ Enabled: false
+
+Lint/InheritException:
+ Enabled: false
+
+Lint/SafeNavigationChain:
+ Enabled: false
+
+Lint/ElseLayout:
+ Exclude:
+ - 'language/if_spec.rb'
+
Lint/EmptyExpression:
Exclude:
- 'language/**/*.rb'
@@ -67,6 +133,10 @@ Lint/EmptyWhen:
- language/case_spec.rb
- optional/capi/spec_helper.rb
+Lint/ErbNewArguments:
+ Exclude:
+ - 'library/erb/new_spec.rb'
+
Lint/FormatParameterMismatch:
Exclude:
- 'core/kernel/shared/sprintf.rb'
@@ -77,12 +147,21 @@ Lint/NestedMethodDefinition:
- language/def_spec.rb
- language/fixtures/def.rb
+Lint/ShadowingOuterLocalVariable:
+ Exclude:
+ - 'core/binding/local_variables_spec.rb'
+ - 'core/kernel/local_variables_spec.rb'
+ - 'language/block_spec.rb'
+ - 'language/proc_spec.rb'
+
Lint/UnreachableCode:
Exclude:
- 'core/enumerator/lazy/fixtures/classes.rb'
- 'core/kernel/catch_spec.rb'
+ - 'core/kernel/raise_spec.rb'
- 'core/kernel/throw_spec.rb'
- 'language/break_spec.rb'
+ - 'language/optional_assignments_spec.rb'
- 'language/fixtures/break.rb'
- 'language/fixtures/break_lambda_toplevel.rb'
- 'language/fixtures/break_lambda_toplevel_block.rb'
@@ -96,3 +175,30 @@ Lint/UnreachableCode:
Lint/UriRegexp:
Exclude:
- 'library/uri/regexp_spec.rb'
+
+Lint/Debugger:
+ Exclude:
+ - 'core/binding/fixtures/irb.rb'
+
+Lint/Loop:
+ Enabled: false
+
+Style/BlockComments:
+ Enabled: true
+
+Style/Lambda:
+ Enabled: true
+ EnforcedStyle: literal
+ Exclude:
+ - 'language/lambda_spec.rb'
+ - 'language/proc_spec.rb'
+ - 'language/numbered_parameters_spec.rb'
+ - 'language/it_parameter_spec.rb'
+ - 'core/kernel/lambda_spec.rb'
+
+Style/EmptyLambdaParameter:
+ Enabled: true
+
+Style/StabbyLambdaParentheses:
+ Enabled: true
+ EnforcedStyle: require_no_parentheses
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index 25c67ade02..f998002c6d 100644
--- a/spec/ruby/.rubocop_todo.yml
+++ b/spec/ruby/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2018-04-03 22:23:59 +0900 using RuboCop version 0.54.0.
+# on 2026-05-29 08:10:07 UTC using RuboCop version 1.86.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -11,16 +11,22 @@ Lint/DuplicateCaseCondition:
Exclude:
- 'language/case_spec.rb'
-# Offense count: 6
+# Offense count: 20
Lint/DuplicateMethods:
Exclude:
- 'core/array/fixtures/encoded_strings.rb'
- 'core/method/fixtures/classes.rb'
+ - 'core/module/const_added_spec.rb'
+ - 'core/module/define_method_spec.rb'
- 'core/module/fixtures/classes.rb'
+ - 'core/module/method_added_spec.rb'
+ - 'core/module/name_spec.rb'
+ - 'core/proc/new_spec.rb'
- 'core/unboundmethod/fixtures/classes.rb'
- 'fixtures/class.rb'
+ - 'language/assignments_spec.rb'
-# Offense count: 5
+# Offense count: 8
Lint/EnsureReturn:
Exclude:
- 'language/fixtures/ensure.rb'
@@ -28,17 +34,21 @@ Lint/EnsureReturn:
- 'language/return_spec.rb'
# Offense count: 10
+Lint/FlipFlop:
+ Exclude:
+ - 'language/if_spec.rb'
+ - 'language/precedence_spec.rb'
+
+# Offense count: 10
Lint/FloatOutOfRange:
Exclude:
- 'core/string/modulo_spec.rb'
-# Offense count: 29
-Lint/HandleExceptions:
- Enabled: false
-
-# Offense count: 2
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
Lint/ImplicitStringConcatenation:
Exclude:
+ - 'core/string/chilled_string_spec.rb'
- 'language/string_spec.rb'
# Offense count: 4
@@ -48,95 +58,75 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb'
-# Offense count: 6
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: runtime_error, standard_error
-Lint/InheritException:
- Exclude:
- - 'core/enumerator/lazy/fixtures/classes.rb'
- - 'core/exception/fixtures/common.rb'
- - 'core/module/fixtures/autoload_ex1.rb'
-
-# Offense count: 5
-# Cop supports --auto-correct.
+# Offense count: 12
+# This cop supports safe autocorrection (--autocorrect).
Lint/LiteralInInterpolation:
Exclude:
- 'core/module/refine_spec.rb'
+ - 'core/string/shared/to_sym.rb'
+ - 'language/alias_spec.rb'
- 'language/defined_spec.rb'
- 'language/fixtures/squiggly_heredoc.rb'
-
-# Offense count: 16
-Lint/Loop:
- Exclude:
- - 'language/until_spec.rb'
- - 'language/while_spec.rb'
+ - 'language/string_spec.rb'
+ - 'language/symbol_spec.rb'
+ - 'language/undef_spec.rb'
# Offense count: 8
-# Cop supports --auto-correct.
-Lint/MultipleCompare:
+# This cop supports safe autocorrection (--autocorrect).
+Lint/MultipleComparison:
Exclude:
- 'language/precedence_spec.rb'
-# Offense count: 12
+# Offense count: 9
+# This cop supports safe autocorrection (--autocorrect).
Lint/ParenthesesAsGroupedExpression:
Exclude:
- - 'core/string/fixtures/freeze_magic_comment.rb'
- 'language/block_spec.rb'
- - 'language/fixtures/send.rb'
- 'language/method_spec.rb'
# Offense count: 1
-# Cop supports --auto-correct.
-Lint/RedundantWithIndex:
- Exclude:
- - 'core/enumerator/with_index_spec.rb'
-
-# Offense count: 26
-Lint/RescueException:
- Exclude:
- - 'command_line/fixtures/debug_info.rb'
- - 'core/dir/fileno_spec.rb'
- - 'core/exception/cause_spec.rb'
- - 'core/exception/no_method_error_spec.rb'
- - 'core/kernel/fixtures/autoload_frozen.rb'
- - 'core/module/autoload_spec.rb'
- - 'core/mutex/sleep_spec.rb'
- - 'core/process/euid_spec.rb'
- - 'core/process/setsid_spec.rb'
- - 'core/process/uid_spec.rb'
- - 'core/thread/abort_on_exception_spec.rb'
- - 'core/thread/shared/exit.rb'
- - 'language/rescue_spec.rb'
- - 'library/erb/filename_spec.rb'
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: AllowedMethods, InferNonNilReceiver, AdditionalNilMethods.
+# AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?
+# AdditionalNilMethods: present?, blank?, try, try!
+Lint/RedundantSafeNavigation:
+ Exclude:
+ - 'language/safe_navigator_spec.rb'
+ - 'language/fixtures/rescue_captures.rb'
# Offense count: 2
-# Configuration parameters: IgnoreImplicitReferences.
-Lint/ShadowedArgument:
+# This cop supports safe autocorrection (--autocorrect).
+Lint/RedundantStringCoercion:
Exclude:
- - 'language/fixtures/super.rb'
+ - 'core/io/print_spec.rb'
-# Offense count: 10
-Lint/ShadowingOuterLocalVariable:
+# Offense count: 1
+# Configuration parameters: AllowRBSInlineAnnotation.
+Lint/SelfAssignment:
Exclude:
- - 'core/binding/local_variables_spec.rb'
- - 'language/block_spec.rb'
- - 'language/proc_spec.rb'
+ - 'core/gc/auto_compact_spec.rb'
-# Offense count: 2
-# Cop supports --auto-correct.
-Lint/StringConversionInInterpolation:
+# Offense count: 4
+# Configuration parameters: IgnoreImplicitReferences.
+Lint/ShadowedArgument:
Exclude:
- - 'core/io/print_spec.rb'
+ - 'language/fixtures/super.rb'
+
+# Offense count: 49
+# Configuration parameters: AllowComments, AllowNil.
+Lint/SuppressedException:
+ Enabled: false
# Offense count: 9
+# Configuration parameters: AllowKeywordBlockArguments.
Lint/UnderscorePrefixedVariableName:
Exclude:
- 'core/io/pipe_spec.rb'
- 'core/io/popen_spec.rb'
- 'language/block_spec.rb'
-# Offense count: 7
+# Offense count: 9
+# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
@@ -144,10 +134,5 @@ Lint/UselessAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'core/module/module_function_spec.rb'
- 'core/module/private_class_method_spec.rb'
+ - 'language/fixtures/def.rb'
- 'language/fixtures/send.rb'
-
-# Offense count: 6186
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
-# URISchemes: http, https
-Metrics/LineLength:
- Max: 588
diff --git a/spec/ruby/.travis.yml b/spec/ruby/.travis.yml
deleted file mode 100644
index 35fea82656..0000000000
--- a/spec/ruby/.travis.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-sudo: false
-language: ruby
-install:
- - git clone https://github.com/ruby/mspec.git ../mspec
-script:
- - ../mspec/bin/mspec $MSPEC_OPTS
-matrix:
- include:
- - rvm: 2.5.3
- env: MSPEC_OPTS="-R2 -ff"
- - rvm: 2.3.8
- - rvm: 2.4.5
- - rvm: 2.5.3
- env: CHECK_LEAKS=true
- - rvm: ruby-head
- - env: RUBOCOP=true
- rvm: 2.4.5
- script:
- - gem install rubocop -v 0.54.0
- - rubocop
- allow_failures:
- - rvm: ruby-head
-branches:
- only:
- - master
- - /^try/
-notifications:
- email:
- on_success: change
- on_failure: change
diff --git a/spec/ruby/CHANGES.before-2008-05-10 b/spec/ruby/CHANGES.before-2008-05-10
deleted file mode 100644
index 18778bc146..0000000000
--- a/spec/ruby/CHANGES.before-2008-05-10
+++ /dev/null
@@ -1,17796 +0,0 @@
- Changelog
-===========
-
-This file contains the entire revision history of the specs from
-December 2006 onwards, when the spec project got started more or
-less officially by converting the remaining Test::Unit style tests
-in Rubinius to the spec style. The history is not preserved in the
-git repository history itself, so this data is here for reference.
-All the commit hashes are from the Rubinius repository.
-
-It still misses quite a few of the earlier, disparate specs and
-tests because up to that point the organisation was much looser
-and gathering an exhaustive accounting of the entire history of
-TDD/BDD would be time-consuming, particularly with the few full
-directory moves in there and such. All of the data is preserved
-in the Rubinius repository if someone is interested in that bit
-of history.
-
-Be aware that the history contains some Rubinius-specific specs
-by necessity. If you find any commits listed that were _solely_
-for Rubinius, feel free to strip them out.
-
-Thanks to everyone committing up to this point--over 2600 commits
-in just this incomplete version. Keep it up.
-
-
-
- Revision History
-------------------
-
-
-commit 2b24a1e84c350810817885eeb6532f43c698a95c
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Fri May 9 16:45:07 2008 -0700
-
- Fixed up pack for base64 and uuencode to be MUCH MUCH cleaner and 2x faster
-
-commit 022bc5dbfafcf1f9fd5e25820104718bd4d45661
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 9 23:51:47 2008 +0200
-
- Share common specs for BigDecimal's #mult and #*.
-
-commit 414e7eedce9d0cea982e24f1031c407daccc648b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 9 23:19:38 2008 +0200
-
- New rubyspecs for BigDecimal#mult
-
- * Verifies that proper signs are calculated when
- zero is involved.
-
-commit 6883d7d0c67f7be84e7ea1703912452eaecaac6c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 9 22:54:49 2008 +0200
-
- New rubyspec for Module#new with block.
-
-commit f8bd3e34014a7351470685676b6b168abd787794
-Author: Phil Hagelberg <technomancy@gmail.com>
-Date: Fri May 9 12:53:00 2008 -0700
-
- Added specs for OpenSSL::HMAC.hexdigest and .digest
-
-commit 686c28493d42b9c798aa791823395d1000423225
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 9 20:20:13 2008 +0200
-
- Some more rubyspecs for BigDecimal's #floor and #ceil.
-
-commit aba022a6620ec8d3a09067e9677f0f9c5d8078ee
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 9 17:51:35 2008 +0200
-
- New rubyspecs for BigDecimal's #floor and #ceil.
-
-commit e4d844ba5851a798b7acb684cf68fdcef353d13c
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu May 8 22:13:58 2008 -0700
-
- Excluded stdlib specs from default CI run. Added spec/full.mspec.
-
-commit 6a133574617cb435ad1684f208430112ff6839f6
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu May 8 16:19:50 2008 -0700
-
- String#unpack overhaul. NO extra methods littered through Fixnum/Integer/String. NO procs. More readable, but still messy.
-
-commit 11dd3ae2c4e0dd81304e85ba662db41196f1ce4c
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed May 7 23:59:31 2008 -0700
-
- Fixed constant type clash for ModuleSpecs modules.
-
-commit 4e702d10b32fdba62cdeae476b8217019839c3b0
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed May 7 21:42:11 2008 -0700
-
- Some specs for Kernel#__add_method__ and Module.__add_method__.
-
-commit 819649f24f59819be185b0562b94f9089f8c000c
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed May 7 14:48:01 2008 -0700
-
- Added spec for Kernel#eval with binding from method defined by #eval.
-
-commit d73b17b88b6084fdf7cab764b0fbdd3b3882dd81
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed May 7 10:06:26 2008 -0700
-
- Use literals in Bignum#to_f specs (alternate fix for #535).
-
-commit ee211770eb8792b3f58f78ff60eec6d5289caa20
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed May 7 02:38:00 2008 -0700
-
- Added specs for big uncovered areas, still not 100%
-
-commit 7ce9bc2d7edc64f6886c3d34836bc0394414ed66
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue May 6 03:56:19 2008 -0700
-
- Fixed typo
-
-commit af3407251ee0f287ec80232c354153af169636e4
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue May 6 22:01:23 2008 +1000
-
- Fix bug in Debugger::Output.wrap
-
-commit d9322306ea70f2b847b0f806bdb13ea02f2d6b4d
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon May 5 13:09:32 2008 -0400
-
- Fix some bugs in BigDecimal#/. More may yet lurk.
-
-commit 2f3a4cc14433858b13caa932c8a50c31e024c7e8
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon May 5 12:04:26 2008 -0500
-
- Adding more specs for REXML::Element
-
- * Covers REXML::Element#{add_attribute, add_attributes, add_namespace, add_text, clone, comments}
-
-commit 7db8c2b563ea474cf2db5fa14bb2a6345c8c469f
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon May 5 10:54:00 2008 -0500
-
- One more case for YAML.load specs
-
-commit 098decdf510b05f82ff9a6cc6769cf478a3236ab
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun May 4 22:29:35 2008 -0400
-
- Define BigDecimal#ver.
-
-commit f6f1fe6a667570e4c1521649b964dca1352d1c32
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun May 4 22:12:08 2008 -0400
-
- BigDecimal#new: Make space between '-' and 'Infinity' unparsable, as per spec.
-
-commit 503aae7cdbb208da8f25080762e17f0866845c4d
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon May 5 06:19:40 2008 -0400
-
- Method call parsing spec from Jim Kingdon with minor addition.
-
- * Moved the SyntaxError producing code into an #eval because the file
- cannot be compiled to run otherwise.
-
-commit 398d5de0a0ffaf746e39e5f6a6ded02483fd1842
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon May 5 02:26:39 2008 -0400
-
- Spec for :match node, implicit Regexp matches against $_.
-
- * Compiler and Language specs.
-
-commit 206cea31c6a93fe434948dcb79321e2c119edf21
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat May 3 11:40:17 2008 -0400
-
- Implement BigDecimal#power and #**, fix some bugs in #mult.
-
-commit a197099d9be6e48ad32480ae323302c83146147b
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat May 3 02:18:35 2008 -0400
-
- Fixed a logic and syntax error in BigDecimal#mult specs.
-
- * Removed some parentheses too.
-
-commit 081afd58a29ccd5025b806f53e9d7679b9296a7f
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat May 3 02:25:45 2008 -0400
-
- Make sure subclasses that implement their own Hash#default work (Merb)
-
-commit 203ca288175416fadb110b2aa9cdf8cfbf13215d
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat May 3 01:49:35 2008 -0400
-
- Specs and implementation for module include order (fixes abstract.rb)
-
-commit c788a9f2d9c4561a2837bbf78f68a6885d626917
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 18:14:32 2008 -0400
-
- Implement BigDecimal#*, as well as #mult without precision support.
-
-commit 57d78528ff4cf249d906785ffbfdde1fda4aa3cc
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 17:36:15 2008 -0400
-
- Implement BigDecimal#/ and #quo. Not perfect; still relies on #/.
-
-commit c42cc2cacc347d8284650c7046d4dadf94d7d4a5
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 16:13:07 2008 -0400
-
- Fix a typo in specs.
-
-commit ae179b410665da18628f249e6796f1e07ab83763
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 16:10:43 2008 -0400
-
- Get BigDecimal#floor basically working.
- * The failing specs depend on #/, which isn't implemented yet.
-
-commit f8221117d174b91affe406c8089ed25e887232b3
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 16:06:32 2008 -0400
-
- Fix bugs in BigDecimal#add and #+. This also affects #sub, #-, and #ceil.
-
-commit cdd196daf7643e846b7f3582b1e441b883e02aba
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 15:41:29 2008 -0400
-
- More specs to fix bugs in BigDecimal#add and #+.
-
-commit c1c52a2a531b570fa1025d99e464d93c570cf59e
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 15:22:33 2008 -0400
-
- Write another spec for BigDecimal#ceil.
-
-commit 71b65cdbfa5aae461fc52c997df9fca3bee9c8d5
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri May 2 14:47:34 2008 -0400
-
- Write tests for a bug in BigDecimal#add and #+ where 0 + 1 = 0.1.
-
-commit 55988ef53879c1c489c570b3f37717365c7f8e2b
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat May 3 01:04:11 2008 -0400
-
- Fix use of alias keyword inside instance_eval
-
-commit d4011595a0077e91665f85410d458c57367cf50b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 2 20:38:15 2008 +0200
-
- Added news specs for BigDecimal#mult.
-
-commit b6771644d35b6b8f3c87f7f4461bcaba99cd976f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 2 19:41:09 2008 +0200
-
- More BigDecimal#divmod rubyspecs.
-
- MRI-specific bug is hidden behind ruby-bug guard.
-
-commit 854a011324ce717cfd47ddec6389a9e9abb0db18
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 2 18:45:29 2008 +0200
-
- New BigDecimal#divmod specs.
-
-commit b9806e0efb2a8e51d70f6d51733df7bed88152d9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 2 16:45:10 2008 +0200
-
- A couple of test cases for BigDecimal's #quo, #div, #/.
-
-commit 3cf6c1e03001ba1dda966e3392b665f5b08a1b9d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri May 2 15:03:37 2008 +0200
-
- More tests for BigDecimal#floor.
-
-commit b70023978562af89cf4349e14e9443adb37ecbbe
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu May 1 21:15:29 2008 -0400
-
- Improved a spec description for String#index.
-
- * The description looks exactly like we had the wrong implementation
- relying on % 256 and someone wrote a spec to make sure that did not
- happen. However, the description was more or less meaningless to
- what was actually being specced.
-
-commit 6e6aa411ff4c7a837d5d4adb9ab893719cf9e122
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu May 1 10:48:20 2008 -0700
-
- Fix a number of things to pass all def specs
-
- This is the result of ping-pong between Evan and Wilson. It refactors
- out enclosing_class from being used, and instead information is always
- pulled directly from the StaticScope object. This lets us inject proper
- scoping changes in ruby.
-
-commit 2db27aef88e2ca7752beba846d172ede276275e0
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu May 1 19:03:50 2008 +0200
-
- Implemented Socket.unpack_sockaddr_un
-
-commit d515221698e02b52ed4661113d659744fbfae36f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu May 1 18:18:32 2008 +0200
-
- Forgot to update spec tags for TCPSocket.gethostbyname
-
-commit bf839a99c3a5b773b6b96c6d5a1fcc5056511e7a
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu May 1 14:03:30 2008 +0200
-
- Implement File#mtime specs
-
-commit b8c713e6b972b464788c740b4283a5b4226c123c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu May 1 13:55:36 2008 +0200
-
- Implemented File.lchmod and initial specs
-
-commit 059c926d7280c2e7c9f8bf710c5aef70cde3e777
-Author: Adam Wiggins <adam@heroku.com>
-Date: Sun Apr 27 15:03:31 2008 -0700
-
- IO.popen read/write pipes
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit d9a050aa45efd00a40395b7ac7ac069f4be1fd1c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu May 1 16:25:18 2008 +1000
-
- Spec fixes for Tuple#to_a
-
-commit 0b610359fbfe8137fdba95d90b659238168d6788
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 30 17:45:51 2008 -0400
-
- Update spectags.
-
-commit 024ebfdf3fa9c54b8a81134edb52fe10b09e4b91
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 30 22:56:44 2008 +0200
-
- Added BigDecimal#divmod excludes.
-
-commit e12d21a90760df723c0f48265cb49a9c4463db7c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 30 20:51:06 2008 +0200
-
- More tests for BigDecimal#divmod.
-
-commit 68cfef604f9b5411ca9e0349883bac4f59541f0d
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 30 16:47:31 2008 -0400
-
- Make BigDecimal#finite? handle NaN correctly, and refactor accordingly.
-
-commit 5066bcb8881241caf6d13be625b32633bda6567e
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 30 15:01:12 2008 -0400
-
- Make BigDecimal#<= and #>= pass Vladimir's new specs.
-
-commit 49601aff01c394fe2168f5f221a987be63a9ebc7
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 30 20:20:18 2008 +0200
-
- Various improvements to BigDecimal rubyspecs.
-
- * Corrected comparison specs (properly add arrays there)
- * New reminder specs
- * New modulo and % specs
- * Tagged rbx failures
-
-commit dd1700b747ba26b27eff0b249623aca559db06e1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 30 17:48:20 2008 +0200
-
- More test cases for BigDecimal#modulo and #%.
-
-commit 8eb9dc1b0aee3587f4da8b9cbe306fd431159d79
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 30 16:57:16 2008 +0200
-
- New specs for BigDecimal#modulo and #%.
-
-commit 4a846f807fe2c4c12d8719bc5c9ccb4ab696aff9
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Tue Apr 29 15:29:34 2008 -0500
-
- Fixes REXML::Element#namespaces specs
-
- * Use sort on the arrays to make sure the specs pass on JRuby too.
-
-commit 823683a864072ef6a81e808dbf792dee45d29c52
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Tue Apr 29 14:54:08 2008 -0500
-
- Adds more specs for REXML.
-
- * Specs for REXML#{inspect, namespace, namespaces, prefixes, text and text=}.
-
-commit a11a10760ce92ee373e04a5445234521a27874cc
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 17:55:55 2008 -0400
-
- Committing so we can bisect.
-
-commit df94214b1d132b02e3dd5b166d1c7c5cd5d50a21
-Author: Drew Olson <olsonas@gmail.com>
-Date: Mon Apr 28 19:21:07 2008 -0700
-
- Added spec for Array#remove_outer_arrays
-
-commit ec4ece9c06b42c257b4ffce2cf319f0ad23f65e8
-Author: Drew Olson <olsonas@gmail.com>
-Date: Sun Apr 27 20:15:47 2008 -0500
-
- Added more edge cases for recursive arrays to spec for File#join
- * an empty array containing an empty array which contains a recursive array should return
- '[...]' when File#join is called on it.
-
-commit 698a5d291cf63e56e9a3508a8850c77fa2c23430
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 16:17:05 2008 -0400
-
- Implement BigDecimal#=== as alias of #eql?.
-
-commit 18f515e735eecc519be55a6e3253db7135a137ad
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 16:09:43 2008 -0400
-
- Implement BigDecimal#sub.
-
-commit b331faa567dc1d98163c6447897221877cf756eb
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 16:04:06 2008 -0400
-
- Implement BigDecimal#add.
-
-commit f3f94c9b53045ddde335981897e2f6087dab7ef2
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Apr 28 12:01:41 2008 -0500
-
- hack to fix DRb.start_service spec to at least test start_service
-
-commit 4c8d6d90c69615386e26c71633e242f4e1f19342
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Apr 28 11:56:47 2008 -0500
-
- spec for DRb.stop_service to see if it clears the socket correctly
-
-commit 03cb539f42f0b558fa29911c1dfc71ec5f2b183f
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Apr 28 11:20:17 2008 -0500
-
- Revert "Revert "Made DRb spec depend partially on PID so multiple runs don't clash.""
-
- Apparently this is a supposed fix for concurrent spec runs, not for the spec failure
-
- This reverts commit 08695d9a6940ab74f6eb8965e449a417002a42a6.
-
-commit 2172e2ac20b69a97c2ad66551b3620a43bfda700
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 02:14:18 2008 -0400
-
- Make BigDecimal#exponent return Bignums as necessary, not just Fixnums.
-
-commit dc93d06163e80cdf89a67532654a850828119287
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 28 01:23:19 2008 -0400
-
- Correct implementation of BigDecimal#+ and #-. There's still a lot of repetition to be factored out, but this algorithm is more correct than the last try.
-
-commit 1da58bb7f0afbba4f8412e06983304dc7d887ac9
-Author: Luis Lavena <luislavena@gmail.com>
-Date: Thu Apr 24 16:37:59 2008 -0300
-
- Corrected small typo on File#join specs under Windows.
-
-commit b287619579ad11535722a2374b6f849d88fe9931
-Author: Drew Olson <olsonas@gmail.com>
-Date: Thu Apr 24 14:24:10 2008 -0700
-
- Spec for File#join now describes correct behavior for arrays with recursive sub-arrays.
-
-commit 5830380895c0bec16c6af39d0f29d8d70268028d
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Sun Apr 27 14:53:47 2008 -0500
-
- DRb.start_service spec fails because of a timing bug in DRb
-
- See http://jira.codehaus.org/browse/JRUBY-2347
-
-commit 08695d9a6940ab74f6eb8965e449a417002a42a6
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Sun Apr 27 14:51:16 2008 -0500
-
- Revert "Made DRb spec depend partially on PID so multiple runs don't clash."
-
- The spec is designed for sane behavior, if Rubinius or the
- implementation of DRb is causing problems then they should be
- fixed, not the spec in this case. Fixing the spec will only
- hide the bug.
-
- See http://jira.codehaus.org/browse/JRUBY-2347 for more commentary on the problem.
-
- This reverts commit f89bd8c6c425c9d9bcc3e589b8d3b05ce3ccbced.
-
-commit 94ba0884c8e7f398b6fe8d6736834f62f6a49815
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Apr 27 21:23:47 2008 +0200
-
- More checks for BigDecimal#abs specs.
-
-commit 80932d25ca95e2e8c803d244a7636e3004525ade
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Apr 27 21:10:26 2008 +0200
-
- More test cases for BigDecimal#finite? specs.
-
-commit 4b541ed23ccac65f6f4b2ef8aad56e9aa7a69e12
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Apr 27 21:04:08 2008 +0200
-
- Added testcase for BigDecimal#infinite? for NaN.
-
-commit 4a1f39426fc60ae7c2ed0470259fa0752a46d030
-Author: Adam Wiggins <adam@heroku.com>
-Date: Sat Apr 26 22:57:09 2008 -0700
-
- IO#write returns 0 when writing a blank string, to match behavior of MRI
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 56c0088f9b075769933c8c87e3c2d256cff3a3e8
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun Apr 27 00:28:47 2008 -0400
-
- Typo.
-
-commit c11410654b9046cdb58dba1d116f58ce74f4c263
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun Apr 27 00:24:32 2008 -0400
-
- Finish implementing #@- and #infinite?. Update spectags, of course
-
-commit dc9f427ecb9d55559d800af70f9c1a3f2f2123b5
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun Apr 27 00:07:31 2008 -0400
-
- Amplify a comment.
-
-commit b9776b953ae67f2088e44b640145af464a1cf942
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sun Apr 27 00:02:48 2008 -0400
-
- Get BigDecimal#+ working. I hate this algorithm, but it works without running out of memory.
- * Update spec tags.
-
-commit b87ff5c22891f19ad0b956e7e02cc3a3d1adcc93
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 14:27:00 2008 -0400
-
- Implement BigDecimal#coerce.
- * Update spectags.
- * Rewrite one spec so it doesn't depend on BigDecimal#-, which is not yet implemented.
-
-commit f89bd8c6c425c9d9bcc3e589b8d3b05ce3ccbced
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Apr 26 15:52:49 2008 -0700
-
- Made DRb spec depend partially on PID so multiple runs don't clash.
-
-commit 3c49a1d16f20726c4ee2d7eb5f5c671537aa59d5
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Apr 26 15:13:47 2008 -0700
-
- Added wordsize guard for BigDecimal#exponent spec.
-
-commit 3aac5f6d64f4cbbca70ecf01b7ed9be596fa5b76
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Apr 26 15:09:40 2008 -0700
-
- Updated spec_helper and renamed CaptureOutput to IOStub.
-
-commit 94322a6a95770a030d28925cc7213a38c5687ea1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Apr 26 23:16:59 2008 +0200
-
- A bit more test cases for BigDecimal#-@.
-
-commit 9919c5e3be59562532c967b479c959cf6270046e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Apr 26 21:01:44 2008 +0200
-
- New specs for BigDecimal#uminus.
-
-commit c3e74531f1ca1e70671f529671c0fa474968dc87
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Sat Apr 26 13:08:04 2008 +0200
-
- FreeBSD seems to work like the rest, not darwin
-
- Tested on FreeBSD/i386 7-STABLE
-
-commit c06a091b285f388f09b11037975921662759eea2
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 12:14:33 2008 -0400
-
- Implement BigDecimal#exponent, update spectags. Looks like parts of #** have accidentally stopped failing too. :)
-
-commit e5b753b7e659b29f5ed4aa57018f922111b238f5
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 11:53:55 2008 -0400
-
- Specify return type of BigDecimal#ceil as BigDecimal, as per library documentation.
-
-commit 0ca3b9ceb6ef5ca1898250b89f75c0194b5da481
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 11:50:24 2008 -0400
-
- Fix BigDecimal#inspect output, update spectags.
-
-commit ca99aa062afe9106ec614e2d8969d3491803c9a2
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 11:48:00 2008 -0400
-
- Specify return type of BigDecimal#ceil as BigDecimal, as per library documentation.
-
-commit 587a5cdbbfa4cccdbfe98339ca999f1d63bd66cf
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Apr 26 15:02:33 2008 +0200
-
- Corrected one Array#hash test case.
-
- Now Array#hash pass MRI 1.8.6, 1.8.7, 1.9 and JRuby.
-
-commit f86bdb98b8b9f5ea878c5d142f3a694e5278db77
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Apr 26 14:19:14 2008 +0200
-
- Quarantined couple of specs that fail on *ALL* implmenetations.
-
- Probably, we need a better way to do that, but quarantine
- is a quick and simple way, easily detectable later on.
-
-commit 7ca928211180c66b9879afbc382c376a7649e1b0
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 00:51:39 2008 -0400
-
- Implement BigDecimal#to_f, update tags. Will this need more work?
-
-commit 69dec41f6b5b532c5de7f46e97f97c9e102305c7
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 00:44:40 2008 -0400
-
- Implement BigDecimal#truncate.
- * Update spec tags.
- * Reorganize variables slightly to remove duplication.
-
-commit c823e62c3a6776b62f65c34b16bdca5748d1add9
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 00:36:43 2008 -0400
-
- Implement BigDecimal#truncate.
- * Update spec tags.
- * Reorganize variables slightly to remove duplication.
-
-commit 3f4e5dc78de5bf3e81ae1ce7a0d14852a32aeade
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Sat Apr 26 00:16:38 2008 -0400
-
- Rewrite spec description to bring it in line with what the spec actually does. :)
-
-commit 15d87e8a983d08d99fc3ec6bfbb7f36ed0cd4c4e
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 25 18:09:33 2008 -0400
-
- Implement BigDecimal#to_i, update spec tags.
-
-commit 59873b144ea836e2f9bbef7d5186a1287155e76a
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Apr 25 20:46:17 2008 -0400
-
- Specs for autoload path normalization
-
-commit 71fe2d45d147fe2c41937ae5ef6dbb8814f491c4
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Apr 25 17:05:17 2008 -0400
-
- Use a separate class in Singleton 'new' specs to avoid contamination
-
-commit 2dc8f9eb9c6db014bd6cc132d987fdb4612816f8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Apr 25 16:45:28 2008 -0400
-
- Handle more nightmare Autoload edge cases by hooking into Kernel#require
-
-commit 5c1a375a15adbe20a9bf3d1b95e1f2d30feaa90e
-Author: Michael Fellinger <m.fellinger@gmail.com>
-Date: Sat Apr 26 04:26:52 2008 +0900
-
- Spec for Module#autoload when the load path has already been required
-
- Signed-off-by: Wilson Bilkovich <wilson@supremetyrant.com>
-
-commit ee47a0cc0da787599479fc8dd085b7481b591176
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Fri Apr 25 15:41:19 2008 -0500
-
- Enabled another $_ spec and added a proc dispatch scoping test to $~ and $_
-
-commit eabc4609758dc99727c77493c58f187782ea957f
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Fri Apr 25 15:32:03 2008 -0500
-
- Added some basic specs for $_: implicit assign, explicit assign, scoping
-
-commit 61194dec429a9f288791156639f058e45a4e72e9
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Fri Apr 25 14:49:53 2008 -0500
-
- Add some specs for $~ scoping and assignment.
-
-commit 4c5cec4f6e10864c68b140e71cc2559e7a7d636b
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 24 18:28:08 2008 -0700
-
- Added incomplete tags for CSV spec stubs.
-
-commit 6e231caef62e678413e86317881aaab200d0802e
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 24 18:15:06 2008 -0700
-
- Reprocessed library CSV specs with new mkspec.
-
-commit 4cdc61a76cce73b52f05f53f820838cc7e3c2823
-Author: Michael Fellinger <m.fellinger@gmail.com>
-Date: Fri Apr 25 08:46:32 2008 +0900
-
- Updating specs for the module #included calling #extend issue.
-
- Signed-off-by: Brian Ford <bford@engineyard.com>
-
-commit 40e775bf036aa59e69268708f8c78b8a56e0f9ce
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 24 17:10:55 2008 -0700
-
- Moved #bignum_value helper to MSpec.
-
-commit 9b52edbb14ff2fc18faa429daf4ceaff5b87db11
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 24 14:37:53 2008 -0400
-
- Implement BigDecimal#fix, make #frac trap for a few common cases without running out of memory for big numbers.
-
- * Update spec tags.
-
-commit 6a604c0a9863073cfd7540ff755e7ca035a7dff5
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Thu Apr 24 19:32:14 2008 +0200
-
- Don't run Process.setpriority spec on FreeBSD
-
-commit 0ab639af500d947c5b5feb1d8f00f5fbc97a0edc
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 13:37:23 2008 +0200
-
- Adjusted IO specs to supply blocks for each-like methods.
-
- See [ruby-core:16557] for more details.
-
-commit a7b603a9ce6bfb570785e803bdb89ae36bb6253d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 13:14:40 2008 +0200
-
- Fixed IO, Process, Regexp specs ('should' was missing).
-
-commit 26de6c05c050d0dbcb073c407abda47f964bfd29
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:50:46 2008 +0200
-
- Fixed File specs ('should' is misspelled)
-
-commit 99a2b23d8fb42cb377cb3fb9ab2569c555aec8bf
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:47:57 2008 +0200
-
- Fixed Array specs ('should' was missing).
-
-commit 67b301a03fd6f7f0fa38ce106ab05825f2cbb15c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:43:39 2008 +0200
-
- Fixed specs ('should' was missing), some new test cases for BigDecimal.
-
-commit aecbea57de7ee1b50bd4b06871dd08e762a6ccb8
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:35:54 2008 +0200
-
- More test cases for BigDecimal#nan?
-
-commit 7aaf8fa137b8961ca122eb92e7447936ad7a44cc
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:26:20 2008 +0200
-
- More test cases for BigDecimal#zero?
-
-commit 58ecee694f191aa05e7867544cf8d63129558447
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:19:11 2008 +0200
-
- A bit more test cases for BigDecimas#-.
-
-commit e946dd03d590e29a1d344e7579d5ff047df4a76b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 24 12:17:16 2008 +0200
-
- New and updated specs for BigDecimal#-.
-
-commit 01d82db424b4e447b98e5f2eb3e162b991dece8a
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 24 01:25:20 2008 -0700
-
- Tag for new private setter method spec.
-
-commit c0ee2e133a4e5fc179b96329ffd3934dd9263c2b
-Merge: 374ab81... e9826b9...
-Author: Tony Arcieri <tony@medioh.com>
-Date: Thu Apr 24 02:19:00 2008 -0600
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 374ab81e2c01ea5ac48cda2004ae92a989d7f3d7
-Author: Tony Arcieri <tony@medioh.com>
-Date: Thu Apr 24 02:18:26 2008 -0600
-
- Specs for calling a private setter method on self
-
- * Not presently working under rbx, works under MRI
- * I don't entirely know the process for this, but this is expected to break
-
-commit 39505393f330b5f622788f1d98ea8ff3781499c7
-Author: Luis Lavena <luislavena@gmail.com>
-Date: Thu Apr 24 04:04:32 2008 -0300
-
- Fixes Dir fixtures and specs for Windows.
-
- Usage of special characters *, ?, | and : is not allowed under Windows
- * and ? represent wildcards, | is pipe tunelling and : is drive letter
- separator.
-
- Files or Directories cannot contain slashes (\/), wildcards, double-
- quotes, pipe tunelling or stream redirectors (<>).
-
-commit 2ecc076e488ed1a519fc5b6876c68a3d91d55c87
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 23 22:55:44 2008 -0700
-
- Update tags for newly passing File.join specs.
-
-commit ff3756e179920b84d5a55fc7bbc2688706df044f
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Apr 24 01:09:17 2008 -0400
-
- Add specs for nested method definitions and other complex scenarios
-
-commit 24785f7c28cde09ce0400e5d80f832ae11cddefa
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Apr 23 20:56:55 2008 -0400
-
- Spec for using ||= to initialize a class variable
-
-commit 98b0c44057cb827107cae0f0174b5e81ac2064fd
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Apr 23 19:49:21 2008 -0400
-
- Rewrite descriptions of language/def specs
-
-commit 598c287cc36179644a1bbf2a303a56fc85bb1b12
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 23 12:39:04 2008 -0700
-
- Replaced use of :mswin with :windows in platform_is[_not] guards.
-
-commit 01fe417f27ad43495327a522ece2f02769064df7
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 23 21:30:34 2008 +0200
-
- Added excludes for BigDecimal#div specs.
-
-commit 46f022d49c394b027491295e7fd5cb305af33404
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 23 21:27:42 2008 +0200
-
- More specs for BigDecimal#div
-
-commit 72433091c6a845c5f550b27111748e29fb5eac09
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 23 10:56:57 2008 -0700
-
- Added #tmp helper to MSpec for returning a temp file name.
-
-commit f4e975e5255fb36bb8e9be7d310850135ce3515f
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 23 10:54:42 2008 -0400
-
- Implement BigDecimal#frac, update spec tags.
-
-commit b60deba2368a1212d6acd3e49481ba9495de7f2f
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 23 10:49:39 2008 -0400
-
- Correct a spec error.
-
-commit e19cf9401c029f90e117b1c17083c928b0d1c9ca
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 23 10:24:50 2008 -0400
-
- Implement BigDecimal#-@, update spec tags.
-
-commit c3fc05389c75aca3150038814b324266501fdb8f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 23 16:12:24 2008 +0200
-
- A bit more test cases for BigDecimal#sqrt.
-
-commit b2a220f86887bfe6030a34bc8cd1b748c88cc2b8
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Wed Apr 23 01:43:16 2008 -0400
-
- Get BigDecimal#to_s working according to spec.
-
- * Implement #to_s.
- * Update spec tags.
-
-commit 82638601be12e410413047779f01840d6d0db3d8
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Apr 23 09:56:48 2008 +1000
-
- Refactor Debugger to remove dependencies on Debugger::Interface
-
- Also:
- - Add List#inspect to show number of items in list
- - Fix decode output to show original instructions in place of
- yield_debugger
- - Improve regex used to match method names to handle more
- operators
-
-commit 41c64f2825d347fbe2ef9edc33dd8f1e84773251
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Apr 22 18:12:06 2008 -0400
-
- Spec and implementation for NilClass#dup
-
-commit d3e313ed38a847e29225ba814a956d0929ea6460
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Apr 22 22:03:47 2008 +0200
-
- New and updated specs for Bigdecimal's #abs and #sqrt.
-
-commit 2013e106181879b886f2e1cb78e81f52cd284666
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Apr 22 15:52:10 2008 -0400
-
- Re-implement Module#autoload and autoload?. Now passing all autoload specs.
-
-commit 9156271e2b12138e2b2b712a76f0110f20a757b7
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Apr 22 15:34:43 2008 -0400
-
- Add (failing) spec for toplevel autoloaded constant access
-
-commit 8eb5451f88a37dc247e42913c1d72d072a9b02ef
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Apr 22 19:06:00 2008 +0200
-
- One more test case, for BigDecimal#sqrt with nil.
-
-commit e7894fb78cf92b53e9bdc6dcf023d8dd2d66b2ed
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Apr 22 18:52:24 2008 +0200
-
- More detailed specs for BigDecimal#sqrt and fixes for old ones.
-
-commit 527a4b663c487cd9222ee2e6917e330ff9a130a1
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Apr 22 12:38:53 2008 -0400
-
- Rename ambiguously-worded autoload spec
-
-commit 3e6f16c41569dbba291bc3cececf137fc8952ee2
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 12:31:17 2008 -0400
-
- Change to a significand-and-exponent implementation.
-
- * Update spec tags.
-
-commit f1b2bf51042ca563ca74a9cf83db0e46a1bfabce
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 09:54:53 2008 -0400
-
- Fix BigDecimal#zero, update spec tags. Also make #precs deal correctly with lowercase exponents.
-
-commit d0171de114e777f07a3e62972663475dd7747b05
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 09:24:06 2008 -0400
-
- Implement BigDecimal#precs.
-
- * Get #precs working. This will be less tortured once I implement a significand-and-exponent format.
- * Update spec tags.
-
-commit e1fc7c6dc4c02c1763947c34d05f894661a84525
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 01:30:10 2008 -0400
-
- Continue implementing bits of #inspect and updating spec tags.
-
-commit e4371f120c9c5c3c88a26d5f24f0d3ab888c954f
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 01:24:14 2008 -0400
-
- Implement BigDecimal#==/eql? and the beginnings of #inspect.
-
- * Find a way of implementing the equality test that satisfies the specs.
- * Don't be so baroque in parsing strings in constructor.
- * Update spec tags.
- * Fix regression in abs_spec.
- * Start implementing #inspect. Not really ready for prime time yet.
-
-commit 0494c1c35582381345194c76f7384eb9044797fc
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Tue Apr 22 00:41:03 2008 -0400
-
- Start implementing BigDecimal#sign and #zero?.
-
- * Clean up specs for #sign.
- * Write some initial code to get these working. Not all there yet.
-
-commit 3c071b5f921898d87437803a500535b639d465ef
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 21 23:43:10 2008 -0400
-
- Get BigDecimal#abs working.
-
- * Implement the function.
- * Improve the spec.
-
-commit 054582f3b89d757f033cd5f09cbf90fa08ad81d6
-Author: MenTaLguY <mental@rydia.net>
-Date: Mon Apr 21 22:32:42 2008 -0400
-
- fix linked actors spec (sort of)
-
-commit d7a7d0c4d0d83d7e69216c96a249c4091fe75323
-Author: MenTaLguY <mental@rydia.net>
-Date: Mon Apr 21 22:28:29 2008 -0400
-
- fix up registration spec
-
-commit 645784c3d39f776f583874e7c9244ff3de64cfe7
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 21 19:56:51 2008 -0400
-
- Update tags on failing specs.
-
-commit 960faf5382d90db376ff14bb836463f1860a4b62
-Merge: 2e2150f... 046ba62...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 21 18:46:45 2008 -0400
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 046ba622836321f487f241c145a3bdf0968f0a67
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Apr 21 18:44:50 2008 -0400
-
- Specs for failing Module#autoload case (replicates a scenario from Merb)
-
-commit 18a2a26fa511d4943a724e27ce09e5855a257e90
-Merge: 1f5f4b5... 991c6e6...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Mon Apr 21 14:15:07 2008 -0400
-
- Merge branch 'master' of git://git.rubini.us/code
-
- Conflicts:
-
- lib/bigdecimal.rb
- spec/ruby/1.8/library/matrix/diagonal_spec.rb
- spec/ruby/1.8/library/matrix/element_reference_spec.rb
- spec/ruby/1.8/library/matrix/shared/identity.rb
- spec/ruby/1.8/library/matrix/shared/transpose.rb
-
-commit edd397c82a924e406eabbcd7e84243d94f8e8067
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sun Apr 20 18:11:23 2008 -0500
-
- Adds MinGW to the IO#popen spec guard
-
-commit 10df9f89189637b2c5a54b01a88eca6c9fbb4601
-Author: Adam Wiggins <adam@heroku.com>
-Date: Sun Apr 20 14:53:41 2008 -0700
-
- IO.popen specs for reading and writing to pipes
-
-commit 3f70eceb3b9415a14f602c5b96121a459dca1e67
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Apr 19 22:32:28 2008 -0700
-
- Fix silly typo in Numeric#quo specs.
-
-commit 6101a4992ddc15c0140f4d7702cf88d2d3a2ac53
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Apr 19 22:23:14 2008 -0700
-
- Guard affected specs with conflicts_with :Rational.
-
-commit 354445f4d20ec66f207d65d1ccceb681bba7fff0
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sat Apr 19 14:23:14 2008 -0500
-
- Clarifying some of the Matrix specs
-
- * Fixes two errors introduced by 28700c5cf7
-
-commit 2f5ca541fc08f0c033bc6541c72962228ea607de
-Author: Eero Saynatkari <projects@kittensoft.org>
-Date: Sat Apr 19 15:07:49 2008 -0400
-
- Compiler specs' TestGenerator relies on broken #=== semantics, comply.
-
-commit 37cc9d4d6eb3442814ecc51845f025f464da64f7
-Author: Eero Saynatkari <projects@kittensoft.org>
-Date: Sat Apr 19 15:05:30 2008 -0400
-
- Specs for default #=== and its relationship with #== and #equal?
-
- * Rubinius deviates to not check object id directly.
-
-commit 28700c5cf7630be59877122e6470c42622b7365a
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sat Apr 19 13:53:33 2008 -0500
-
- Additional specs for Matrix
-
- * Some of the constructors in Matrix keep referencing the original arguments after creation, these specs cover those cases.
-
-commit 12b0bc93e5a6b328ad0968c03c47af71f671aae2
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sat Apr 19 13:06:04 2008 -0500
-
- Replace object_id for equal? in Matrix specs
-
-commit ae377f0e56b8f31356935b3ac0800f561b2d1b2c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Apr 19 14:49:34 2008 +0200
-
- Fix File::Stat#uid specs
-
-commit 2e01a86a3977fe87f4f0734e50598b41f66f29d7
-Author: MenTaLguY <mental@rydia.net>
-Date: Sat Apr 19 03:24:32 2008 -0400
-
- Gutted and reworked Actor, following Erlang more closely.
-
-commit de40303e17e2de1e7980564b43ee162c5080afa6
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sat Apr 19 01:05:43 2008 -0500
-
- Fixes Matrix#clone specs for MRI
-
- * Makes sure the values (not the references) of the original rows are copied.
-
-commit 2b3a44158ae93ab5883da22e5f36df92485f3ad4
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Fri Apr 18 22:47:15 2008 -0500
-
- Fixes a few things inside the Matrix specs.
-
- * Removes some of the "needs to be reviewed for completeness" messages.
- * Changes some of the descriptions
-
-commit 3be265a93a75b6a0267b1770f8cad671c4244671
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:26:29 2008 -0400
-
- Matrix.unit, one more alias for .identity.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 57aa8ba9a1dbdf62e9cf644bbde4603b841ffc76
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:25:55 2008 -0400
-
- Name spec correctly.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 3390dc4c6725d996eeb0c2e4ec73949bc0be2290
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:23:54 2008 -0400
-
- Specs for Matrix.scalar and .identity/I.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 958ca1faa1dc60ce591b4b2f768f22ac7f6cb56f
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:22:09 2008 -0400
-
- Move the "needs to be reviewed" indicator to the right place.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit bf3eab630654eaaca9256850d258343e3024989e
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:03:45 2008 -0400
-
- Use size functions instead of constants.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 3981c931e7f4fde730d51614d40e44b9209347f9
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 11:58:22 2008 -0400
-
- Specs for Matrix#clone and #transpose (alias #t).
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 72e1ea8900a638c796de9e715c5dffcf4ac90546
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:27:06 2008 -0400
-
- Basic specs for Matrix.zero.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit f5d294ad941c477060e9b5d2329790db7e1e5700
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:20:27 2008 -0400
-
- Move before block to a clearer place.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit b6bc5b224ade56ab96f3585b6b1c25e6dd5e1ad5
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:19:27 2008 -0400
-
- Write specs for Matrix.diagonal.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit b4d056baa33a2181ab64c065ad1eb4adebcfaddf
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:11:11 2008 -0400
-
- Some initial specs for Matrix#[] and Matrix.[].
-
- These are in the same file because of coding conventions, but they probably should not be since .[] is a constructor and has very little in common conceptually with #[], which is a subscript operator.
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 5476d836577c0fbdbda097762862cf153ffb5e07
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Apr 18 18:35:34 2008 -0700
-
- Some method profiles of data provided by John Lam.
-
- Run these as follows:
-
- bin/mspec -w rails.yaml spec/ruby
-
- We'll be adding our own trace script, but for now, these
- are snapshots of methods used by Rails loading a simple
- "hello world" controller. The rails.yaml file is core
- methods. The core.yaml file is generated by NameMap from
- mspec/bin/name_map.rb.
-
-commit 24c71675cc63c86832ef8bc55d2f0167dff53073
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 17:24:08 2008 -0400
-
- First stab at BigDecimal.
-
- * A skeleton of a somewhat naïve implementation of BigDecimal.
- * Updated spec tags.
-
-commit 1f5f4b59400b8b11df83b274efc8ce98186220ef
-Merge: 9d21b0e... 968a0ec...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 17:28:02 2008 -0400
-
- Merge branch 'bigdecimal'
-
-commit 9d21b0e890a9394658689af2bdee7e449cd2200b
-Merge: c3f3507... 1a08506...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 17:25:09 2008 -0400
-
- Merge branch 'master' of git://git.rubini.us/code
-
-commit 968a0ecda8477b33ceab2e7d0c7e7d084a105bdb
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 17:24:08 2008 -0400
-
- First stab at BigDecimal.
-
- * A skeleton of a somewhat naïve implementation of BigDecimal.
- * Updated spec tags.
-
-commit 1f410d918a59b9b49e87a407cc8fba4bbf342a79
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Apr 18 22:34:53 2008 +0200
-
- Fix a bunch of specs and minor issues in File::Stat
-
- Specs for File::Stat#<=>, File::Stat#ino, File::Stat#inspect,
- File::Stat#mode, File#Stat.initialize and some minor bugfixes
- such as the fact that File::Stat needs to include Comparable
- (like MRI).
-
-commit d6f2c6995941762878f4b777a39b0c23ea654605
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Apr 17 22:30:36 2008 +0200
-
- Remove specs for non-existent File::Stat#initialize_copy
-
-commit c3f350716a35cb869b3ea0289c0e404d07b8819f
-Merge: 810afff... b861102...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 16:18:34 2008 -0400
-
- Merge branch 'master' of git://git.rubini.us/code
-
-commit 72101783ec6e66a4f9ac3f9c90f7e8f5b67058ec
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 17:05:26 2008 -0700
-
- Reworked masgn specs to evaluate L2R and assign L2R. excluded.
-
-commit 4e4bec628b21938617bdfa5a2ef17aedf02c112c
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 15:17:00 2008 -0700
-
- trailing whitespace is killing me... evan\! fix your editor\!
-
-commit 810afffa2e549048947c07b30d77be255db42d73
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:26:29 2008 -0400
-
- Matrix.unit, one more alias for .identity.
-
-commit 2c84f77535d677a42bee93759c77f79c2cdd4d93
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:25:55 2008 -0400
-
- Name spec correctly.
-
-commit 762f5ee0f7ba4234847c695c92e3ed27dd05e134
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:23:54 2008 -0400
-
- Specs for Matrix.scalar and .identity/I.
-
-commit b68295e0046a2eb1fb911ea891d6e0a29174ea30
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:22:09 2008 -0400
-
- Move the "needs to be reviewed" indicator to the right place.
-
-commit 4b6e1097feafe2247e59d6004a36bb0987734138
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 12:03:45 2008 -0400
-
- Use size functions instead of constants.
-
-commit 2086f0c1f1f899f2e41307a5434a5bb6446e20a2
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 11:58:22 2008 -0400
-
- Specs for Matrix#clone and #transpose (alias #t).
-
-commit 2939c55b2e9f38b5115b98429de97bc4fff6f165
-Merge: a47f2b8... 42d3212...
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 02:09:07 2008 -0400
-
- Merge branch 'master' of git://github.com/evanphx/rubinius
-
-commit a47f2b852ca309a68b687157a6cd973716328887
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:27:06 2008 -0400
-
- Basic specs for Matrix.zero.
-
-commit aa3b2eeef70cb8967ef6c92ee24a226c2d1202c1
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:20:27 2008 -0400
-
- Move before block to a clearer place.
-
-commit ca6ac1e59ddb268b388975a2fb5b11e6026e65c8
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:19:27 2008 -0400
-
- Write specs for Matrix.diagonal.
-
-commit b24216d8b0ecfba6888f909415e2523eaed2aeb2
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Fri Apr 18 01:11:11 2008 -0400
-
- Some initial specs for Matrix#[] and Matrix.[].
-
- These are in the same file because of coding conventions, but they probably should not be since .[] is a constructor and has very little in common conceptually with #[], which is a subscript operator.
-
-commit 9313f29ed952f604e0d124ced38ee930b5780b27
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 17 22:35:43 2008 -0400
-
- New spec tags for Complex#%.
-
-commit 08f316de96c94b7d4865d77873327deddeabb664
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 17 22:32:08 2008 -0400
-
- More specs for Complex.
-
- * Specs for <=>, conj/conjugate, to_s.
-
-commit 973c304cc16fa6b78dba31de11b151da2daae762
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 17 22:09:20 2008 -0400
-
- More specs for Complex
- * Complex#abs, abs2, angle, arg, and %. Not sure that % is correctly specified.
-
-commit e32b26694277065fe28f138dca837b8c0509c735
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 17 21:17:26 2008 -0400
-
- More specs for Complex.
-
- * Write specs for * and /.
- * Rewrite + and - to use alternate constructor syntax.
-
- Signed-off-by: Marnen Laibow-Koser <marnen@marnen.org>
-
-commit 0cbf88a6c61e477f4b9a7758a9fab1258efbf30f
-Author: Marnen Laibow-Koser <marnen@marnen.org>
-Date: Thu Apr 17 20:46:04 2008 -0400
-
- Write some specs for Complex.
-
- * Basic specs for Complex.new, Complex.new!, Complex#+, and Complex#-.
-
- Signed-off-by: Marnen Laibow-Koser <marnen@marnen.org>
-
-commit 71909e78b8d77f7e48d306e30f51fbc21b5fbefb
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 17 15:26:53 2008 -0700
-
- Reorganize and fix Matrix specs.
-
-commit 5a9325457696dfba3c410c0adcbdec706ecda3bf
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 17 12:49:45 2008 -0700
-
- Added spec templates and incomplete tags for CGI.
-
-commit d62de6b4096a9b3bd3fda197b70d6e603596e865
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 17 21:12:08 2008 +0200
-
- More detailed speecs for BigDecimal#new
-
-commit ebd6fb8f879f94ff51b74cb4e76080fad7b66cb5
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 17 19:55:31 2008 +0200
-
- More detailed specs for BigDecimal's <, <=, >, >=, <=>.
-
-commit 8caef40cbe873dc2825bc0ba1e66f983b8219cca
-Author: MenTaLguY <mental@rydia.net>
-Date: Thu Apr 17 01:16:25 2008 -0400
-
- add tag object argument to send_in_*
-
-commit 0596b1aca45a85de5f3d727632585da924fd3eb0
-Author: Matthias Reitinger <m.reitinger@mytum.de>
-Date: Sat Apr 12 10:11:13 2008 +0200
-
- New specs for BigDecimal.new.
-
- Signed-off-by: Marius Nuennerich <marius@nuenneri.ch>
-
-commit 5c176e50fe962de1095a75221b4d63e75acc505f
-Author: Benjamin Stiglitz <ben@tanjero.com>
-Date: Wed Apr 16 11:32:18 2008 -0700
-
- Cleaned up Numeric#div spec
-
- The spec names are no longer quite as atrocious; the spec output is now fairly
- readable. The different Integer-Float quotient permutations are now correctly
- specified as well.
-
- Signed-off-by: Brian Ford <bford@engineyard.com>
-
-commit e1406b19c51bfca5f6936d143087043316c68c13
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 15 20:07:48 2008 -0400
-
- Specs for Kernel#p behaviour.
-
- * Args vs. no args.
- * Record separator is not taken into account.
-
-commit 30c717e1736b65a852df501f71e320599fc17786
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Apr 15 21:32:13 2008 +0200
-
- Fix typo in File.grpowned? spec
-
-commit 1bc17a0b4c8f19b84ffdd0b17ec24243a1df6092
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Apr 15 21:31:02 2008 +0200
-
- Fix File.grpowned? and it's spec
-
-commit f49cf4d0319b5772ede7bcddd763c691d5253b18
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Apr 15 20:44:18 2008 +0200
-
- Update tags for implemented File.grpowned? specs
-
-commit ea19fb07cb7b789165aec5da0f571345b96f1f0f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Apr 15 20:41:02 2008 +0200
-
- Spec File::Stat#grpowned? and implement File.grpowned?
-
-commit c411b15b9f94fec21b02a9208cbae4b42452431d
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Apr 15 20:19:24 2008 +0200
-
- Properly rename File::Stat#dev_major and File::Stat#dev_minor specs
-
-commit 26ba3ad30cd726b058cd76f23dc7a79555be724e
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Tue Apr 15 10:25:44 2008 -0700
-
- Quarantine the cvar-related instance_eval spec for now; it's not clean.
-
-commit d72c609ce4567d7a7fdfd2ee4713ac07033c81db
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Mon Apr 14 20:13:38 2008 +0200
-
- Use EnvSpecs where possible
-
-commit 8ccdf2d612f15515837095e2e4a570861024294c
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Mon Apr 14 17:42:36 2008 +0200
-
- Use EnvSpecs module for platform dependent stuff
-
-commit 130e4bdb1d9fa9512dfe45d4ff4d718096683cdb
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Apr 14 19:45:24 2008 +0200
-
- Fix specs for a bunch of File::Stat methods and implement File::Stat#<=>
-
- Created specs for atime, blksize, blocks, ctime, mtime and <=>
-
-commit e5aa89ff13128afb9b43ad77678792aeae4d48ea
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Apr 12 17:54:57 2008 +0200
-
- Remove tag for fixed File#lstat
-
-commit 21cd4a10833ef3bdda1593423faccb334de16536
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Apr 12 17:52:33 2008 +0200
-
- Remove unneccary spec placeholders for File#stat / File#lstat
-
- The shared spec already tests this behavior. With the new added spec
- for the difference between the two, File.stat / File.lstat is pretty
- well covered for now.
-
-commit eacb4f8a4d0ba606458a5756ddd6f2ce723a3dfa
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Apr 12 17:45:55 2008 +0200
-
- Specced different behavior between File.stat and File.lstat
-
-commit 4ae163810074effc068babf538f004e9ff117156
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Apr 14 16:49:04 2008 +1000
-
- Refactor Debugger interface into a CmdLineInterface class
-
-commit e61241498f6ca63b7d5e50e94a70456bc40e929b
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Apr 14 14:17:03 2008 +1000
-
- Breakpoint clean-up
-
-commit ae738f21979edf727437438b992629dd0b59a42e
-Author: MenTaLguY <mental@rydia.net>
-Date: Sun Apr 13 16:14:34 2008 -0400
-
- elminate Mailbox#clear; difficult to implement with sane semanitics
-
-commit 76385484049e47f53b840ddf3c0dfe9e365ca8cf
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Sat Apr 12 16:39:19 2008 -0500
-
- More specs for REXML::Element
-
-commit 00547bc562c359ddac13d04a5c955ee25171bcb4
-Author: Matthias Reitinger <m.reitinger@mytum.de>
-Date: Sat Apr 12 11:15:12 2008 +0200
-
- Fixed incorrect check for object equality in BigDecimal#nonzero? spec
-
- One should not use == to check if the method returns self, but equal?
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit e8403792167c86f120ce7bdcd1e2c7ce1bc31fea
-Author: Matthias Reitinger <m.reitinger@mytum.de>
-Date: Sat Apr 12 11:31:25 2008 +0200
-
- Eliminated use of to_s to check for NaN in BigDecimal specs
-
- Changed "to_s.should == 'NaN'" to "nan?.should == true"
-
- Signed-off-by: Federico Builes <federico.builes@gmail.com>
-
-commit 5883dd78ad92031c920bb9ee2b703702969a5854
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Sat Apr 12 09:42:11 2008 -0500
-
- A few more instance_eval specs, for non-immediate numerics and cvars.
-
-commit e8fd8e696d5487fa698a9a8b1bab2fb54b420133
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Sat Apr 12 08:28:41 2008 -0500
-
- Added instance_eval spec for defining methods under immediates.
-
-commit c23b365a95862cd438e6228929a3a4e935d60de9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 22:09:06 2008 +0200
-
- New rubypsecs for BigDecimal#fix and #frac.
-
-commit 6b6b63ebedb61466b4f04f510bf859574efec7d9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 20:07:07 2008 +0200
-
- New rubyspecs for Bigdecimal#floor and #ceil.
-
-commit 75e9118aea32baaeec82efedb5106c63bb0eef44
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 17:50:36 2008 +0200
-
- Corrected Bigdecimal specs since they were missing "should" statements. :)
-
- Also, added some more cases.
-
-commit 18fafb2e1f653887fdd3cdef693448d9b2bea29e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 17:21:02 2008 +0200
-
- New rubyspecs for BigDecimal's #power, #** and #exponent.
-
-commit 35e32daa38c7df385aac99f7b709a4038141faaa
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 13:41:13 2008 +0200
-
- New and updated rubyspecs for BigDecimal#precs.
-
-commit e0172d4eee7a775ab53562477997855ed66615a7
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 12:31:22 2008 +0200
-
- More rubyspecs for BigDecimal#split and some corrections for older ones.
-
-commit 37d312770700da5eb124fdce7a7b1687c2d9b839
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Apr 11 13:55:00 2008 +1000
-
- Get breakpoint handling working properly
-
-commit 498b95a720e98b70b56af9dfd2c1ba20c0bf89c3
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Apr 9 17:23:56 2008 +1000
-
- Make ISeq#decode return symbols rather than objects by default
-
-commit b8bda0546cdb9ac04ae629f13ccfce5f474e6f2c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Mar 17 14:33:45 2008 +1100
-
- Ensure breakpoint original instruction is correct
-
- When multiple breakpoints are set at the same location,
- only the first breakpoint sees the original instruction.
- This commit ensures the BreakpointTracker detects such
- situations, and updates the breakpoint to set the correct
- oringinal instruction to use.
-
-commit 2700924f23e0283a059583f9e92188b1c3c4f220
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Mar 13 17:20:49 2008 +1100
-
- Reorganize Breakpoint class hierarchy
-
- Refactor Breakpoint class hierarchy in preparation for
- adding PersistentBreakpoint and BreakpointRestorer classes.
-
-commit bfa69d930c38897df18b656d7b86f0b549bed57f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 03:01:37 2008 +0200
-
- Some more test cases for BigDecimas#finite? and #nonzero?.
-
-commit 71a4b0a51ea4da0c41d7b096aa7b88deb8d0d049
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 02:42:33 2008 +0200
-
- A bit more rubyspecs for BigDecimal#sub and #to_s.
-
-commit 8ff9ae455c6c7f4b38f3b4dcbdc6c677759f13e2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Apr 11 01:35:16 2008 +0200
-
- New rubyspecs for BigDecimal#truncate.
-
-commit f0a5c13f218d1e2187dfff09bd27cbd6dde544ca
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 15:09:55 2008 -0700
-
- Converted VMActor specs to dir/files. Added incomplete tags.
-
-commit df74b0fd98597b51d4c1d51ae09706d51e1a5d3c
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 15:01:08 2008 -0700
-
- Converted Mailbox specs to dir/files. Added incomplete tags.
-
-commit 29d223d8bfcc36edc16db58d50f8186905df773a
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 14:49:52 2008 -0700
-
- Converted Actor specs to dir/files. Added incomplete tags.
-
-commit 08ab8db440cfdaa7e06b19a0d88750678d4fccbf
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 10 22:09:39 2008 +0200
-
- New rubyspecs for bigdecimal, and excludes.
-
-commit b76a9e964899348d667181d288c5d4ec0e422c9f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 10 19:33:03 2008 +0200
-
- One rubyspec for the class definition: def nil:Foo; end
-
-commit c526f5744ece40e312340556991ee54e4504ebcd
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 00:53:06 2008 -0700
-
- Processed Rational, Complex, Matrix with mkspec.
-
-commit 3de6f530c42bdca8c9b1202e60d0d14850024d15
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 00:27:40 2008 -0700
-
- Processed IO with mkspec. Added incomplete tags.
-
-commit faaf8bdb8893f71234d7e2fab07aa11d6c556384
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 00:17:35 2008 -0700
-
- Clean up especially bad whitespace in File specs.
-
-commit fedda8f6865c6cdb07c7599606204f0700042574
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 10 00:09:56 2008 -0700
-
- Processed File specs with mkspec. Added incomplete tags.
-
-commit 09f6f1b5138b7ca1d276a8c68ee6bf1cba7691b7
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 9 23:42:40 2008 -0700
-
- Processed Kernel specs with mkspec. Added incomplete tags.
-
-commit e3ca2e3e077c0e026b96e1e68808b95d44233cf5
-Merge: cf0c855... 4d0d1f6...
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Thu Apr 10 02:48:31 2008 +0200
-
- Merge branch 'master' into bigdecimal_specs
-
-commit cf0c8552f31cfd856822c8aa43a5d9d265481ac0
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Thu Apr 10 02:40:22 2008 +0200
-
- Next bunch of specs for Bigdecimal.
-
-commit 4d0d1f6b98ac2dafa487ece31512443a07bbc928
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Wed Apr 9 23:42:10 2008 +0200
-
- Fix ENV specs
-
- * Try to avoid `env`
-
-commit dfcc69ea8bd78e9e463defdef3b4529a5af40bb5
-Merge: 75e6ccd... 6a50f0d...
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Wed Apr 9 22:26:26 2008 +0200
-
- Merge branch 'master' of git://git.rubini.us/code
-
-commit 75e6ccd48bce9e0e939a0ff1d484f14a029969f9
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Wed Apr 9 22:26:11 2008 +0200
-
- Fixes for ENV
-
- * Add specs
- * Add some missing methods to ENV
-
-commit 6a50f0d2f5146901fe96fe86802df155c9266a21
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Wed Apr 9 21:11:05 2008 +0200
-
- Fixed failures for BigDecimal#specs.
-
-commit 09bc62e39a8b92c25aeb6287f9fbf4e9cd2b9a6f
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Wed Apr 9 19:55:45 2008 +0200
-
- Bunch of specs for BigDecimal.
-
-commit c281add79d621f6327740109895c624dd25a2e1b
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Wed Apr 9 09:13:29 2008 -0500
-
- Cleaning up UPSocket#send specs
-
- * Got rid of the weird exception catching
- * DRY things up a bit with before :each
-
-commit 8ebefe3c0a61b7aab8ac3d0ae9768c35b657cdb6
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Wed Apr 9 09:11:43 2008 -0500
-
- Adding spec helpers to REXML specs
-
-commit e3064084efbbac1147d477435010d933ce101413
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 8 22:20:43 2008 -0400
-
- Amended spec wording for Singleton._load slightly. Updated exclude.
-
-commit 23e621625b95e0db82bd406a5eb8fa7324e41a6e
-Author: Chris Shea <chris@tie-rack.org>
-Date: Tue Apr 8 15:49:11 2008 -0600
-
- Create spec for Marshal.load of Singleton instance
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit eec07baa07d591059c64f32c0ddef169cfcccaef
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 8 20:20:02 2008 -0500
-
- Thread#wakeup deadlock for MRI marked as ruby_bug
-
-commit dbb744d9692c2432d7aebecac17365125efe9087
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 8 20:02:08 2008 -0500
-
- spec for wakeup which causes MRI to deadlock when it shouldn't
-
-commit 208a7df6ec2d3c8f550a7ac24db849e593cdc9f3
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 8 17:58:15 2008 -0500
-
- specs for Thread::list
-
-commit f6f307e75e49cdf597b0b3755ab214c6fc1950dd
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Wed Apr 9 00:54:34 2008 +0200
-
- specs for BigDecimal.new and BigDecimal#zero? (plus tag files).
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 5b1f2043f70b0088f1c32be79eeaa8179c2210a6
-Author: Jeff Rose <jeff@rosejn.net>
-Date: Wed Apr 9 00:44:27 2008 +0200
-
- Specs for Actor linking and registration, and Mailbox timeouts.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 4eea149d3d503c121fb7c65115e374838fff8c8a
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 14:55:18 2008 -0700
-
- Added extra Array subclass dup spec
-
-commit 783a884931b718b8fa65dd9768fbebd8a0d1ac0c
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 14:18:45 2008 -0700
-
- minor cleanup
-
-commit 0e047cc97aa6a5acd7193bdde1139f6a89f108b8
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 14:18:27 2008 -0700
-
- minor cleanup
-
-commit f4797827393e0d9d0e5df5aa5184ecebb066d766
-Author: Matthias Reitinger <m.reitinger@mytum.de>
-Date: Tue Apr 8 17:08:32 2008 +0200
-
- Extended Symbol#inspect spec and reworked Symbol#inspect to fulfill them
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit b3c3a5f60177f9c52725b6cacf019412d2c747ea
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 8 17:29:58 2008 -0400
-
- Excludes for BigDecimal specs.
-
-commit b7cd3c38d146a7833ef1d426ea8acd4ee4cb09bf
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 8 17:13:48 2008 -0400
-
- Switched #requires around to have access to #pretty_inspect.
-
-commit aba428095e09ead8ed66895b175e5f3673c4310e
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Tue Apr 8 17:45:13 2008 +0200
-
- Spec for BigDecimal#to_f.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 20a5789f9dc4e6d30dffb594476b354e4aeee201
-Author: Thomas Lachmann <thomas_lachmann@gmx.de>
-Date: Tue Apr 8 17:21:39 2008 +0200
-
- Spec for BigDecimal#finite?
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 896609e7ae8ee12c72e4e3ce86897c1f8b98f3fb
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 02:03:22 2008 -0700
-
- overlooked 2 specs
-
-commit 77774ed4300d5245c58dbcc686cd72dc48f08a1f
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Apr 8 02:00:24 2008 -0700
-
- Added a bunch of specs to String#to_f
-
-commit 1b91113c3e8fb46a0d355cae9000ee4c82f95ac3
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon Apr 7 21:46:17 2008 -0500
-
- More specs for REXML
-
-commit 2460839e3fbe2967b9df70db3de33b2a102b9a44
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Apr 7 12:19:40 2008 -0700
-
- Reworked how MSpec handles config files. Use 'set :sym, value' now.
-
-commit 67d3869e9b3fef6d47727206d02814da410e02fc
-Author: Jeff <rosejn@warp.(none)>
-Date: Mon Apr 7 15:04:09 2008 +0200
-
- Adding specs for Mailbox and Actor, and renaming the VMActor describe to match the standard scheme.
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit 7391c1fbc02966165de03724c42fc1d5243ac99f
-Author: Marius Nuennerich <marius@nuenneri.ch>
-Date: Sun Apr 6 22:29:22 2008 +0200
-
- repair UDPSocket spec
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 5a205207faad0a85271bfcb459390793702c4143
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Apr 5 04:54:21 2008 -0400
-
- Partially revert "Add spec files for cgi.rb."
-
- This partially reverts commit e2714f2fd2d8825ac8af761a5a4545e4d0731735.
-
- Conflicts, left these files:
-
- spec/ruby/1.8/library/cgi/escapeHTML_spec.rb
- spec/ruby/1.8/library/cgi/escape_spec.rb
- spec/ruby/1.8/library/cgi/rfc1123_date_spec.rb
- spec/ruby/1.8/library/cgi/unescapeHTML_spec.rb
- spec/ruby/1.8/library/cgi/unescape_spec.rb
-
-commit 22f3042377731cb6ff963b9e322b24014b286895
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Apr 5 03:18:15 2008 -0400
-
- Added excludes for the CGI specs.
-
-commit 7b9f5a213c971636b663e992fcb8578888d27f52
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Sat Apr 5 13:03:59 2008 +0900
-
- Add spec file for CGI::rfc1123_date().
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 31edbd64bba7f352930ac04d51b63e72553796a9
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Sat Apr 5 13:03:14 2008 +0900
-
- Add spec files for CGI::escapeHTML() and CGI::unescapeHTML().
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit fc321869d73f58dcfbb55ba374646c1568528004
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Sat Apr 5 13:01:33 2008 +0900
-
- Add spec files for CGI::escape() and CGI::unescape().
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit e2714f2fd2d8825ac8af761a5a4545e4d0731735
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Sat Apr 5 12:44:57 2008 +0900
-
- Add spec files for cgi.rb.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 2a1d0ad7e51ba52a918111d53be6a641c41a0445
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Apr 4 22:21:47 2008 -0400
-
- Improved the *rest argument count spec a bit.
-
-commit e8053e4bb108cf877ac8fdafc104eb34bad671f0
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Apr 4 20:38:23 2008 -0400
-
- Specs for unlimited argument count for *rest defns.
-
-commit 03e092e45015f8115f806e11460121c560e60b4b
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Fri Apr 4 17:54:25 2008 -0700
-
- Converted symbol spec to be generative, allowing easier pattern detection
-
-commit bbda617127a8ac319a58fa190d43b3a0d960d309
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Apr 4 14:07:50 2008 -0500
-
- updated File#inspect tags
-
-commit 38eb679d6b6c5aef8bccb2139e681c926b3290c7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Apr 4 06:00:37 2008 -0400
-
- Specs for ~/ expansion in #require, #load. It has broken at some point.
-
-commit 2d600c01205fbb7ccd98e7f7a88ebcbd0e1d1d43
-Author: Paul Thornthwaite <tokengeek@gmail.com>
-Date: Fri Apr 4 08:43:42 2008 +0100
-
- Updated specs for Set library
-
- * Added specs for Set#subset and Set#proper_subset
- * Added specs covering empty sets and comparisons
- * Corrected spec string to include ? on superset method names
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 3a547c2b82434c64b72967ebd917fc063ff1317d
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Apr 3 23:16:18 2008 -0700
-
- Fixed GetoptLong specs to not depend on value of ARGV.
-
-commit 5dd9b0ecdddfd990d6387a0a7c70173ea0cededa
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 2 23:27:04 2008 -0700
-
- Add config file for and rework MSpec runners.
-
-commit 773a13ed9005628e48ed146180041caa035f4072
-Author: David Yip <yipdw@member.fsf.org>
-Date: Thu Apr 3 03:18:48 2008 -0400
-
- Added spec: full contents of StringIO stream should be accessible after rewind.
-
- Spec tested against Ruby 1.8.6p111 and Ruby 1.8.6p114 on OS X 10.4.11.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit ba2ca41cb29ac08c94231a2383940464e6fd1c9d
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Thu Apr 3 08:45:49 2008 -0500
-
- Updated tags for REXML specs
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 09c080bf33092b9d147d1b0a5de920fce8527fdc
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Thu Apr 3 08:45:26 2008 -0500
-
- Fixes whitespace in REXML::Element specs
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 3a997bc18f589b91b4cd518448644171f3054abf
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Thu Apr 3 08:29:23 2008 -0500
-
- More specs for REXML::Element
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit d250939060a4a91a6fee59bd4bfa4e86eb271373
-Author: Paul Thornthwaite <tokengeek@gmail.com>
-Date: Thu Apr 3 14:36:42 2008 +0100
-
- Specs for Set#superset and Set#proper_superset added
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 01399738d5ad0136ef205b8501b12012c7e42230
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Apr 3 18:09:20 2008 -0400
-
- Removed excludes for Object#kind_of?, #is_a?.
-
-commit 0e7d1c6e02e5617bb251366e0d60760edb29377e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Apr 3 20:04:34 2008 +0200
-
- Fixed copy-paste error in Object#is_a? specs.
-
- Adjusted the Object#is_a? exclude.
-
-commit 4a9cb7cc0c734b4280c3a65906c85e1c1e2f4990
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Apr 3 19:02:05 2008 +0200
-
- Add specs for #kind_of? / #is_a? behaviour that are failing in Rubinius.
-
-commit e88fdb6cbd9fa829a81e6c7664e88f6956ddae64
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Apr 3 07:18:56 2008 -0400
-
- Spec to check `A = 12; class A; end` raises TypeError. Works as is.
-
-commit 3c0db09626333405bdcb72e62ddb8fb2ea176ff5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Apr 3 06:44:32 2008 -0400
-
- Spec for const lookup: `A = 12; class A::B; end` should raise TypeError.
-
- * Currently crashes due to a lookup problem.
- * VVSiz discovered and reported.
-
-commit edda5994c293e4d26b4a741e90e0ab61513e8dec
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Apr 2 16:39:09 2008 +1100
-
- Do not strip leading spaces in debugger output
-
-commit eecc2bca5045921368378abfccafcf70339441f9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 2 21:34:52 2008 +0200
-
- Enabled File#truncate testcase for JRuby.
-
-commit 4d555cf50dfe6a8e9cb2f24a6a636a9df3f03768
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Apr 2 20:03:02 2008 +0200
-
- Added test case to File.open rubyspecs.
-
- Courtesy of David Yip.
-
-commit 42f0b52cd9fbac4a39fc1e5c2a241462bee5bf3b
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Apr 2 01:11:38 2008 -0700
-
- Use kind_of instruction since #kind_of? is not available at all times.
-
-commit 9ee52514eee820b9af7c9e6d2eaaca8d2bca363b
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 1 17:16:47 2008 -0500
-
- IO#reopen should return self
-
-commit f1481283091fcbe662fd01d409f5a2d2d7e3aa59
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 1 18:57:06 2008 -0500
-
- added primitive io_close_ng and tagged IO#close spec failures
-
-commit 3861e75e01af9319e2af879e2644fc8509947903
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 1 16:07:27 2008 -0500
-
- IO#close should return nil and refactored TCPServer.accept specs
-
-commit d6dfbd3b0bab57453e67991c3320744b08346979
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Apr 1 15:04:18 2008 -0500
-
- DRb specs now attempt to check if server is up/down prior to each call to start_server
-
- note that there is something wrong with the way stop_server works in rubinius as it appears that the TCPServer is still binding the port. Spec is tagged to deal with this but technically it's probably a bug in TCPServer
-
-commit 4119fe8baab45be6b1d1370b8a9537e710b1a60a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 1 12:40:47 2008 -0400
-
- Sanity changes to #load specs to bring them up to date.
-
- * Please change the specs if you change the implementation, sheesh.
-
-commit 3b58cb35abeba31f7ac72e3ab37b2630949406a7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 1 10:59:58 2008 -0400
-
- Spec for forced recompiling through second parameter of Kernel#load.
-
-commit 5d7a73ae15a4c40e31486a60cbb66f3de1ac4697
-Author: David Whittington <djwhitt@gmail.com>
-Date: Wed Apr 2 02:57:35 2008 +0000
-
- Add tags for failing private keyword specs
-
-commit 1b2f118be7ff9b6adfea736ecbbb8f3fd8dd0f49
-Author: David Whittington <djwhitt@gmail.com>
-Date: Wed Apr 2 02:53:43 2008 +0000
-
- Added a couple evil private keyword tests
-
-commit f58c67e33a99f751c3520ab65c96e28a91c45900
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 1 09:59:22 2008 -0400
-
- Conditional compilation. Rubinius.compile_if($DEBUG) { p somevariable }.
-
- * Hacky and probably fragile but it seems to work. Whenever the gvar
- given as condition evaluates to false, the entire block is omitted
- from the produced bytecode. If it evaluates to true, then the extra
- block itself is stripped and only the block contents remain.
- * Do NOT use indiscriminately until we have played around with it for
- a bit to avoid problems.
- * Manipulates the sexp, not the AST to avoid worrying about locals
- and scopes and whatnot.
- * Enabled by default; for example -d will work out of the box (you
- do need to have the file recompiled obviously.)
-
-commit 4f78ee2b0bebb9170a483927af9c7520ca67f912
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Apr 1 09:58:53 2008 -0400
-
- Specs to verify conditional compilation in the compiler.
-
-commit 8dfece35e3bc83e14e92bfee9ea0ebabb795da70
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Apr 1 01:07:14 2008 -0700
-
- Fix up language symbol specs.
-
-commit 29cc22f2c1f7ce2ce15a7f339d1159cf93510daa
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Apr 1 00:40:34 2008 -0700
-
- Constant lookup only searches class or module (#457).
-
-commit 538611f2aa06a1cf1c3958583bd6a8487deee994
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Mar 31 18:03:41 2008 -0400
-
- Spec for empty loop body.
-
-commit fd0d1079671d7664de3a6a836c5e5624d487a4e1
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Mar 31 23:47:40 2008 +0200
-
- Spec for constant lookup on non Module or Class objects
-
- This exposes the bug also described in ticket \#457
-
-commit 3b7cf550c70db2dd53cb58ef3efd2651ee352134
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 31 21:53:40 2008 +0200
-
- Added a couple of Dir.glob/Dir[] rubyspecs.
- (Courtesy of Roland Swingler)
-
-commit bbfa77a8517390bdc807f41bfe6d101791980d8f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 31 19:04:09 2008 +0200
-
- Fixed DRb rubyspecs (proper spec name, removed invalid file, better cleanup).
-
-commit d8a4fb0b16dc4c722cf148ff83bcad05fbb4af1e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 31 14:29:54 2008 +0200
-
- Make sure Marshall#load rubyspec closes the file.
-
-commit 4082a7663eaef50000be46d909c22fbb97a1a3e8
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 31 13:57:35 2008 +0200
-
- Reverted new Range#step rubyspecs, since they fail on MRI and JRuby.
-
- Partial revert "Fixes for Range#step."
- This (PARTIALLY) reverts commit a6b06a67207c40ffa9ccf191c051fdf2fa0f5359.
-
- The specs are reverted since they fail on:
- MRI 1.8.6 pl 36 (Ubuntu default)
- MRI 1.8.6 pl 114 (Current compatibility target)
- MRI 1.8.6 from 1_8 branch
- MRI 1.9 from Ruby trunk
- JRuby 1.1 from trunk
-
- The specs expect that to_f is invoked, but MRI and JRuby don't behave
- that way. Furthermore, Float is not a special case. There are other
- cases, like Rational. Take a look into MRI code, there is no special
- handling for Float.
-
- Please, test your spec updates at least against the current
- compatibility target (MRI 1.8.6 patchlevel 114) to avoid problems.
-
-commit 6d9680ecaaa2a9aadd35699c8064bf6481acc107
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 31 13:23:20 2008 +0200
-
- Added new rubyspecs for IndexError out of String#[]=
-
-commit c8a52bb7cf191bb35efc89c560bdeced4241f015
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Mar 31 04:38:49 2008 -0400
-
- Split Regexp#=~, #match specs; they behave differently on match.
-
- * #=~ Returns index, #match returns MatchData.
- * Grammar fixes.
-
-commit 6c2727e928991cdf9f809cb5941c3afedb5171ff
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Mar 31 04:07:17 2008 -0400
-
- Fix Regexp#match, #=~ spec to actually be shared. Exposes #454.
-
-commit e258a2bccafffba57ab86d1c1a104839bda424da
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Mar 31 03:30:48 2008 -0400
-
- Spec to verify IO behaviour with an altered BufferSize from Le Huy.
-
- * Moved spec to spec/core/io/ and simply used the first one.
- * This problem seems to have been largely corrected.
-
-commit 7a39be8bea055464838ff24c70e170a91f8df68c
-Author: Ben Burkert <ben@benburkert.com>
-Date: Sat Mar 29 19:39:11 2008 -0500
-
- Added spec for Module#define_method
-
- Methods defined by define_method with a proc should have the
- same scope for local variables as the proc.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 12c639d90ff3d14f8010ca7c782612bd7c1777ab
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Mar 29 23:58:13 2008 -0400
-
- Tony Arcieri's specs for inter-VM Actors.
-
- * VMActor implements the Actor interface to work in Rubinius' Multi-VM
- context: VMActors can reside on any VM instance.
-
-commit a0d0884aa3c9e7a6fa949cbde1cdf2392bc4ff23
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Mar 29 15:59:42 2008 -0400
-
- Module#attach_foreign allows using a symbol to give the function name.
-
- * Specs for the same.
-
-commit a5f397f38d6c9eafcac163c2cf678d5c55a6b79b
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Mar 28 23:40:04 2008 -0400
-
- Specs for FFI in general and Module#attach_foreign in particular.
-
- * Very basic specs to verify that FFI in fact works correctly.
- * We need to define what the behaviour should be in the case of e.g. an
- incorrect function signature. Currently it may or may not cause SEGVs
- depending on the exact usage. Remainder specs are in but quarantined.
-
-commit 3dc5c635b56bc599a718a94f990976b67ab52b6c
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Mar 26 02:01:12 2008 -0400
-
- Specs for Module#attach_foreign.
-
- * The method is a replacement for #attach_function but allows
- giving the library name as well to access external libs.
- * This acts a higher-level interface to FFI.create_function. The
- "real" FFI specs will be written for that method instead.
-
-commit 677412353409ba4e5d67f19a3d095c62d009c88f
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 28 18:04:40 2008 -0700
-
- Added CType#isctrl, #toprint. Rework String#inspect, #dump.
-
-commit 87ba991b9b488b808ebf729b9e41765df76cc602
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 28 15:09:11 2008 -0700
-
- Reworked String#each and #sum. Added String#modified? and specs.
-
-commit 204d8ce1a792a61882e549953b5b878139ac9cda
-Author: Hongli Lai <hongli@plan99.net>
-Date: Fri Mar 28 23:32:18 2008 +0100
-
- Spec: Marshal raises EOFError on loading an empty file
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit f6e698f96ce9e2a8c8abe856322add02931df8b7
-Author: Michael S. Klishin <michael@novemberain.com>
-Date: Sat Mar 29 02:20:23 2008 +0200
-
- Tag new spec for ensure as failing
-
-commit ef7e4436389a0f4346b3a3bc5c275b653f46d6bb
-Author: Hongli Lai <hongli@plan99.net>
-Date: Fri Mar 28 23:22:44 2008 +0100
-
- Add spec for exception handling inside ensure block.
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit f54c91f6cb7498fe44b1b05a1372d9f6ed3ea1ee
-Author: Stuart Halloway <stu@thinkrelevance.com>
-Date: Fri Mar 28 10:11:05 2008 -0400
-
- Fixes Pathname#absolute? and #relative?.
-
- * specs now pass
- * underlying cause was corner case in File#basename
- * new passing spec for corner case
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit 0d4606d53d8fc0bcb2370bd648546abffd402673
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Mar 28 16:45:47 2008 -0500
-
- fixed CSV::Reader.parse spec to use local fixtures
-
-commit 35a15c6c85ebb6eabaec16e03aa88399061844e9
-Author: Alister Lee <rubinius@dev.shortepic.com>
-Date: Sat Mar 8 18:11:24 2008 +1100
-
- Beginning of specs for CVS::Reader.parse
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit d4161a379eab621e338a8c82f088b834756082e9
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Mar 28 16:39:50 2008 -0500
-
- removed csv/reader/parse_spec to commit alister lee's spec
-
-commit 534806c10a95435873efcb0d215732d7da4f2fd6
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Mar 28 16:38:03 2008 -0500
-
- mkspec generated specs for csv.rb
-
-commit a6b06a67207c40ffa9ccf191c051fdf2fa0f5359
-Author: Stuart Halloway <stu@thinkrelevance.com>
-Date: Fri Mar 28 06:09:34 2008 -0400
-
- Fixes for Range#step.
-
- * previously failing specs pass
- * new spec added to cover float/int difference
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit 6886ec5851783c5364ff5bc464ee94071fc8535e
-Author: Michael S. Klishin <michael@novemberain.com>
-Date: Fri Mar 28 00:06:56 2008 +0200
-
- Update stdlib and specs for REXML from 1.8.6 patchlevel 114 (see details!)
-
- * Update stdlib/rexml to use REXML from Ruby 1.8.6 p114.
- * REXML in p114 is screwed up: call sites were not updated
- after REXML::Formatters::Transient#initialize arity
- change. Ruby 1.8.x branch in SVN though has
- completely different REXML layout and organization
- (rev. 15833) so there's no way to fix it until we know
- where REXML changes are headed in 1.8.x branch.
- * Update REXML spec and tags for it.
-
-commit 3145a74a85d72f6ef8a93384a74d96a589bfb5eb
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Mar 26 22:27:41 2008 -0700
-
- Rework and cleanup of various String methods.
-
- Also, ensure that when Strings are converted through FFI
- and passed to C functions, the char array is explicitly
- terminated with \0.
-
-commit 9ba3e515b49729e0cb80181af9e28e3ce4c70e97
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Mar 26 18:40:57 2008 -0700
-
- Shuffle some String methods. Add specs for and rework String#substring.
-
-commit 990d47b84bc6301be2a8bcbaccbae65ef697c417
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Mar 25 16:22:45 2008 -0700
-
- Added String#compare_substring. Reworked String#chop! and #chomp!.
-
- Also, to ensure that ByteArray instances that are accessible in
- Ruby are properly handled by C functions, changed string_equal_p
- to use strncmp instead of strcmp.
-
-commit f47c446daa136e6f31f5c590dd535ba22e89a0b2
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Mar 25 11:36:16 2008 -0700
-
- Fix errors in String#count_table spec descriptions.
-
-commit 9425d0de9a7883c14de6ae9ae5db05ab92141ab9
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Mar 26 22:38:48 2008 +0100
-
- Guarded two failing specs on OpenBSD that also fail on MRI
-
- MRI on OpenBSD also suffers from the 0.0 / -0.0 issue (the
- GCC version on that platform too). The child reaping spec
- also fails on both MRI and Rubinius
-
-commit 288a6e2ca3675a1e60bfd6b8b328c2a4d513c12f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Mar 26 22:15:16 2008 +0100
-
- Fix Socket specs for more strict BSD behavior
-
-commit 63513d23f16ca7919b8605e016a3a941b79c0834
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 25 17:20:53 2008 -0700
-
- oops! extra exclude
-
-commit a36a4bf8cde95c99282e07f46438430588288736
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 25 17:20:19 2008 -0700
-
- really minor changes
-
-commit e9b759812deaf97e7fe5846c116d53f69b63e244
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 25 17:19:41 2008 -0700
-
- Added the sucky parser spec--not passed yet
-
-commit 90eb74998e132373e6b96e3c66bfa909854e3ef0
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 18 17:41:50 2008 -0700
-
- Added spec for 'a [ 42 ]'
-
-commit 2d34643c75b53b832e89d2473d501ab1c8a5df02
-Author: David Whittington <djwhitt@gmail.com>
-Date: Wed Mar 26 08:01:20 2008 +0000
-
- Tagged Generator specs as unstable due to memory consumption
-
- Each spec consumes > 60MB of memory. After looking at the specs there is no way
- they should be consuming that much memory.
-
-commit 52d81e0593dbca8abfecefe2e9c3d2ab504cfe0b
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Mar 25 10:43:17 2008 -0700
-
- Added String#copy_from primitive. Reworked String justify methods.
-
-commit 1aabda50ea82974b96a7032a0ea13865b2332b5d
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Mar 24 21:57:02 2008 -0700
-
- Added Tuple.template and reworked String#tr and friends.
-
-commit bc7d9ccb8b8ca77d8479f325ea314fc09bc34907
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 21 00:51:10 2008 -0700
-
- Rework methods that behave like String#count.
-
-commit 1e5ac9a6818c972882e080aeb723a105108e0c57
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Mar 19 21:25:07 2008 -0700
-
- Rewrite of String#casecmp, approx 2x faster.
-
-commit c39f2cb708169d35c2fbeb969ee3323c704f0566
-Author: Matt Palmer <mpalmer@engineyard.com>
-Date: Tue Mar 25 21:09:37 2008 +1100
-
- Some specs for the timeout library
-
-commit cb69bdadeb10cf6b4b2c71a095562f8d8371d76d
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon Mar 24 17:55:23 2008 -0500
-
- Small fix for Socket.getaddrinfo spec
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit 5c3a61edef3c456b8296e65f8e06026347339a36
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon Mar 24 17:06:36 2008 -0500
-
- Fix for the socket's issue
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit f3fd9ac4eebd0bc2a0a06bbe06921463d03177eb
-Author: Federico Builes <federico.builes@gmail.com>
-Date: Mon Mar 24 14:10:46 2008 -0500
-
- Fixes specs for Socket and adds a gethostname spec
-
- * Changes hardcoded "localhost"s to Socket#gethostname calls.
- * Adds a simple spec for Socket#gethostname
-
- Signed-off-by: Michael S. Klishin <michael@novemberain.com>
-
-commit 7131328bc02057b16071a933fe98f331b27e00bb
-Author: Michael S. Klishin <michael@novemberain.com>
-Date: Tue Mar 25 00:24:01 2008 +0200
-
- Applied slightly modified patch by Federico Builes:
-
- * Add REXML::Document and REXML::Attribute specs
-
-commit cb464295e5accb00e783f7f9e2a0b10c64ad6579
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Mar 23 12:06:07 2008 +0100
-
- Added new Range#step rubyspecs.
-
- Excludes for rbx also updated.
-
-commit 7d181716ac3b92d8a31a20ec30daee455d36fc58
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Sat Mar 22 14:51:30 2008 -0500
-
- Added order-of-evaluation spec and tags for rubinius failures.
-
-commit 5caf94ce6deb5e28c9a3de02e60a9b86cbdaf7ec
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Mar 21 12:37:02 2008 -0500
-
- tagged new specs for pathname
-
-commit 62f88983ee3fa1b09d8f7df56e35cbfdac6d2a06
-Author: Martin Stannard <mstannard@gmail.com>
-Date: Fri Mar 21 12:10:23 2008 +1100
-
- added some specs for pathname library
-
- there are failures in absolute and relative specs
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit 655f61650bb299f38c9fd978594baa483fc0d0cc
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 18 16:22:24 2008 -0700
-
- Reduced parser todos from 113 to 89
-
-commit f97b2fc2ee3310e81871200125bbd7e33c2636bf
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Tue Mar 18 13:51:31 2008 -0700
-
- Moved sexp_expectations.rb to fixtures subdir
-
-commit 0a185e5ac48954cf4addae0c8f09dcb5be259f8e
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Mar 17 17:55:50 2008 -0700
-
- Added f'd up note about the spec failing
-
-commit 978f043e1ed3a2b7cb7d4129e0002be485b0a78c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 18 21:17:32 2008 +0100
-
- Fix Process.groups spec
-
- Process.groups can return an array with the same gid multiple
- times on certain platforms (at least on FreeBSD and OpenBSD).
-
-commit 8812658dde5e317dfebd0ea3c159ad0a1b98e8e8
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 18 21:02:00 2008 +0100
-
- Update spec tags for ERB
-
-commit 47216560d4a980cbaac2855e0c5ee302e0754bf8
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 18 20:53:16 2008 +0100
-
- Update spec tags for IO
-
-commit 7d34f4053023d99c3be4964bfebb3a1c74cd40c9
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 18 20:32:39 2008 +0100
-
- Update spec tags for File
-
-commit 8a66bc6f5e378f49febb80fba37723a7de0d2475
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Mar 17 15:46:51 2008 -0700
-
- Added specs for File.[l]chown/#chown, code for File.lchown.
-
-commit 960872ae163a5615f513c58d727a7fd93664673e
-Author: Glenn Davy <glenn@thor.local>
-Date: Mon Mar 10 10:00:40 2008 +1100
-
- Make File.fnmatch respect case when using square brackets
-
-commit 0e32f8e224543a3c152b0351540eaa36fdfcdb06
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Mar 17 11:04:27 2008 -0700
-
- Added exclude for failing spec added in b635fcf0.
-
-commit 62687753b239984acba4f0e80899ca75a8a08cfe
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Mar 17 10:56:31 2008 -0700
-
- Fixes and specs for Module class_variables methods.
-
-commit b635fcf041707fe55a26b7709aef8dc1b2509161
-Author: Charles Oliver Nutter <charles.nutter@sun.com>
-Date: Mon Mar 17 12:52:13 2008 -0500
-
- Add a simple Module#private spec.
-
-commit 2aa98e1df50bba768b57018f6e90c56fe39206f4
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 17 13:28:17 2008 +0100
-
- Make sure no processes left hanging after IO#close specs.
-
-commit 8f332dde4460c03c378f1d1ecc1fbae54557d8ee
-Author: Matt Palmer <mpalmer@engineyard.com>
-Date: Mon Mar 17 16:44:24 2008 +1100
-
- Raise an Errno exception if a write fails
-
-commit 55c830063115e4455eeda3f8de639a7f7e0624f5
-Author: Matt Palmer <mpalmer@engineyard.com>
-Date: Mon Mar 17 16:42:16 2008 +1100
-
- Raise IOError if we attempt to write to a readonly file
-
-commit ad64c0ea7598b8a4c62ba2dd435f70c976186a50
-Author: David Whittington <djwhitt@gmail.com>
-Date: Sun Mar 16 04:24:54 2008 +0000
-
- Modified file type specs to search for sockets in /var/run instead of /var
-
- Doing a find on /var could take quite a while + might do nasty things like do
- finds on backup files etc. Running a find on /var/run should be faster and
- safer.
-
-commit ff5e9d3b9d7f3e484211b66fff96e665ed13614b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Mar 12 17:44:55 2008 +0100
-
- Revert "Added simple spec for range splatting".
-
- This reverts commit 9b3988436a21f61c86168a7566d472c4dfa22162.
-
- The spec uses '=' instead of '==', and it verifies something
- that is not true for MRI (1.8, 1.9) or JRuby.
-
-commit 004662e54477269a98475f84724972b82885d9cb
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Mar 15 01:09:43 2008 -0700
-
- Exclude failing UNIXServer.new spec.
-
-commit 13340924519f607d9c48da04c3f3ab41a1de3e86
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 14 18:14:06 2008 -0700
-
- Tagged unstable Process.kill specs that cause hangup on linux.
-
-commit c4a4dc19a26db058594c8056933cdab42d4f26fd
-Author: Matt Palmer <mpalmer@engineyard.com>
-Date: Fri Mar 14 21:13:31 2008 +1100
-
- Fix up IO#write spec so it works cross-platform
-
- It looks like the Linux implementation of IO#write and IO#read are a bit
- different from the OS X version, because the spec worked on OS X.
- Presumably this tiny change won't cause any conniptions.
-
-commit 33890d9a77d5a34c15263f84b9b415ffc084815a
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Mar 14 14:42:11 2008 +0800
-
- Remove fail tags from passing ruby/1.8/core specs
-
-commit 4bdd3df099fe627d158f4c6d35e5a7df0a891e86
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Mar 14 12:58:40 2008 +1100
-
- Fix bug where stepping by line would sometimes skip a line
-
-commit 260190092afbcfadd1a6e1d6db1674ecf021b686
-Author: Matt Palmer <mpalmer@hezmatt.org>
-Date: Sat Mar 8 19:26:41 2008 +1100
-
- Put in an explicit IO.new test for single-argument
-
- Assuming that your UDPSocket tests passing will prove that IO.new takes
- one argument might have been, in retrospect, a little retarded.
-
-commit 58216e07f0728415762fe5fbe98e1e984dfea31b
-Author: Matt Palmer <mpalmer@hezmatt.org>
-Date: Sat Mar 8 18:45:17 2008 +1100
-
- Mark changing failures in the CI test suite
-
- Fix up so that the CI doesn't fail as a result of my previous changes to the
- UDPSocket specs.
-
-commit 36f91c5da132f309fbf6d047fd74ebd8aa7cbf22
-Author: Matt Palmer <mpalmer@hezmatt.org>
-Date: Sat Mar 8 17:26:49 2008 +1100
-
- Rearrange the UDPSocket test cases for better separation
-
- * open_specs now only contains a spec that calls UDPSocket.open;
- * send_specs now has separate tests for ad-hoc and connection-oriented
- sends.
-
-commit b40c1cf434bd0879f672ec1dc471f1e1dfaccc1c
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Mar 13 17:07:50 2008 -0700
-
- Add (failing) Symbol#to_yaml spec based on ticket 322
-
-commit c0bcb0151379fe9858d0fafd2ef56cf1b08daff3
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Mar 13 16:23:37 2008 -0700
-
- Apply ticket 351 and resolve ticket 350 (RbYAML bugs)
-
-commit a8d6e8cddfd8bc2dccaa93b25adfb31b39b96dba
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 13 16:25:55 2008 -0700
-
- Removed all should_not raise_error from shared/time_params.rb
-
-commit 01f09f4e5697c4a775ac321a71d3b777196d9001
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 13 15:47:37 2008 -0700
-
- cleaned up spec with new raise_error block form
-
-commit e965fc735311915dd43c47cc4853e163376cc6be
-Author: Lachie Cox <lachie@smartbomb.com.au>
-Date: Sat Mar 8 17:14:37 2008 +1100
-
- enhanced syntax error to give same message as MRI
-
-commit 868b38152ca99189fce85542a9068c0d01ee4a41
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 13 15:07:33 2008 -0700
-
- Added exclude for last patch applied
-
-commit 9b3988436a21f61c86168a7566d472c4dfa22162
-Author: Patrick Hurley <phurley@gmail.com>
-Date: Mon Mar 3 14:04:14 2008 -0500
-
- Added simple spec for range splatting
-
-commit 3c7a017e173945d3f9b18d566bb1c3d6d04e97e4
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Mar 13 17:18:39 2008 -0500
-
- fixed tags for new constant specs
-
-commit a966436b7be78bc063e32bc16496f5cabbb0a152
-Author: Matt Palmer <mpalmer@hezmatt.org>
-Date: Sat Mar 8 14:56:58 2008 +1100
-
- Make sure modules included in Object are found
-
- Add a spec to make sure that constants from modules included in Object are
- found. Evan is committing the fix for this separately.
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit 4e0ddd3e701f68b592cb69972f7d587b90392913
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Mar 13 15:05:54 2008 -0700
-
- Correct a 'defined?' spec added by ticket 388
-
-commit 407095d8ffbf0563fa46e5d4ed6a08423eddb2ad
-Author: Martin Stannard <mstannard@gmail.com>
-Date: Sat Mar 8 15:47:59 2008 +1100
-
- Added tests where defined? method should return string descriptions of objects
-
-commit f366309a8fff28552d7d27101d8b3d7b4352e235
-Author: Gianluigi Spagnuolo <glgspg@gmail.com>
-Date: Fri Feb 29 10:42:42 2008 +0100
-
- Fixed Array set element problem
-
-commit 42c22bf542edc8c8379587507fd9e35ba25b190c
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Mar 13 17:00:31 2008 -0500
-
- updated tags for new read specs
-
-commit 45c43a7ab3310a41b0b3367f4762a1bb55b02405
-Author: Ben Askins <benj@supernova.local>
-Date: Sun Mar 9 11:41:49 2008 +1100
-
- Fix typo in file/open_spec.rb
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit a221ea56325fe082154a629094abb27d40919a39
-Author: Alister Lee <rubinius@dev.shortepic.com>
-Date: Sun Mar 9 15:27:34 2008 +1100
-
- Specs to expose defect in eof treatment in IO.read
-
- Signed-off-by: Charles Comstock <dgtized@gmail.com>
-
-commit 4967adb3d49252aae75b6b57159fb5879ac75db1
-Author: Myles Byrne <myles@ducknewmedia.com.au>
-Date: Sat Mar 8 12:14:20 2008 +1100
-
- Check existence of ArgumentError
-
-commit 45e46234da288052e639bb5c9c122874fd4d4e1c
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Mar 13 10:28:54 2008 -0700
-
- Fix File[Test].size? and specs for it.
-
-commit d467bf21c4037784a21ba964b24c28fc80b34736
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 17:36:56 2008 +0800
-
- Fix IO::foreach when separator is nil
-
-commit 70615e1c15692b8a8149e1616c802db9eb5bad11
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 17:32:40 2008 +0800
-
- Fix IO#flush to raise IOError on closed stream. Remove empty tag files.
-
-commit 9c9e7f422c98bf6add6c9a426ae25e3a6dbced85
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 17:29:31 2008 +0800
-
- Fix IO#fcntl to raise IOError on closed stream
-
-commit 215d600002948efb949422c0163aa9bbe5790507
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 17:27:43 2008 +0800
-
- Fix IO#dup to raise IOError on closed stream
-
-commit 879ee8124a2ad8ce83bcd9c51b2d6df0baecb40d
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 16:29:03 2008 +0800
-
- Fix a bunch more IOError when closed stream
-
-commit 487d9561992eb03c3d12de5128772cd194b37b8b
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 16:26:33 2008 +0800
-
- Implement IO#read_nonblock
-
-commit 15c58fa2c47d2dc61b3dac436ab3b56a727b7dc5
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 15:46:22 2008 +0800
-
- Fix remaining IO.read specs
-
- * Passing nil to length treats it as no length limit
- * Passing nil to offset treats it as 0
-
-commit 9daee4f9c3b62db34b07d74171d1017fa823533c
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 15:32:13 2008 +0800
-
- Fix IO#sync to raise IOError on closed stream
-
-commit 2ac848c09e055b3eacc8bb18f713d56715484063
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 15:24:36 2008 +0800
-
- Fix IO#sync to raise IOError on closed stream
-
-commit 36aa8577603f1d8ca76344fc3e889bb7c991bfe9
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 14:51:13 2008 +0800
-
- Fix IO#sysseek to raise IOError on closed stream
-
-commit 3307f5a4db121c2097b450278bc3cf19550f267b
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 14:48:30 2008 +0800
-
- Fix IO#pos and #IO#tell to raise IOError, move their specs to shared
-
-commit 72890065371f3e1d1cde43618a3da04c900749aa
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 14:39:21 2008 +0800
-
- Implement IO#to_io
-
-commit 4977bd1f22278e19ba69203c2545ad97c297ae23
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 14:33:03 2008 +0800
-
- Remove IO#isatty tag file also, since they are sharing the same specs
-
-commit 5dd3115465852ddb03b7100b21739f9d38f0ee58
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 14:29:13 2008 +0800
-
- Fix IO#tty? should raise IOError on closed stream
-
-commit 063f56b4c402180c2c989a15b75fe7a15d4c5c61
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 13:55:55 2008 +0800
-
- Make IO#syswrite use the shared IO#write specs
-
-commit 22de413f6cccb3eb100fd29da90c2ded84ea19f3
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 12:08:50 2008 +0800
-
- Update IO#write_nonblock's tag
-
-commit 25a5ac7e9123512e87e6460f1fa5ecbcfc7349b5
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 12:07:22 2008 +0800
-
- Pull out 2 differences between IO#write and IO#write_nonblock specs
-
-commit a40dbd0f36f0237bc27c905c399aba1e62bbfa70
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 11:39:03 2008 +0800
-
- Alias IO#write_nonblock IO#write and make IO#write specs shared
-
-commit 1c8eb4bc04405753dd607af1f5d231df01fd2536
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 11:06:09 2008 +0800
-
- Make the mock return a string to prevent a coercion error
-
-commit a85b2105c826a7d39dc45c90cad37faf75baac86
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 10:39:00 2008 +0800
-
- Fix IO#write should raise IOError on closed stream
-
-commit e8c8af1aa888dc3e5600cad64f03c09aebaf6d22
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Mar 13 10:34:08 2008 +0800
-
- Fix IO#to_i should raise IOError on closed stream
-
-commit 49d48c381b7ed0f2576c2c5bff3ac8825a0dd49e
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Mar 12 17:56:26 2008 -0700
-
- Fix the insanity
-
-commit 646136d0f75b165a3a62266791556d3f4f03c835
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Mar 12 17:04:30 2008 -0700
-
- Finally got compiler specs passing
-
-commit 052bbcbe4f51b322ae44dc387320f9b4964d74cd
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Mar 12 16:23:58 2008 -0700
-
- Correctly set Syslog mask in Syslog::open and add crappy spec for it
-
-commit dbabc5bda94a2bd77b2cb777666d286155c75ee0
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Mar 12 14:55:08 2008 -0700
-
- Correct Syslog specs and modify syslog.rb to pass them
-
-commit 5b8bee08f2a19d6f25df98183a24745ed33ed519
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Mar 12 14:54:38 2008 -0700
-
- Modify Kernel#load specs so that they pass on 1.8.6-p111
-
-commit b96974693cee75772b09052f8ec7110a000c2429
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Mar 12 14:00:42 2008 -0700
-
- Fixed specs for wilson's compiler encloser changes
-
-commit 2a21597719bea1ea7db27a552ea6dfb6865963d7
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Mar 12 14:00:06 2008 -0700
-
- half work on pretty_inspect
-
-commit 6e398ca491b67a6c468798fd92a9764f70bc68a8
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Mar 12 15:18:02 2008 +0800
-
- Share String#to_a a specs with String#entries
-
-commit 2ff775cbcf2ade4315fbdbb37fa78ee84a1e645a
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Mar 12 11:59:26 2008 +0800
-
- Add String#to_a specs
-
-commit 4f1204bac224ad28375f06e5fb77156367895156
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Mar 11 19:53:32 2008 -0700
-
- Spec and implement Array#pack 'v' option
-
-commit 91d51783f44c3a9b1adfe03b7b9fa35476494ce1
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Mar 12 12:45:56 2008 +1100
-
- Debugger::Output#wrap should handle width of 0
-
-commit 51c316464ad44cadad7ecd997ce45e8392695f4c
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Mar 11 15:26:52 2008 -0700
-
- Implement support for :postexe nodes (END { some_code })
-
-commit 569dd9f10d5194c22335ce58a678d1f9c73f91d0
-Author: oleg dashevskii <be9@be9.ru>
-Date: Wed Mar 12 03:54:39 2008 +0600
-
- Import matrix lib with specs (#389 and #400)
-
- Original patches by Chris Lloyd and matta.
-
-commit 6beb50b7cc2dd3a0f57f3dee45767bb363082159
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Mar 11 13:20:07 2008 -0700
-
- More Integer#times specs.
-
-commit 746d89d6d55c82f26be08f182301926efd62d362
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Mar 10 15:39:26 2008 -0700
-
- Correctly set the enclosing class for evaled code.
-
-commit 218cc7fbdd1b5d1c52248e65817752b8a50821ad
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 10 04:46:00 2008 +0100
-
- Added JRuby speciifc guard to singleton rubyspecs (JRUBY-2239).
-
-commit 25e3f23e78f2b17e02d2c0a058925f8a0ec0d790
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Mar 10 11:25:38 2008 +0100
-
- Be sure not to close the socket before the Errno.handle call
-
- Also a small fix for a spec that fails on OpenBSD
-
-commit 9e7fdf3b0040971f7b8402b9cf5422efaedb2f4f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Mar 10 09:54:16 2008 +0100
-
- Fix TCPSocket#new spec, BSD systems make a distinction between IPv6/IPv4 localhost
-
-commit e5512b2a7725a67471eba086b107b0f4b1f136b2
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Mar 10 08:35:50 2008 +0100
-
- Fix for failing unpack_sockaddr_in spec on Linux
-
-commit b9eab2266e5d1f073b6f876710dc9e848fe25b0c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 23:37:05 2008 +0100
-
- Remove spec tag for now fixed Hash.allocate
-
-commit b6ba9a757b0531791424df38bce6587a53db6002
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 23:12:16 2008 +0100
-
- Remove tag for now correct Fixnum#[] spec
-
-commit 6785c2b44da90d95ef77e98cba42a953828b622f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 23:11:37 2008 +0100
-
- Fix Fixnum#[] specs
-
-commit 0aa09ce9b7269d54cdef583a2eaf0cb57c32f773
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 23:05:21 2008 +0100
-
- Removed tags for working Socket specs
-
-commit 18b27b0ebdc3713962771ca75c1321cabee08d61
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 22:48:45 2008 +0100
-
- Untag now working IPAddr specs
-
-commit f4c0d08bec8fb2db7d130363b0609de7b7720d7e
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 19:56:25 2008 +0100
-
- Slow IPAddr specs are now fast
-
-commit ff71385a67b2853130e63f9942bcea6ac69d591f
-Author: Eero <ruerue@yawn.kittensoft.org>
-Date: Sun Mar 9 10:35:27 2008 -0400
-
- Specs for #412. Array#sort and #sort block form calls #<=> on elements.
-
- * Block form should not expect anything of the elements, all is
- done through the return value of the block.
-
-commit e6edd1bb4bc52053bdb834d52e31fa185f2a2d62
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 14:51:00 2008 +0100
-
- Updated tags for IPAddr because of fixed bit operations
-
-commit 4f59fa9bd187822cd836aa046bb8fd40e4412c30
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 14:49:02 2008 +0100
-
- Fix Fixnum and Bignum shift operations to match MRI
-
- Added behavior for the edge cases, but took a different
- approach than the LH tickets. I don't think we should
- change coercion functions for this.
-
-commit ad8c630662dcb611cd955db08a6f4d53d1dc0dfd
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Mar 9 13:43:38 2008 +0100
-
- Fix Bignum#& and specs for Fixnum AND, OR and XOR
-
-commit 2529acd5e1cc8e61bd995e00834ee1f6941b1d9d
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sun Mar 9 14:18:04 2008 +1100
-
- Fix require_spec and load_spec.
-
-commit 57c7ded8e4d9567aa3c392e8a8262389387ebbfb
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sun Mar 9 12:25:40 2008 +1100
-
- Don't spec .rba require behavior in spec/ruby/1.8.
-
-commit ac630b23da01dcc3a1de1bfa06bac4d301a5031b
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 8 17:23:34 2008 -0800
-
- Better fix for calling to_proc on BlockPass nodes
-
-commit c17b32d44be8452cd867a8212a0fd8bb49c94821
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 8 16:34:02 2008 -0800
-
- Tag failing Method spec for CI
-
-commit c5d4a3b8f84b7558a5dfedb699a1a3ee4d61f118
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 8 16:26:58 2008 -0800
-
- Call Proc.__from_block__ on block_pass arguments
-
-commit a63f457821e67d138d9cf1c5ac8b0760cb25bfc2
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sun Mar 9 10:42:51 2008 +1100
-
- Remove support for zip rba files, libzip. rake clean required.
-
-commit 142222e41bddd2138d82f349f73dbc0fe2cf3fc2
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Sat Mar 8 16:23:37 2008 -0600
-
- Adding a spec for Method#to_proc proc used in define_method.
-
-commit b748efa9904baf0be26aa5b7297fc8ba76e46a74
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 8 13:09:44 2008 -0800
-
- Fix Module#method_defined? and friends for accessors
-
-commit 9b9d8216014c95eb7b4a925e93d0db8e9f5fd308
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Mar 8 10:46:18 2008 +0100
-
- Adedd a couple of GzipReader#rewind specs.
-
-commit 4612812bde4a2fccbaa72ea54ef76c7d964d216b
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Mar 8 15:49:57 2008 +0100
-
- Fix the Array#pack specs, network order is the same everywhere
-
-commit a720bba1619deb4358b453f58913d30a1a311b07
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Mar 8 15:27:47 2008 +0100
-
- Fix Sprintf for positive non decimal notation
-
- This fix combined with the pack/unpack implementation for
- type n also fix some IPAddr specs.
-
-commit caef838aca82665d4c2f691e4873e339a9c7238d
-Author: Lachie Cox <lachie@smartbomb.com.au>
-Date: Sat Mar 8 12:47:19 2008 +1100
-
- updated Array#pack specs to work on big endian machines
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit e3763469a224b4b3668bc1ddef2d982245787646
-Author: Lachie Cox <lachie@smartbomb.com.au>
-Date: Sat Mar 8 12:42:36 2008 +1100
-
- Added implementation of pack schemes for "n" and added handling of multiple items for "i","s" and "l"
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 41b26c49f5a16377af2c677eb702d665dd062a56
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sat Mar 8 15:35:10 2008 +1100
-
- Fix IO#pos EOF spec. Pair: Lincoln, Evan.
-
-commit 1e039fb5c9bcff987769c8644ec47c30aa250952
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sat Mar 8 14:53:01 2008 +1100
-
- Fix Zlib::GzipWriter#finish. Pair: Lincoln.
-
-commit 8551da47a01ef24eaf31fac55253fb05fe81cfcd
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sat Mar 8 14:21:08 2008 +1100
-
- Add Zlib::GzipReader #eof?, #pos, #read w/length
-
-commit a4dba8317311cc3a51231895b2eaea09daaa61be
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Sat Mar 8 10:41:33 2008 +1100
-
- Ensure #pos clears internal eof flag
-
-commit 407e1a4191da6ecd59c1347198a60be2556e043b
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 7 17:04:09 2008 -0800
-
- Tweaks to LookupTable. Converted Errno::Mapping to use LT.
-
-commit eb937c8f1041884e412e3d074387ca9f14bb03ef
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 7 13:48:45 2008 -0800
-
- Fixed LookupTable#delete. Added LookupTable#entries, #dup.
-
-commit d7d9bfd01180cf2c4fc74d2709f71fc7dd59f2f6
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Mar 7 15:03:14 2008 -0800
-
- Bandaid fix for failing #autoload specs.
-
- These need to be properly scoped. However, changing
- :A to ModuleSpec:A causes a sigbus.
-
-commit aea5cc446cd2c1b0cbd29e606b21b6d5959eb5ee
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Fri Mar 7 16:18:19 2008 -0500
-
- Add rb_gv_get and rb_gv_set, plus specs.
-
- Add rb_set_safe_level, rb_secure, and rb_safe_level methods, and specs.
-
-commit cd0b8969487af84a4f40466714dab2d5a1efc224
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 6 17:11:20 2008 -0800
-
- excluded
-
-commit e40f2bb09d8e3137de2856cb1e9c9438945603dc
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 6 17:11:00 2008 -0800
-
- More specs to test out const scoping with eval
-
-commit 3926add9039d1af4a60b633ef8805d471f28e02f
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Mar 6 17:01:21 2008 -0800
-
- Further clarified StringIO#getc specs.
- They weren't really testing what they were doing.
- Fixed StringIO#getc. now properly pushes single chars and sets @pos so it can be mixed with puts/write as needed
-
-commit d2d3750c4960d4a6f2a5d2b16b8bae3d598fbe36
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Thu Mar 6 19:16:24 2008 -0500
-
- Add rb_define_global_function to subtend, with tests
-
-commit 4ab5cc17b70b6569cf9311142d4b278dedfd0a64
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Mar 6 09:53:20 2008 -0800
-
- Added LookupTable and specs.
-
-commit 1ca8a272137ed7020cb977bf51dd2b7164ccbd7e
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Wed Mar 5 17:28:40 2008 -0600
-
- TCPServer.new coerces non-integer port to string and uses getservbyname logic.
-
-commit f0c03880972c19d1a12367dc51ed77f69d9ce8ca
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Wed Mar 5 16:44:33 2008 -0600
-
- Add a couple specs for killing/raising in a thread blocked on accept.
-
-commit 9f80ef157851671727653f46225b99af5d1a259e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Mar 4 21:26:33 2008 +0100
-
- Proper spec for %u with negative bignums and comments on MRI behavior.
-
-commit 3f9c36081c9b62bcde40206e64afdc2ac088bee8
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 4 19:09:56 2008 +0100
-
- Update tags for fixed File#chmod specs
-
-commit 735e818c38f8cefe0cd90514dac5282845a67dd4
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Mar 4 15:13:23 2008 +0100
-
- Improve testing of coercion in File#chmod specs
-
-commit 77a717f5962b2965ad9146e16cb36bedac891c80
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Mar 3 18:16:04 2008 +0100
-
- Adjusted syslog specs to better handle impls that don't provide syslog.
-
- For example, JRuby does not provide syslog (yet).
-
-commit 605bdc53e9dd4fb95dae6557d9ee6f9e2b8ceb80
-Author: David Whittington <djwhitt@gmail.com>
-Date: Mon Mar 3 08:44:33 2008 +0000
-
- Modified Bignum threshold specs to take into account platform wordsize
-
-commit 0af27d11d7dd68cfe49985dc4588933cc41f4fc8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Mar 2 16:40:15 2008 -0500
-
- Tag headius's new to_proc spec as failing
-
-commit b1caeeac673451a960917bb699a20e74cf488432
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Mar 2 13:30:35 2008 +0100
-
- Adjusted Kernel#catch test a bit, to make it more generic.
-
-commit 60f9544ade9d6e71fe3e423ab82cc87838478032
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Sun Mar 2 04:36:53 2008 -0600
-
- Add a spec for #363, & not coercing using to_proc.
-
-commit 70aa320f7f5bc75ed95362b0fb6d724e64224a88
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 1 17:17:55 2008 -0500
-
- Tweak new Marshal spec to pass on MatzRuby
-
-commit 35476e1bde23de26c01df409b750e91ef981fefc
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 1 17:11:53 2008 -0500
-
- Tag new failing Marshal spec
-
-commit d9f83819f1ed2505740ae0737199fecab29809bb
-Author: Jared Luxenberg <jared@jaredlux.com>
-Date: Sat Mar 1 16:20:18 2008 -0500
-
- Added specs for marshalling subclasses of Hash with init parameters
-
- Test that Marshal.dump gives correct output for such an object (passes)
- Test that Marshal.load is able to deal such an object (fails)
-
-commit 6039a3bd457c5d3dc99f5935999da574d17f1e5d
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Mar 1 16:20:08 2008 -0500
-
- Tweak Process.setrlimit spec for odd Linux platforms
-
-commit 25cfa6a96315ee203d06381ee3ddb76b60023360
-Author: Chuck Remes <cremes.devlist@mac.com>
-Date: Sat Mar 1 10:24:55 2008 -0600
-
- Fixes a race condition on OSX when "find"-ing character devices
-
- - on OSX the spec fixture would return /dev/fd/0 as a character
- device when run from the command line. This always succeeded.
- When run as a subprocess (like from cron or rubuildius'
- IO#popen) then OSX uses /dev/fd/0 and /dev/fd/2 for capturing
- stdin, stdout, stderr and others in that environment. While
- the fixture would "find" /dev/fd/2 as a character device, by
- the time the assertion tested it the underlying OS would change
- it to another device type causing the assertion to fail. This
- is just bad luck. We now grab the #last device found rather
- than the first.
-
-commit b6e95321df023ac989c4e5bb926ec55493260bc9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 29 16:04:10 2008 +0100
-
- New rubyspecs for IO#ungetc.
-
-commit 9bd2f0740c71d426cfa3c3636c2451762f640c14
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 28 21:59:35 2008 -0800
-
- Specs for Hash.allocate. Fix awaits replacing Hash with LookupTable in core.
-
-commit c1d979639bfc19072351211815ffd5c8da772dcd
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 28 21:56:33 2008 -0800
-
- Specs and fixes for Module.allocate.
-
-commit 904fd6136f00bab5fec62e8e702a0508dec44bac
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 28 19:45:39 2008 -0800
-
- Specs and fixes for Array.allocate.
-
-commit 776a24f0d14bbb5127c804cf0579960335c1a049
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 28 19:35:55 2008 -0800
-
- Specs for String.allocate and fixes to make them pass.
-
-commit fa35211f357ff1b9660a318c12b86ca156c5f26d
-Author: Ari Brown <ari@aribrown.com>
-Date: Thu Feb 28 20:27:55 2008 -0500
-
- Moved stdlib/syslog.rb to lib/syslog.rb . it works!
-
- * everything runs! yay!
-
-commit 8f103a6f9d7a168e37d1063e40bee960d64fc609
-Author: Ari Brown <ari@aribrown.com>
-Date: Thu Feb 28 19:42:11 2008 -0500
-
- Added specs and the constant module for stdlib/syslog.rb
-
- * added some specs for that which is testable
- * fixed the constant module so the constants are defined
- * fixed 'undefined method' problem in #write (private)
-
-commit 0c89dc90fdcb7933169e23462197d59f9627f510
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Feb 28 14:31:05 2008 -0800
-
- Added basic throw/catch specs. Fixed raised NameError to contain the name
-
-commit c8f4db4270984b60a087dd423c9e0da3e3760622
-Author: Phil Hagelberg <phil@hagelb.org>
-Date: Thu Feb 28 14:11:30 2008 -0800
-
- tag failing proc spec
-
-commit a1591319696385191f3301516d2f8265cd8fedcb
-Merge: f167f8f... 3f1acce...
-Author: Phil Hagelberg <phil@hagelb.org>
-Date: Thu Feb 28 13:43:52 2008 -0800
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit f167f8f6f7f3a1b8804a5452643236a23c0ce4c4
-Author: Phil Hagelberg <phil@hagelb.org>
-Date: Thu Feb 28 13:43:40 2008 -0800
-
- failing spec for returning from procs
-
-commit 3f1acce781c0dcf43698441036a085a0cef02d29
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Feb 28 16:14:55 2008 -0500
-
- Basic support for UNIXSocket and UNIXServer
- Fix some 'Errno' typos in socket.rb
-
-commit afbf38613364436630933753d99ee94c03b85074
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Feb 28 21:34:10 2008 +0100
-
- Added specs for File.fnmatch with case-sensitive brackets.
-
-commit 28323bda3d1f3295371b6ea99ed8ba6ee15661bb
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Feb 28 20:47:51 2008 +0100
-
- Added specs for File.fnmatch with '**/' patterns.
-
-commit 893ff4729d024198d5b423cc4426153f49cb5ebe
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 28 11:30:49 2008 -0800
-
- Fixed lookup of class variables defined in metaclasses.
-
-commit dee531b18d96199d608d8e2e8e27f54ef500a716
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 27 21:47:13 2008 -0800
-
- Additional Symbol#inspect specs. Another try at making them pass.
-
-commit 3bfb705b709ab35593684a68b35fb0ee8e1e01d7
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 27 21:46:37 2008 -0800
-
- Silence 'woot' echo on ubuntu from #system specs.
-
-commit 7fb76f2c4a9fb0c5695a38b90150ea6f50097237
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Feb 27 18:05:48 2008 -0800
-
- Fixed Symbol#inspect from over quoting
-
-commit 4ac32e4c9d0ff55aad50a00944f1a64931cfd1c6
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Wed Feb 27 17:18:09 2008 -0800
-
- Added some pretty rude specs for Kernel#system and got them to pass.
- Fixed a wierd problem with system/exec not cleaning up the fork process right
-
-commit 73be3b88af1ac96a6d4afabddd2871cfc4691eec
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 27 15:36:17 2008 -0800
-
- Fix String to properly initialize backing store when subclassed.
-
-commit 5ab2f9e594b7e66a04028e60f3517488e345f508
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 27 15:04:09 2008 -0800
-
- Scope classes used in String specs.
-
-commit e45d58100850443fedada905f654bae3f4144790
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Wed Feb 27 17:04:58 2008 -0600
-
- Add /devices to find commands; Solaris uses /devices instead of /dev.
-
-commit 1403477197873d613cfb93d644f78b4067d180d3
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 27 20:21:48 2008 +0100
-
- Adjusted Env spec, to be able to run it on Solaris.
-
- grep is replaced by egrep, since older greps don't
- take -e parameter (like on Solaris).
-
-commit b239a3b615d341f982a7a4a3a1b1200d95f79684
-Author: Adam Shelly <adam.shelly@gmail.com>
-Date: Wed Feb 27 04:09:24 2008 -0500
-
- Amending specs for Array#pack('U')
-
- * rbx is now passing most specs
- * failing specs are due to String#unpack.
-
- Signed-off-by: Brian Ford <bford@engineyard.com>
-
-commit 328c40e0f24601e739f404ab252652deca477513
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 27 02:46:21 2008 -0800
-
- Fixed Array instantiation to work with subclasses.
-
-commit 96c4ea885fbd075765b9d234de2754df3c857b07
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Feb 27 09:26:25 2008 +1100
-
- Move Debugger::Output specs to match new location of class
-
-commit c59f16f34f47860b200c6de4a2c1144c566de3dd
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Feb 26 10:23:14 2008 -0800
-
- Exclude new failing Array specs.
-
-commit 27248a45f079fd5a8cdb9ee71d008d135dcbe63d
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Tue Feb 26 00:10:29 2008 -0600
-
- Add additional Array tests from BFTS.
-
-commit a0e156f4c5bc12bf39950afeb58a6962b37efaa7
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Feb 26 16:53:01 2008 +1100
-
- Fix Debugger help output formatting to use wrapping
-
-commit fa5304d42c72a07b09cece99cb22c90f6b399a51
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Feb 26 13:22:31 2008 +1100
-
- Add wrapping to debugger column output
-
-commit 1a5d830b41eef37bb78168c959dd5b2f0757fde4
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 25 18:58:11 2008 -0800
-
- Conform Bignum#div, #divmod to weird MRI maths.
-
-commit eb5c6e367990bfdd193bcdf3055009f3e3e1aeaf
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Feb 26 13:23:29 2008 +1100
-
- Fix Debugger specs to pass on ci
-
-commit a2feff6782a052a9b71da90e9d4e1b2d991cc598
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Feb 25 18:53:24 2008 -0500
-
- Patch by Jos Backus (josb) - Closes ticket 364 (FreeBSD warnings)
-
-commit cee08883cc3de2e41a88b506f7d7f8d40697eaa2
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Feb 25 13:20:21 2008 -0800
-
- Fixed autotest churn by removing empty.txt and moving to /tmp
-
-commit f26bb0c4e3b8435a853a9f4843173748d98075fd
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 25 11:25:10 2008 -0800
-
- Add the rest of spec/* directories to CI process.
-
-commit 29f36833e79de6115c27d744adf158e1b3ba42f0
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 25 00:29:45 2008 -0800
-
- Excludes for spec/kernel, spec/debugger to run with CI.
-
-commit 12bbdf70af31d5168c2df0a9b53651f94b36899d
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 25 00:22:13 2008 -0800
-
- Excludes for subtend specs so they will run with CI.
-
-commit 0cbc2b1f20d8aee7ea74eb14e1f9cf242f8b47d5
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 24 23:57:56 2008 -0800
-
- Remove specs for removed Compression::ZLib.
-
-commit 1b4fbc76c2eb84e5cb45562f54ac105784f9e134
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 24 23:49:57 2008 -0800
-
- Conform Ar specs.
-
-commit f8e62002711c3cfd8024faca497775f7253a326a
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Mon Feb 25 05:24:54 2008 +0100
-
- Add a second case for truncating IO buffers that specifies too-small size.
-
-commit 9f3e25289cc52cd3f3fb240de1ad82a16a8b135c
-Author: Nikolai Lugovoi <meadow.nnick@gmail.com>
-Date: Tue Feb 12 23:19:27 2008 +0200
-
- Fixes for String#to_sub_replacement:
-
- * removed String#replace_slashes
- * using plain byte-by-byte scan instead of regexps to detect and handle backslash escapes
- * better handle unknown escapes and cases like '\\\1'
- * updated specs for String#sub
-
- Signed-off-by: Brian Ford <bford@engineyard.com>
-
-commit d87df0b7634ae37f85fc8f2795e4c8c425614b11
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Mon Feb 25 02:57:27 2008 +0100
-
- Add a spec for Enumerable#inject with a *arg; JRUBY-2162 exposed it.
-
-commit f04fcabf8c064dfcbf3b118bdc83289da169a30c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Feb 24 21:24:51 2008 +0100
-
- truncate behaves different on OpenBSD, changed specs according to MRI behavior
-
-commit b74a2f45b32a02469d61d4ace04912ec25f19543
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Feb 24 20:18:02 2008 +0100
-
- Looks like Darwin does provide Process::RLIMIT_AS
-
-commit 7113973abff64eeb1304b15be46f07d301d84f3f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Feb 24 18:25:55 2008 +0100
-
- OpenBSD doesn't provide Process::RLIMIT_AS, so this spec should be excluded
-
-commit 49b72719bf5c732f4aa2ad0d70e5a224556fb471
-Author: oleg dashevskii <be9@be9.ru>
-Date: Sun Feb 24 11:04:07 2008 +0600
-
- Spec for method taking lambda and block.
-
- * should raise SyntaxError
- * passes on MRI
- * fails on rubinius
-
- Signed-off-by: oleg dashevskii <be9@be9.ru>
-
-commit 60bbc8506d70571249972dbf124df520f0a4a476
-Author: Chuck Remes <cremes.devlist@mac.com>
-Date: Sat Feb 23 10:23:09 2008 -0600
-
- Fix unpack_spec expectation for little-endian byte ordering
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 17e45cee97057684e6c24608f97de48c28947384
-Author: Chuck Remes <cremes.devlist@mac.com>
-Date: Sat Feb 23 09:44:37 2008 -0600
-
- Fix unpack to use native host byte order for formats /ILQS/
-
- - unpack_spec had a bad expectation on little-endian platforms
- - unpack_spec got some updated description strings to correctly identify
- the host byte ordering expected in the spec
- - kernel/core/string.rb now unpacks formats /ILQS/ in the platform's native byte
- ordering
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 1540cb7caa0f200ed6d318971fb7302cd089e27d
-Author: Chuck Remes <cremes.devlist@mac.com>
-Date: Sat Feb 23 08:10:00 2008 -0600
-
- Add some missing endian guards to the unpack_spec
-
- - in my haste, forgot one set of guards around some specs
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 8488676fc0dac5db5d01dd92e061476226d58bd1
-Author: Chuck Remes <cremes.devlist@mac.com>
-Date: Sat Feb 23 00:19:33 2008 -0600
-
- Fix several Array#pack and String#unpack bugs related to byte ordering (endiannes)
-
- - added a small utility method endian? to the kernel module; determines host byte
- ordering by taking a symbol (:big, :little) and comparing it to Rubinius::ENDIAN
- - modified Array#pack to check for the native byte ordering for /ils/i formats
- - modified String#unpack to use native byte ordering for /DdFfIiLlQqSs/ formats
- - modified String#extract_number to do special processing for big-endian platforms
- and for formats using native byte ordering on a big-endian platform
- - added little_endian and big_endian guards around several String#unpack specs;
- now passes running against MRI and rbx
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit f8146d29bfdf67349f3f9c0c7105ce595981255f
-Author: Gianluigi Spagnuolo <glgspg@gmail.com>
-Date: Sat Feb 23 12:44:25 2008 +0100
-
- Added some test to Regexp.quote to manage tab and white space
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 714efa8574687e1fd31f904a4f35cce8056719f5
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Feb 23 00:01:38 2008 -0800
-
- Fixed Digest specs to pass with RSpec.
-
-commit a0fe2f7fa080729b77b32ffe21be5705a162ed71
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 22 22:26:52 2008 -0800
-
- Remove ffi_decode_sockaddr, replace with existing ruby code.
-
-commit b2baf0911e4a88ba2f6c4cb8e3e31d2a3aa1c6bf
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 22 17:06:18 2008 -0800
-
- Move Ar to kernel/core.
-
-commit 01baf002a8c7bd6e249b9477c1f78e6b99a67bf6
-Author: Philipp Bruschweiler <blei42@gmail.com>
-Date: Wed Jan 16 00:11:12 2008 +0100
-
- added specs for SHA256/384/512
-
- these specs were as well shamelessly copied from the md5 specs.
- they work, but every sha* class has a folder for itsself, that's a
- lot of duplicatd code. maybe someone with more experience in
- writing specs should have a look at this.
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 924224fcf655da90148ebd8234033a71e1b23090
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Fri Feb 22 17:13:14 2008 -0500
-
- Catch no block given in rb_yield, raise LocalJumpError
-
- As well, define that as an exception for subtend
-
- Update spec
-
-commit 3748843421832df5b842a677ddd2e55fbefb0b5f
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Fri Feb 22 17:04:33 2008 -0500
-
- Update rb_yield spec
-
-commit f60ca442b1466f29432995700457e8b34f4ff294
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Fri Feb 22 17:00:36 2008 -0500
-
- Fix rb_yield call
-
-commit a75afc4595fd20d7853ff65afe015de88b265b93
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Fri Feb 22 16:48:17 2008 -0500
-
- Add blocks to subtend methods, as they should be able to access them like any other method.
-
- Also, update the spec
-
-commit d9911f8b00243f3c95759612dde35edf6edaa678
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Thu Jan 31 13:54:24 2008 -0500
-
- Add block specs and rb_block_given_p
-
-commit b6c806f0d8213c4751c69638174f60b80f9ba303
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Feb 22 15:31:58 2008 -0500
-
- Failing spec and exclude for left-to-right masgn evaluation order
-
-commit 8f9e3c9e5e7dfc535e8fe6b10b945587586651ec
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Feb 22 13:59:44 2008 +0100
-
- Fix Socket#getservbyname, not every platform defines http/udp
-
-commit f29ff3bcaf0bf83d2924d08ea5f6c0bbb5df9948
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Thu Feb 21 16:47:02 2008 -0800
-
- Allow Ar to create archives
-
-commit e50ec6470dfc905198065a98b65b33a99da60e15
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Feb 21 20:20:41 2008 -0500
-
- Some compiler specs for 'defined?' handling
-
-commit ba5a0d87182d83000205e1202f5c473568a50489
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Feb 22 01:08:51 2008 +0100
-
- Fixed #332 and cleaned up Time a bit. Thanks to gls
-
-commit edf1e0d530ebb39a1b46d0fa518b9ca85db544da
-Author: Evan Phoenix <ephoenix@engineyard.com>
-Date: Thu Feb 21 02:01:21 2008 -0800
-
- Fix the last usage of block return (ie, internal long return).
-
- * LongReturnException is now used whenever a block requests that
- it's home context should return.
-
-commit 83ed7161701202d48490e7f38b568bc504f9690f
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 23:59:47 2008 -0800
-
- Added little/big_endian guards to Array#pack and String#unpack specs.
-
-commit 65b4ed86002371f2b56759aadc61e61c1cbbdba4
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Feb 20 22:49:19 2008 -0800
-
- Exclude Socket#unpack_sockaddr_in spec. See tag comment.
-
-commit 9fbda05c4dffb964a9f10e26d62240fbd52200a0
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Feb 20 22:48:31 2008 -0800
-
- Exclude super slow IPAddr specs.
-
-commit 3d39fb35dcd3c28fa626aeb96057b927c6bfe7c9
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 18:54:50 2008 -0800
-
- Redo expectation in Socket#getaddrinfo spec.
-
-commit 69576ede38d9bf09d1afd0120726ca756a0aa7cf
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 18:31:27 2008 -0800
-
- Account for variable length array in Socket#getaddrinfo.
-
-commit f396bd718572d9402d0d7eeb8da02474914396a8
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 17:59:29 2008 -0800
-
- Use File.delete in YAML specs instead of rm.
-
-commit 7698ec3855ce572f1e10962596804b82f3cd6534
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Feb 14 10:07:48 2008 +1100
-
- Hook-up new StepBreakpoint to new debugger step commands
-
- * The commands step and stepi have now been added to the
- debugger, and step into called methods.
- * The commands next, nexti and out have been converted
- to use the new StepBreakpoint. The legacy versions
- remain, but have been renamed as ln, lni, and lo; these
- will be removed once the new commands have proven stable.
- * Replaced VM method cache command with VM send site command
- to show details of SendSites in the current method.
-
-commit f192d65ec5eb31b4a807b9c3eb7360b84739d9f2
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Jan 31 16:43:19 2008 +1100
-
- Initial implementation of StepBreakpoint
-
- StepBreakpoint class moves step logic out of the Debugger
- and into breakpoint, where it more logically belongs.
-
-commit fd0ff43d2d384e221ff8de611843f3406d192657
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 17:04:46 2008 -0800
-
- Fixed YAML spec to pass MRI. Added fails tag for rbx.
-
-commit d69834a5217ddc6667b495fbe7d4dd8ad413ba88
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Feb 20 15:42:25 2008 -0500
-
- Fix dead code in TCPSocket.new specs
-
-commit 4644222e63046783933ca9b2e4514e3ff21fbb57
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 12:31:14 2008 -0800
-
- Add missing tag file for method_spec.
-
-commit 230d5d506f4203bcd3922880fae506fa480e6308
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 12:17:13 2008 -0800
-
- Fix typo in socket specs.
-
-commit a5d49537832a9cc33b07cade265af0834f123533
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 12:09:11 2008 -0800
-
- Move specs for calling methods to language/method_spec.rb.
-
-commit ead32a1f2820a4e2fcc906a8e7f3603490ba901c
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 11:53:45 2008 -0800
-
- Use bignum_value where a Bignum is intended in the specs.
-
-commit 1021345337bca1f928879713cb84a76b9c7935a1
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 10:21:42 2008 -0800
-
- Removed unused require 'stringio' from io/syswrite specs.
-
-commit cfd51af482321b4d672d69569de185f582a21831
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 09:00:36 2008 -0800
-
- Symbols as Fixnums is long deprecated. We don't spec it.
-
-commit a8bd2a1aba97653625a9b568d1a7112b5fce45f6
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 00:15:54 2008 -0800
-
- RbYAML is not in Ruby standard lib. Move specs for it to spec/library/rbyaml.
-
-commit 56b454af2ded18d0459bc974efa666ccf3b8de0f
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 20 00:10:24 2008 -0800
-
- Restrict specs in spec/ruby/1.8 to current stable 1.8 version.
-
-commit 22e01d1914db92d159ee15d3cf73c9d6e9d0a24b
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Feb 19 23:20:27 2008 -0800
-
- Fix Dir#pos=/#seek specs. We shouldn't spec undefined platform behavior.
-
-commit d522af83d0cfcdf39932afff7ba7d75d77dd0453
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 20 11:51:44 2008 +0100
-
- New IO.read specs.
-
-commit 77fdbe404e31f44e1c302eb99a7ff129523183ce
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Feb 19 16:14:43 2008 -0800
-
- Add library to read/write ar(5) files
-
-commit d7702f979732de90358dc35d795c6ac621f815bc
-Author: Matthijs Langenberg <mlangenberg@gmail.com>
-Date: Mon Feb 18 18:04:27 2008 +0100
-
- writen some examples for Base64 module
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 33b189478c05bd687ac8b062cd5307a3290d8931
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Feb 19 00:27:51 2008 -0800
-
- Convert platform guard :size option to :wordsize.
-
-commit cbcdb8346a2c75ba65910b486cee718cd3aa5175
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Feb 18 23:07:41 2008 -0800
-
- Exclude TCPSocket.new for now, hangs on ubuntu gutsy.
-
-commit ec990b6ebcd35cbf9dc192852f37e184c3e4079b
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Feb 19 15:55:25 2008 +1100
-
- Re-enable debug on context change
-
- The cpu_yield_debugger_check was not being performed as
- a result of changes to method dispatch related to the
- implementation of SendSite.
-
-commit aa585b7e637e2fd873602ee6725256429f413582
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 18 18:59:18 2008 -0800
-
- Removed :version guarded specs that are not current stable.
-
-commit 431af5920a0a02dfca927961a2d6457ae5f050e2
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 18 17:40:56 2008 -0800
-
- Added new tags files for excludes.
-
-commit 10dd37903533cac9a6f77ead70f3aa9ee1dc9098
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 18 16:38:58 2008 -0800
-
- Removed deprecated $deferr from getoptlong.rb. Moved to /lib.
-
- Small fixes to other library specs to get them running under CI.
-
-commit ee2dabf771a5e6d8d70c47fa49b1298d2d002c8c
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 18 00:42:54 2008 -0800
-
- Use the spec guards properly.
-
-commit 91d6c64be8827768ba2e39b80a4eb81b9affc122
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 17 22:40:21 2008 -0800
-
- Deprecate #setup, #teardown in specs; use #before, #after.
-
-commit 6ba49012504c08973e1fb2fd1b9fce75c351d148
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 17 22:00:56 2008 -0800
-
- The #fails_on guard has been removed. Use #ruby_bug or tagged excludes.
-
-commit e24231f5c62c0b73768c7503f50b53e8ffc345d1
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 17 21:08:01 2008 -0800
-
- Renamed *_excludes.txt to *_tags.txt for specs.
-
-commit a1c707b517e13115692173bc2048309e74c00915
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 17 20:45:14 2008 -0800
-
- Hand merge recent excludes changes to spec/tags directory.
-
-commit 838bee7e99bb1179c9a3a7782dcab9c2b904e72e
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 17 00:17:51 2008 -0800
-
- Moved excludes from spec/data to spec/tags. Added "fails" tags.
-
-commit 8ad91b03788d89ccd12fbcf19c06c9ef4f0cfee8
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 4 19:19:00 2008 -0800
-
- Misc fixes to get MSpec running specs.
-
-commit a683dd75786ab6c6a255c9bac399dc6be7aaa4b5
-Author: Tyler McMullen <tbmcmullen@gmail.com>
-Date: Sat Feb 16 23:39:38 2008 -0500
-
- Add support for H and h to Array#pack.
-
- * Updated array/pack_spec with specs for H and h, separately
- * Updated Array#pack to handle both with a single block of code
-
- Signed-off-by: Brian Ford <bford@engineyard.com>
-
-commit b1d3ba9d10f6a9ea87d8cb9be21d0d432e973117
-Author: oleg dashevskii <be9@be9.ru>
-Date: Mon Feb 18 01:18:24 2008 +0600
-
- Update specs for calling methods.
-
- Nasty binding stuff (first noted in #293) got specced and put into excludes.
-
-commit 02225daa5cef4fa3f48cac73d4bf0f9d02f3ebe0
-Author: oleg dashevskii <be9@be9.ru>
-Date: Sun Feb 17 23:20:08 2008 +0600
-
- Cross-breed and update for, while & until language specs. Little fix for hash spec.
-
- The compiler drops out on "for @@var in 1..3", so this is commented out.
- Variable scope stuff arrived into excludes.
-
-commit f43383a150131278d30535196e8da4e60dff97b1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Feb 17 13:10:55 2008 +0100
-
- New specs for RangeExceptions out of Fixnum and Array methods.
-
-commit 7d1c744d9c1ae50376be406a28e383a04ca6b4fc
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Feb 16 13:49:11 2008 +0100
-
- Corrected copy-paste error in recent fixnum specs.
-
-commit 08982321472008f7645212289d2624d19053ed7e
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 15 21:18:53 2008 -0800
-
- Fix IO#read for large files and small parts of files.
-
- Fix IO#read with buffer.
-
- Fix IO#eof? when buffer reaches eof.
-
-commit 1d07588d61b3835a6165c5de1f731277812cff79
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 15 19:11:42 2008 -0800
-
- Add missing spec for IO#eof? and fix.
-
-commit e0a6c8e179e48b423b6eb142b27460cd86d0223b
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 15 17:50:47 2008 -0800
-
- (Last change was ok). Force check for data so #eof? works
-
-commit d7e67c257c213f9e25b3123ce85576feb71a0089
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 15 17:28:48 2008 -0800
-
- Revert "Force a check for more data on the IO for IO#eof?"
-
- This reverts commit 3d4427e802756678608bf9840ba6f26fc81cf7fe.
-
-commit 4c1182c184bb6c2c97c5fc8ce83f242fe5f5144b
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 15 17:26:08 2008 -0800
-
- Force a check for more data on the IO for IO#eof?
-
-commit 94466db3347889850feb25dd7c83883df21bac92
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Feb 15 14:13:29 2008 -0800
-
- Added Float examples to Bignum bitwise operator specs.
-
-commit 3a668451d3bcc46b162a69ce1f8ec5d6a98b2d22
-Author: Brian Ford <bford@engineyard.com>
-Date: Fri Feb 15 13:44:24 2008 -0800
-
- Added bignum_value helper. Added specs for Fixnum bitwise operators.
-
-commit 217eb67a4c2f0bf1222628abfecfadbede5fb3b8
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Feb 15 21:09:43 2008 +0100
-
- Fix process specs for FreeBSD
-
-commit f25e0e130110ebbef0b5bc0c28c9b08db6c73a1f
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Feb 15 13:18:40 2008 +0100
-
- Removed now working exclude for Array#sort
-
-commit 56af7be26dcc9b7270de6d96e73e09a4f17cc710
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Feb 14 20:48:37 2008 -0500
-
- Improved Array#sort, #sort! specs.
-
-commit 714ea4b5245172cc6d5c815ef7399d1a991dd83f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Feb 13 10:30:22 2008 -0500
-
- Improved Array#sort specs a bit.
-
-commit 8944e873848c610182405c2de466e41e6260573d
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Feb 13 02:34:37 2008 -0500
-
- Tuple#swap specs.
-
-commit 24199f731dba40b72af6d121121dec9f085f890d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Feb 14 20:03:16 2008 +0100
-
- New rubyspecs for IO#reopen.
-
-commit 4f70320e5b7089c74b3899216763cd37d8854230
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Feb 14 17:27:32 2008 +0100
-
- Removed JRuby-specific guards. Please don't use guards to hide bugs.
-
- Guards to be used only when it is agreed that the JRuby behavior
- is intentionally differs from MRI. For plain bugs, guards should
- not be used. Instead, we maintain spec exclusions in JRuby repository.
-
-commit 0198a11b3bdf60983846a6c722dfa11d1b9f57bb
-Merge: ef3393e... 1f1e32e...
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 15:57:57 2008 +0100
-
- Merge branch 'mutle_file_specs_refactoring'
-
-commit 1f1e32e5e1fd12fb323e2a74a7f5caae96aa867b
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 15:18:14 2008 +0100
-
- Specs for File#chown #flock and #truncate now pass on JRuby
-
-commit 3a8e601d5205e050f83179376d2be3e922e80c20
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Feb 14 17:25:02 2008 +1100
-
- Fix context specs to wait for debug listener thread
-
-commit 608d7a99e75d293d6f9786cee940c0dd23156be3
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 12:59:32 2008 +0100
-
- Adding guards to only run File#chown and File.chown specs as root.
-
-commit b3a1069cf6c18b844b9eced32b7bcdb91ad7c558
-Author: Brian Ford <bford@engineyard.com>
-Date: Thu Feb 14 01:31:47 2008 -0800
-
- Rework Bignum#==. Change Numeric#== to conform to MRI.
-
-commit 4eb58ebc45b2ee79f01d75fdb3e9104c73ad66e2
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Wed Feb 13 23:56:37 2008 -0800
-
- Common implementation for Zlib::Inflate and Zlib::Deflate.
-
-commit 1804fdacce5c195a90befe502706d1f1e066e886
-Author: Brian Ford <bford@engineyard.com>
-Date: Wed Feb 13 19:31:20 2008 -0800
-
- Port of JRuby's File.fnmatch to Ruby (yeah, like writing Java in Ruby).
-
-commit 1a78da8438535ee8ed231359bdb15ff3624c6b37
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 01:27:52 2008 +0100
-
- Adding File#truncate improvements from #325 and #326
-
-commit 5b62acbdcf0aab2e89be5ac3e12859ae36cd6950
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 00:47:53 2008 +0100
-
- Adding File#truncate with specs
-
-commit 1a2b3dde4f67abe0936e7ec6fb749e5bb8fda7d2
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 00:36:32 2008 +0100
-
- Adding File#chown with specs
-
-commit e132cd6f11285f0e106a5d2a292e23c8375fa1ee
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 00:12:31 2008 +0100
-
- Renamed File#flock spec to properly reflect an instance method
-
-commit 00cd22ccdf2b70fa53693000d4a5bb803c7d6df6
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Thu Feb 14 00:07:05 2008 +0100
-
- Adding File::flock with specs
-
-commit 3c9b3e4e4272889dd26ec9ddb25f7aaf88c6c380
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Wed Feb 13 23:25:30 2008 +0100
-
- Adding File::chown with specs
-
- * The spec works fine on OS X, but was not tested anywhere else
-
-commit c894a6c46b4a3d0b9010020c394d3ba366bf145e
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Feb 13 11:59:38 2008 +0100
-
- Module#undef_method should accept string parameter, not only symbols by Nikolai Lugovoi (#321)
-
-commit c968d5c29cc3126c789cf5bb2005bd9637e85312
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Feb 13 11:52:10 2008 +0100
-
- Update excludes for File#truncate
-
-commit 408e69864546aea061e006073bb452b8db8c4610
-Author: Ragnar Dahlén <r.dahlen@gmail.com>
-Date: Wed Feb 13 11:15:31 2008 +0100
-
- Implement File.truncate, passes specs.
-
- * Adds truncate, ftruncate (not used yet) to posix.rb
-
- Only tested on Mac OS X 10.5.1.
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit 5c75721d5a78e25a77e9f068bf4c95e729604959
-Author: oleg dashevskii <be9@be9.ru>
-Date: Wed Feb 13 11:26:34 2008 +0600
-
- Remove tests that have been superseded by precedence_spec.
-
-commit 83a372674786a0be51a206cadcae644d72a1e8d2
-Author: oleg dashevskii <be9@be9.ru>
-Date: Wed Feb 13 11:05:34 2008 +0600
-
- Made a real precedence_spec.
-
- One test still commented out till the bug with flip2 is fixed.
-
-commit c3988a4a906594c050e058add8aa6996870dc115
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Feb 13 02:10:49 2008 +0100
-
- Remove excludes for File#stats specs
-
-commit 1624b463d0f70a27b6772d90626c94b6eed4e5c4
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Feb 12 18:25:05 2008 -0500
-
- Add specs for pass subclasses of Module to 'include'
-
-commit 64b0fb4131276feda0d0ab13301824b20f8d7f8e
-Author: oleg dashevskii <be9@be9.ru>
-Date: Wed Feb 13 00:49:37 2008 +0600
-
- Make Dir.chdir spec work when /home is symlinked to /usr/home.
-
-commit 8cbf6312df160f30e284a4537039f808a42543fe
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Feb 12 12:30:19 2008 -0500
-
- Add failing Array#sort spec and matching exclude
-
-commit 9bef807b3b469b8790edbe96f1442394d528cb5a
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Feb 12 12:09:11 2008 -0500
-
- Move Time#<=> specs around until the descriptions make sense
-
-commit 60fbbc62cb04b2fddcd406f01f906482fbc84370
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 12 05:33:49 2008 +0100
-
- Mark JRuby as not deviating from MRI on unboundmethod specs.
-
-commit 4e6d8f7e3326f937a6916ed11984172670a71094
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Mon Feb 11 23:26:31 2008 -0800
-
- Zlib.adler32
-
-commit 2f2d10e1aa57bae79f7fcda5e5a30b2a2ef3e37c
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Mon Feb 11 23:12:40 2008 -0800
-
- Zlib.crc_table
-
-commit 49b9e4b624074d151e89f078c4080a0a7584abaa
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Mon Feb 11 22:56:52 2008 -0800
-
- Zlib#crc32
-
-commit 7cb2ebfa008afc96135912ceefdbd81b1cd7e478
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Mon Feb 11 17:36:32 2008 -0800
-
- Fix class variables for RDoc.
-
-commit 571d837bbeff221daacebc79c1ccab7de15c77f2
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Feb 11 08:54:36 2008 -0800
-
- Exclude [r]dev_(major|minor) specs. We need some autoconf facilities.
-
-commit fb2bc81d50bf504e3997d009e3c13f841b859803
-Merge: 55a52f1... 9b58a59...
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Mon Feb 11 16:19:02 2008 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 55a52f18133fc9f92eef64838008a83dfaab3ffc
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Mon Feb 11 16:18:37 2008 +0100
-
- Removed Math.asinh excludes.
-
- It wasn't working on OS X. Evan fixed the culprit FFI over the weekend.
-
-commit 9b58a59ca21c6622d246e629410230bfbe8cd4ce
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Mon Feb 11 21:24:05 2008 +0900
-
- Modified to address differences of SyntaxError class between MRI and Rubinius in 'erb/filename_spec.rb'
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit d1c4280b70b82d6cd541251e3d7e1a3091fb304f
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Mon Feb 11 20:19:12 2008 +0900
-
- Add 'erb/util/shared/url_encode.rb' which is missed file
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit b4b1114ac7dffabd672d462b5857a7e1957e8f07
-Author: makoto kuwata <kwa@kuwata-lab.com>
-Date: Mon Feb 11 19:10:58 2008 +0900
-
- Add spec files for erb.rb
-
- Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
-
-commit dfdf90968e78f14e0755b5f3279ec878034dbdb5
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Mon Feb 11 00:09:23 2008 -0800
-
- Added singleton specs (and reorganized stale one):
- * Singleton#_dump
- * Singleton._load
- * Singleton#instance
- * Singleton.instantiate?
- * Singleton.new and Singleton.allocate
- * Singleton#dup and Singleton#clone
-
-commit 54c4a4cab187be4328d6a810bae4bc4bd01ca1d8
-Author: Brian Ford <bford@engineyard.com>
-Date: Sun Feb 10 20:19:30 2008 -0800
-
- Additional specs for File::Stat#rdev, #rdev_major, #rdev_minor.
-
-commit 6b2f05af4758c488b3e2e3b19ee9d2e872817932
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Feb 10 23:00:41 2008 -0500
-
- Rubinius now passes all 'super' specs
-
-commit 5be84fce241c67bd8439bccbe54cec575b0ea93a
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Feb 10 22:53:11 2008 -0500
-
- Failing spec for 'super' behavior
-
-commit 975d51e80d3df437eaa8ddd3c3384a5766255b12
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Feb 9 15:18:37 2008 -0800
-
- Exclude Process constants spec until LFS is fixed on 32bit linux.
-
-commit 236def62bcfa3dca75a6eebf378a68235c4613ed
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Sat Feb 9 17:04:59 2008 -0500
-
- Fixes exclude
-
-commit 26bedb481b45e77434b487c6395903c6110ef99e
-Author: Yehuda Katz <ephoenix@engineyard.com>
-Date: Sat Feb 9 16:01:58 2008 -0500
-
- Moved bad variables spec out
-
-commit 87efbf9036e5c524e1b40481c89107538d574ba8
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Feb 9 11:26:30 2008 -0800
-
- Revert all File::Stat stuff. We'll fix Dir first.
-
-commit 1f5bc0f98a23fc90b9bd00048af1551df8e534f7
-Author: Brian Ford <bford@engineyard.com>
-Date: Sat Feb 9 00:39:20 2008 -0800
-
- Reduced File::Stat.stat primitive further. Details follow.
-
- * Added ffi_major and ffi_minor to calculate the major, minor
- parts of st_dev and st_rdev.
- * Added (temporary) new primitive basic_stat to change the
- return type from a tuple to a single MemoryPointer instance.
- * Added simple specs for rdev, rdev_major, rdev_minor, nlink.
-
-commit e478731a2fc558c62cecbe327c5b35882d90b53d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 8 16:45:05 2008 +0100
-
- One more rubyspec for File#open.
-
-commit 5f6ac709500cb64df110a44d31e0c0b89dd68aec
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 8 16:39:47 2008 +0100
-
- New rubyspecs for File#umask.
-
-commit fddaa684bd7e8c403ff96179ca71a5837f609b63
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 8 16:30:20 2008 +0100
-
- New File#chmod rubyspecs.
-
-commit ed20c3f9f36f343a37e2ac05ea91d84b54c87bc8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Feb 8 12:00:57 2008 -0500
-
- Correctly guard Bignum specs for CI
-
-commit 36e9749984d6e4412c26d348afa8c501cf043ecf
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 8 13:09:37 2008 +0100
-
- Some more specs for File#new and File#open, and permissions.
-
-commit 29376695550c5608f466d63d49de76a6ee163e37
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 8 12:10:27 2008 +0100
-
- New specs for IO#new and IO#open, invoked with permissions parameter..
-
-commit 8cf27fcd86f88b75716b65dc1d94b721c01c3af9
-Author: oleg dashevskii <be9@be9.ru>
-Date: Fri Feb 1 21:03:08 2008 +0600
-
- Heredocs and more stuff added to string_spec.
-
-commit 2cccd38a081c0303f8fa567058e4c26fa354abc5
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Feb 8 12:51:53 2008 +0100
-
- Add exclude for currently failing for_spec
-
-commit 031bb1b565a3446ab995ea55e6ae8890573ba6c0
-Author: oleg dashevskii <be9@be9.ru>
-Date: Fri Feb 1 20:23:56 2008 +0600
-
- Added more tests to for expression spec.
-
-commit 73e40331c6b4c1c1b6e41ae312299f6815e089c2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Feb 7 19:12:46 2008 -0500
-
- Add a failing spec for Array#join and then fix it
-
-commit fa49548fe704252c352a1bc4833b5da20262061a
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Feb 7 23:12:03 2008 +0100
-
- Fix last two Failing Time specs for Time#+ and Time#-
-
-commit e4e51c6aa39e5a5a61b0df919ba02b88d4878f43
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Feb 7 22:35:57 2008 +0100
-
- Fix Time.at so it also works with floats
-
-commit f5505522fd0396c3864fce155681ac577bf2e7e6
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Feb 7 17:10:48 2008 +0100
-
- Fix Time#<=> for objects other than Time
-
-commit e8ab7b5eb30da84262a9395e20ac420e83674edf
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Wed Feb 6 13:59:18 2008 -0800
-
- Only call Class#inherited once
-
-commit dc9ff28ae919292287f5562b8c105ff6310c5920
-Author: Phil Hagelberg <phil@hagelb.org>
-Date: Wed Feb 6 15:00:59 2008 -0800
-
- Kernel#eval should be a module function
-
- Added a spec as well
-
-commit 7dd83410a2159fd65f951689a8a1297baded4fa6
-Merge: 698ffa4... 339fed9...
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Wed Feb 6 22:54:12 2008 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 698ffa4e04fee58da5c3f2191372c4e4f2bc070d
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Wed Feb 6 22:51:54 2008 +0100
-
- Adding missing specs for ftools
-
- * specs for chmod, compare, copy, install, makedirs, move and safe_unlink
-
-commit 339fed9821b75de056febc406b32fe52ff9354a9
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Feb 6 22:00:46 2008 +0100
-
- Forgot to remove spec excludes...
-
-commit 7ecca7222823a82252ed09b17eefafe6fec9f12e
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Feb 6 21:46:19 2008 +0100
-
- Fix last two failing Dir#glob specs
-
-commit fec39f27d287ca74becbecc120de8533e346b864
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 18:13:13 2008 +0100
-
- A few more corner cases fo IO#lineno specs.
-
-commit 3691d3f9a202abb22e11024e41b868d531a549be
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 18:02:50 2008 +0100
-
- New rubyspecs for IO#lineno.
-
-commit a5b0f9aa15c9372f74816e77073926780a9cc219
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 15:58:26 2008 +0100
-
- Improved IO#foreach specs.
-
-commit 91ea9f304c75592e7454411ef21391a0e34da5e5
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 15:03:02 2008 +0100
-
- New rubyspecs for IO#gets and IO#foreach.
-
-commit 9c494786fbf400bb295e1f19d142e2c903c21e54
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 13:37:43 2008 +0100
-
- New rubyspecs for IO#foreach.
-
-commit cdbbeba8f3351fe43f44d732348f380599ad5719
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 10:40:13 2008 +0100
-
- New rubyspecs for IO's sysread and read with buffer argument.
-
-commit e1cb4410b7e0a0ba2fd580784334bdfd05ba4b8a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 10:15:29 2008 +0100
-
- Excluded rbx failure after spec rename.
-
-commit 1fde018b9378b55f6d51cb85bd65813b5cef5493
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Wed Feb 6 02:50:44 2008 -0600
-
- Tidy up an apparent copy/paste mistake in IO#syswrite spec
-
-commit 1aa624e625dafaeebd70eac11819f02ecf570f8e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Feb 6 00:19:39 2008 +0100
-
- New IO specs for writing non-string data.
-
-commit f94a0cffd5fd0e186a9403d97800b55f8c44bdd1
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Feb 5 15:13:47 2008 -0800
-
- Regenerate zlib stubs.
-
-commit 52ce0e702170676ce02dcc288305097d58834cf8
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Feb 5 13:34:47 2008 -0800
-
- Add Zlib spec stubs
-
-commit b24ad594837b974a3ae3b207d63ce5cdc956a1a0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 5 21:45:09 2008 +0100
-
- Added some boundary test cases for Float.
-
-commit 1a8c9966fa148fc3e912f8aecd42c8c00ca4f89c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Feb 5 22:46:18 2008 +0100
-
- Removed problematic Marshal spec because 2**40 is a Bignum on some archs and a Fixnum on others
-
-commit 6ad8a0a25f20fd137bcb7fcb83bc88440a2a2069
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 5 17:03:56 2008 +0100
-
- Eliminated file descriptors leakage out of IO tests.
-
- These things make runs unpredictable, causing all kinds
- of troubles (non-deterministic failures, fluctating
- number of tests).
-
-commit 95ac3cb9900c52e4819b37166c71840d4bb4e3d9
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 5 14:50:31 2008 +0100
-
- New rubyspecs for File.open with block.
-
- Also, IO.open specs improved to handle closing better.
-
-commit 66f636c346a63853ae37a06f1c3e8b5083370892
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 5 13:22:34 2008 +0100
-
- New tests for IO.open, and additional cases for IO's inspect and stat.
-
-commit dfb941da0f7503bce58dc88a85ccfd201615e13b
-Author: Brian Ford <bford@engineyard.com>
-Date: Tue Feb 5 01:57:20 2008 -0800
-
- Ezra's patch for Regexp#inspect, #309.
-
-commit c5f9381ee74ed2d9c91cca1dd2ce9719b6f51bd8
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Feb 5 10:07:57 2008 +0100
-
- Corrected IO test to not interfere with Kernel#puts tests.
-
-commit 751293c1ea14de1b1d2757bf5d60b082cc771e7a
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Feb 4 17:43:06 2008 -0800
-
- removed empty excludes
-
-commit 206399aee9ae7845d76c0726702c424b9fc44e80
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Feb 4 17:39:45 2008 -0800
-
- StringIO#seek now raises if passed bignum offset - should be platform specific, but this'll do for now
-
-commit b00f04ec0fcd8f8edf9943abb5999f1cca9e9e9e
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Feb 4 17:06:34 2008 -0800
-
- Knocked off the last of the method excludes.
- Tightened up the spec for #to_s
-
-commit 3d4f87741135343a2e8ec6032fa3a69529cfbf69
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Mon Feb 4 16:51:37 2008 -0800
-
- Fix Hash#key? to work with objects that have the same #hash.
-
-commit f814a15639f6e6ecd47ab99ad9e37e93fd6bc165
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Mon Feb 4 15:17:08 2008 -0800
-
- Fix Marshal format version check
-
-commit 6d9e0afb5600416e5d66d5123abcfa5dd6c40903
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Mon Feb 4 14:24:48 2008 -0800
-
- removed tmpfiles from dir/fixtures and moved them to tmp where they belong
-
-commit 4e18d1cf49573b1fa3f484686352734aa39457d0
-Author: Ruben Nine <ruben@leftbee.net>
-Date: Mon Feb 4 02:32:26 2008 +0100
-
- Added support for tag:yaml.org,2002:sym to RbYAML library.
-
- Signed-off-by: Jonas Pfenniger <zimbatm@oree.ch>
-
-commit 220ed05f204f4b8fe7f1f303fae9a18988f8879b
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Feb 4 17:16:44 2008 -0500
-
- Use an example number that is actually a Bignum everywhere in compiler Bignum spec
-
-commit db3f20c8ec905641de887bbd1ed581aa78f73471
-Merge: e33350e... 6e3dad3...
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Feb 4 16:50:14 2008 -0500
-
- Merge branch 'wilson64'
-
-commit 6e3dad3e5b2e982f96e991e9df2d46de5bf4ee1f
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Feb 4 16:49:09 2008 -0500
-
- Use the correct Fixnum#size spec on 64bit platforms
-
-commit e33350eddc3441b2ebe06336500e6445406285d1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 22:12:14 2008 +0100
-
- Moved one IO#inspect spec to File#inspect specs.
-
- Since the behavior is File-specific.
-
-commit 1586e3a2c5d12f5438adddb8c84bc90c3defee82
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 20:57:09 2008 +0100
-
- Add more IO specs. God, make it stop!
-
-commit e64f3b02423acb783ba8a62996847b0393e7f3ee
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 20:33:57 2008 +0100
-
- And more IO specs.
-
-commit 3d584f0ee2cf988720bb5985c20b3bec6c2e143f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 20:08:26 2008 +0100
-
- Next batch of IO methods specs with closed streams.
-
-commit 6e22a99350195cfa7a40d6049d6d72a9ae7e1168
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 19:47:06 2008 +0100
-
- And yet more specs for IO methods with closed streams.
-
-commit 12e8d881b90cbd60bc792693e799923fdb1041b0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 19:20:39 2008 +0100
-
- More rubysecs for IO methods invoked on closed streams.
-
- Plus some refactoring to move repetitive code to the fixture.
-
- NOTE: two specs marked as fails_on :rubinius due to fact
- that they crash rubinius.
-
-commit 3ae3cafcb10725953c8e595641af277f36c88677
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 18:39:34 2008 +0100
-
- New rubyspecs for IO#to_io.
-
-commit 4980bb83f53845e88cd0d1a3b0823fdbf0c0a001
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 18:09:36 2008 +0100
-
- New rubyspecs for IO#ungetc.
-
- Unfortunately, MRI doesn't follow some of its own
- specified behaviors...
-
-commit f27fe4f3e4ccb298dcaa5014dac69d3148ee169e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 17:18:08 2008 +0100
-
- Added rubyspecs for IO's putc, puts, printf, print and closed streams.
-
-commit a1d7b67942aed8d1b185476dee6f2d99403ed227
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 17:07:00 2008 +0100
-
- Added rubyspecs for IO#pid.
-
-commit cfa1ef21ce862a05ae352a4fe49a3ac4c04b9bed
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 16:36:21 2008 +0100
-
- Added new rubyspecs for IO#sync and IO#sync=.
-
-commit b4f6c33c17e57fa44322124af088a97d475905e2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 16:20:50 2008 +0100
-
- New exclusions for rbx.
-
-commit 60309280c48b2bd1f1d8a5ea018f401e75b7dac1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 16:17:27 2008 +0100
-
- Added new tests for IO's pos, pos=, rewind, seek on closed streams.
-
-commit 40414ad1b39222494ff2a79a0091890a60b7adf1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 14:26:13 2008 +0100
-
- One more test for IO#eof?.
-
-commit 29db340f24c043b240fec6722c323fa1567ce855
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 14:19:46 2008 +0100
-
- Added new rubyspecs for IO#getc and IO#getchar.
-
-commit 0e0a987782fc7834ba95a2e8e2c8ab6cd8dcea81
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Feb 4 13:54:59 2008 +0100
-
- More rubyspecs for IO#eof?.
-
-commit f7d1139e4eace4a86f0c0512bf9269964442628d
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Feb 3 15:55:10 2008 +0100
-
- Fix Date#strptime specs
-
-commit ac4600fcb42928aeba508371aea2f76510e70d5c
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Feb 3 13:26:52 2008 +0100
-
- Fixed Time specs for non Rubinius platforms
-
-commit a5081ca646e99ec94fedfabf03b7eb0a8d37afc3
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Feb 2 23:53:52 2008 +0100
-
- Fixed Time specs for 64 bit archs
-
-commit 26eef47571b921fe6b3228033119e5969c4100db
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Feb 2 13:30:16 2008 -0500
-
- Updated IO excludes.
-
-commit 8edd73d9915f72ee70b661b23e8b42f8b985fa9c
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Feb 2 10:45:23 2008 -0600
-
- Repair IO#sysseek spec to not write to fixture file; uses a tmpfile now.
-
-commit bf6348c935c816a981672e9c26a40354cf0d722c
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Feb 2 02:35:42 2008 -0600
-
- Additional IO#sysseek spec for the warning after buffered writes
-
-commit 5241316a1c74e6580fb91940a9f061047e89cdbf
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Feb 2 02:32:36 2008 -0600
-
- Modify IO#seek specs for IO#sysseek, adding appropriate error tests
-
-commit 7f124cbf66b96fdcdaec73917e86eedfb4a9ddf8
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Fri Feb 1 18:05:15 2008 -0800
-
- Refactored Marshal#dump specs and merged with fixtures/marshal_data.rb
-
-commit 3766b3ed41ffba71ecb1bef8079027bffe518e2a
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Fri Feb 1 16:54:32 2008 -0800
-
- Refactored specs for Marshal#load
-
-commit e134d5bf8e247f4a231bfbfc1c3251b262f219e4
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 1 15:36:06 2008 -0800
-
- Update excludes for recent failures
-
-commit 8ded8b443f55b47a1c30b59cfb0d96d8752d5fa9
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 1 15:11:37 2008 -0800
-
- Process.group spec is missing a suplemental group on OS X
-
-commit 4b7de6ff839b220115dd29f34b5a9f46cb8f5bef
-Author: Evan Phoenix <ephoenix@engineyard.com>
-Date: Thu Jan 31 17:16:13 2008 -0800
-
- Add proper primitive failures, fix empty symbol.
-
-commit dc55c88beee6a3a3a7fd352c1e374ecf84863459
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 1 16:17:00 2008 +0100
-
- Fixed 2 Date#strptime specs that otherwise would pass only in January.
-
-commit 86c372d0fb50aeb6235ed1595d18a876e09330db
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 1 15:32:40 2008 +0100
-
- Few specs for Time#<=> with non-Time arguments.
-
-commit 765ef93acd294922dc22a986213a5842ce3e67a7
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 1 14:09:01 2008 +0100
-
- Added more specs to Time#+ and Time#-.
-
-commit af76adac2182e46e34e68d29b3cd8614edd27d50
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 1 13:38:20 2008 +0100
-
- Added more test cases for Array#join on recursive arrays.
-
-commit bb15b72393b34d3d10bb644fb1d6ce47b6dc0826
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Feb 1 13:15:24 2008 +0100
-
- Added more test cases for File::join with recursive arrays.
-
-commit 7041b2aef1e574dfe220a70da5210c683074f8ae
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 1 03:18:31 2008 -0800
-
- Describe an unambiguous method.
-
-commit 84edf54799e0ccd09276a5cda3fccf544f971c48
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Fri Feb 1 03:07:48 2008 -0800
-
- Use fixed Marshal data for all specs and fix many broken or useless specs.
-
- Clean up spec naming and definition.
-
- Use descriptive names for test classes.
-
-commit e0c3aa074c9525450a7a667ec2cc843ff3560e65
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 23:29:57 2008 -0500
-
- Hash.new patch from Phil Hagelberg + MethodTable workaround.
-
- * The Hash.new patch splits a separate #setup method so that subclasses
- can override #initialize without problems.
- * Because it is part of the core code, MethodTable needs to explicitly
- call #setup in its #initialize.
-
-commit a32f16d9288c5c0822cc6962ce3caed5e1bac5d0
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 15:35:08 2008 -0500
-
- Updated Module excludes.
-
-commit df731f327c4d47373ba6f2fe2f79d5d9acbf398e
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 15:30:11 2008 -0500
-
- More Module#module_function specs in #eval and #module_eval.
-
- * #module_eval separates the two scopes but #eval does not.
-
-commit 6358e5893c52042c10c355173d1ad8441a00bcfa
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 15:13:49 2008 -0500
-
- Better Module#module_function specs.
-
-commit 1646bb6e99a6b4190641046ae730ea1be9c8be2a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 13:59:20 2008 -0500
-
- Various whitespace removal in preparation to fix #module_function.
-
-commit 108601d85d2c41d05f9c00945664d9980e0e46c3
-Author: Evan Phoenix <ephoenix@engineyard.com>
-Date: Thu Jan 31 13:39:53 2008 -0800
-
- Add meta_send_call instruction, speeds up calling blocks
-
-commit 50f9c50820b4305877af1c7fd7597c5dc94c623c
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 12:20:11 2008 -0500
-
- Added LC_ALL=C for all other platforms for Time specs too.
-
- * If it breaks, report and we will figure out something else.
-
-commit 26059c1570c5ad2a64a796e2678ff2d9ace23e58
-Author: Pierre Yager <pierre@levosgien.net>
-Date: Tue Jan 29 22:48:22 2008 +0100
-
- Fix for bin/ci spec failure on localised linux
-
- * Force system date to be executed against "C" locale
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit e5ce9e7c29a34f685f7d3f8a9f855db28aece460
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 31 11:32:56 2008 -0500
-
- Removed trailing whitespace for Time and some Time specs.
-
-commit 3546f721ac86efa318b3802a2f498d41aa830c9f
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Thu Jan 31 10:53:53 2008 -0500
-
- Subtend: Add rb_define_private_method, rb_define_protected_method, rb_define_module_method, etc.
-
-commit 7553cb993a0c7e60c2212800b0ecc033ffc0b206
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Thu Jan 31 10:39:08 2008 -0500
-
- Add rb_class2name in subtend
-
-commit 4570b7c5d837025d765a6a2909d5536c466b9dcb
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Jan 31 02:26:09 2008 -0800
-
- quick addition of 2 exclusions
-
-commit 53c76326e76869a87ad0fc67adbd3aef9059ee35
-Author: Ryan Davis <rdavis@engineyard.com>
-Date: Thu Jan 31 02:15:15 2008 -0800
-
- Parser spec updates
-
-commit 8fb2eb68858a1ee1dafb06b833f43d6da817756f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 19:29:25 2008 -0500
-
- Slightly more permissive TCPServer.new spec for hostname string.
-
-commit 2a60dbbf011e806ae51c30ab2cb2b8e7b9b633a5
-Author: Mutwin Kraus <mutwin.kraus@blogage.de>
-Date: Wed Jan 23 18:41:12 2008 +0100
-
- Fixing TCPSocket#new for localhost (with specs for both IPv4 and IPv6)
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit f485a6818a754c8110feafa9f6dced42a99187d0
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Tue Jan 29 21:13:28 2008 -0500
-
- Making Enumerable#inject only accept one paramter
-
- Uses 'Undefined' idiom, which fixes spec, and cleans up code (thanks
- for the pointer Eero)
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit ebfa5a0bf9f8e3efe61c0d34fe63a8cd74b7ddf8
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Tue Jan 29 20:52:16 2008 -0500
-
- spec to verify inject accepts one argument, at the most
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit b131b80df72a9ceaa9e920b7f78434f301135a6f
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Wed Jan 30 00:33:03 2008 -0500
-
- Adding Enumerable#count spec, including a few failing specs.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 82b63bc0f5b79735a8021b6c5c69786dc76fa7f6
-Author: Alexandre Perrin <alexandre.perrin@epfl.ch>
-Date: Tue Jan 29 15:59:22 2008 +0100
-
- udpdated language/string_spec.rb
-
- * added spec for class/global variable with the \# simple interpolation
- * added spec for ends of a \# simple interpolation
- * added more delimiter character with the percent String construction
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit c58110bde52d64b30cf36ba3cb342357f3654812
-Author: Evan Phoenix <ephoenix@engineyard.com>
-Date: Wed Jan 30 17:19:26 2008 -0800
-
- Fix break. It now uses LRE to properly return to callsite and appear like
- it returned.
-
-commit 45109c222502de955d705f810333d8e7b331c953
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 31 00:42:12 2008 +0100
-
- Added Date#strptime specs
-
-commit fe60e6a022d9e64bb568ccd47494f07a99382c58
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 11:36:46 2008 -0500
-
- Updated excludes for Marshal. Looks like Fixnum/Bignum issues.
-
-commit 209dde412310edc384be7d4a86bdfb0444f3b3bf
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 01:45:27 2008 -0500
-
- Updated IO/File excludes.
-
-commit 91031e51e49a1a3ddb9f74da31e2ed65c48e1ef5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 01:43:11 2008 -0500
-
- IO.new and IO#close use stream API.
-
- * IO.new uses fdopen() to open the given fd which also checks the mode
- string for us. The returned FILE* is stored as a MemoryPointer in
- @fptr.
- * IO#close checks for presence of @fptr and if found, uses fflush() and
- fclose() to release the handle instead of going the normal route.
-
-commit f4d64553a2a53c77235ef9acc3353ac455514057
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 01:20:32 2008 -0500
-
- Made probably broken File.open spec compliant_on :ruby.
-
- * File.open should not take three args. File.new does.
-
-commit dc496f35502b4642137d3f0f74571c8245a6ae56
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 30 01:19:29 2008 -0500
-
- Slight IO.new spec tweaks.
-
-commit a9d9288315e88cffd59ec1b27e3c3209ceb1a3a9
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Jan 29 20:32:44 2008 -0500
-
- Combined IO.new and IO.open specs for the shared parts.
-
-commit effa81cce1d42f7c1bc2e275cb75bd9069e934b8
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Jan 29 19:14:51 2008 -0500
-
- Changed specs to use the two-argument IO.new.
-
-commit 1394b360fe70966e25809a349b400a69262060ca
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Jan 29 14:56:47 2008 -0500
-
- Rewrote IO.new specs (still a bit sparse.)
-
-commit 94d50eb3e60971ffeff28bffa0beaff405c581bd
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 30 21:47:35 2008 +0100
-
- File#utime specs to use be_close rather than ==.
-
- On some platforms, direct comparison just doesn't work,
- producing non-deterministic test failures.
-
-commit 0f5574c28ff08c96326298b98b4ea50108168044
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 30 13:13:25 2008 +1100
-
- Remove race in debug_context_change specs
-
-commit 00a62c3476dd0717f5c4caece453914e1392de9d
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Jan 29 14:39:06 2008 -0800
-
- Remove bogus Marshal specs for Fixnum/Bignum changeover
-
-commit db1b140db0fbecf70f8adda983e010ef2bbe94c4
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Jan 29 22:58:18 2008 +0100
-
- Finished first version of Date specs. All public methods are specced
-
-commit 8ee52fd8dfd3ef6048c63b30d8aea71da944abb2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 29 17:21:57 2008 +0100
-
- Follow rbx lead, and allow deviation in UnboundMethod#== for JRuby.
-
-commit f670bcb9e086ac9cc73b6ef6083966b296268f04
-Author: Caleb Tennis <ctennis@engineyard.com>
-Date: Tue Jan 29 09:46:50 2008 -0500
-
- Fix typo
-
-commit 4e990269fd42aabd48cdc29b4288c78984d0e5cf
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Jan 29 02:44:20 2008 -0800
-
- Add File::join recursive Array spec.
-
-commit 4d947218e949e19515a9e89af99d4823048f3bb2
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Jan 29 02:41:54 2008 -0800
-
- Fix File::join spec name, duplication
-
-commit a38e10ddc19ebd59f8775a01f3e899c5348ba23f
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Jan 29 02:40:37 2008 -0800
-
- Make File::join remove extra / appropriately.
-
-commit 074251c03093ba40c0fc3558d512a77844ac45aa
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Tue Jan 29 00:53:23 2008 -0800
-
- Make File::join specs more clear, remove whitespace
-
-commit f968bbe15a27d8ac6716d103119d41c4eef37696
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Mon Jan 28 18:07:24 2008 -0800
-
- Use const_lookup in Marshal, fix #marshal_load.
-
-commit 7e00b857f56879564c1bf27f2e694f3c0783a4bb
-Author: Eric Hodel <ehodel@engineyard.com>
-Date: Mon Jan 28 17:23:26 2008 -0800
-
- Support nested modules in Marshal
-
-commit 5c6e2af3d9ace07ca8387c5aecaa5c1d85e8d81f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 28 20:22:40 2008 -0500
-
- Added specs for rest of the filetypes to File::Stat#ftype specs.
-
-commit 221a077bef5e9007b548993eaf16c86137c6b0b3
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 28 20:08:12 2008 -0500
-
- Added support to spec file type against sockets too.
-
-commit 9cb4791db10bc79f8c30a86f17e6c099dabeea80
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 28 19:52:07 2008 -0500
-
- Moved File and File::Stat-related fixtures to fixtures.
-
- * Module FileSpecs defines methods that yield filenames corresponding
- to specific file types so they can be easily tested.
-
-commit c28c85602d3ab6770ed567a64b744baa15795511
-Author: Ben Hughes <ben@pixelmachine.org>
-Date: Sat Jan 19 16:10:36 2008 -0500
-
- Added spec for File::Stat#dev, dev_major, and dev_minor
-
- * Check that the result values are Integers for each operation
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 86ce52e32a35cb11564d0d5f306f4eea6d6b714d
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Jan 22 15:21:38 2008 +1100
-
- Added yield_debugger on context change
-
- Added capability to set a flag in the VM that causes a
- yield to the debugger to occur immediately following a
- change in the active context. This provides a foundation
- for step in logic for the debugger, which need only set
- a flag on a task and have a breakpoint triggered at
- whatever receiver is activated following a send.
-
-commit 3904ff2fbb209b8c2d476bb3f4a4ea4825a16f6e
-Author: Brian Ford <bford@engineyard.com>
-Date: Mon Jan 28 17:58:35 2008 -0800
-
- Fixes for mSpec to coexist with autotest.
-
-commit 45f2d6de4b025acfa2429d88c729a3eb58a79528
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Mon Jan 28 17:08:45 2008 -0800
-
- Added more brains to .autotest. Removed bad files that it pointed out
-
-commit 70eaa7feffcfd552c51b67a651cdf6063c9b549a
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Mon Jan 28 15:57:24 2008 -0800
-
- Add File::Stat#dev.
-
-commit 020f4bec691ba658fab0f1ff24fa5df5a6f1921f
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Mon Jan 28 16:13:11 2008 -0800
-
- Added enough process spec exclusions to drop the HUP issues
-
-commit 76b393566f2a89001952dbf1ec46dd52a5750448
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Sat Jan 26 10:58:42 2008 -0800
-
- Fixed autotest support (needs latest version of zentest).
- Minor clean up on bin/ci and kernel/core/module.rb.
- Hacked mspec/matchers/base.rb to output with pretty print.
- Fixed mspec's runner to output time BEFORE failures. Fixes unit_diff.
- Updated Parser excludes.
- Deleted a bunch of excludes.
- Updated spec/parser/sexp_expectations.rb with latest ParseTreeTestCase.
- Started adding a rewriter to make maintaining sexp_expectations easier.
-
-commit d147f6f0a87e30e240750d8c660bc89f8c84a472
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Mon Jan 28 18:20:38 2008 -0600
-
- update CI excludes
-
-commit 159f17a228fa6a42cea79b9e3663e1f2b9dea9e4
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Mon Jan 28 18:07:56 2008 -0600
-
- add Marshal specs
-
-commit 72e739590b6bbe571607df674e2f4106c64c8042
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Mon Jan 28 15:15:26 2008 -0800
-
- Fix String#gsub when matching '^'.
-
-commit fc8c2c5584305b3e0b2a74ba8250a0b7072a372f
-Author: Ben Hughes <ben@pixelmachine.org>
-Date: Sat Jan 19 16:20:55 2008 -0500
-
- Added specs for File::Stat#ftype. #264.
-
- * Tests "file" and "directory"
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 2f9872b66d4dffc82e0a97e617fb9de18105f668
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 19:56:06 2008 -0500
-
- Better living through mocks. String#+ spec cleanup & correction.
-
- * String#+ in fact raises a TypeError when given ANY non-#to_str
- object.
- * Simplified spec code.
-
-commit f5a0f1e0e401db8f28727cdd8be99228c9c6aee3
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 19:37:08 2008 -0500
-
- Removed trailing whitespace in String.
-
-commit 03c1c270236786b66930063669b95ac7cbf17f10
-Author: Matthew Draper <matthew@trebex.net>
-Date: Thu Jan 10 22:40:35 2008 +1030
-
- String#+(65) throws a TypeError, unlike String#<<(65).
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit a17ede3e9c85c1bd2e06efa7381c1e5dbab47f80
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 19:10:33 2008 -0500
-
- Minimal IO#open specs, IO#sysseek. Merged from Chen Yufei's patch.
-
- * Merged patch by hand, most of it was already implemented separately
- too.
-
-commit 30116d672d950687646c1668eac4d9f5b10f4df7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 18:53:19 2008 -0500
-
- IO#readline EOFError spec modified from Chen Yufei's patch.
-
- * Patch was out-of-date, applied by hand.
-
-commit 1b81e68249741d53b38857440bba897987d00e43
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 17:44:30 2008 -0500
-
- Separated and excluded NUL byte stripping for String#lstrip specs.
-
- * Rubinius does strip leading NULs, MRI does not.
-
-commit 55f50888f22288b0fa45298d873dd265d7340aec
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 16:52:51 2008 -0500
-
- Updated various excludes.
-
-commit b085f63d66519f93b59e3851b7e6796877e97107
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 16:47:24 2008 -0500
-
- Documented Method, deleted unnecessary Method#module spec.
-
-commit f71f5c91e8ceab59d59614fe885dfeff096d7655
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 15:41:26 2008 -0500
-
- More precise specs for Method and UnboundMethod #to_s / #inspect.
-
- * Checks presence of own class, method name, name of the Module where
- the method is defined and name of the Module where the method was
- extracted from.
-
-commit 400b522d27515698e0a35b2507a4a8825ec9bf8f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 15:22:46 2008 -0500
-
- Rewrote Method#unbind specs, touch-up for Module#instance_method spec.
-
-commit 57bddb7b38dbb762b2469c51eb961e01f03c8518
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 14:50:38 2008 -0500
-
- Updated UnboundMethod#== spec for Rubinius/MRI difference on Modules.
-
- * Rubinius' UnboundMethod#== is true for methods from included Modules also.
-
-commit 8503c92f914d72e72eeeaede225f52242a1afad9
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 14:25:29 2008 -0500
-
- Rewrote and added Module#instance_method specs.
-
-commit 8541f4cf83f8b776276e81ca41eb0f7b595e4fb7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 13:43:36 2008 -0500
-
- Improved/added UnboundMethod#bind specs.
-
- * Removed unnecessarily specific error message check. Exception type
- is plenty.
- * Specified correct behaviour only in terms of Method since a Method
- is returned and anything after that is not #bind's responsibility.
- * Rubinius allows binding to any object that is kind_of? with respect
- to the Module that the method is *defined* in. MRI requires that it
- can only apply to objects of the same Module that the method was
- extracted from.
-
-commit fc7073c85b5e201265e24a82c19bd6413681f6e1
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 13:02:24 2008 -0500
-
- Removed trailing whitespace in UnboundMethod#bind specs.
-
-commit bde0cacff5f061accab7feb8a27b2417456f2f95
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 12:38:39 2008 -0500
-
- Specced Rubinius to deviate in UnboundMethod#==.
-
- * MRI requires that both UMs were extracted from the exact same
- Module. Subclasses etc. are not OK even if the UMs both refer to
- the original in the parent. This is somewhat nonsensical and
- harder to implement so Rubinius allows it.
-
-commit e7ba146d3d0ef0aed1d297d157008661458723eb
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 12:16:07 2008 -0500
-
- Much more comprehensive and precise UnboundMethod#== specs, documented.
-
- * #== has some stupid behaviour but this is what we get.
- * Explanation of criteria in the method doc.
-
-commit 43f2226c8882900a472f0a5347fa549936e8f000
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 09:37:51 2008 -0500
-
- UnboundMethod String representation specs improved.
-
- * Specs require that the returned String contains this object's class
- and the [Module]#[method_name] it was extracted from.
- * The spec specifies nothing else about the format or order etc.
-
-commit 67e3b5993d92776e0c9535549e8ffdb172225d52
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 09:11:19 2008 -0500
-
- Trimmed whitespace for kernel/core/method.rb for patching.
-
-commit c61c5185589cf5a86b58b2e8c8b8d7a26cdc25ec
-Author: Scott Taylor <scott@railsnewbie.com>
-Date: Mon Jan 14 00:23:27 2008 -0500
-
- fixing the specs for UnboundMethod#inspect
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 48bcca32329d48a20d5a6f2dd19598ea7b4167ce
-Author: Scott Taylor <scott@railsnewbie.com>
-Date: Mon Jan 14 00:16:24 2008 -0500
-
- UnboundMethod#==, plus an extra spec
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 232015fed94b59adf627a7712da0d5d4d44c87d0
-Author: Scott Taylor <scott@railsnewbie.com>
-Date: Mon Jan 14 00:03:32 2008 -0500
-
- UnboundMethod#bind
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit fcd0139307fd48f78f122457af1af43a543343ce
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 12:11:34 2008 -0500
-
- Updated excludes for IO#write.
-
-commit eed253158fe0cc20b91f6c8dcc06f6a671092d84
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Sat Jan 26 14:36:33 2008 -0800
-
- IO#write calls #to_s on it's argument
-
-commit bb5ff251bcc4baceac25a3a1fa64797b94551145
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 03:22:02 2008 -0500
-
- Updated #attr_writer spec that was picking up a stray method.
-
-commit fa985a57f6cf802d6a83a6d02a31dd7fd33ebd36
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 01:20:27 2008 -0500
-
- Module#const_get can now access top-level constants for Modules also.
-
- * Modules explicitly check Object last, Classes already do it since
- they all inherit from Object.
- * Added some more specs too.
-
-commit fbc1cfb2d461891ee478802f44de3736959905a7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 00:47:52 2008 -0500
-
- Renamed the Module field 'parent' to 'encloser.' Some docs.
-
- * When dealing with Modules and Classes, 'parent' is an ambiguous term.
- In typical OO literature, 'parent' means the superclass which is not
- the case here. Two separate sections of code already showedsome
- uncertainty about the intent of this field.
- * Added a few bits of documentation to Module.
-
-commit 92903e92564857350061d83f8eb3b54886986ac3
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 00:36:10 2008 -0500
-
- Updated Module excludes.
-
-commit a705e687ce0d55e7ea184e1a3e67ba8d9d7c610c
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 27 00:24:20 2008 -0500
-
- Improved Module#const_get specs for better coverage.
-
-commit bca6aef9b81166f9c5f4aeaafc673a54710d4d35
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 19:57:33 2008 -0500
-
- Corrected semantics of spec statements for Module#const_get.
-
- * Specs were correct but the description was inaccurate.
- * Prettified just a little.
-
-commit f699c18b68dee73086afb92d15b61745319a5321
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 19:55:40 2008 -0500
-
- Module#const_get specs for top-level constants by Le Huy.
-
-commit f3831a0693ea90271843bcc5910516e5a40ed3c1
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 19:15:27 2008 -0500
-
- Module whitespace cleanup before patching.
-
-commit e3cbe8136351f055bd99f10646d4f77515078430
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sun Jan 27 00:51:55 2008 -0600
-
- A few basic IO#write specs for file IO
-
-commit fd05adfedf70d795d8d91f650d5b76b05104dd7a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 18:54:35 2008 -0500
-
- Specs for Enumerable#max_by (Rubinius extension.)
-
-commit 560b6460745c7821b9479b356c032a10daaa61ec
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 18:53:52 2008 -0500
-
- Specs for Enumerable#min_by (Rubinius extension.)
-
-commit 6ab0bc901bdc60bde1e251f72f0028dfb736a2dd
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 14:25:41 2008 -0500
-
- Updated excludes for Enumerable.
-
-commit 2e09eedb31e15c791e491e97bc2af1977a629c2b
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 14:20:19 2008 -0500
-
- Fixed Enumerable#max and #min nil problems using Undefined.
-
-commit d8e6ebf604fdcc228e9158336250dd29c6d35932
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Sat Jan 26 13:22:33 2008 -0500
-
- Failing spec for finding max when Enumerable contains nil
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 313ee6badb177c101e39e122c5b5d6ff4d73d93d
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Sat Jan 26 13:01:06 2008 -0500
-
- Failing spec for sorting a list that contains nils
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 467e8a60e0e25003894013e68f6d48e7bd6a22fc
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Sat Jan 26 12:01:15 2008 -0500
-
- adding failing spec for sorting enumerables that contain nils
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 8719a4ad46d7643c6e54aab3dffedb6831bde5f3
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 13:42:11 2008 -0500
-
- Whitespace cleanup before applying Enumerable patches.
-
-commit 015a0d023e8c649160800ddb8a269aa789266d51
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Jan 26 13:31:00 2008 -0500
-
- Added/changed the Dir open specs after previous simplification.
-
-commit 6735df441af2489d47674b0cc500dab37dd4319e
-Author: Jonathan Younger <jonathan@daikini.com>
-Date: Thu Jan 24 17:09:49 2008 -0700
-
- Simplify Dir#open spec dependencies.
-
- The "takes a block which yields the Dir instance and closes it after"
- expectation was failing because it depended on File.for_fd working
- properly with closed file descriptors which it does not.
-
- This revision removes the dependency on File.for_fd as well as
- IO.sysopen (which is not yet implemented in jruby) such that
- the spec now passes on ruby, rbx and jruby.
-
- Signed-off-by: Eero Saynatkari <rubinius@projects.kittensoft.org>
-
-commit 27834ebec570c78011eaaf37998272d46ab9d118
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Jan 26 21:51:13 2008 +0100
-
- Added Date#strftime specs and fixed some constants
-
-commit 767e58ec38af7c3bc78dd98541fb8235616e9691
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Jan 26 21:45:23 2008 +0100
-
- Add spec for Rational#round, works because of added Numeric#round
-
-commit 2497d3b7b9d6112356204dc429c3c368e1a65573
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 26 12:31:45 2008 -0800
-
- Templates for Rational specs.
-
-commit 5d63550a13cad4acbae3ae67e9ee9f672cbe5e61
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sat Jan 26 00:47:35 2008 -0800
-
- Revert back old date.rb, but use newer date/format.rb, with some fixes
-
-commit ecd3ee8a0a528f516283558585b86e729bd388ec
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 21:47:38 2008 +0100
-
- Updated not_compliant_on --> not_supported_on, where appropriate.
-
-commit 78ca098893d6231f74386eeadf0c30787f3dd2e6
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Jan 25 12:18:43 2008 -0800
-
- A couple of easy fixes, fix Time to handle 2 digit dates, pull in trunk date
-
-commit fe8433cda8ca49835e2581f35bbf0d31025e84c1
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 18:42:31 2008 +0100
-
- Better detection of AF_INET6 support in socket specs.
-
-commit 1834801229bf8b2c0abfea4c18448ed105691682
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 18:16:56 2008 +0100
-
- Added a guard for undefined AF_UNIX in Socket specs.
-
-commit 3af242cc180675272ee24d588f3328bc11342048
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 14:32:04 2008 +0100
-
- New specs for IO#seek, IO#pos=, StringIO#seek and non-fixnum args.
-
- Rubinius fails all of them.
-
-commit 0ef7d55ebb5108bd5cf2f951236c8fade3999dfb
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 13:42:08 2008 +0100
-
- New specs for String#unpack with 'Q/q' patterns.
-
-commit 907081db80262a1403f659433934ef707c2ddee0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 25 12:35:07 2008 +0100
-
- Adjusted socket specs, so they pass on MacOS (MRI/JRuby).
-
-commit 9cca76acbe066da357692a19d5af1c8f5e4601c9
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 24 17:31:38 2008 -0800
-
- Fix race in compiler version number, fix regex spec
-
-commit be18fcc2e0ee16f861f1e2bff0636c3288bce8d6
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 24 15:10:00 2008 -0800
-
- Be more flexible with set_priority (OSs are a bitch)
-
-commit 845336d81df42b5d1f93123ef148b78c2b220d25
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 24 13:46:08 2008 -0800
-
- Kernel flesh out, passes all but 1 spec now
-
-commit ab87e7641336dfb07f0ad99cc2881ec59a25053a
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Thu Jan 24 12:36:50 2008 +0100
-
- Changed __const_set__ to handle corner cases.
-
- * Kernel#__const_set__ is now the catch-all. It triggers on things like :
- M = 3
- M::M = 3
- * MAIN#__const_set__ is forwarded to Object
- * Module#__const_set__: logic has been moved here, it is no more and alias
- of Module#const_set because it needs to trigger a warning on re-assignment.
-
-commit 13dbdf62e802028cb61f9375196712f0b789ff37
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Jan 24 21:30:02 2008 +0100
-
- Added some SystemCallError specs.
-
- And exclusions for rubinius too.
-
-commit 75e2aac1d4b031fa36c8967549452436521b5eea
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 23 19:41:30 2008 -0800
-
- Rework Class.new and Module.new to initialize without VM help
-
-commit 2551e57644d091d44e5e2fa715a017a557a0b18c
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 23 19:03:51 2008 -0800
-
- Userland now uses __const_set__ for 'A = 3' syntax
-
-commit 400c5ceaf677aa2cd05a451c22144613ad7bdbe9
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 23 14:32:26 2008 -0800
-
- Introduce kernel/user land. Adds use of Module#__add_method__
-
-commit 9ee17f227ebe572b09d44b3b0d703b9f95717751
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 23 14:50:25 2008 -0800
-
- Fix Hash#clone
-
-commit bf4875d337017736bd94781c1bf4cd7500fae5f5
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Jan 23 22:55:02 2008 +0100
-
- Implemented Enumerable#inject fix
-
-commit 0bd07f50ba75910ab579e3356dae93bc32b695bd
-Author: Jacob Maine <jacob.maine@gmail.com>
-Date: Wed Jan 23 15:46:06 2008 -0500
-
- Enumerable#inject(nil) should yield nil as the first 'memo'
-
- * Currently yields the first element of the enumerable instead
-
-commit 319f937284e60acc156c6b7f91e56d460e65ac94
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 18:12:56 2008 +0100
-
- Excluded the IO#new spec.
-
-commit 04da4120d939603d4a64aab71bbf94ca202e04b2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 18:11:45 2008 +0100
-
- Added IO#new spec (block should be ignored, warning printed)
-
-commit 5617c3eb81a3f1d8f9a581695fe7897fadee500a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 17:50:48 2008 +0100
-
- Excluded failures after IO specs additions.
-
-commit 107a072689bc9b97842f049f4fab2860ab79237d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 17:48:34 2008 +0100
-
- Added specs for IO#open/popen, File#open with close inside block.
-
-commit bc3393a9041f8116d53bedfa6b604ec6dce3fd19
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 23 14:25:13 2008 +0100
-
- Revert "Added Module#name memoization spec". dbussink told me this behavior
- is not wished.
-
- This reverts commit ff411600202a59d00ffaca2c51330599c6b84966.
-
-commit 73e7d61d756cb7a06ea18b7f92c49bbebb06cc3f
-Merge: ff41160... 1dab607...
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 23 13:57:28 2008 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit ff411600202a59d00ffaca2c51330599c6b84966
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 23 13:55:36 2008 +0100
-
- Added Module#name memoization spec
-
-commit 1dab607a79b79b370eda4776daf07a262451aea0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 13:28:29 2008 +0100
-
- Added IO#close specs.
-
-commit c78091236495f4a16aa874de97cce3ec485c1f5b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 23 12:54:25 2008 +0100
-
- Added IO#close_write and IO#close_read specs.
-
- And all of them fail in rubinius. (not implemented)
- And most of them fail in JRuby. (recent bugs)
- They pass just fine on MRI 1.8.6 (p111 and latest)
-
-commit dc39943a4595855d64f23f9155a4e9cf658c39a3
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Jan 23 10:37:45 2008 +0100
-
- Small refactor of regexp_new
-
-commit 132ac4986a648dbf1354216145e5715a727a735b
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 23 00:14:34 2008 -0500
-
- Type.coerce_to no longer falls prey to identity fraudsters.
-
- * Type.obj_kind_of? directly uses the internal kind_of instruction
- so that overridden #kind_of? does not get in the way.
- * Type.coerce_to uses Type.obj_kind_of? for its checks so that
- Core can safely use it without worrying about breakage due to
- overridden #kind_of?.
- * Specs for both and a little documentation.
-
-commit 192882902154c9a68554337ccd1b8f3ee9aedd9e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 23 00:42:24 2008 -0800
-
- Remove Symbol#to_i and Symbol#to_int. Farewell bastard children.
-
-commit f854667ff62528fe541c8cf67b9a1b291598d654
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 23 00:35:29 2008 -0800
-
- Removed Fixnum#to_sym and Fixnum#id2name, as well as fixed specs
-
-commit eb6cbc3604c81cc093edb1c182be1e456b05bef6
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 23 16:30:22 2008 +1100
-
- Added specs for context iseq manipulation
-
- Added specs to test MethodContext#reload_method and
-
-commit fd5fb764ee21b354b75b84f34906663874a24639
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Jan 22 22:28:02 2008 -0600
-
- spec for DRb method call using a block
-
-commit a928762b48f7dc84bba0d43125063e9d8d54f183
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 22 19:15:10 2008 -0800
-
- Better test of #instance_method.
-
-commit c055a5981bf4ecfd2efc0df74adb071056ff83b9
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 22 15:40:59 2008 -0800
-
- removed remove_method_excludes.txt
-
-commit 08cb27454e7ae73e79bb432887dba917feaa1f92
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 22 15:36:36 2008 -0800
-
- Clarified undef/remove specs a bit.
- Fixed remove_method to raise NameError if you're not acting on local method.
- Removed some fails_on calls to make specs pass... gonna remove them all soon.
-
-commit 62d93ac7916ff0d56a5b40ae1b9b501f10081638
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 22 15:35:05 2008 -0800
-
- Fix up sysread and syswrite, disable testing for warnings on rubinius
-
-commit a482b17c4bfe9f40474839ba0cce2a37d8524c62
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 22 15:13:19 2008 -0800
-
- Remove stale binding excludes
-
-commit f45030d33a9e1fe3c6bc111401a893e5649239f7
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 22 15:03:37 2008 -0800
-
- Update Proc excludes
-
-commit 7f932fbdf5fa4e16df10d7731313d458ca21966c
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 22 14:55:50 2008 -0800
-
- Add Proc#==
-
-commit 811cbe8ef876ef452051a9b07b3c95dbf57a7d9f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 23:41:55 2008 +0100
-
- Removed debugging stdout from one spec.
-
-commit 2bf52de43bb90721d921f6d29504a8f098ed09b5
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 22 14:11:17 2008 -0800
-
- Removed a lot of passing specs from the excludes
-
-commit b0e5a9ba6577c301f2737682d745128e268ebdab
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 22 14:02:38 2008 -0800
-
- Fixed Symbol::all_symbols
-
-commit 68ae0b5acd647b9ebd73e53638b728cfaee6b6e0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 22:09:45 2008 +0100
-
- Revert "Completed MRI's Module#name spec with corner case."
-
- This reverts commit 970ede321d31ec75dd578866c683defe768fa356.
-
- This spec seems like an implementation detail rather than
- a specified behavior. It was agreed on IRC to revert it,
- and that rbx won't support it.
-
-commit cc0e45cab2167e0fbc1d29308a5dcb4e7e077319
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 22:06:28 2008 +0100
-
- Revert "Module#name memoization work."
-
- This reverts commit 7cd9fce4908aaeea9a35e273a3f15ed7ee7aa783.
-
-commit 996f9f4e5fc05f1b3aa618db3e1a4947730780b7
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 22 12:23:39 2008 -0800
-
- Fix LongReturnException to be terminated in the correct place
-
-commit f453121dd2f3b4d9506a3f1c1e61d24e46bc9083
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 20:53:45 2008 +0100
-
- Corrected Module#instance_method failing spec. It was failing on all impls.
-
-commit c1d59239ddea95e73e2edd3a97ed6e1113a35d3c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 19:58:32 2008 +0100
-
- Corrected Module#instance_method spec, it was failing on MRI/1.8/1.9/JRuby.
-
-commit ef5f4489caac2ad4bad94783a780aa40a054481c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 22 19:30:48 2008 +0100
-
- Corrected String#to_f spec.
-
-commit 7cd9fce4908aaeea9a35e273a3f15ed7ee7aa783
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sun Jan 20 22:00:34 2008 -0600
-
- Module#name memoization work.
-
- * Module#name is now memoized on access if @name is set
- * Full module path is lazily calculcated on memoization
- * Module#const_set(Ruby) and module_const_set(C) only set @name and @parent.
- * The following methods unifily use module_const_set:
- * cpu_const_set
- * cpu_open_class
- * cpu_open_module
- * module_setup_name
- * Module#calculate_name reworked, hack removed
-
-commit 7b4ef1344812faa76018ab41cc7fba97a3af8448
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Tue Jan 22 02:47:49 2008 -0600
-
- implement more of Marshal.load
-
- Float, obj._load, obj.marshal_load, IO.read, proc arg
-
-commit 41f07f0253a8fba205dbb0402e5d5e88c115d76c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Jan 22 16:32:01 2008 +1100
-
- Fix Task#get_stack_value to not raise exception from primitive
-
-commit 14c811adaba3e8cfc5104d70e67c2e89c18cac4d
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 21 19:28:18 2008 -0800
-
- Exclude Kernel#require is private spec when running with RSpec.
-
-commit 05a180e0051a0409c685d326a41e882545faaa53
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 21 19:26:41 2008 -0800
-
- Explicitly run /bin/sh to get around limited /bin/pwd on linux.
-
-commit c09b3da391995a0e9006055ce19e838d3f180947
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 21 19:09:07 2008 -0800
-
- Protect String#% specs from segfaulting on linux (ubuntu gutsy).
-
-commit d36b3f65f92b08ae078812788482387077d03380
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 21 17:55:03 2008 -0800
-
- Removed use of `pwd -P` as at least ubuntu bin/pwd doesn't support it.
-
-commit 6d7a8292fb9a68a0dcfbd3f29f595e0ecf5902ae
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 21 17:54:11 2008 -0800
-
- Unexclude Kernel#callcc specs as Evan's recent commits seems to fix it.
-
-commit eb04d409575772a85510770bd0db4f36490de6aa
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Mon Jan 21 13:28:06 2008 +0100
-
- Fix Regexp error handling
-
-commit 93e50808eb7355c404a7f5295923083c8cf63549
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sun Jan 20 22:00:34 2008 -0600
-
- Quarantining IO#dup spec "sharing" example due to platform differences.
-
-commit ae9e2829becc495892c7ddce5eae67514f268120
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 10:26:56 2008 +0800
-
- Update Module instance_method_specs excludes after revert put it back in
-
-commit df6c82f97987c233eab0534740054e2d0f0f2f2c
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 10:25:00 2008 +0800
-
- Revert "Update CI excludes for Module"
-
- This reverts commit 8aa00146f2eee9576094daa76c6f158b0deaf2e2.
-
- * Fails when run with other specs
-
-commit 6f5245d4c20bf009bc120967f4a93d24faae66ba
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 10:23:15 2008 +0800
-
- Revert "Update CI excludes for Symbol.all_symbols spec"
-
- This reverts commit cb27e31b2a757ad108842bfa579eb9170d6cf244.
-
- * Returns an F if run with other specs in ./bin/ci
-
-commit ec9677e593247ed8dfcbfc680151d04ac97936e3
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 10:11:35 2008 +0800
-
- Fix Module instance_method_spec to match the inspect with a regexp
-
-commit 7e3474a16ec20094630e865594405ea7f1658c58
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 10:08:06 2008 +0800
-
- Module#instance_method raises TypeError/ArgumentError on invalid arg
-
- * Fixed spec to expect TypeError when passed nil
- * Fixed spec to expect ArgumentError when passed non-symbol/string
-
-commit 8aa00146f2eee9576094daa76c6f158b0deaf2e2
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 09:41:37 2008 +0800
-
- Update CI excludes for Module
-
-commit 9158b959d30babdceafc416650c1ba3234e5029a
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 09:10:06 2008 +0800
-
- Add alias for Proc.to_s from Proc.inspect
-
-commit cb27e31b2a757ad108842bfa579eb9170d6cf244
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 09:09:40 2008 +0800
-
- Update CI excludes for Symbol.all_symbols spec
-
-commit 7f16f313c907de0e22762d97fbba24e70c3259a3
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 21 08:46:36 2008 +0800
-
- Raise TypeError/ArgumentError for invalid Thread key
-
- * Raise TypeError is key is nil
- * Raise ArgumentError is key is not Symbol or String
- * Correct the description of Thread's element_set_spec to use #[]=
-
-commit 0b849f884beae9d11327e315da5c79fe789b8391
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Jan 20 23:05:33 2008 +0100
-
- Added rubyspecs for Zlib.crc32.
-
-commit 67b52b6fb92b9e9a037e584474cff2dc97ce0163
-Merge: e6d8a61... 6f08d5e...
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Sun Jan 20 22:30:52 2008 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit e6d8a61771b76198c0784677bb0a8fc97b1988bc
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Sun Jan 20 22:30:29 2008 +0100
-
- Fixed Struct#[] and Struct#[]= with negative indexes.
-
- * Added corresponding specs
- * Fixed kernel/core/struct.rb code
-
- Example:
-
- s = Struct.new(:x, :y)
- x1 = s.new(:a, :b)
- x1[-4] #=> should raise IndexError: offset -2 too small for struct
-
-commit 6f08d5e21473d0f2adff66a32acd46ddd8945fa0
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 20 12:47:11 2008 -0800
-
- Added spec for Kernel.format.
-
-commit 6ab2691b455ac07643d98dc58f8a0f45487ab20d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 20 11:52:56 2008 -0800
-
- Added sane handling of non-reals for #format %e, %E.
-
-commit 1caab1ce237a52d78a402a5f0a7ce1d3ed9ac6b7
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Jan 20 18:55:27 2008 +0100
-
- Add spec for singleton_methods and fix for Fixnum
-
-commit d7c46a0a1660f1d53e03a97571f3ec7b2431d0e4
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sun Jan 20 12:29:10 2008 +0100
-
- Added failing spec for Regexp#new that could cause a segfailt. Needs error handling as stated in shotgut/lib/regexp.c:122
-
-commit d15c6605b7fb7db337d87ac1bd15f9a1371caa42
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 19:28:00 2008 -0800
-
- Added language spec for return within a block.
-
-commit 3b516c028c4c9e064fbe839f0f9402a135eb90b0
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 17:27:13 2008 -0800
-
- Added spec for class vars set from Kernel#instance_eval based on #267.
-
-commit 970ede321d31ec75dd578866c683defe768fa356
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Sun Jan 20 00:44:04 2008 +0100
-
- Completed MRI's Module#name spec with corner case.
-
- It looks like Module#name is memoized in MRI
-
-commit caf440ac6a8037a2c223834c0ca4c5decd8e68ab
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Jan 19 22:48:31 2008 +0100
-
- Revert "Wrapped one spec to prevent JRuby crash."
-
- This reverts commit 9f266e3c785c7e3edbb6a30271f32debe6c14164.
- JRuby issue is resolved.
-
-commit 9673e2c1c5a1142af52a0d82d8981bdd9e236c27
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 12:46:12 2008 -0800
-
- Changed IO#syswrite to use should complain matcher.
-
-commit 8522186df7050782c4911f40aef381106e5e8c5b
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 12:29:12 2008 -0800
-
- Added mSpec lambda { .. }.should complain matcher for warnings.
-
-commit 9f266e3c785c7e3edbb6a30271f32debe6c14164
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Jan 19 21:24:13 2008 +0100
-
- Wrapped one spec to prevent JRuby crash.
-
-commit 54d1989997561271553ba72bd99f59ef2deb7c72
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Sat Jan 19 19:13:06 2008 +0100
-
- Fixed "X::X = 3". It would return a tuple instead of 3.
-
- * changed shotgun's const_set instruction to push the variable on the stack.
- * added corresponding specs under `language'
- * found a new problem but added it to excludes
-
-commit d25ec129902789bc7d636ff5ccda8ff858ae38d3
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 10:21:19 2008 -0800
-
- Added spec/README. Reformatted mspec/README. Removed old sprintf spec.
-
-commit 5eb06e3010707de1e273c23b3f0addf2ceaa824d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 19 09:37:29 2008 -0800
-
- Removed unused Sprintf, rename YSprintf to Sprintf.
-
-commit c144abc12230175a2a503c4426804ed19c8559e7
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Jan 19 16:21:08 2008 +0100
-
- File::Stat time functions should return Time objects and added stat and lstat instance methods on File
-
-commit 177ef99db435a59e942566f7904167fc5e849d8d
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 19 22:24:16 2008 +0800
-
- Fix ThreadGroup's add spec
-
- * Fix is by initializing a new ThreadGroup on Thread setup
-
-commit 3fad84ec370eda1cab596adf5589e43240dfc381
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Sat Jan 19 12:16:55 2008 +0100
-
- Removed empty *excludes.txt for better searchability
-
- `find -name "*excludes.txt" -size 0 -exec git rm {} \;`
-
-commit 9a2b1e6232f36c7a1508085b4606e25fbcf3cb4a
-Author: Jonathan Younger <jonathan@daikini.com>
-Date: Fri Jan 18 23:19:16 2008 -0700
-
- Additional String#% platform specific formatting failure fixes
-
-commit aa32d6fcbed79b9e2afedc00f429ea78f5c540d3
-Author: Jonathan Younger <jonathan@daikini.com>
-Date: Fri Jan 18 22:12:23 2008 -0700
-
- Fix String#% platform specific formatting failure
-
- Darwin and FreeBSD return a different string format than other platforms,
- so a different expectation is needed to match the appropriate format.
-
-commit c64dfd449dc89ec0016f14afd7f85522dbaa4148
-Author: Jonathan Younger <jonathan@daikini.com>
-Date: Fri Jan 18 21:05:44 2008 -0700
-
- Moved String#% specs to ruby/1.8 and fixed to work with rbx and MRI
-
-commit e5e7f44983f1dbbc79726776b56a9cc7cb910e9f
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 18 19:53:50 2008 -0800
-
- Updated IO excludes.
-
-commit b8b549dbc1aaf63e15717c3902d4485c97f845f7
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Jan 18 21:40:01 2008 -0600
-
- Add regexp matching for output matcher and enable warning specs for syswrite.
-
-commit 004bd58b597034cbe734d9b7da318135a689190f
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Fri Jan 18 21:06:38 2008 -0600
-
- implement some of Marshal.load
-
-commit 2c52db8022f060866d839992aaa6bff0f61963cf
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 19 11:21:55 2008 +0800
-
- Fix UnboundMethod#bind
-
-commit a5680db20cf998f0db292e3b9aa69ed74fb19b10
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 18 17:49:44 2008 +0800
-
- Implement UnboundMethod#==
-
-commit a1de7b0f405830f6bfe8000c051f4445135d8f63
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Jan 18 20:54:11 2008 -0600
-
- Added some specs for sysread/syswrite on a file and p flushing to File.
-
-commit e7bc994d96398519ca205e87dec8e775bb0e67c6
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Sat Jan 19 01:31:46 2008 +0100
-
- Fixed File#utime segfault
-
-commit 9887c6135e9353c3094dcf3c76d8e788b98f2bed
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 18 22:00:10 2008 +0100
-
- Added Time#strftime specs for '%U' and '%W' patterns.
-
-commit 0338fb5adb325e58d1ce61bccc9310fc7284e235
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 18 20:35:23 2008 +0100
-
- Added two testcases for String#% rubyspecs ('x', 'X').
-
- There was a bug in JRuby's sprintf, which wasn't
- detected by rubyspecs.
-
-commit 97db9fb72d6205227d61d92ed3153331b2328f97
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 18 10:50:00 2008 -0800
-
- File#utime spec. Some cleanup of File#open specs.
-
-commit 10647cf8abfd0ea7a87d39978a22f68fdfa9fbd6
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 18 17:08:04 2008 +0100
-
- Wrapped 3 IO spec tests into fails_on :jruby.
-
- Because these tests just break the spec run completely.
-
-commit cf6195eeabe382c4267e295ab786acedaed89050
-Author: Jonathan Younger <jonathan@daikini.com>
-Date: Thu Jan 17 21:55:48 2008 -0700
-
- Fix specs that use `pwd` to use -P option so that symlinks are resolved
-
-commit 1b79705fb965ecd6fc897b6bf14c605d8325dabe
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Jan 18 15:57:46 2008 +0100
-
- Added IPAddr specs by manveru. Closes #262
-
-commit f05b96b33970e3f08da5c8992f7c6cb710649f42
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 18 02:23:15 2008 -0800
-
- Fix spec for IPv6 environments
-
-commit 2007019ebad7974d7a54e6d599320675548313f0
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 18 17:39:09 2008 +0800
-
- Fix UnboundMethod#inspect to use regexp
-
- * Also aliased UnboundMethod#to_s to UnboundMethod#inspect
-
-commit c47b473b99b59074673adb7e8d50a250e34436e7
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 18 17:37:29 2008 +0800
-
- Use a regexp to match the inspect output instead of deviating on rbx
-
-commit 8dc2a2b3115a49a15ed931301b1999560ee27db5
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Jan 18 01:05:14 2008 -0800
-
- Fix up specs and finalize LongReturnException
-
-commit 7c30ca7337b56a4194eb58952f74662e222b7707
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 17 23:23:27 2008 -0800
-
- Add support for return in a block obeying ensure properly
-
-commit c06fc665c6bf5898163f2854b93d62b8b314216e
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 17 21:20:42 2008 -0800
-
- Changed Exception#backtrace to return an MRI compatible one.
-
- * Exception#awesome_backtrace returns an Rubinius Backtrace
- instance, as Exception#backtrace used to.
- * Added templates for Backtrace specs.
- * UnHACKed lib/test/unit to use the #backtrace as expected.
-
-commit a29f35c5a45776f10132c3ce0ef058b1e98a4f75
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Jan 17 20:18:04 2008 -0500
-
- Guard failing Process.setpriority spec, add an exclude to CI
-
-commit 333d5c6920c01366c8b2887ecc7e33f775210c00
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 17 16:50:31 2008 -0800
-
- Specs and fixes for Class.inherited.
-
-commit ac90d87a69c19c441b854660105d21ed771989f0
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Thu Jan 17 16:37:31 2008 -0800
-
- One more step into the foray of bootstrap madness... removed useless 0 from lasgn nodes. needs full clean
-
-commit 0dbabefd081be4890d0d789a9c3ec122b9196cf8
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 17 12:00:55 2008 -0800
-
- Fixes to enable RSpec 1.1.2 to run the spec/ruby specs.
-
-commit 9bd611ff5c5b411518c2f4ce5d3cd4b93f4bcebe
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 17 08:25:24 2008 -0500
-
- IO#puts, #isatty fixes from Dan Lucraft, slightly modified.
-
- * The #puts spec exposed an issue with String#suffix? which Ifixed in
- fa9a6c which means IO#puts did not need to be changed.
- * #puts spec uses output_to_fd.
-
-commit 3f519a98bbc3a66d59884add5fcd98d5ca095149
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Jan 17 08:02:51 2008 -0500
-
- String#suffix? specs and correct behaviour.
-
- * The suffix can be the entire string, there is no need for it to
- just be a substring always.
-
-commit ca6fa9cd760b06827f4f953ff28e8baed357f447
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 17 12:48:20 2008 +0100
-
- Additional Date specs
-
-commit 8541022ffc918879142ecb3707e977050f774ece
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 17 00:47:04 2008 -0800
-
- Added ?d, ?e, ?f to Kernel#test.
-
-commit e6f36980c2c94414e5c051b35d9ce403c492f1a2
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Jan 17 02:18:25 2008 -0600
-
- Fix my oops; missing 'do' for the fails_on
-
-commit 44483d8e414f107b3202cc69b8cdfbbe1222ee33
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Jan 17 02:07:57 2008 -0600
-
- Add a fails_on guard to IO#printf spec for JRuby; output dies otherwise
-
-commit 53a36c934ec44fad7e6d18424cb13b37496cf720
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 16 18:39:34 2008 -0800
-
- Updates to compiler and core to protect Fixnum#/.
-
- * Added compiler plugin SafeMathOperators.
- * Added very simplistic way to pass flags to the compiler.
- * Added -frbx-safe-math flag
- * Changed core Fixnum, Float, Bignum, and Numeric methods
- to use #divide rather than #/. Aliased #/ to #divide.
- * Updated Rakefile to send flag when compiling core.
-
-commit feb260b904d87487428b558f7b7e9ac0170c160c
-Author: Ryan T Mulligan <ryan@ryantm.com>
-Date: Wed Jan 16 22:47:02 2008 -0600
-
- very minimal SHA1 specs
-
-commit 511732d932d2fe934968c78b89cefa46e699b996
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Wed Jan 16 16:30:40 2008 -0800
-
- Moved old spec excludes to new location and deleted all old
-
-commit cae6bba077190e158ceee7b8991daf16fd8c55d1
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Wed Jan 16 13:36:19 2008 +0100
-
- Added more Date specs
-
-commit 75d49657f31091d37dfdba1fc5487164db861802
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Jan 16 15:58:42 2008 -0600
-
- more specs for TcpServer and TcpSocket
-
-commit b1d45cb0fdc573bfe5995456d846c11747d48b90
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 16 13:31:33 2008 -0800
-
- Implement ObjectSpace.define_finalizer, using WeakRef.
-
-commit 4e8a0d264dc7d5a4866a1a1b83238bebb47e4ab6
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 16 21:51:52 2008 +0100
-
- Removed platform-specific specs in spec/ruby/1.8/core/signal/list_spec.rb
-
- There is not direct way to know if a signal exists or not, since it all
- depends on <signal.h>. In practice, there is no real risk for rubinius
- to miss a signal.
-
-commit 32537f8d3378154f7f52c278cd56a7d4159a3446
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 16 12:41:54 2008 -0800
-
- Added IO#printf, fixed Kernel#printf to use IO's.
-
-commit e7bccb3f38f6ace3cb25a9f227ab5f6b1d2be346
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 16 21:19:48 2008 +0100
-
- Signal.list spec now passes. bin/ci removed list_excludes.txt
-
-commit b3a6461af30f2c144b4ee65e8539c51291e0156b
-Author: Jonas Pfenniger <zimbatm@oree.ch>
-Date: Wed Jan 16 20:03:15 2008 +0100
-
- kernel/core/signal is no more platform dependent
-
- * Now publishing platform.conf with rbx.platform.signal.* (only using the ones
- defined in MRI's "signal.c")
- * Signal::Names is now published with those values on @after_loaded@
- * New method: Signal.list => Signal::Names
- * Added EXIT=>0 and CLD=CHLD exceptions (see "signal.c" in MRI)
- * Updated the corresponding specs for more details (on FIXME, please help !)
-
-commit bdbd712a5953f011f8d6f1142d50a452e1607f65
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Jan 16 13:42:01 2008 -0600
-
- updated Continuation excludes -- Kernel#callcc specs still bleedover
-
-commit 22d32d3461660ee7cd29760163b622fc94b6ea5b
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Wed Jan 16 01:55:21 2008 -0600
-
- apply Marshal.dump patch by Justin Bradford. #252
-
-commit 513de8ab67ab9c017285a48108ccceb185ebaf24
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 16 16:44:34 2008 +1100
-
- Bunch of Debugger fixes
-
- * Debugger now has proper quit behaviour, which causes
- the debugger to remove all breakpoints, clear the debug
- channel, and resume the debuggee.
- * Fix singleton(-ish) semantics of Debugger; essentially,
- only a single Debugger instance can be instantiated at
- one time.
- * Added a bunch of specs for the above
- * Changed Rubinius::VM.set_debug_channel to accessor
- style Rubinius::VM.debug_channel.
-
-commit 2174009b215ce2f0445fc8df4711e7e6c64b0332
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Tue Jan 15 21:59:30 2008 -0600
-
- add Marshal.load specs
-
-commit ec002dd0f0daddedaa5241c4f8f6d85fad0e9768
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 16 09:47:28 2008 +1100
-
- Move VM under Rubinius namespace
-
-commit 983c54400542a03535accf2705ae227ae58970dc
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Tue Jan 15 15:24:10 2008 -0600
-
- Added spec for File.new coercing filename using to_str.
-
-commit ff6a081de28711b0d8c1136e6e4272baf769043c
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Jan 15 14:29:43 2008 -0600
-
- since DRbObject is within DRb it should be a subdirectory but mkspec generated the wrong path to helper
-
-commit a48cbbd3f5da3c971a215423b3e27b058de04196
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Jan 15 21:15:09 2008 +0100
-
- Add more Date specs
-
-commit 9de289f1bbae86b12bc383e7e535de404f8aaa5f
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Tue Jan 15 14:58:31 2008 -0500
-
- Add a servent class to StructGenerator for Socket.getservbyname
-
- Also, add Socket.htons and Socket.ntohs for byte order encoding
-
- And complete Socket.getservbyname along with specs.
-
-commit d9e37ff3c0f975a418fafbc7163ee1a9717dd92b
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Jan 16 03:31:05 2008 +0800
-
- Fix Proc#[] calling the wrong #call method
-
- * Re-aliasing in Proc::Function because aiases don't follow subclass
- methods
-
-commit 2273c919e80ab7186e3139941dc4d73a292bcd2d
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Jan 15 19:30:23 2008 +0100
-
- Add add and minus specs for Date
-
-commit 1325e22c11c48c366d9f0387823de5941b59df66
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Jan 15 16:35:23 2008 +0100
-
- First specs for Date object
-
-commit a3b76d162e58e75b4523151bb6911c840db8319f
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Tue Jan 15 12:58:14 2008 -0500
-
- Implement Socket#pair (and Socket#socketpair) with corresponding spec.
-
-commit 836f1cf828ab62606a6b0e2f7313228b7482dcbe
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Jan 15 11:47:11 2008 -0600
-
- generate spec files for DRbObject
-
-commit ef99f25be36f6ccd33b297bed14c1175847f1ecc
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Jan 15 11:31:08 2008 -0600
-
- generated spec files for DRb with a basic spec for DRb.start_service
-
-commit 9637cf1e77efd1a3b53e6c4d82a7c7afe8509621
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Jan 15 18:48:09 2008 +0100
-
- Eliminate stdout from IO#dup spec runs.
-
- At least, under JRuby it was printing things like:
- "No such file or directory".
-
-commit 30a2fce2a4fd7e840586ce8ae390ecb632c8bee0
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Tue Jan 15 23:00:32 2008 +0800
-
- Implemented Dir#pos which fixes #pos, #pos=, #seek, and #rewind specs
-
-commit 013ab2e88ecd8d887c6a0009e7f8d2add4849143
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Tue Jan 15 22:52:26 2008 +0800
-
- Revert "Updated CI excludes"
-
- This reverts commit 15d1c7674496a99bf1d5ec42420864b22bf1569a.
-
-commit 15d1c7674496a99bf1d5ec42420864b22bf1569a
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Tue Jan 15 21:50:55 2008 +0800
-
- Updated CI excludes
-
-commit 18470055d83a43c3371609aaac4471767adb3b1b
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 15 04:32:54 2008 -0800
-
- Make TCPSocket.new work. Use socket library names for familiarity.
-
- Make inheritance hierarchy of sockets better match MRI.
-
- Add syscall names to Errno.handle checks.
-
- Spec less of the socket library.
-
-commit bd34303986a068b40cce1366c85ea288fc24a3f5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 14 23:55:38 2008 -0500
-
- Regexp subclasses work now. Documented Regexp.new.
-
-commit 343acee55519fc97a35a9d50e8bdcfd679d432b7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 14 23:49:47 2008 -0500
-
- More Regexp.new specs.
-
- * Subclass initialization verification.
- * Multibyte options are case-insensitive.
-
-commit 758a468ffafdeea78016dbbce78f21e19f6735f6
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Mon Jan 14 18:22:32 2008 -0800
-
- Fixed require modifying LOADED_FEATURES even if require raises an exception
-
-commit 5c8ff74b64f7ec6bd4c413b0e0e93334dff009ca
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 14 21:57:19 2008 -0500
-
- Fixed Regexp#kcode specs.
-
-commit 34867cc1f1f3b7ac3145fb926491c0dc44629312
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Mon Jan 14 22:41:58 2008 -0800
-
- Add Socket::getaddrinfo. Raise SocketError appropriately.
-
-commit e2009a38a8e1ef0dff6394b92a677f3120280f72
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Mon Jan 14 22:39:55 2008 -0800
-
- Remove platform-specific code, remove spec of socket library behavior.
-
-commit 5afa1c34808c68c17bc02f5f76c42d64efdd7dd2
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Tue Jan 15 00:32:14 2008 -0600
-
- Modified retry-in-rescue example to test nested blocks and be clearer.
-
-commit 17fd0cb781ec90d268668c5678e1135eb5f6e323
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 22:28:46 2008 -0800
-
- Added Module#autload?.
-
-commit 96ca83312d1b5a1e38e25f94504f6f69a137b96d
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 21:50:37 2008 -0800
-
- Updated CI excludes for language.
-
-commit ef4f49de672d40f43f53dadff1aa8fdbcafe1d45
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Jan 14 21:37:23 2008 -0800
-
- Fix specs for dregx change, fix regexp for specs
-
-commit 5cd2ef2a173394910249d93d8ef433d220f2d9a9
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Jan 15 16:32:15 2008 +1100
-
- Fix breakpoint specs
-
- The breakpoint specs were interfering with one another,
- due to the fact that each was modifying the bytecode for
- a fixture class that is compiled only once.
-
- Workaround this by saving off the bytecode and resetting
- before each test.
-
-commit 29bf88b07f87182d94fcf7c550724efc07067239
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 20:00:27 2008 -0800
-
- File spec/data/critical.txt is empty! Congrats to everyone!
-
-commit 8082760cc2215742464a9846295ec4a8a0c49244
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 19:37:33 2008 -0800
-
- Removed Module methods from critical excludes.
-
-commit d075c115087c001d0d35562aeeea21efadc5e3b6
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 18:53:46 2008 -0800
-
- Added not_compliant_on :rbx for class variable specs that use Fixnums.
-
-commit 23f1b523da2478f2ad962f0045dca3e7034f9b56
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 18:16:46 2008 -0800
-
- Multiple fixes for #class_variable_get/set. Updated CI excludes.
-
-commit dbc5675058aa426dbfbbf7489d5393819edb16f8
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Jan 14 16:42:27 2008 -0800
-
- Fix attrasgn usage to pass specs
-
-commit 3e250999d6f1a7fdaf2bb5cd169a1024e2ab5ddc
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 16:07:08 2008 -0800
-
- Removed leftover excludes for compiler[12].
-
-commit a2b8b5511e79b47fa7777e716ee16511fdec3fd4
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Mon Jan 14 16:47:21 2008 -0600
-
- Remove the goofy Hash#delete spec and replace with two others.
-
- The old version of this example depended on individual hash buckets having a
- specific ordering, which overreaches a bit. The new version, while a little
- cumbersome, should work correctly regardless of hash implementation or hash
- and bucket ordering.
-
- I also moved out a few lines that were unrelated to this example into a
- separate one.
-
-commit 67d858885f1841e9c9aa295150da3c472949198d
-Author: Gregor Schmidt <ruby@schmidtwisser.de>
-Date: Mon Jan 14 14:57:53 2008 +0100
-
- Passes Module#extended specs by added extended method to module and adding a call to it in Object#extend
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 302ba965def902ccc5d3e97ed6bd5841f09d8f00
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 14 14:14:08 2008 -0800
-
- Philipp Brüschweiler's patch for String#%, #242.
-
-commit abaf2efa9e467bb7b5ef3b53b8490f1e056a832e
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Mon Jan 14 16:59:23 2008 -0500
-
- Another round of socket specs, and add a Rake StructGenerator to find sockaddr_un if it's available
-
-commit f5d0e435023a80bcc4c101a8d3ab9fc056a14c80
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Mon Jan 14 15:52:47 2008 -0500
-
- More socket specs
-
-commit 7bbc927a9d8a6f9202025be62a3db861ced3216f
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Mon Jan 14 14:58:34 2008 -0500
-
- More socket functions and specs.
-
- Namely, this implements a Socket::SockAddr_In class that is a FFI::Struct around the
- sockaddr_in C struct. This gives us a better ability to inspect what's going on in the
- struct from the Ruby side of things.
-
-commit f351c6d3d8831705f0398abdae240abba9252a75
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Mon Jan 14 11:09:04 2008 -0500
-
- More socket specs update
-
-commit cb8ce936394cafa00f77008083bccf9cded59f28
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Jan 14 14:39:41 2008 -0500
-
- Split process/constant expectations into Linux and BSD sections
-
-commit 0964d53edd80367611f63cd6eb4b294ec898cc8d
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 14 10:04:53 2008 -0500
-
- Revert IO#dup spec to unmask errors, removed FileUtils dependency.
-
- * Any errors occurring in specs should generally be raised normally
- so that any potential problem or spec deficiency is exposed.
-
-commit 04f542e928c5fa0df460d8f11b4d87e008fa343f
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Jan 14 13:36:49 2008 -0500
-
- Update Process::Constants to fetch values from RUBY_CONFIG
- Update process/constants_spec so that it passes on MRI as well
-
-commit 0ad02b57fd040196d11662bd1ab9b259dc2ce6d2
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Mon Jan 14 12:23:20 2008 -0600
-
- squash Marshal.dump bugs
-
- * fix order of evaluation problem
- * put more objects in links and symlinks hashes
-
-commit ed98b9a14459b011f97fee5c781410c4d413ed9a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 14 17:36:00 2008 +0100
-
- Updated Arry#pack specs to guard for always big-endian JRuby.
-
-commit 550f07dc7551573a975183209ba8904fdbd62607
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 14 15:57:04 2008 +0100
-
- More robust cleanup in IO#dup specs.
-
- Without it, mspec against JRuby was reporting EIGHT
- failures, while only 5 tests are actually exist.
-
-commit 1ea4f82183190c4c87da48c381f1db417c7403ac
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Mon Jan 14 09:26:36 2008 -0500
-
- Updated some socket specs
-
-commit e20ab7ea377cd39209011b44204d2688b53611c5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 14 02:23:26 2008 -0500
-
- Fixed Regexp.new kcode setting, improved Regexp specs.
-
- * Regexp kcode can be upper- or lowercase.
- * More robust Regexp#options and #inspect specs.
- * Updated Regexp excludes.
-
-commit cc71f359aa65101d2c00cfbb0c396b7cdc697ef2
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Jan 14 01:25:21 2008 -0800
-
- Improve bytecode performance a tiny bit, fix Kernel#`
-
-commit c561368c03c605de41746fac2ce5a6386fcf4f54
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Mon Jan 14 03:17:15 2008 -0600
-
- Quarantine a suspicious TCPSocket.new speck failing on MRI on OS X.
-
-commit 71a9cf2afbbe6903b8d652b3ee201957e0b0c633
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 13 22:58:16 2008 -0500
-
- Finished IO#print specs.
-
-commit ff75b95a690051736f49a9a113d21027f7f03e92
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 13 22:44:21 2008 -0500
-
- IO#dup and specs.
-
-commit 02f1c03f4df3327ce1ddd20e2249a5e9830627a0
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 23:11:48 2008 -0800
-
- Justin Bradford's patch for Float failure, #237.
-
-commit e43c148954ad609c438e5a4f14811c0349239374
-Author: Matthew Draper <matthew@trebex.net>
-Date: Fri Jan 11 21:35:57 2008 +1030
-
- Kernel#Integer is very fussy about the strings it accepts.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit adad84f7a26bf40809366f2f7b6acfc61dcfefc2
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Mon Jan 14 00:31:12 2008 -0600
-
- Class.inherited gets invoked regardless of visibility
-
-commit c746fad52e9503d04c3cf65de979b0a5a9f9e495
-Author: Matthew Draper <matthew@trebex.net>
-Date: Mon Jan 14 10:25:58 2008 +1030
-
- Many of Kernel's methods should be module_functions.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 0b8a4bfefaed3179f96721fdde35e32ed8ff7263
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 21:43:45 2008 -0800
-
- Update CI excludes for Regexp. Remove empty CI exclude files.
-
-commit 89a87edbc61a877621c6f43266000aff32e92ae7
-Author: Warren Seen <warren@warrenseen.com>
-Date: Mon Jan 14 07:12:13 2008 +1100
-
- Fixes visibility of methods passed to Module#module_function
-
- * Make instance methods versions of functions passed to Module#module_function private
- * Correctly identify visibility in error message raised in Module#set_visibility
- * Added specs for module_function
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 25d6fa558f88732d1aa28c68b0eb7c9910366243
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 13 20:42:52 2008 -0500
-
- Updated Regexp excludes.
-
-commit 69e200276898f1c9208be527bdc64c318c56f86e
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 13 20:24:42 2008 -0500
-
- Shared spec for Object#dup and Object#clone.
-
-commit 8a6fe609224c126bcf86987edd3f0690fc9e45ff
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Jan 13 18:19:56 2008 -0500
-
- VM calls private hook methods now. Object#dup and #clone specs.
-
- * Object#dup and #clone have rudimentary specs which also partially
- confirm the private hook fix through #initialize_copy.
-
-commit 84773b6ba63ea6f715dcc4e99e0a8a2e2b739152
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Jan 11 10:46:15 2008 -0500
-
- Specs for Regexp.{new,compile}, updated excludes for same.
-
-commit 6c1603723bba7d58203aa9b03bbf92b4900e53d1
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 18:49:40 2008 -0800
-
- Numerous fixes for File::Stat.
-
- * Implemented readable(_real)?, writable(_real)?, executable(_real)?.
- * Implemented a number of helper methods like rowned?, rgrpowned?,
- superuser?, rsuperuser?. Made these private.
- * Implemented owned?, grpowned?.
-
-commit d1b05e0bf98a3cdfda8a3d2398e78035a49c0c66
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Jan 14 12:25:41 2008 +1100
-
- Deprecate meta_send_stack* opcodes
-
- The code path for these opcodes is almost identical to
- send_stack, and no measurable performance improvement
- comes from using them.
-
-commit 154fe5e1faad94f371c51a979240a6d7f5cd8909
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 20:07:12 2008 -0500
-
- Implement BasicSocket#setsocketopt for String optvals, and add a spec for it.
-
-commit c21636d6b2502db344049e7dc62d42ff8c18b040
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 19:34:50 2008 -0500
-
- Add specs for BasicSocket#getsockopt
-
-commit 1584f41148b8d8967df4c3ee6376b59919cb7db3
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 19:24:58 2008 -0500
-
- Add Array.pack for i, s and l arguments.
-
-commit 7131e187e19bf0889f8ece802495865f7b3f1e5c
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sat Jan 12 13:55:20 2008 -0800
-
- Cleanup String#split, add edge case check
-
-commit 4ff46602c8a54a61697bb8d9eaa9ae89e56f7abe
-Merge: 1c95721... 908ccff...
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 14:49:48 2008 -0500
-
- Merge branch 'socketspecs'
-
-commit 908ccff0a854038372dad0780e1de35727e2d657
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 14:49:17 2008 -0500
-
- Some TCPSocket spec mods
-
-commit 1c95721bd873c4b30c187bfa7673cd7e3568a0fb
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 10:20:43 2008 -0800
-
- Fixed File::Stat specs to output method name correctly with -f s.
-
-commit acb7505d41aa789157e50962253e686827a702d5
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sun Jan 13 12:07:06 2008 -0600
-
- update CI excludes
-
-commit c8db419ae06e9642b346e1bcae99367f3b72845f
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sun Jan 13 11:55:50 2008 -0600
-
- squash bug in Marshal.dump
-
- symbols need a separate links hash
-
-commit eb953ae2c3fdeac4ae13b5461246b9f51b0f39cc
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 09:40:39 2008 -0500
-
- Make the spec text more verbose
-
-commit db013bc06cef2dea4b77a215d4437e2172b391b6
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Sun Jan 13 09:04:08 2008 -0500
-
- Commit an updated spec that shows the failure on rbx and passes MRI,
- w.r.t. opening a module and aliasing a private module function from that
- module.
-
-commit 759a9f8bd70ead9b5d2fc67b3872e3bf3bd34001
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 01:45:07 2008 -0800
-
- Updated CI excludes for File::Stat.
-
-commit 107feb74eaf01c09d8c5bd14ac29e53900a5ed26
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 13 00:38:00 2008 -0800
-
- Modified File, File::Stat, FileTest specs.
-
- * Added templates for File::Stat specs.
- * Added shared specs for some File::Stat methods.
- * Altered toplevel File shared specs to take the name
- of the constant to enable File::Stat to use a fixture
- proxy but still have the correct name show with -f s.
- * Split out specs for missing files because File.[l]stat
- behaves differently than e.g. File.file?.
-
-commit e1a13f7ecfe7f2d18fd6ac20dd8c63cbd6d11855
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sun Jan 13 02:26:09 2008 -0600
-
- implement more of Marshal.dump
-
- obj.marshal_dump, IO.write, depth limit, exceptions
-
-commit bc070232eab1bfa5d294897487339d259a406e74
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sat Jan 12 15:16:21 2008 -0600
-
- implement more of Marshal.dump
-
- Float, obj._dump
-
-commit ad7a67ed5a3a1399773dda74c4688e9b00c8f9aa
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 13 01:46:36 2008 +0800
-
- Update CI excludes for Process.initgroups
-
- * It was affected earlier by the Enumerable lambda/Proc-arity issue
-
-commit 7b7a1e3e4712f35688823543b7a7c3c25405ef77
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 13 01:40:22 2008 +0800
-
- Fix implicit block in Enumerable not passing the arg check in Proc#call
-
- * Changed instances of lambda to Proc.new and arity once again
- returned the correct value. Will investigate, but until then, this
- passes.
-
-commit d9c21aaa18044bd54ed3b1f6ec5daacf9bd250fa
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 13 01:02:00 2008 +0800
-
- WIP Fix block argument checking
-
- * Passes all the proc/lambda call specs
- * However, specs for methods that add implicit blocks like
- Enumerable#all fail because their arity is somehow 0 - excluded for now
-
-commit 3d400bc8a91a793f49dcf5655dc28e6141d999d0
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 12 20:03:26 2008 +0800
-
- Update CI excludes and add Module#class_variable_get to critical.txt
-
-commit 6bf7b8616837649ddd2c1435a54c86ed30910985
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 12 19:27:12 2008 +0800
-
- Move custom classes for NoMethodError specs into fixtures
-
-commit 10cc61bb816ae67a7fad5b135f66d263d7ee07b1
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 12 19:20:27 2008 +0800
-
- Swap the protected/private method calls around in the NoMethodError spec
-
-commit 6b2e66d3f9222b52cdae42b57206363ad47949e2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sat Jan 12 11:51:28 2008 +0100
-
- Corrected Module#alias_method spec.
-
- Now it should pass on both MRI and JRuby.
-
-commit 67f74a936655b72c689d09c77d9fbe9d7194a0a0
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sat Jan 12 17:50:22 2008 +0800
-
- Fix proc/lambda/Proc.new arity
-
-commit 03440114d5e3f07111cdcae3657258cae4c803e7
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 11 13:24:26 2008 +0800
-
- Fix Kernel.Integer parsing of invalid String
-
-commit 598598c10c66de38b52a8092cdd2fa99604eda6e
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Sat Jan 12 00:21:22 2008 -0800
-
- Clean up expectations to use a common list.
-
- Update excludes for other things using shared glob specs.
-
-commit 55aa5a1f10655618e45d0ec84502cc13c982227e
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 11 23:31:45 2008 -0800
-
- Specs for File.fnmatch handling of Regexp specials.
-
-commit 7c0dc7edfcdf4948047ba051b0cbed7ba761f1dc
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 11 21:57:10 2008 -0800
-
- Dir.glob support for {}.
-
-commit 9a097fe5634c1109919d1e120b1276827371c332
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 11 19:42:31 2008 -0800
-
- Exclude {} specs for WIP Dir.glob
-
-commit ccdc6f5ae5fabbd0d2c32072811e2ecf7cca8987
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Fri Jan 11 21:40:04 2008 -0500
-
- In MRI, you can alias private module methods. Not so here. This spec catches it.
-
-commit 8b402d1e32dc283124375374532024f6cfe7020d
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 11 17:35:21 2008 -0800
-
- Added toplevel shared specs. Converted File, FileTest specs.
-
- * spec/ruby/1.8/shared is the directory for sharing
- specs across multiple classes.
- * Added methods for FileTest
-
-commit c6aea2e10d7a4d0ee14175d5b79894e1e11699b1
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 11 15:59:34 2008 -0800
-
- Converted File/FileTest#exist(s)? to toplevel shared specs.
-
-commit 06a5d8a3d5874303a71e4e9b939b44c204041edf
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Fri Jan 11 17:39:39 2008 -0500
-
- Fix failing specs in udpsocket/open_spec.rb
-
-commit 530e40005d09140fdb55608890f0994f3a48d8be
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Fri Jan 11 13:11:58 2008 -0500
-
- Observer specs
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 0907a20d2bad2207be8e937c403c49634f3a23b6
-Author: Caleb Tennis <caleb@tarknology.com>
-Date: Fri Jan 11 12:24:44 2008 -0500
-
- Add observer to lib and base-spec file
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit ec0ff1dfa1ee9de38d35537bec5071f6bb31cf7f
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Fri Jan 11 13:11:02 2008 -0600
-
- implement more of Marshal.dump
-
- Array, Hash, links
-
-commit 640e81394ad2385b535b08b535a4fca06a5f3eec
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 11 10:24:54 2008 -0800
-
- Added CI exclude for failing MD5#== spec.
-
-commit 3c238cc9f4b32f63bc681bd64a507fc2ff49b017
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 11 10:00:50 2008 -0800
-
- Converted Socket specs to use subdirs for subclasses.
-
-commit 2b98950eaa33b532fcef079b0997f9793228c608
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Jan 11 09:23:23 2008 -0500
-
- Specs and implementation for IO#print. Closes #222.
-
- * IO#print without arguments spec excluded due to a lack of a lower
- level output matcher. To be added shortly.
-
-commit d65c8c6899cf8e4a1fa56486cf417451e0c7fce6
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Fri Jan 11 19:19:56 2008 +0100
-
- Fix String#* spec.
-
-commit 481e075bfeb9f8fb3bd4db645129a463307de09e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 11 17:41:07 2008 +0100
-
- Improved digest/md5 specs a bit, some new test cases.
-
-commit 67f48236da3d114638310ab37bcc706719bf7fcd
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 11 11:59:06 2008 +0800
-
- Updated Method's specs as Method#inspect and #to_s deviates on Rubinius
-
-commit 76846154773a87bc8d99c97e91250abda22f6378
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 10 19:24:57 2008 -0800
-
- A bunch of fixes found while working on Socket
-
-commit f69613740662d3ba4f85573c6c860a5987b29765
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Fri Jan 11 00:17:14 2008 +0100
-
- Fixed Time object for throwing errors where appropriate
-
-commit 9396386f700646d0c55b9a7a75bc399dfe055d2c
-Merge: baae72c... 4d2e53e...
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 10 22:39:24 2008 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit baae72cc47c9c1f41c3478732b7bbfdfe514024a
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 10 22:39:11 2008 +0100
-
- Fixed Time#xmlschema conversion
-
-commit 4d2e53e7376080e42b84dca486debcf4f153f32f
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Thu Jan 10 15:17:00 2008 -0600
-
- implement more of Marshal.dump
-
- negative Fixnum, Bignum, Regexp, Struct
-
-commit abdbcd70bba99149b7391effa48452971407b4d2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 13:18:52 2008 -0800
-
- Annotate Rubinius spec as non compliant.
-
-commit 2a2b3a016bfd70eb8cd14b6a043d59f119e0ad7c
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Jan 10 21:52:18 2008 +0100
-
- Re-added divmod specs for Ruby/JRuby, with comments.
-
-commit 2f079e416e4389b091c8c9b5522d49c6f356c6c9
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 12:29:39 2008 -0800
-
- Updated Bignum#divmod specs.
-
-commit 7a5c79415f2e6555bf2c69e416f6d3189f2e0c3e
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 10:46:05 2008 -0800
-
- Simplify wording of VM.coerce_to_array specs.
-
-commit abc1237a0c96ecd77baee6ecbcf71a7bba338139
-Author: Ryan T Mulligan <ryan@ryantm.com>
-Date: Thu Jan 10 12:35:23 2008 -0600
-
- md5 is now fully 1.8.6 MRI compatible
-
- * MD5 digest specs
- * Specs pass on MRI and RBX
- * Platform::POSIX.memcpy hooked
-
-commit 9f991bd850c51cd624169b51768c2215d4b56edb
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 11 01:35:15 2008 +0800
-
- Method#bind raises TypeError when binding a method from a non-descendant
-
-commit fc029ab13ded7eeb1ba838b99f00e2f14e232d65
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 11 00:12:44 2008 +0800
-
- Implement that Precision.induced_from raises TypeError in certain cases
-
- * For case when mixer class doesn't define it's own induced_from method
- * Update CI exclude for precision
-
-commit 35d1a7bc3694bdcc327dd5ac89ca0f261e0bd705
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Jan 10 16:57:38 2008 +0100
-
- Added one more Bignum#divmod testcase, known to fail on some implementations.
-
- In fact, this test case fails on Rubinius and JRuby.
-
-commit 955676613f5e38cf029998e2712013e4575dd03e
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 10 16:12:37 2008 +0100
-
- Changed spec failing on MRI
-
-commit f7b4f3fe02833081cc7f40c0feebbef0e5012f10
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 10 15:58:23 2008 +0100
-
- Fixed Float#divmod
-
-commit aff6e1fc1a16eb9e7b7e207ebc2234154d891a92
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Jan 10 22:53:25 2008 +0800
-
- Converted VM specs
-
-commit 969c0d8e0dbf43caa3999976cf259c623ff05ff1
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Jan 10 22:50:17 2008 +0800
-
- Convert Options specs
-
-commit cc7c9dcb6697dea991342328a9b00fa01740e809
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Jan 10 22:28:42 2008 +0800
-
- Replace example blocks using 'specify' with 'it'
-
-commit 7a5fa30a71072346abda17cdb79c2aa3b3922239
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Thu Jan 10 15:27:49 2008 +0100
-
- Fixed Bignum#quo
-
-commit f2aafe4a352fd884d217b0361d2e7e617f58ebd5
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Jan 10 20:38:45 2008 +0800
-
- Converted Generator specs and generated new CI exclude files for it
-
-commit edb7e341d9b3ab1c3bdc08bc57ec55d6bf8ace8b
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Thu Jan 10 19:33:53 2008 +0800
-
- Remove generator_spec.rb because of spec conversion
-
-commit bb4de530c5980f0205875bdb5548e40a22ef6a62
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 01:45:47 2008 -0800
-
- Updated CI excludes for library because of spec conversions.
-
-commit 61a66f69fe3a94d9ad5568ee2dd846cfc0b5211a
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 01:45:17 2008 -0800
-
- Converted Socket specs.
-
-commit 167e05039eeeeb959f7aab1f3611268170037296
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 00:59:20 2008 -0800
-
- Converted YAML specs and added template files for other methods.
-
-commit 027f568f79222cdee492f088edf8a2f14250635a
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 00:47:35 2008 -0800
-
- Converted ostruct specs and added template files for other methods.
-
-commit e964c9342ade9341518bc46cf998703a2c16aa2b
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 00:39:49 2008 -0800
-
- Converted ftools specs.
-
-commit 6263280187c81b0ee27893eae90f9d6a8a511b65
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 00:26:40 2008 -0800
-
- Converted Etc specs.
-
-commit 7b94284063222eef42b9b7ad0d1c820adabe210d
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 10 00:39:01 2008 -0800
-
- Fix a few more Kernel bugs
-
-commit 1c58ee51f388da0490a7815c9a1787d21e151aab
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 10 00:08:15 2008 -0800
-
- Fixed path for mock dirs in Dir specs.
-
-commit 320f7e7d3503d53216733f9b6eb75c387155ae5f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 9 22:44:37 2008 -0800
-
- Converted StringIO and Singleton specs.
-
-commit 5a94a7c3b73103c99a337a089f9cf2c7e601d2bc
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 9 21:50:14 2008 -0800
-
- Converted stdlib Singleton specs.
-
-commit 12864a2057d1b6f5fa392f34d1fa3e8873a8c566
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Dec 24 23:06:12 2007 +1100
-
- Initial commit of Rubinius Debugger
-
- * Created Debugger class for debugging Ruby code in Rubinius
- * Added Kernel#debugger convenience method to set a breakpoint
- and activate the debugger at the point at which the
- debugger statement is encountered.
- * Implemented the following debug commands:
- - h: get a listing of commands
- - b: list breakpoints
- - b <Method>: set a breakpoint at the start of the method
- - n: Step to the next line
- - ni: step to the next VM instruction
- - c: continue execution until the next breakpoint
- - l: list source code around the current breakpoint
- - d: decode VM bytecode around the current breakpoint
- - v: display local variables and their values
- - vs: display the contents of the VM stack
- - Anything else is evaluated as a Ruby expression in the
- context of the current breakpoint (so you can, e.g. change
- the value of locals before resuming, etc)
-
-commit 01a189cc3e52e8bcc6f22bcc5713e765bba84160
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 9 10:29:27 2008 -0500
-
- Object#is_a?, #kind_of? and #instance_of? specs.
-
- * Removed obsolete kernel specs for same.
-
-commit ab9645614bbbd0bca63c215819c12cc85a1507b1
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 9 21:35:39 2008 -0800
-
- Converted specs for stdlib Time.
-
-commit 733b069f11c7136175036154a45b924cf89cc8ff
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Wed Jan 9 20:01:09 2008 -0600
-
- update CI excludes
-
-commit 01e98dee4c24838ca518610443e43473ffdcf43c
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Wed Jan 9 16:42:07 2008 -0800
-
- Fixed block args for |*a|
-
-commit dc9c1d05dd5e0e828a77acc09220f5894a9aa453
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 9 16:04:11 2008 -0800
-
- Fixed Enumerator spec style. Updated YAML excludes.
-
-commit 0363685a97df83feb0d07f40a7a5c4d7a78e2a27
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 9 14:55:53 2008 -0800
-
- Spec for String#sub bug.
-
-commit 23052eb5f993c959fdb2b327895df08e0a344edb
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 8 23:47:27 2008 -0800
-
- Implement { } matching for Dir.glob
-
-commit c90b2531d183e4534268d4699634828f29e803cb
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 8 23:44:35 2008 -0800
-
- Spec File::Stat#blksize.
-
-commit 62d2a1809936a304c0cf0b94fd28f5b83932f58f
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 8 22:47:37 2008 -0800
-
- Implement Dir.glob '{a,b}'
-
-commit d9430ad1a3e582e830a994a83d6f99e017bfbe4d
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Jan 8 20:56:37 2008 -0800
-
- Fix module X::Y; end; X::Y.name
-
-commit 1baa9468e0d89777fdb6f23e78e8ab510a19d534
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Wed Jan 9 16:16:35 2008 -0600
-
- incomplete Marshal.dump
-
- an evil ivar_as_index is added to Object to hold
- the names of modules that extend the object
-
-commit 85e98490fe45446e03801840d4628149f8977098
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Jan 9 12:26:19 2008 -0800
-
- Move compiler2 => compiler, and Compiler2 => Compiler
-
-commit 5aa5cc66e2b0196728c80eb394ec3b2dfccd77ae
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 9 10:30:42 2008 -0500
-
- Centralised specs for Object#=~.
-
-commit e1fe9f57c942460338a18e38f66fbf6feb69b4bc
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 9 13:23:59 2008 +0100
-
- Added few edge cases to Numeric#eql? tests.
-
-commit b8dfd675fad5e82ebfd50c737beb9a9b919a9c8b
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Jan 9 15:52:18 2008 +0800
-
- Remove excludes for String#slice with the fixed send in place
-
-commit d7f69f17ac30f6b3161851e8df6a1e0a7694219d
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 8 22:42:43 2008 -0800
-
- A couple more fixups
-
-commit 055d7545c7046102cd92b7054992b1b47f711c4a
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 8 22:31:50 2008 -0800
-
- A boatload of fixes done while getting flexmock and rake running
-
-commit fd7c266e52c25d151214512cc801901813630d7a
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Jan 9 11:49:02 2008 +0800
-
- Removed last array exclude due to fix in 02e6e28
-
-commit 690626f43f7b4ce888de081033eaadfba543acff
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 8 18:58:50 2008 -0800
-
- Removed subtend specs from CI run. Increase File#mtime tolerance.
-
-commit dec4f25a47a9a962b77a97dea47985fe17421e5f
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 9 13:39:51 2008 +1100
-
- Specs for stack usage
-
-commit d699f6605db86e6f6bc61d0f3a79fc1535816c70
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Wed Jan 9 10:38:06 2008 +0800
-
- Add spec to illustrate Numeric#divmod bug in MRI and rubinius (excluded)
-
-commit 8a55f3047dc0fd502bb632dc9f5bdb9668b180fe
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 8 18:32:18 2008 -0800
-
- Subtend CI exclude to (hopefully) fix the build server runs.
-
-commit 33bde75b57a88baa850edccea382e1130ed586da
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 8 17:19:30 2008 -0800
-
- Added spec/compiler2 to CI. Added CI excludes for compiler2.
-
-commit 6964fc5644fddeef2238591674786f035d9db842
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 8 17:19:20 2008 -0800
-
- Fixed up against evan's changes. ping
-
-commit 9423d1e8e9ed91fb9f0934b939899c753972cee1
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue Jan 8 20:11:54 2008 -0500
-
- Fix warnings encountered when running compiler2 specs under MRI
-
-commit d71ad87c14a4378ad2f01c49d90304c29be548f3
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jan 8 17:02:02 2008 -0800
-
- Fix a block_arg bytecode generation case
-
-commit 57199b5b468c0009512a479e13bbcf086d0d9526
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 8 16:16:07 2008 -0800
-
- Added new combo bytecode/runtime tests for block args
-
-commit 8a88699af73d272a61332e11d022bd629aa0460d
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Tue Jan 8 16:15:24 2008 -0800
-
- Improved inspect output for compiler spec objects. Added convencience methods for testing iter bytecode generation.
-
-commit 0dd9cd298cf735dc13cc2a2410ad6b5195790c11
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 8 13:19:21 2008 -0800
-
- Added subtend specs to CI. Updated subtend excludes.
-
-commit c07a5273844b32fe39090bb16d0e4ad59ecb0564
-Author: Dirkjan Bussink <d.bussink@gmail.com>
-Date: Tue Jan 8 21:28:48 2008 +0100
-
- Fixed given_spec? because of changed block_given? behavior
-
-commit 0f9a8dfee9dd1c7af1f8ba69497c8dd85539760a
-Author: Nitay <nitay@powerset.com>
-Date: Tue Jan 8 11:49:41 2008 -0800
-
- Fix setpgid spec using pipes to avoid race condition
-
-commit 09feb8677c529d04969e63d1ff4e3746037611cf
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 8 10:00:06 2008 -0800
-
- CI excludes for ruby/1.8/library.
-
-commit cda3d86fa44f1d62fe503e54f42c5c5df361b8f9
-Author: Benjamin Andresen <bandresen@gmail.com>
-Date: Tue Jan 8 08:22:49 2008 +0100
-
- Added explicit umask to File permission spec so it won't fail on
- non-standard umasks.
-
-commit 6df303e29d7fd04f4a1a0af379f4947854dd4635
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Mon Jan 7 23:20:22 2008 -0500
-
- Method#== and specs from Scott Taylor, slightly tweaked. Closes #137.
-
-commit 9b86b12be687bb29e25d0292786351d89a698adc
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 7 19:45:24 2008 -0800
-
- Added CI exclude for Array#pack.
-
-commit 17a746b0aa2c89aa9e61b8965d125e962748c20d
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Mon Jan 7 21:07:25 2008 -0600
-
- adds Marshal.dump and Float#to_s specs
-
-commit d5c19db2778e0cc3cbee5bf994b511448cb6bd78
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Mon Jan 7 15:31:11 2008 -0800
-
- Fix IO#pos=
-
-commit 21f44f03f0aa44b2f172f89ad27797c943dc618b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 7 22:03:28 2008 +0100
-
- Remove non-needed std output from Array#pack test.
-
-commit 9ec20509ad6533876bbbc984052e6b7e05d2ea55
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 7 21:50:46 2008 +0100
-
- Added Array#pack tests with empty array.
-
-commit 35170103bdba14d824780a41112f12034cb5c79e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 7 21:13:47 2008 +0100
-
- Added Array#pack tests with 'w' pattern.
-
-commit 71b00e03ce2c6424fd262d737feb991835605da2
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Jan 7 20:46:58 2008 +0100
-
- Added Array#pack('U') test with negative values.
-
-commit 7be0813127635ea54909179c9553c5052c4a3d90
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 7 18:00:03 2008 +0800
-
- Add specs for Array.[]
-
-commit 0b762336e8c6040cbbe794cece64c56bfa46c296
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sun Jan 6 23:35:35 2008 -0800
-
- Fix breakages, comment out at_exit spec (need a better way to test)
-
-commit 8896e459f1bffb7ae2da2f2aa708419e6316cb4b
-Author: Matijs van Zuijlen <Matijs.van.Zuijlen@xs4all.nl>
-Date: Mon Jan 7 14:03:03 2008 +0900
-
- Spec to demo failure of cases like "yield 1, *[1, 2]"
-
-commit 79da85bb1b1d63e617251b3a3ea6b0657c1e8ddb
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Mon Jan 7 13:04:22 2008 +1100
-
- Modified CompiledMethod#decode to use #local_names
-
- * CompiledMethod#decode now leverages new #local_names
- method to return the names of locals accessed via
- push_local/set_local etc.
- * Removed excludes, as all decode specs now pass
-
-commit 89c1026cecbb9fcd09a62139e2d28b24b5658c25
-Author: David Whittington <djwhitt@gmail.com>
-Date: Mon Jan 7 01:37:10 2008 +0000
-
- Added args to NoMethodError raised by Object.method_missing
-
-commit 0e4a02f0e2fede5d785b15a6b34c582c6ba586f1
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Sun Jan 6 12:43:14 2008 -0800
-
- Removed redundant Bignum#to_s. Moved private radix_to_s to bottom. Cleaned up to_s spec a bit
-
-commit 48446c40a759d60b7465d82b40f2911d0f7e444b
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sun Jan 6 13:45:22 2008 -0600
-
- Add some additional Math.asinh specs from JRuby.
-
-commit 7c81ca307cd01d3752a08487bc3742c8452d61c4
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Mon Jan 7 00:41:10 2008 +0800
-
- Add failing specs for Time.{local|mktime|utc|gm}
-
-commit 35816e118b327a150a2d26638f289633f5e51f16
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 6 17:56:23 2008 +0800
-
- Add spec for Time.local to handle string arguments (excluded for now)
-
-commit f9f36f5bb99ddb62e15cb9a9ddd98414e3df93e2
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Sat Jan 5 23:44:33 2008 -0800
-
- Allow Regexp to match nil.
-
-commit e650c39627b81498fc97c51725f2ac1277870e15
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Sat Jan 5 23:38:52 2008 -0800
-
- Add some IO#read specs
-
-commit 20257ecce0d3161fae7ac78454f2b8672f2c1de3
-Merge: bc576b8... e549cc5...
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 6 14:45:13 2008 +0800
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit bc576b8e26fdb43d050df4fe3ad5ed974ec85057
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Sun Jan 6 14:44:44 2008 +0800
-
- Fix handling of string-like second parameter to Time.local
-
-commit e549cc53a4905f21082a97cd6bcb279ace6d9eae
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Sat Jan 5 22:31:42 2008 -0800
-
- Don't shift more bytes than available in the Buffer.
-
-commit 71285a2a9a8d0d3e71c678872ff2a146d5b2dc16
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Sat Jan 5 22:53:51 2008 -0500
-
- Fixup the Process specs for setpgrp, getpgrp, setpgid, and getpgid.
-
- They no longer may unwarranted assumptions about the relationship
- between a progress group ids and process ids.
-
-commit 7b57b3ac6df612f81d60d3a31b030ba054b357a6
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 5 13:22:51 2008 -0800
-
- Patch from Brandon Mitchell for #195, Float#to_s bug.
-
-commit 70ddfd43fd727122f56e8bdfcf3febd1ac1b5479
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 4 01:01:11 2008 +0800
-
- Fix for Time#yday spec when Time.at might return yday+1 depending on tz
-
- * Wrapped Time.at in a with_timezone("UTC") for consistent results
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 7d4396e4e69fb7b046efdaaf87d1090a02c883a0
-Author: Kamal Fariz Mahyuddin <kamal.fariz@gmail.com>
-Date: Fri Jan 4 02:26:38 2008 +0800
-
- Fixed Array#fill behavior when passed index and negative count
-
- * Added additional spec when negative count is acceptable
- * raise ArgumentError when negative count absolute value exceeds index
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 8af2b55313eb55082df6a71cd3e6bd865f2901fc
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Jan 5 13:33:26 2008 -0600
-
- Save mtime during file creation to make mtime spec more reliable.
-
-commit 7043933af0475370462984c8d2df2b9301e58cfa
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 5 00:45:01 2008 -0800
-
- Updated CI excludes after spec description changes.
-
-commit 3d7650100ba1756a4d67be8044e31498ea96d88e
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 4 21:13:28 2008 -0800
-
- Multitudinous style cleanups in spec description strings.
-
-commit d54ed8791a74661adb87c938e92e037ece924c90
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sat Jan 5 00:29:22 2008 -0800
-
- A real, working eval and friends.
-
- * Implements binding, eval, etc.
- * Passes all eval and instance_eval specs currently
-
-commit 02ad19ab4132bf5d3ae35c2e11fa1a963d1f1805
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Jan 4 00:25:39 2008 -0800
-
- Fix a few more String specs, fix Integer()
-
-commit d67cfbcf4e7d35641de555ac1edd61b51780def8
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 4 19:16:43 2008 -0800
-
- Make class variables work with inheritance.
-
- Move class_variable* to Module.
-
-commit d79836e04d72796b723cdaab228871c87abe064a
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 4 16:26:21 2008 -0800
-
- Replace Struct with a Struct that can be subclassed
-
-commit 8efb042a9c160af9e9c177ca14aed220dedcc26f
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Fri Jan 4 15:41:43 2008 -0800
-
- Finished |*args| spec. Fixed MethodDescription and TestGenerator inspect methods
-
-commit 76cc487434f6cd9d60356560f1bbc3fba000397c
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Thu Jan 3 16:54:56 2008 -0800
-
- Fuck you git. Adds a broken spec to compiler2/masgn for splatted goalpost arg
-
-commit dd2697b602a732e3e00c131f54f9cc557ae0cbe3
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Fri Jan 4 15:40:50 2008 -0800
-
- Failing spec for case when with an empty body
-
-commit 22dcedebd484f655bba51399e38e83c5a14d4053
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Jan 4 18:31:48 2008 +0100
-
- Added Time#local specs with string-like second arg.
-
-commit 43ff733a3097fff44ba8a12334f20a1bf77a965f
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Jan 3 23:54:34 2008 +1100
-
- CompiledMethod#decode now uses local variable names (if avail)
-
- * CompiledMethod#decode now looks in the bonus tuple for the names
- of stack and slot local variables
- * Moved compiledmethod specs to spec/core/compiledmethod
-
- Note: Compiler2 appears not to be setting the bonus tuple, so code
- compiled under it cannot decode local names at present.
-
-commit 06006ec2a053ae49b243fa0aa98fc71c2ea7a524
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 4 01:24:49 2008 -0800
-
- Updated CI excludes.
-
-commit dff2e75df3c371522b6a3ba4495d269bf793fe97
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 4 01:01:24 2008 -0800
-
- Updated CI excludes for Bignum.
-
-commit 569fa3b9fc81410ce9fe6568427f0a0bc65b7036
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 3 19:26:22 2008 -0800
-
- Updated CI excludes for String, Regexp.
-
-commit 7aedec383850eacad5db8248bfcea7615a3d1793
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 3 17:48:32 2008 -0800
-
- Fix up setrlimit/getrlimit on darwin
-
-commit d9aea8bba7276b53ca7c18b8625531be389d2cdc
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 3 16:40:09 2008 -0800
-
- Refactor $~ out as a global, into Regexp.last_match directly
-
- * Uses MethodContext to store $~ now, so it's method local.
-
-commit c19dde305fd751c14a1b4dc798557e0b63c08c8d
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 3 16:25:54 2008 -0800
-
- Clean up compiler2 specs
-
- * For is still broken, needs more love
-
-commit d02603a7e225d3b48ecf7899ea74768880aba7ec
-Author: Gregor Schmidt <ruby@schmidtwisser.de>
-Date: Wed Dec 12 16:56:11 2007 +0100
-
- Add default implementation of Module#method_added
-
-commit 7ba5d1478106e4e0f5fcf21c66029df2f38d7e2f
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Sun Dec 30 17:55:21 2007 -0500
-
- Unquarantine Process.kill specs.
-
-commit d68b380bdd2e0a0ec3bd968ffabd02f6e30a3aa1
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Tue Jan 1 22:14:59 2008 -0500
-
- Improve kill, wait, detach, and setpriority specs for Process.
-
- Restore any previously installed signal handler after the spec has run.
-
- User IO.read(1) instead of IO.getc since rubinius has it implemented.
-
- Fix a failing Process.detach spec uncovered by the raise_error fix.
-
-commit da7329d094b6ff437d37e6a1fcaf93883ac9172f
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Mon Dec 31 16:23:24 2007 -0500
-
- Add specs for Process.setrlimit, Process.getrlimit, and Process.setsid.
-
-commit 42bef2feb46434b0ea67bc3f93d941d587c2d9c9
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 3 12:46:57 2008 -0800
-
- Updated Process spec excludes.
-
-commit ca98172b8a923cce1691b0fcc5d2418417d82662
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 3 10:07:55 2008 -0800
-
- Update CI excludes for IO from Evan's fixes.
-
-commit cde20d6c32156e4fc06859f1e84414f81f5af69e
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Jan 2 23:40:59 2008 -0500
-
- Fixed #require specs.
-
-commit 06d99a2ac4be06b50848056b381c91531293a49e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Jan 3 01:12:29 2008 -0800
-
- Add read buffering to IO, passes 100% of IO specs
-
-commit 86170283715371b5a87c0518f89c2b882a49bc93
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Jan 3 01:21:52 2008 -0600
-
- Fix off-by-one on a few signal values. Doh!
-
-commit c7a64b10410308cec83077a66cda5859b326f296
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Jan 3 01:13:27 2008 -0600
-
- Modify Signal.list spec to not depend on hash ordering.
-
-commit f2980d9584c08d873cf1646c281d083946bcbc6c
-Author: Nitay <nitay@powerset.com>
-Date: Wed Jan 2 14:36:56 2008 -0800
-
- Module#autoload:
- * raises a NameError when an invalid constant name is given
- * raises an ArgumentError when an empty filename is given
- * does not autoload when the specified constant was already set
- * registers the given filename to be loaded the first time that the Module
- with the given name is accessed
-
-commit e68bd05defe5ab749110af507c86769c9a036b25
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Wed Jan 2 19:04:48 2008 -0600
-
- Removing 'Range#initialize can't be called twice' spec.
-
- Evan agreed that these specs aren't useful, and I don't believe they're
- within the bounds of reasonable language specification since they're
- going around visibility and testing behaviors no sane programmer would
- ever be able to see.
-
-commit 1870720bac174feb627654f08c1749e1666c2acc
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Wed Jan 2 18:54:33 2008 -0600
-
- Fix inspect spec to guarantee the target thread is actually sleeping.
-
- A reminder for folks adding Thread specs: You *CAN NOT* know that a target
- thread is sleeping unless you are polling for status == 'sleep'. No amount
- of channel, lock, or state variable tricks will get around that. Please
- use polling if you want to guarantee a target thread is asleep.
-
-commit df3057a541862bbd1c5c72b8626bb591bb5ae6fd
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 2 16:39:37 2008 -0800
-
- Refactor Module#undef_method spec to #respond_to? and #instance_methods.
-
- Now only method dispatch is tested for #undef_method. #respond_to? and
-
-commit d2ecd4119a152370210ccb6c2a816c9dccb9fe90
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 2 16:00:09 2008 -0800
-
- Fix Rails indenting and whitespace
-
-commit f5b8afee4931bd09b0ce9fb88fc959c2ea0a1743
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 2 15:30:41 2008 -0800
-
- Fix Module#undef_method and Module#instance_methods
-
-commit 82bf31562361a21f85a90d5628a40ff50280c555
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 2 14:10:35 2008 -0800
-
- Rebuild excludes for #eof?
-
-commit b2aa0d56b04d7da5d333ba1449acda7c0b64c0c4
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Wed Jan 2 14:09:21 2008 -0800
-
- Add IO#eof? spec.
-
-commit addeb47d834d1ce60f8146f747defacf1682e6c4
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 2 22:31:30 2008 +0100
-
- Removed JRuby spec excludes.
-
- The JRuby excludes will reside in JRuby repository.
-
-commit 3239661ed5c38b37c966588341a043d6cdd9445b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Jan 2 21:28:11 2008 +0100
-
- Corrected String#modulo tests after clarifications from ruby-core.
-
-commit a0f3ba6632f8486e8f07a21a8e4720d8727ba4d2
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 2 11:28:42 2008 -0800
-
- Fix require_spec_recursive on Ubuntu.
-
-commit 857c39564df2d8da480f549fff46ec3ab880066e
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 2 00:48:53 2008 -0800
-
- A couple fixes. Updated CI excludes for last couple failures.
-
-commit 58c48ed05b493c71ee445062f27d47909e18b395
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 1 23:49:14 2008 -0800
-
- Updated CI excludes.
-
-commit 426f5a15eaac05ed1e900433837de0b9d0246c8d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 1 22:43:47 2008 -0800
-
- Moved CI excludes files from .spec dirs to spec/data/*.
-
-commit a1d6211f3185f23cbc2c929f0352feca05fd079c
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 1 22:03:43 2008 -0800
-
- Moved ruby specs to spec/ruby/1.8/...
-
-commit af55eefd29c8acaf462efe03d2e0b3d95195cb21
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 1 21:44:35 2008 -0800
-
- Updates for bin/ci and bin/mspec.
-
- * Removed -2 switch from both because compiler 2 is default.
- * Added CI_EXCLUDES_DIR and -E switch to bin/ci to allow for
- specifying the exclude directories. The default is '.spec'
- in each directory containing spec files. Use a path starting
- with a '/' to create the exclude directories relative to
- that path, otherwise the exclude directories are created
- relative to the directories containing the spec files.
- * Moved spec/excludes.txt to spec/data/critical.txt
-
-commit 0e6645eb74f1f63b84f674dbcdfa991153a3ccd0
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Jan 2 12:10:39 2008 +1100
-
- Couple of Breakpoint changes
-
- * Raise ArgumentError if no block given (spec for this
- existed, but was masked by RaiseErrorMatcher bug)
- * Added line property to Breakpoint
-
-commit 36a7acddfe74ab25895d13dd775741b042ba3b0c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Jan 1 23:10:13 2008 +1100
-
- Reorganise breakpoint specs to new dir layout
-
-commit 8aa6712dd9e5e870194f77ff74dc8cf11c273805
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Dec 21 16:15:19 2007 +1100
-
- Refactored BreakpointTracker in preparation for debugger
-
- * Moved code from debugger.rb to breakpoint.rb
- * Refactored code extensively to support debugger
- * Added breakpoint specs
-
-commit d16e905a67d64f67d7a24ce113f39b4b059c4139
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 31 17:51:59 2007 -0800
-
- Removed the rubinius dir from specs. It was redundant.
-
-commit 85ed07b6d739f013892a6cbcae5d0bb2c19f6e80
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 29 15:45:31 2007 -0800
-
- Split Ruby specs proper from Rubinius specs.
-
-commit b8e1466dc1b814bfb2022c1e4319d5ba63f5d762
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 29 15:02:55 2007 -0800
-
- Updated guards in specs.
-
- * Changed guard names to new, more descriptive names.
- * Removed all #extended_on guards for Rubinius-only specs.
-
-commit 5773ebe9e6f78abec9bfb03f144b5c7a86a27c7e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 29 00:50:56 2007 -0800
-
- Changed Float constants specs to compare against precise values.
-
-commit 71874fcdc9eaf45a5adecf57d7609831a2a8e6c2
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Dec 29 17:26:06 2007 -0600
-
- Fix dump_spec to expect 1 or more write calls, rather than exactly 1.
-
-commit d4bfb39910aa4adf2c0c4e2dee214487bac34093
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Dec 29 14:51:38 2007 -0600
-
- Add a spec for procs being block-passed and some peculiarities therein.
-
-commit 1b0333479bf6da2c76c8d3c1e1640dc156086d9f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Dec 28 08:24:30 2007 +0100
-
- Improved ObjectSpace#each_object spec test.
-
- Previously, the test was failing from time to time,
- depending on Garbage Collector behavior.
-
-commit 3d7e628acc6699f9652383317bd416d8c75329d5
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Fri Dec 28 05:27:24 2007 +0100
-
- Updated Time specs to use new :os guard.
-
- The Time specs use this :os guard to properly detect
- which external program with proper parameters to invoke.
-
-commit 7662638e9afa631f0581fc1c2b2b422b1b926f98
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sat Dec 29 03:06:51 2007 -0600
-
- adds Marshal.dump specs
-
- for nil, true, false, String, Symbol, Fixnum, Bignum
-
-commit 93431a28d687372b95f1a1420a3bd1f24e660117
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Dec 29 00:15:44 2007 -0600
-
- Guard Continuation specs to not run on JRuby (JRuby does not, will not support continuations)
-
-commit ccf745b9eafe068de6f888de24387bc0a0e68859
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Sat Dec 29 00:08:04 2007 -0600
-
- Fix for Fixnum size spec to guard "java" platform with 8 byte size
-
-commit 6f448f0dd72b5df2cc69e28db3d5593f897a9dbd
-Author: MenTaLguY <mental@rydia.net>
-Date: Sat Dec 29 00:58:58 2007 -0500
-
- a more modest spec for Thread.pass
-
-commit b32c2d95d044a4979ab92b5881e32fc8b169d931
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 23:51:10 2007 -0600
-
- Adjust Float MAX spec tolerance to work on both JRuby and MRI, since there's a few powers of precision difference.
-
-commit af7bb00beeb359fd6183def039b9a1fcd0ce7c48
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 23:39:15 2007 -0600
-
- Expand Float divmod array equality comparisons to use be_close with a default tolerance.
-
-commit dbdf373751bce2c8a334315c8c5ed21458614c70
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 23:34:09 2007 -0600
-
- Add a tolerance to the Float induced spec around the same scale as the value under test.
-
-commit a713d277e6a8148d4c53b66a3a8fa3aedbd6a108
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 23:31:25 2007 -0600
-
- Modify Float multiply spec to be_close with a TOLERANCE multiplied by a similar scale as the value under test.
-
-commit b82d8af43356de31d16b1c36296d9e819ce70d46
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 23:13:38 2007 -0600
-
- Fix Module class_variables spec to sort the variables before checking if they are all there.
-
-commit 1e60a25b57273dd6fd7e21b0a443da1f5c0be9e5
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 19:44:51 2007 -0600
-
- Mark Process#fork specs as not_compliant_on jruby.
-
-commit 021a6ff317ed826a46ca2168f4ee9c7540a27214
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 19:19:14 2007 -0600
-
- Remove fail and "failure" guard around the require/extension spec, since an unimplemented spec isn't necessarily a failure of any kind.
-
-commit 520c423860ef6553dae34eefd85188ab9b4773f6
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 19:12:52 2007 -0600
-
- Modify previous compliance change to callcc spec to use not_compliant_on instead.
-
-commit ab85bfff2f9fea8e28f9518311aacccd30f380dd
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 17:56:42 2007 -0600
-
- Remove compliance guards on identical spec's link/unlink, since they don't blow up now and JRuby supports them.
-
-commit e79c8af0ad6fb7ddf094b6ba4747932145f9b89b
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 15:19:24 2007 -0600
-
- Removing "fail" and "failure" wrapper from unimplemented "loads extension files" spec; an empty or unimplemented spec is not a failing spec.
-
-commit 0f6b7387bcc8df946ec8d7504cc3935b6d0f9c58
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 15:06:07 2007 -0600
-
- Add compliance to callcc specs, so JRuby doesn't run them (since it never will)
-
-commit ed43292ce58468e31b771eb4926a39dff8d70793
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 14:48:45 2007 -0600
-
- Make umask spec work with different host process starting umasks, clean up literals to be easier to read through.
-
-commit 7e9f96741739e544c547f2898e8b5183dec87323
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 14:43:02 2007 -0600
-
- Fix goofed-up paths in requires for rubinius-specific Integer spec
-
-commit d54fb1e7c3f586a6d8ac200d6de839ebe6cb4c46
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 28 14:40:50 2007 -0600
-
- Move rubinius-specific spec from core/kernel/Integer_spec to rubinius/core/kernel/Integer_spec.
-
-commit eb561025707736ebe196eab3b4ff2bd1c98f45a4
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 27 23:51:42 2007 -0800
-
- Fixed language/block specs to guard ruby18 feature.
-
-commit 5659d057d756effe3acba1037d0ad6d638d930dd
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 27 22:58:17 2007 -0800
-
- Changed Bignum specs to use value suitable for all implementations.
-
-commit 2646b1a17f898f05233622c9251c3c36632e82a7
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Thu Dec 27 23:43:42 2007 -0600
-
- implements m directive for String#unpack
-
- moves a couple misplaced methods from Numeric to Integer
-
-commit 496d6761d7377081ff76b263a51bb39d0e30d80a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 18:07:45 2007 +0100
-
- Marked one Rubinius-specific Kernel spec test as such.
-
- Kernel#compile is not official part of Ruby.
-
-commit 50e35293bd3a117874203a75d214c3435170e5d3
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 17:43:03 2007 +0100
-
- Corrected String#pack with 'DEFG' pattern test.
-
- Now, numeric comparison of values is used, with precision,
- not literal string comparison.
-
-commit 0ef00fe14a04ef240fcca17d15271f92f2a44525
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 16:00:20 2007 +0100
-
- Added String#inspect test case with malformed UTF-8 string.
-
-commit 5bbde0cda03ea782090586a9afdb620663633456
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Dec 27 13:30:34 2007 -0600
-
- switched ThreadGroup specs to use Channels
-
-commit e3abd8b834b9f923d94ae381e81977feb4a4f6f8
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Dec 27 13:22:20 2007 -0600
-
- added Thread#stop? and fixed Thread#status + specs for Thread#status
-
-commit f8835353bc8be47760f70811616991463e4e681e
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 09:18:24 2007 +0100
-
- "Unexcluded" one Struct spec test for JRuby.
-
-commit 8a1b127cb33e43b916b0ccd820c6e16680cd4030
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 09:12:23 2007 +0100
-
- "Unexcluded" 6 Hash tests for JRuby.
-
-commit ae4ce805fb7611ea6de12b01b2500f501b54bd6a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Wed Dec 26 09:01:35 2007 +0100
-
- "Unexcluded" 27 Array tests for JRuby.
-
-commit c84540f96d7e265732a204ed72b3873545624444
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 27 00:08:06 2007 -0800
-
- Fixed Set#delete? spec to actually call delete?.
-
-commit e137c3279f511b49442ce2cea1b1832c1a0c6ab0
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 27 00:00:56 2007 -0800
-
- Added some specs for Set.
-
-commit 8054ed86a93a72ad4629d6f52455892d620138b0
-Author: Nitay <nitay@powerset.com>
-Date: Tue Dec 25 17:30:56 2007 -0800
-
- require should prevent recursive includes infinite loop
-
-commit 23fb497a7ba2a853cbdc5e8a38b091df284a377e
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 26 16:50:22 2007 -0800
-
- Updated status output options for bin/ci and bin/mspec.
-
- * Made dotted the default output format for bin/ci.
- * Added -m MARKER option to ci and mspec.
- * Added "Started" output as requested by autotest folks.
-
-commit 036b073753763afe86330d3f7fa0f61d755ac991
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Dec 26 10:41:01 2007 -0500
-
- Moved class fixture back to spec/fixtures/.
-
-commit 91d46b86a86270bb3174909a2d5cbc343ea138c7
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Dec 25 19:20:18 2007 -0500
-
- Added specs for $~, $&, $`, $', $+ and $1..N.
-
-commit c434614505511b8816548efcf4a4cf56d77220f4
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Dec 25 19:19:11 2007 -0500
-
- Improved language-level class specs, moved fixture.
-
- * Class fixture copied to spec/language/fixtures/.
- * Disabled unnecessary class instance variable check and added
- new ones.
-
-commit 0a49f3485fe7e26cc7d7d5bc3cb800ddf9fd6231
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Dec 25 19:13:22 2007 -0500
-
- Changed strange_block_args_subspec.rb to block_args_subspec_strange.rb
-
- * Name change to improve alphabetical sorting.
-
-commit 2ac50215dd32fd7ad2f2c20c7ae06ed73dc9f856
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Dec 25 13:32:06 2007 +0100
-
- Added tests for Array#pack with "U" pattern.
-
- Note: The tests are exclided for Rubinius.
-
-commit 4c0993fa90010322bb823a9799a8b3ccdd585e2e
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Wed Dec 26 04:07:02 2007 -0600
-
- return excluded spec
-
-commit 0a69d9cd5a7d3a0be9411fa00c4eeebe5d270a0c
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Wed Dec 26 03:55:43 2007 -0600
-
- implements @AM directives for String#unpack
-
- squashes bug in a regexp where an alternation of things
- between begin and end assertions wasn't wrapped in group delimiters
-
-commit ddda4d49f5535577c147d2154ecdae7cb4e32e24
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 26 01:16:13 2007 -0800
-
- Moved Kernel#load/#require fixtures to spec/fixtures.
-
-commit 0438e9e61c5958c5daf691b025e34bc79e7b2573
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 26 01:06:12 2007 -0800
-
- Reorganized specs to group all Rubinius specs under spec/rubinius.
-
-commit a4c3e286e44ee3df88395b9b5f44d5804154ed2b
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 25 19:32:55 2007 -0800
-
- Updated CI excludes.
-
-commit 8535481571712cf8c35f437c42ec53dcbfd44bc0
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 25 15:52:53 2007 -0800
-
- Enhanced guard for detecting :ruby, :ruby18, :ruby19 engines.
-
- Changed dir specs to create the fixture directories with every
- run to prevent pollution of the directories from causing spurious
- errors.
-
- Added spec/core/dir/fixtures/mock to .gitignore.
-
-commit a6b07ec37da7a59f34f45dfc84a66729b12f63b7
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 24 16:25:16 2007 -0800
-
- Removed Dir specs mock directories from version control.
-
-commit b0e4addbf7c6505c760e143e5fac0dab0109d8ac
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Dec 25 13:17:28 2007 -0500
-
- Updated CI excludes for Dir.
-
-commit 80a9c6c2e2e5cd2acdcb6492c4a06fef258bb49e
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Dec 25 13:17:09 2007 -0500
-
- Moved Rubinius-specific parts of #load/#require specs to extensions.
-
-commit 85f6b6e24518868f39ff39a5014a41a233237671
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Tue Dec 25 02:53:45 2007 -0600
-
- implements U directive for String#unpack
-
- uses only one of the exception messages every time
-
-commit b414c94db1fa1af8e6cd3382c34fc6de5ed3bd1e
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Mon Dec 24 16:42:22 2007 -0800
-
- Merge identical specs
-
-commit e0f28c224a2348dbf7c005694971a86f8e6162e1
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Mon Dec 24 15:59:24 2007 -0800
-
- Kernel.Integer() shouldn't pass a base to String#to_inum
-
-commit eb93da7c578599469fe209f7b1d30f0f77d148f5
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Dec 23 16:43:33 2007 +0100
-
- Wrapped one String#crypt case into compliant block for JRuby.
-
- "hello".crypt("\x00\x00") is not really defined,
- and heavily platform dependent.
-
-commit 7594c89cf2f017cb1fffad16bac6fcc7c9629422
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Sun Dec 23 10:53:30 2007 +0100
-
- Added JRuby wrapper for String#% test.
-
- Allow "%e" % (0.0/0) in JRuby to return "NaN", and not "nan".
- I think, returning "NaN" is a proper behavior, and
- it seems that MRI 1.9 is also following it.
-
-commit eaf9e328e81f9c1d4e80737a96d0eea6b511fabb
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Mon Dec 24 06:55:30 2007 -0600
-
- implements BbHhIiLlSs directives for String#unpack
-
-commit 701945421d6a656f8b0b183052c4535a895e2afd
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 24 00:44:26 2007 -0800
-
- Converted specs to use the new #platform guard syntax.
-
-commit 238fbbc2331a1926f3d3f447d8433b046e7d34ac
-Author: Tom Mornini <tmornini@engineyard.com>
-Date: Sun Dec 23 15:43:26 2007 -0800
-
- Clean up language on now understood and fixed alias_method e2mmap spec.
- Fixing the alias_method problem has now uncovered something in const_set,
- so I've included a very vague test (require 'e2mmap') to document the
- problem until it's better understood.
-
-commit 69149b261ac13cc1a2b7c80c7b103d397fd96b9b
-Author: Tom Mornini <tmornini@engineyard.com>
-Date: Sun Dec 23 14:13:22 2007 -0800
-
- Add spec for alias usage that breaks e2mmap.rb
-
-commit 71d9a4144811b2c9c74edc55f348637c57b0cb84
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sun Dec 23 05:25:37 2007 -0600
-
- implements aDdEeFfGgXx directives for String#unpack
-
-commit bebafb1383a5126c959c33a1336f3a2e4b6993f6
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 18:16:14 2007 -0500
-
- Saner specs for stream-style Dir access. Passes 1.8.6-p111.
-
- * Dir#read, #tell, #pos, #pos=, #seek and #rewind which are a part
- of the stream interface to Dir no longer rely on platform-specific
- position values, instead opting to just ensure they work as expected.
-
-commit a2e4c318a3406c9532404611f14d2790695c0a7a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 16:29:00 2007 -0500
-
- Enabled Time#at spec to work with BSD `date`.
-
-commit 0e983f2e948ab997834dbc703e9eeb11d86a7022
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 16:17:14 2007 -0500
-
- String#to_i spec to check for correctly parsing 0x-1 and the like.
-
- * This was fixed in 1.8.6-p111.
-
-commit 5e635a46f4733bcc2071b52ea076584614fe5655
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 15:52:03 2007 -0500
-
- Fixed various String spec issues and added a few. Passes 1.8.6-p111.
-
- * String#% with o for octal numbers is still broken but that seems
- to be due to MRI's sprintf.c.
-
-commit 780f22bde03e280f5af2509bef260585341f4e0b
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 15:48:55 2007 -0500
-
- Fixed incorrect use of #should raise_error.
-
-commit 0b239b4f66c20ad5690e429639c4bf11a809ab58
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 12:22:20 2007 -0500
-
- Hash specs fixed. Pass under 1.8.6-p111.
-
- * Changed to use HashSpecs#frozen_hash and #empty_frozen_hash
- for clarity and being less error-prone.
- * Fixed various typos causing problems.
-
-commit 9a2450e5c51333474cf012c3a1364e95384af9e0
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 12:20:48 2007 -0500
-
- Kernel.caller specs revised. Pass 1.8.6-p111.
-
- * Fuzzier matching of the data in the call stack.
- * Fixed specs for omitting frames.
-
-commit 692f4e8a652e273096c0f77ffe571318c59d2b12
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 10:59:19 2007 -0500
-
- File.ftype specs pass on 1.8.6.
-
- * Use `find` to locate specific file types instead of relying on
- predefined paths being correct.
- * Re-enabled character devices.
- * FreeBSD does not implement block devices.
-
-commit f1251ebc602311ec305a4b1b35a765ee45b9c164
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 10:11:07 2007 -0500
-
- Bignum#div returns an Integer if evenly divided.
-
-commit b62e1b7a21df1d7736767530f216148b8a93e38a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 09:52:33 2007 -0500
-
- Fixed Array spec failures under 1.8.6-p111.
-
- * Array#fill raises if given a negative count.
- * Array#initialize will always raise if frozen.
-
-commit e3d6a3df6c1dfc37731ff4de5de32dc996bb61bb
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 09:37:46 2007 -0500
-
- Silence warnings from removing *.rbc in #load and #require specs.
-
-commit a11171e853b3efb94b4cba03786ea851d81411c6
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Sat Dec 22 07:39:40 2007 -0600
-
- implements CcQqVv directives for String#unpack
-
-commit eea90994f2a1b76ed11b29e05a16c9c299d59235
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Dec 22 00:23:29 2007 -0500
-
- Added __FILE__ specs to #load.
-
-commit 0e04ca49ebdba35a7a293b6de82d9d67c6ff4ac5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Dec 21 22:59:50 2007 -0500
-
- Correct __FILE__ information from #load and #require.
-
-commit 51c2543fe032b680a6c8f8cf8121196070c61c66
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 21 23:51:37 2007 -0800
-
- Replaced use of @path1 with equivalent nil in File#fnmatch.
-
-commit b9f979393456dc3c93250e3a50b54b489a25c5d1
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 21 23:29:51 2007 -0800
-
- Added -w to bin/mspec to emit warnings. Fixed warning in mSpec.
-
-commit 16ce249216f490b9f7921aa69932f9e8bd60ca0e
-Author: Jeremy Roach <jero_rub@yahoo.com>
-Date: Fri Dec 21 22:50:40 2007 -0800
-
- Implements N, n, and Z directives for String#unpack.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit e1d292e28fe409c087f314bb139371a1f248850d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Thu Dec 20 15:04:12 2007 +0100
-
- Fixed race condition in ThreadGroup#add specs.
-
-commit 469527ddf33484a4a77f3d73c611e9a393bd48ad
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Dec 21 12:02:50 2007 +1100
-
- Added CompiledMethod#decode specs
-
- * Added UnboundMethod#compiled_method accessor
- * Improved robustness of ISeq decode when dealing with junk at
- the end of an iseq
-
-commit 08c2f5c29a2debed90ae1fff817c30e269913609
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Dec 20 23:45:53 2007 -0500
-
- Re-enabled purging .rbc files in require_spec and fixed the masked problem.
-
-commit dd4f3c52e79d01e826918e49fa626d7358f87901
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 20 22:53:48 2007 -0800
-
- Clean up a couple of failures seen in ci. spec/core passes.
-
-commit a5667632ae8d112c0271e00cbba53a274075cd1a
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 20 22:49:05 2007 -0800
-
- Removed legacy, unused spec/reports/base.txt.
-
-commit 853e100b6f7fff24e4aaa40ed30c6add523f8df2
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 20 17:49:36 2007 -0800
-
- Fix a bunch of String specs (thanks random8r)
-
- * Note: rubinius now has the same behavior as MRI for Nan,
- Infinity and -Infinity when using String#to_f
-
-commit b220f4921fd799ac28c60132ca08cf16df6f713e
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Dec 20 15:37:25 2007 -0600
-
- fixed require specs to work correctly on any run including first
-
-commit 56ac483e3559e1d4913e4c36c9a8f007523fdab0
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Thu Dec 20 19:36:21 2007 +0000
-
- Fix typo in spec/core/regexp/union_spec.rb
-
-commit 634300eed40ef0ded16ab7cac7865dd783486c2d
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Dec 20 03:46:59 2007 -0600
-
- Add 'sleep' checks to threadgroup spec to avoid the same race conditions seen in kernel/sleep_spec.
-
-commit 72b7123c9b3d1d266f4ce035b4e99dd0c2dbd88d
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Dec 19 22:46:17 2007 -0500
-
- New compliant (moreso, anyway) #load and #require.
-
- * Improved #load and #require.
- * Specs for the above.
- * File.to_sexp and String#to_sexp allow empty input. They are
- processed as a file containing 'nil'.
- * Archive#get_object_fuzzy allows no extension or .rb instead
- of .rbc only.
-
-commit fe633062095096fe00599cbb89aa4370ab5ccb3e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 19 23:03:08 2007 -0800
-
- Fix Kernel#puts
-
-commit 364ca08cbbb1848b549d99deb11e2449ad99334a
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 19 23:10:17 2007 -0800
-
- Updated CI excludes.
-
-commit 5f1c381560a8d4d594749d42b5b2feeec341d4e5
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 19 22:24:10 2007 -0800
-
- Fix Kernel#open
-
-commit 3b3ed6304deab01cb448665c5f4b17d813f04e65
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 19 21:43:58 2007 -0800
-
- Cleanup more method specs, all pass on rubinius now
-
-commit 76bbbf275f4e835444f684b2e688b292f20c1ffe
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 19 18:08:09 2007 -0800
-
- Implement protected methods
-
- * Added a bit more verbose specs to methods_spec.rb, to show
- specific cases.
-
-commit dce06b35481bb1951c587d36f63abaae069d0ae4
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Dec 18 22:28:30 2007 +0100
-
- Wrapped one String#unpack test case into compliant block.
-
- The test case is platform-specific, and not suitable for, say, JRuby.
-
-commit bb4945ea7b9253150f753508e92633b6e355194a
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Dec 18 21:30:24 2007 +0100
-
- Added new String#unpack test to exclude file for CI.
-
-commit 1bd8beb8e0b335f1de309d6320312a1b64af1e4d
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Tue Dec 18 19:51:47 2007 +0100
-
- Added more tests for String#unpack with Z/Z* patterns.
-
- These patterns are known to be tricky, and their
- handling was changed during Ruby's life.
- See [ruby-talk:98364].
-
-commit d26edc2269a77667dbefcfb1ea6212d8ada9ef97
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 19 01:25:27 2007 -0800
-
- Fix a bunch of Task GC problems, better memory management.
-
- * Use ALLOC* macros instead of malloc/calloc directly
- * Also, simple fix for Time
- * A Kernel#loop implementation
-
-commit 4143b92e6112241ff2facd64047491ce579bf0e9
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 19 00:43:32 2007 -0800
-
- Finished converting Object.new to mock() in specs.
-
-commit 9cae61f827d2eeca0a744e551551efd6bc85a2ae
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 19 00:02:46 2007 -0800
-
- Spec #it blocks must be inside #describe blocks for RSpec.
-
-commit 7df00ef6d2471d0b37829e0a4d1ef45edf782a44
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 18 23:28:43 2007 -0800
-
- More conversion of Object.new to mock() in specs.
-
-commit 12463512d0ad48fae3a1843d9d409649551dd13b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 22:53:38 2007 +0100
-
- Corrected String#* test to pick large enough Bignum, even on x64.
-
-commit 79cbff2c9a0cb15e9e5767f94242fa4360a0c4a0
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 16:43:16 2007 +0100
-
- Removed race condition from Kernel.sleep spec.
-
- This problem caused JRuby spec runs to hang.
-
-commit 3032e60e10dd1ae61ffb40b351f4f6731395602b
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 15:43:42 2007 +0100
-
- Enabled one Hash#rehash test case for JRuby
-
-commit 1808106191856f4f82b948abc5c7e708a747d059
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 15:40:49 2007 +0100
-
- Issue #153: Hash#rehash test enforces unspecified impl detail
-
- Wrapped the test so that it won't run with JRuby.
-
-commit efbf30477ea289911d9cafbde89ecbe2c8c65089
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 15:25:23 2007 +0100
-
- Corrected :mri --> :ruby
-
-commit 60a3ede3c64b62fb26905ed1c236c0e241b64515
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 15:23:42 2007 +0100
-
- Issue #182: String#to_f spec corrections for NaN, Infinity
-
- JRuby AND Rubinius treat "Infinity".to_f, "-Infinity".to_f ,
- "NaN".to_f differently than MRI.
-
- MRI returns 0.0 in all those cases, but JRuby and Rubinius probably
- do something more meaningful, they return Infinity, -Infinity and Nan
- respectively.
-
- It was agreed that JRuby's and Rubinius' behavior is a feature rather
- than a bug, and worth preserving and checking for.
-
-commit 521a82d8c325a33b3409423d61b589c7b8681870
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 15:14:28 2007 +0100
-
- Refactored commonly used generators into fixtures.
-
- Thus reducing copy-paste.
-
-commit 86820a339c74e3ca8fc9515e5fdf31ad42780201
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 14:12:43 2007 +0100
-
- Initial version of Generator specs.
-
-commit 91353183ace65d8e751db14a829e8f24d043710c
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 03:18:19 2007 -0600
-
- updated excludes for Kernel#sleep and Thread
-
-commit 6de193c0819f74717eb2e9eff8480f0d801b0e41
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 18 01:01:31 2007 -0800
-
- Replaced Object.new with mock() where appropriate.
-
-commit 1217fa030ff26712e9718ebecfe351830c543d7e
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 02:16:10 2007 -0600
-
- fixed redo in loop by save/restore condmod around loop context in compiler1
-
-commit df757142c774becfc2cbc4b38e43e31056acbae2
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 02:00:27 2007 -0600
-
- spec for using redo,next, and break in one loop
-
-commit 7169fd31b7c22750241212c242bc8aacdafe632f
-Author: Vladimir Sizikov <vsizikov@gmail.com>
-Date: Mon Dec 17 13:08:09 2007 +0100
-
- String#sub specs wrapped to correct JRuby test failures.
-
- JRuby reports Ruby version to be 1.8.5, but in this
- particular case it behaves like Ruby 1.8.6
-
- Differences between Ruby 1.8.5 and Ruby 1.8.6:
- different error raised.
-
-commit 04e228e131d06cd764d69375ddfdf44e4fec2b38
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 01:27:00 2007 -0600
-
- spec for Thread.pass and updated :mri to :ruby
-
-commit 11348e25ba30199e3beb05f8c38c18820fbefc3f
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 01:11:38 2007 -0600
-
- Some minor fixes in Thread specs
-
-commit 5cb3bcbf8f1d2a2237200ca0a9a9c6408d478ad6
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 01:11:05 2007 -0600
-
- spec and basic functionality for Thread.stop
-
-commit 3301fbb3ec43b5252c0aa6d45eb2f0e21581ff0a
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 01:09:49 2007 -0600
-
- Thread.sleep doesn't even exist in rubinius
-
-commit bd964f579f84a39097ecee1271664d672b6553a7
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 17 21:40:16 2007 -0800
-
- Replaced :mri with :ruby for spec guards.
-
-commit d21810882621356c35dcd101daca5ee5549f6607
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 00:42:32 2007 -0600
-
- Threads should report there status of sleep, aborting, and run
-
-commit 85a6476a236bd1e65d42ca03846c662a10842f37
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 18 00:41:09 2007 -0600
-
- Thread#status should return nil if Thread terminates with an exception
-
-commit ecb4455a75f4af2ae0059ca4960c2282b4ec632a
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Dec 17 23:50:24 2007 -0600
-
- specs for Thread#{key?,keys} and added key type checks for Thread#{[],[]=}
-
-commit c1a5d7e52b33ba6686441c61652bcc41ae0547f8
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Dec 17 22:15:37 2007 -0600
-
- specs for Thread#[]
-
-commit c2c7f0adc6ebbad925adb2471b6064b67528b420
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Dec 17 21:47:52 2007 -0600
-
- ensure LocalThread#current != Thread.current
-
-commit d05dac276f36326e143aa75bb43e4ab07bd8ddc9
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Dec 17 21:28:44 2007 -0800
-
- Fix a bunch more Kernel specs
-
-commit 4ddd0e144b4e4f64c51fc8d64952826d92a5e83f
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Dec 17 19:45:26 2007 -0800
-
- Fix Thread.abort_on_exception and Thread#inspect
-
-commit a12ad6fbc2589a7864a7c784386fb6ce7dae1db1
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Dec 17 21:29:49 2007 -0600
-
- Kernel#sleep and Thread#join specs now use locks to maintain automaticity instead of while th.status == 'run' loops
- added a Channel fixture to Kernel to support the use of locks in Kernel#sleep specs
-
-commit 72e3fb453c266e514b817daa66bf6033f1d19e40
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Dec 17 19:01:18 2007 -0800
-
- Fix callcc specs, revert all locals back to using the locals tuple
-
- * compiler1 now does what compiler2 is going to do, ie, only use the
- locals tuple to store locals. Storing them on the stack has proved
- to be a pain, and wont be used further.
-
-commit 6e35be2ddef8d055e064462c88a8b3f33eb4fe0f
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Dec 17 18:37:16 2007 -0800
-
- Faster Class#new, initialize can be private
-
- * Class#new now uses a bunch of inline assembly to be able
- to call a private initialize
- * Clean up Module#name a little
- * Made machine's rbt a little more robust
-
-commit 47a5bbf34ef8a60a18c1c8c6130d493a299ff852
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Tue Dec 18 01:10:33 2007 +0000
-
- Make sure files opened with "w" are truncated.
-
-commit 0fdc8c9b7d05cc2e96908b280ac144de0d04f646
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Tue Dec 18 00:16:27 2007 +0000
-
- Fix excludes for spec/core/stuct/{new,struct}_spec.rb
-
-commit 5b1252e6b2d8f8d70343b06f3520114de2040524
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Sat Dec 15 17:31:25 2007 +0000
-
- Minor fix to struct_spec to include fixture.
-
-commit 4fd0356ab9e9bb5c2a805b1f863b3177458966fe
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Sat Dec 15 16:29:49 2007 +0000
-
- Add case to spec/core/class/new_spec for names of nested classes.
-
- * Updated spec
- * Add some comments where this may be fixed
-
-commit 86736d564f34a2f97f7c7bedcab09c2472861b01
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Sat Dec 15 16:16:26 2007 +0000
-
- Fixes for struct class names.
-
- * Tighten up specs to show what class names should be.
- * Fixes #inspect
- * (Partially) solves the larger issue of an anon class getting a name when
- assigned to a constant - works now when Module.const_set is called.
-
-commit ad0d5ff2396baf43c8b2e37a3132765a074b241d
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Fri Dec 14 02:33:23 2007 +0000
-
- Fixes related to Struct.new
-
- * Fix to method_table to correctly handle DelegatedMethods
- * Changed spec/core/stuct/new_spec.rb to allow :rbx to call
- to_sym on objects passed to Struct.new to get the symbol
- value.
-
-commit 18f10dc700fe24f3bd230063bc7c1e8a82e8348f
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 17 08:58:22 2007 -0800
-
- Updated spec excludes to run with bin/ci under the new mspec.
-
-commit 678fb90c5c8aa96e10a9f95f520312f12f8fa3f2
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 15 22:43:44 2007 -0800
-
- Changed true/false/nil specs to not use def in describe block.
-
-commit 9e132474aafb6a0f0c968c2e085b09bfc07e1a0d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 15 18:49:31 2007 -0800
-
- Fixes to run the specs under RSpec and mSpec.
-
-commit cd3ecf52645b94921db92393e6e4d295d12bba88
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 15 00:59:11 2007 -0800
-
- Misc fixes to mspec. bin/mspec -t r spec finally runs!
-
-commit f3b3f70bb47b04e7a67c1dbc3ae38711857b5184
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 13 22:46:54 2007 -0800
-
- Multitudinous miscellaneous fixups for mspec and mmock.
-
-commit 55ab5b2ee42e4fabcfd8c51d6fac304cdfec31c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 10 01:01:58 2007 -0800
-
- Various fixes to mspec to run Rubinius specs.
-
-commit 86c0f131608b4ad7cba93eabd172a48e5b60ca0f
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 7 15:34:06 2007 -0800
-
- Added runner guards to omit specs that will always fail under RSpec.
-
-commit 75706dbfabbe359b6410f0d3743f0ea682146ac1
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 7 14:03:46 2007 -0800
-
- Added #runner guards to mspec.
-
-commit 3da390988031bf0066a849934ee758475ebbfa04
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 7 02:38:13 2007 -0800
-
- More fixes to run the specs under RSpec.
-
-commit 2b0f4e408b733dcd9089a19d78cd8e4cce20b99c
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 6 18:40:33 2007 -0800
-
- Yet more spec cleanup to run under RSpec.
-
-commit 1e4171d4682f55776e01e42f564714548c1d9bd9
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 6 02:16:42 2007 -0800
-
- More changes to run specs under RSpec.
-
-commit db020d30374e419792f76077757784008953c0a6
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 5 02:01:30 2007 -0800
-
- Various changes to get the specs running under RSpec.
-
-commit 968c2daa5345a0cddb8d3d5bd2b6bf2eeb0c1d6f
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 23:51:52 2007 -0800
-
- Convert remaining mocks to RSpec syntax.
-
-commit e5dc3ac814d1cda923131257dfbc9a30bf501b62
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 23:28:17 2007 -0800
-
- Convert remaining 'should_raise' to 'should raise_error'.
-
-commit a7be230ac71ece2bb8dcece72d629bcd0ce6a5e0
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 18:29:26 2007 -0800
-
- Converted specs from mini_mock to RSpec mock syntax.
-
-commit 4136e2fef4a81eb6e9e14070ff5301638f9acf14
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 02:25:31 2007 -0800
-
- Integrated mini mock with mspec. Updated spec_helper for main specs.
-
-commit d71c0c7412af01d6295d8caab43a80d0221ea16d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 01:49:17 2007 -0800
-
- Added #shared and #it_behaves_like to mspec.
-
-commit da61adc0a079c858385773b12d683e2f5e2cc0e8
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 4 00:43:15 2007 -0800
-
- Converted 'should_be_ancestor_of' to 'should be_ancestor_of'.
-
-commit 5ed0096aac58fef09fc766d808aea74356aacfa8
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 3 17:57:56 2007 -0800
-
- Replaced dev_null with CaptureOutput.
-
-commit 62282bd5cb5c555e6447dcf2d6d0da355913fe8b
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 3 17:30:01 2007 -0800
-
- Replaced 'should_include' with 'should include'.
-
-commit f990a7c58a7eee6dbbb3c50df7682942048b959f
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 3 17:21:50 2007 -0800
-
- Replaced 'should_be_close' to 'should be_close'.
-
-commit c53601c56bd222dfacf03f134132869eb71c5146
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 3 17:10:41 2007 -0800
-
- Finished converting should_raise to raise_error.
-
-commit 165dd99535b0829d2e2364fac24375068969c6ab
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 2 23:22:54 2007 -0800
-
- Convert should_raise to should raise_error for RSpec compatibility.
-
-commit c9ff50a4b4be25614cc0ac2ea5540cfe87a939d3
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 23:30:44 2007 -0800
-
- Moved mspec out of spec dir.
-
-commit e9a40a77b6fa7d08969ea195aabbb930b665fe02
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 23:25:59 2007 -0800
-
- MSpec base formatter and specs.
-
-commit 2fc3ac3f8efbaf0861cadfd59bcdf926d2196284
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 20:32:42 2007 -0800
-
- Port fix to ruby engine detection from mainline.
-
-commit 9a52e660536b4723bf24e2717fec757a1bdfa49f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 01:35:52 2007 -0800
-
- Match RUBY_NAME against /^ruby/ to pick up e.g. ruby1.8.
-
-commit 85536b98862f6abec310bfad03be17652ee65944
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 01:01:46 2007 -0800
-
- Implemented mspec matchers.
-
-commit c953335397c6c8b9d7b27a3d240fde3b3518cb48
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Nov 27 01:35:07 2007 -0800
-
- The rest of the mspec big picture.
-
-commit 2f598f193eb1b10065c8e1a8d5c2aaa89c689072
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Nov 27 00:39:59 2007 -0800
-
- Added base operator matchers and specs.
-
-commit 0cc0b5a97661970d4cbb5e46406e7ee06421e637
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 26 21:03:33 2007 -0800
-
- Migrated mspec and ci runners to mspec dir.
-
- Created stubs in bin/ci and bin/mspec that call the respective
- scripts in spec/mspec/scripts.
-
-commit b98d65eaa90d966fc2f7b8f8387266e241c202de
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 25 01:03:26 2007 -0800
-
- Added specs and guards for mspec.
-
-commit 7bb316d1291c9d0a16904d4a3ee60094a713f215
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 24 21:40:46 2007 -0800
-
- Prevent MSpec's #should(_not) from overriding RSpec's.
-
-commit c446988257a2104d72abd4a362dc21ca6183aab0
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Nov 20 22:47:25 2007 -0800
-
- Defines #should and #should_not for mspec.
-
- Specs for #should and #should_not.
- Adds example for using mspec "base" layer.
-
-commit 1aecf8e828dfd3d86f43d8c9c927e7c0ccb16b68
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 12 00:40:04 2007 -0800
-
- The mini rspec big picture.
-
-commit f2979b03f29e7ac810b81f9087ea53923de5a35c
-Author: Charles Lowe <aquasync@gmail.com>
-Date: Mon Dec 17 15:18:24 2007 +0100
-
- Added missing error checks to Dir.chdir block form.
-
-commit 028fee4e6d48514cae53f87c143bb68501bf58e9
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Wed Dec 12 20:01:35 2007 -0500
-
- Add further specification of size changes during Hash#delete.
-
- This was actually failing a while ago but now passes after recent
- changes.
-
-commit f757f4359c86f778ac8e5931b8915511fd03506d
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Wed Dec 12 19:59:28 2007 -0500
-
- Tighten another spec in core/hash/equal_value_spec.rb
-
- Hash#== compares keys with matching hash codes via eql?
-
- This spec was using hash keys where key.eql?(key) was false.
-
- That's pretty pathological, but there's probably some real
- non-conformance with MRI here. MRI can test for object identity
- without calling eql? so a key is still found even if it doesn't
- eql? itself.
-
- That's not really related to the behavior this spec is specifying,
- though. So, this patch just uses a less pathological implementation
- of eql?
-
-commit 3f73ddf6bec5c704ceb5ed43481971860293353d
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Wed Dec 12 19:49:49 2007 -0500
-
- Tighten spec in core/hash/equal_value_spec.rb
-
- "Hash does not compare keys with different hash codes via eql?" was
- failing because it detected that eql? was called on a key. However,
- eql? was not being used to compare keys with different hash codes
- from the two hashes. Instead, eql? is used to compare a key to itself
- during hash element reference, in order to distinguish between two keys
- with equal hash codes that aren't eql?.
-
- The tightened spec only fails if the keys are compared eql? to each other.
-
-commit e355e98a32f34619628a17f5052750da6881cda9
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Wed Dec 12 12:26:15 2007 -0500
-
- Add specs for hash stability of various Numeric subclasses.
-
-commit 0d774c99254b2c5992a17ecb2a5a12dcd2cad05e
-Author: Chris Shoemaker <chris.shoemaker@cox.net>
-Date: Tue Dec 11 20:37:45 2007 -0500
-
- Add a Hash#store spec for storing unequal keys w/ same hash.
-
-commit edfff4981285007ecac132f565243150a8a8bd7e
-Author: Curtis Schofield <123@noself.net>
-Date: Tue Nov 27 19:02:45 2007 -0800
-
- Specs created for Process#gid and Process#uid
-
- * both are using the unix system command 'id'
-
-commit 4e269d01238537cc45f4c347b12053616007d94d
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Dec 16 23:46:50 2007 +0100
-
- Excluded evil Thread specs.
-
- This makes bin/ci usable (pass) again on my system, where it was horribly
- broken before.
-
-commit b32c46ba95f2ecdaf646a030b96ee9b3737929a0
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Dec 16 23:37:26 2007 +0100
-
- Excluded failing Kernel#eval specs.
-
-commit 0c56f3a1f84dd94d1f9685af9e9d6e0efd0cfabf
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Sun Dec 16 20:24:54 2007 +0000
-
- Tighten up specs for what should happen when array shrinks during iteration.
-
-commit bfa8c532605c9e3b3d7f853516de9aae596c611d
-Author: Hunter Kelly <retnuh@gmail.com>
-Date: Sun Dec 16 19:11:25 2007 +0000
-
- Added specs for Array#each when the array is changed during iteration.
-
- Ditto for Array#each_index.
-
-commit b3aa2af4a3467b4eeb8765010286c12bd5adfbf9
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Dec 15 22:53:35 2007 +0100
-
- Sanitized Object#id spec.
-
-commit cce5b7004a774041d78c3b2e55af8063335a9512
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Dec 14 19:02:57 2007 -0800
-
- Fix sleep spec, implement Thread sleep status and death detection
-
-commit c2475838be23ae287075b7e9ea832013f1db77c4
-Merge: 30f20cf... d061b86...
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 14 10:56:53 2007 +0100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 30f20cfbd67487c426827406890fdb06fac8045c
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Fri Dec 14 10:56:17 2007 +0100
-
- Fix race conditions in Kernel#sleep spec by ensuring target thread is actually sleeping before continuing.
-
-commit d061b864f636210e40982d961b0aa5afc24543d0
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 13 23:04:27 2007 -0800
-
- Fix require specs to not require checked in .rbc or .rba files
-
-commit 41831976d25a4d5a8e26673199276098cc45b4d3
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 13 22:40:43 2007 -0800
-
- Fixed Thread#run, added corruption detection to rbc files
-
- * Thread#run was confusing the Thread scheduler, cause things the VM
- to quit running.
- * Added corruption detection to .rbc files in the form of a SHA1
- hash placed in the .rbc, just after the header.
-
-commit 77f0f29060d5ba3f33dc45029525acb715eb61c2
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Dec 14 15:10:59 2007 +1100
-
- Compiler2 fix for attrasgn in masgn
-
- An attrasgn node contained within an masgn does not include
- the assigned value in the attrasgn sexp. This was leading
- to the argument count to []= to be understated by 1.
-
-commit faaa1932fe05ee4d506b768f8d9d884af5345547
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Dec 12 19:59:11 2007 -0600
-
- fix non-determinism from Thread.sleep by removing blocking sleep
- add check for duration of 0 or 0.0 to instant return and added more specs
-
-commit e98b2d1f9788c1813bef2d920779c95effbd3d9f
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 11 17:27:43 2007 -0600
-
- spec and fix to allow floating point timeouts to Thread#join
-
-commit 801cb5ef58a6debfd348a33f864737cbce7c3d77
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 11 17:26:58 2007 -0600
-
- added noncompliant spec showing that sleep(nil) is allowed in rubinius
-
-commit 84d280810c840d6699b5c9ad094964fe779235df
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Tue Dec 11 16:30:41 2007 -0600
-
- fixed Thread#sleep to allows floats, and switched Thread::sleep, Kernel::sleep to use Thread#sleep on current thread
-
-commit 3d10a8a10741786ba76a4cc1083934f908d52ec2
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Mon Dec 10 17:13:34 2007 -0800
-
- Allow Thread.new to take arguments
-
-commit 4f5258b938a7aacf31e73b5fe6312e3c927d9cf8
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Mon Dec 10 00:21:20 2007 -0800
-
- Fix rb_define_alloc_func
-
-commit 7ab0f524de5a6b796ec1000402392cb138150eed
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Fri Dec 7 15:06:45 2007 -0800
-
- Initial ThreadGroup implementation
-
-commit 53fff95e300b1b26ed16f12c13684eadf8235d7a
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Fri Dec 7 01:30:55 2007 -0800
-
- Add rb_str_substr
-
-commit ec82de9f67e271718b874c0d777765da696bef88
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sat Dec 8 15:26:17 2007 -0800
-
- Add wrapped struct spec
-
-commit 65998d601aae601b3b43878f534362136a01ff17
-Author: Brian Takita & Nathan Sobo <brian.takita@gmail.com>
-Date: Fri Dec 7 17:18:24 2007 -0800
-
- Added specs for Module#undef_method.
-
-commit 97f8c9c32b9400ae42d0dc80aa7e17b22864fce9
-Author: Brian Takita & Nathan Sobo <brian.takita@gmail.com>
-Date: Fri Dec 7 16:13:02 2007 -0800
-
- Moved Object#to_a to Kernel#to_a. Added VM.coerce_to_array.
-
- VM.coerce_to_array will be used for splatting any object.
-
-commit 865ce7d771a101bc8c2c9ae3a82cbc3f37450c4b
-Author: Brian Takita <brian.takita@gmail.com>
-Date: Fri Dec 7 12:47:08 2007 -0800
-
- Merge branch 'array'; commit 'nathan/array' into array
-
-commit b4541a90f84c898e3cd9851ac4b207d559078a59
-Author: Nathan Sobo <nathansobo@gmail.com>
-Date: Thu Dec 6 23:33:10 2007 -0800
-
- Updated language/array_spec.rb for more detail on splat operator.
-
-commit 577b2f1c395dc49165842c405fb47bbb7591158a
-Author: Nathan Sobo <nathansobo@gmail.com>
-Date: Thu Dec 6 18:30:16 2007 -0800
-
- Fixed :many_if for compiler 1.
-
- Before it was translating many_ifs to a flat array of if statements instead
- of nesting them. Also, multiple boolean expressions in the case were not
- expanded to a boolean disjunction.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 1d555fa07aaed8e59e728cb0013daa10b3b17b25
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Dec 6 21:24:44 2007 -0500
-
- Add some JRuby-inspired eval specs
-
-commit 3131fb81eef380d163d028f5587475bbf170befb
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 6 12:19:49 2007 -0800
-
- Fix minor constant lookup issue and add timing to mspec
-
-commit 26897cd85c693cac10229d7467436717552088c0
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Dec 6 11:42:36 2007 -0800
-
- Fix another constant lookup bug
-
-commit 06a3f07999aeb4f7379ea40205451d326d1ba596
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 16:37:15 2007 +0100
-
- Updated CI excludes for IO#each and IO#each_line.
-
-commit b495ab1019e9ee136e9d099faa51cba03c48e947
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 16:01:31 2007 +0100
-
- Extended argument checking in IO.read.
-
- We're now checking that offset isn't negative either. This is done
- before the length argument is checked, mirroring MRI's behaviour.
- Also fixed a typo in the length check.
-
-commit 4fa2fbb6b6c27ced5d6cf902e63e3989c2d29b64
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 14:56:41 2007 +0100
-
- File.truncate raises Errno::ENOENT if the given file doesn't exist.
-
-commit cb7a0a7315e57f1adff0976bcd6b0c4a1a94d8c5
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 14:15:55 2007 +0100
-
- Added support for the length and offset arguments to IO.read.
-
-commit 9fe8f2bd73e28d28b7a9249e629ab7681321e4d5
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 14:07:21 2007 +0100
-
- IO.read only accepts file names and uses File to open and read them.
-
-commit 7ab1d9f3434e3f3b021de2f4087f2502e229c7a0
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 14:00:19 2007 +0100
-
- IO.new(nil) raises TypeError now.
-
-commit 227f6b4bf45b55eb659d41507d38fe5071ef7424
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Dec 6 13:24:31 2007 +0100
-
- Fixed a typo in File.writable?.
-
-commit 645f30882c9dd39d13f49e45f2f32c43ebe25182
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Thu Dec 6 03:51:11 2007 -0800
-
- Update Dir excludes
-
-commit e60ee517013d44c2ec6faf147f7dbd685fa520c2
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Thu Dec 6 00:40:17 2007 -0800
-
- Fix flag checking in Dir.glob
-
- Also clean ".", ".." skipping
-
-commit fa681ad7a3c1d0e1b4fb0702c2fc63cd80ec9377
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Wed Dec 5 18:08:41 2007 -0800
-
- File.fnmatch? should accept escaped wildcards
-
- Also fixes more Dir.glob specs
-
-commit e6b8ce23729606bf6fa748ea63c0e0a59b48a476
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Wed Dec 5 15:35:32 2007 -0800
-
- Don't unescape leading period in File.fnmatch?
-
-commit 1cf054a08b0aeea7c348ff26c71ccaf22c02ce70
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Dec 6 02:36:54 2007 -0500
-
- Rename Array#pretty_inspect to avoid conflict with pp
- Hardcore bikeshed action on the way TestGenerators are inspected
- Change describe.rb to call the renamed pretty_inspect
-
-commit 519d1226027623274766641a256e2a9753257266
-Author: Nitay <nitay@powerset.com>
-Date: Wed Dec 5 16:07:25 2007 -0800
-
- Fix Constant = Class.new setting of name
-
- Signed-off-by: Kevin Clark <kevin.clark@gmail.com>
-
-commit 568c57ca57d4a9183e492024e17aa1352902d1d2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Dec 5 20:31:43 2007 -0500
-
- Clean up mspec output to prepare for unit_diff support
- Use pretty_inspect to display compiler2 TestGenerator output
-
-commit e250521194380f4c942fd6d53664b746ca63e3e3
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 5 17:27:27 2007 -0800
-
- Fix constants spec to scope the fixtures
-
-commit 7010073617a4fa95ea5491284fef97a083d9d4f3
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Dec 5 14:42:27 2007 -0800
-
- Vastly simplify and fix constant lookup
-
- * New constant lookup specs to test behavior
- * Added StaticScope object and field on CompiledMethod which stores
- a StaticScope instance which indicates the lexical scope of the CM.
-
-commit 163e56646a817301201af843b45c973da058688c
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Dec 5 23:00:16 2007 +0100
-
- The spec for Dir#rewind doesn't pass on Rubinius.
-
- It's not platform specific, but we don't have a working Dir#pos yet
- and the Dir#rewind spec relies on it.
-
-commit 3afe61bd78aa9e850f081b83ca2c478ae297bda1
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 5 13:51:05 2007 -0800
-
- Changed mini_rspec to show failures unless being run by autotest.
-
- Added dir_entry.rb to .gitignore.
-
-commit 0c661894b54615ee4915d61569e072ffdfa8826d
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Wed Dec 5 09:17:24 2007 -0500
-
- Much-improved tiny option parser lib/options.rb.
-
- * The Options API is much more user-friendly now,
- size is still about 100 LoC
- * Specs for the API.
-
-commit 092e0081c26eeda2ca6561eb19123b468965c84a
-Author: Ryan Davis <ryand-ruby@zenspider.com>
-Date: Wed Dec 5 01:40:31 2007 -0800
-
- Added support for autotest.
- Requires a new release of ZenTest to actually work.
- I'm tired, I'll do that tomorrow
-
-commit 9e3e41d71d1bab8104ae17ff34aaa2311be3b0b1
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Dec 4 22:59:49 2007 -0800
-
- Commit miss for require specs
-
-commit d1a6f0805b739930e54406188e32ac1e0f30a74b
-Author: Eric Hodel <drbrain@segment7.net>
-Date: Tue Dec 4 22:24:49 2007 -0800
-
- Add specs for Kernel#require, never add .rbc files to $LOADED_FEATURES
-
-commit a60e3bf901b62fbbbef59acb2c6c9f164be1fbbc
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Dec 5 14:10:15 2007 +1100
-
- Cleanup case spec, update excludes
-
- * converted case specs to not use should
- * separated out case specs with target expressions from those without
- * updated excludes for two failing specs under compiler1
-
-commit f0de77911ff0b4532a47fb9803685e8d968d51ec
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Tue Dec 4 09:42:49 2007 +1100
-
- Fixes for compiler2 when_spec failures
-
- * Added compiler2 spec for when without an arg
- * Added spec for when without arg with an else to
- spec/language/case_spec.rb
- * Implemented many_if sexp compilation
-
-commit c9c67738ecae341441098993923838a15b64d166
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Dec 4 20:42:27 2007 +0100
-
- Test Etc.getgrnam() with "daemon" instead of "root".
-
- The "root" group seems to be a Linux-ism.
-
-commit 1fd6d97e8eb20ce9908cc0abd09b7c5555ff5720
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Dec 4 19:31:24 2007 +0100
-
- Post-move fix for the Options spec.
-
-commit ead52428d99549b6b53b8897d969e80072395ef6
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Dec 4 19:12:28 2007 +0100
-
- Moved codearchive.rb, options.rb and readline.rb from kernel/core to lib.
-
-commit 0e4568bcc23011957cc250de2a93031648281b21
-Merge: 78fba04... fbc5ad5...
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Tue Dec 4 00:50:46 2007 -0600
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 78fba04c31e9d97c32862e9e104e3917dcff9137
-Author: Charles Nutter <headius@wlan100.headius.com>
-Date: Tue Dec 4 00:39:05 2007 -0600
-
- Making socket spec more reliable by using nonblocking accept for TCPServer and adding a "ready" flag for UDPServer.
-
-commit 7e925ea53239207f5dd9ac5daddda8e0f1f3b687
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Dec 2 23:33:29 2007 +0100
-
- Implemented Etc.
-
-commit 450778cf5f416f6b9531664d4fff2c159c93cbe7
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Sun Dec 2 01:39:28 2007 -0600
-
- Shared spec for class_eval.
-
- - removed method-arguments from describe string
- This was causing bin/completeness to report 0 examples for Module#class_eval/module_eval
- - examples checking for TypeErrors test the exception is raised, but don't check
- the exact message as it is not part of the interface.
-
-commit cd0d11c7eb23d881f1dd73701bd3edc12c5bd744
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 1 15:28:41 2007 -0800
-
- Updated CI excludes for Dir.[].
-
-commit e41e501bcf686937fbd3b8cfc86f325d7e06184d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 1 10:54:35 2007 -0800
-
- CI spec excludes updates.
-
- * Fixed rake pristine task to whitelist Kernel#require fixtures.
- * Updated CI excludes for Dir.glob and Dir.[].
-
-commit 8f362a0350238366565a373f1feb9594efe03407
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Dec 1 18:50:55 2007 +0100
-
- Make sure we delete the directories we're creating in the mock dir.
-
-commit dfc1b1cd32f47b48dd358ca50226d614425ef8b2
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Dec 1 18:08:27 2007 +0100
-
- Dir.chdir now always resets the working directory when called with a block.
-
-commit 02f41a92bbafd1a555344e1082970e090cd1f9a5
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 30 23:41:29 2007 +0100
-
- Call StringValue on require's and load's argument.
-
-commit 601fd404ba04f383ee286be015edb7e8c58574d5
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Nov 30 14:27:44 2007 -0800
-
- Refactor Kernel#require
-
- * Refactor a bunch of Kernel#require into Compile#require_feature
- * VM.load_library now detects if the extension is already there
- and doesn't readd it
- * Added specs for #require
-
-commit 9b903cb7c5c6a3bfbaa3a7a91dc7bad830af7294
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Nov 30 10:56:02 2007 +1100
-
- Compiler2 fix for anonymous masgn, e.g. * = 1,2
-
-commit 08bc0a2f14494a30d5956d5bdcca9eb37c921780
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 30 00:16:07 2007 +0100
-
- Made check_argcount work with methods that don't take any arguments.
-
-commit 96108240fead7d764f3ec37d5eb20294f3a9dd97
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 29 21:45:32 2007 +0100
-
- Updated the CI excludes for Method#call.
-
-commit 61805ab7fac6ae9855baa05b42aebe66c3a2b3d3
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 29 21:44:49 2007 +0100
-
- Made Method#[] an alias for Method#call.
-
-commit 219d34dedf6ff0ed083cb5f1e8b6a5c437ad366c
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 29 21:22:05 2007 +0100
-
- Enabled the Kernel#method_missing specs.
-
- They pass now that they specs aren't confused by the Dir spec helper
- methods anymore.
-
-commit de5320efe8095e612e235bea7053084bb61d300d
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 29 21:17:58 2007 +0100
-
- Moved the Dir spec helper methods in their own module.
-
-commit 1ae47b5c091c209597bec7475935bbcff34b50b5
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 23:45:09 2007 -0800
-
- Applied patch from #151.
-
-commit adb5b139afa452869464fe53b710d7cb8b93131b
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 20:29:38 2007 -0800
-
- Better fix for guards to distinguish ruby, ruby1.x from ruby1.9.
-
-commit e53f72172e395c7766dcecadd2ffd6c7caf303e7
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 28 20:15:27 2007 -0800
-
- Patches (or modified patches) from #157-162.
-
-commit b07eeee79ea5a0c0160c34aec2d690f1b46f7380
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Nov 28 14:43:41 2007 +0100
-
- Fixed Bignum#modulo and Bignum#remainder.
-
-commit 85b05b5103aaeb5d946e0f691f77af2dafa6f30a
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Nov 28 01:00:07 2007 +0100
-
- Unified the File.unlink and File.delete specs.
-
-commit 2ec59a82f279a4ba6b5b781c90a7714aba767ed9
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 23:30:43 2007 +0100
-
- Be more specific wrt the expected exception.
-
-commit 54236949e9b974d4c4dcf95b63318c844c62aca4
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Tue Nov 27 19:58:50 2007 -0600
-
- Module#<=> is working, Updated CI excludes for Module specs.
-
-commit 55c7529f4c8b02eff7e0b594f33b28750877fca2
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Tue Nov 27 14:53:02 2007 -0600
-
- Specs for Module#private/public/protected
-
-commit 5b693fae3464abb6a5aa05d8236bd8f4610c89d4
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 19:36:06 2007 +0100
-
- We cannot use File.exists? to check whether a symlink exists.
-
- Use File.symlink? instead.
-
-commit e7eb6a8e1e1310c08220db0ed7979ec4c721fccb
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 19:34:48 2007 +0100
-
- Moved the after(:each) block before the specs, so the block is actually run.
-
-commit 4c284abb32029029ab7002147ef544493c7070f6
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 19:00:30 2007 +0100
-
- Added a missing Errno.handle to File.readlink.
-
-commit f163ca7c5e4a03d698a881853d1e0fab8a5be1a4
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 18:42:08 2007 +0100
-
- readlink() only works with symbolic links.
-
- This makes the spec pass on MRI.
-
-commit ca1cb21b5f694b3850a838f88d3ac5ded7de3e1f
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Nov 27 18:40:43 2007 +0100
-
- Naming convention fixes.
-
-commit cbf351cb59152a5528f6c6105cee96c67f7f6fcd
-Merge: f70d531... 5452983...
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Mon Nov 26 19:48:21 2007 +1100
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit f70d5314fcc75ef2e32fbd484de58bd5f7ed6cbc
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sat Nov 24 17:29:29 2007 +1100
-
- Implemented File::symlink and spec.
-
- Kudos to the Melbourne Railscamp :)
-
-commit c4a6a804185c18a182206afc1b8d5209d208077e
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sat Nov 24 01:08:41 2007 +1100
-
- Removed trailing whitespace.
-
-commit 9b9820e512f56b2c23c760887251d72c187aa297
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sat Nov 24 00:50:11 2007 +1100
-
- "Added File::readlink spec"
-
-commit 2dd272afe315dae0ad0b9bd49b6dfa9e98e50b1c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Nov 23 17:11:54 2007 +1100
-
- Spec-ed implementation differences on masgn RHS eval order
-
- Rubinius is (for now) deliberately non-compliant wrt eval
- order of RHS expressions in an masgn.
- * MRI, JRuby eval left-to-right
- * Rubinius evals right-to-left
-
-commit 361a1adcee182cf069352effd0949064b621bddc
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Fri Nov 23 16:16:08 2007 +1100
-
- Additional parallel assignment specs - use of to_ary
-
- * Added spec for when to_ary should be called on the RHS of an masgn
- * Added additional example of a complex masgn (from JRuby tests)
-
-commit 97cb3f5758f102cf8a07262c4c9bef4b22ca88b7
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Thu Nov 22 22:04:51 2007 -0600
-
- Added specs for metaclasses of true/false/nil on metaclass_spec as suggested by rue.
-
-commit d4f9eb7cd5fb17e3e8ce52db39e95a96362d3ad0
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Nov 22 13:05:10 2007 -0800
-
- Fixed wording of Rubinius extension Bignum domain specs.
-
-commit 50e1f80ef54d25aaa69d52a3d422547593836ac6
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Thu Nov 22 17:18:54 2007 -0500
-
- Added excludes for Kernel#open and Thread#abort_on_exception
-
- * Excludes Kernel#open raise specs
- * Excludes Thread#abort_on_exception specs
-
-commit 25607d4d884b4597bc69560e9390cd9dc1f4e44d
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Thu Nov 22 13:47:50 2007 -0600
-
- Specs for Module#alias_method
-
-commit c207618ad4113501aa5df4adb5d5aa3a60f5b9ff
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Nov 22 10:59:34 2007 -0800
-
- Use RUBY_ENGINE first, then pull in rbconfig
-
-commit ed5a46e13b35d6ad48cce1d3eed96c2f78ace049
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Thu Nov 22 11:42:36 2007 -0500
-
- Added basic specs for abort_on_exception
-
- * Added specs for Thread#abort_on_exception ($DEBUG on and off)
- * Added specs for Thread#abort_on_exception=
-
-commit 05ecef9162ba2c4a0da90c966a20a4f45c353d93
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Thu Nov 22 08:39:53 2007 -0500
-
- Added specs for when parameters are missing or invalid parameters are given
-
-commit 25d2c940d561dcac2c06df747762a229dddfbed1
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Nov 22 15:33:17 2007 +1100
-
- Another parallel assignment spec - rhs should evaluate l->r
-
-commit 8e4f8de446b842c13ad45a8e0e2c3c1ebf30bddb
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 21 17:42:17 2007 -0800
-
- Stop-gap prevention for Kernel#callcc hanging CI specs.
-
-commit a9d7163e4d9e8d4fb79c9769691b232676a44bd8
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Nov 21 15:50:39 2007 -0600
-
- remove compliant(MRI) from callcc specs
-
-commit 812e922c8e7cda728d6b7f32933b75eb009eef11
-Merge: 2e221b9... f24bb1f...
-Author: Nathan Witmer <nwitmer@gmail.com>
-Date: Wed Nov 21 12:32:18 2007 -0700
-
- Merge branch 'callcc_spec'
-
-commit f24bb1ffdf941df78098da262a62e881653b1a99
-Author: Nathan Witmer <nwitmer@gmail.com>
-Date: Wed Nov 21 12:31:28 2007 -0700
-
- Added scope-related callcc specs, compliant(:ruby) only.
-
-commit 2e221b9f1d7ffa41431e5bd51fdd36434e7f838f
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Nov 21 14:41:43 2007 +0100
-
- Spec and fix some more String#slice bugs when given nil, also use Undefined.
-
-commit db338d9d8705fd668a5639d483ff47908aa014ca
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Nov 6 16:53:13 2007 +0100
-
- Fix String#rindex when given nil as offset.
-
-commit 6eab3b692a50c1a37cc39c21d743de1488402f64
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 21 00:00:24 2007 -0800
-
- Added MRI stdlib Fcntl to lib/ext with build script.
-
- Added lib/fcntl to load extension. This may need a better solution.
- Added INT2FIX to subtend.
-
-commit 5268c0b29c1fb07a911fe601e30b21ffe04f7e81
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Nov 21 17:02:14 2007 +1100
-
- Additional specs for parallel assignment
-
- MRI allows parallel assignment to:
- - assign via object.method=
- - assign via []=
- - use a lhs arg as an arg to another lhs assignment
-
- All three scenarios currently fail in Rubinius, apparently due to
- miscalculating the number of args to an assignment method under
- parallel assignment.
-
-commit 462f68b95a70c24e41cad5a40969c4651c7de181
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Tue Nov 20 02:12:44 2007 -0500
-
- Added specs for Kernel#open when block is given
-
-commit ab9e40600fd2522d4abce86f7b8bdc632f6e9018
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Mon Nov 19 23:42:55 2007 -0500
-
- Added very basic specs for Kernel#open
-
-commit b47efc9f9872ecca68a06f6864f39617e06762b0
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 19 00:24:15 2007 -0800
-
- Updated CI excludes. Runs clean on Leopard.
-
-commit 3ff04e52bc9cb03439567ddb9b3b63b3034b30c3
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Nov 19 00:03:58 2007 -0600
-
- more specs for Kernel.callcc, ensures callcc return value semantics
-
-commit 06d5312c51b09faef87d2deb53f3c472eaa94100
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Sun Nov 18 17:49:44 2007 -0600
-
- basic callcc behavioral specs
-
-commit 53433f0e9ddba2eac876f7a1fb0f9d292ee37286
-Author: Nathan Witmer <nwitmer@gmail.com>
-Date: Fri Nov 16 16:51:18 2007 -0700
-
- Added Kernel#callcc spec and fix for LocalJumpError with no block given
-
-commit d324779b8b5c8dd84438c08ec4f2b2574282f93e
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 15:17:21 2007 -0600
-
- Added Module.nesting
-
- Some specs are failing on rubinius because the parent
- field is not being properly set.
-
-commit cff726c9dc3631b2e0ddc3e12bd3af532f7e1ef4
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 14:49:38 2007 -0600
-
- Added spec for calling Module.nesting on root level
-
-commit 05adb6070889d7021a1e53ab82b855c3554d4f5c
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 14:45:23 2007 -0600
-
- Fixed specs for Module#constants
-
-commit 1f1c857e1d8c37213a91daaad3fc3bfcbf2bef61
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 14:43:55 2007 -0600
-
- Fixed spec description for calling Module.nesting from methods.
-
-commit 242c947c6e4d007685e8aa0c44ac505c7dab4239
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 14:38:32 2007 -0600
-
- More specs for Module.nesting
-
-commit 3560fd7ef0d5a65a9cb055d87fa7103ed3bdb029
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 10:24:45 2007 -0600
-
- private keyword specs reflecting problem described on ticket #133
-
-commit fd31e1e592237832bd5e605f604d15385df0615a
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 16 04:15:27 2007 -0600
-
- specs for Kernel#block_given? by Francisco Laguna
-
-commit 87ebce4cf2430198578decdb4c7dc1003db37f8e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Nov 15 22:07:39 2007 -0800
-
- Ticket #121 by Jeremy Durham -- File modes
-
-commit 4a67e0ade233aaaa3a2ff17161b298872f8a5f83
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Thu Nov 15 14:20:19 2007 -0600
-
- Splitted enumerable_spec.rb into a file per method.
-
- Added some specs by Francisco Laguna.
-
-commit 0b933650330f57e7db1bf8574d0b7eecf0635996
-Author: Bryan Helmkamp <bryan@brynary.com>
-Date: Tue Nov 13 11:34:20 2007 -0500
-
- Added specs for File.mtime.
-
-commit 42a7de27c1a6082fee7b9baaf05b9394ffe90ddd
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Nov 12 19:57:38 2007 +0100
-
- Updated CI excludes for File#atime and File.new.
-
-commit 3d106d6a9b8ce0b34e7b6f9426da51b83fe5f676
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Nov 12 19:54:43 2007 +0100
-
- Added File#path.
-
-commit 247da25a0120d468fe9f189a6235962f9658b65e
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Nov 12 19:23:09 2007 +0100
-
- File now deals with numeric modes and accepts a permission argument, too.
-
-commit 087deaed0dcf4ae2c8dc713eeccfed9a0ebabe6f
-Merge: 4355e96... 1c9d213...
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 23:15:01 2007 -0800
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 4355e96b05de4d4d086dfa86b8fe19bdcecfbe82
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 23:14:16 2007 -0800
-
- -a
-
-commit 7e975d1aca38a3bfe07fda431aeaba376bce19c1
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 23:09:47 2007 -0800
-
- Get rid of irrelevant specs
-
-commit 1c9d2133fc294964ce08e9a7020083c379f74ca0
-Author: David Waite <david@alkaline-solutions.com>
-Date: Sun Nov 11 23:46:08 2007 -0700
-
- Remove temp directories within mkdir spec on exception.
-
-commit 2110fc75dc6a7ab521249f259bc6fdc78d565b11
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 22:36:08 2007 -0800
-
- Update CI Excludes
-
- * Expected failure of "raise an Exception if it has
- the wrong number of argments" due to dispatcher bug
-
-commit 0f2a183a46ba085d9c99ed4767cd18c0482e6d45
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 22:14:07 2007 -0800
-
- Implement File#atime
-
-commit 671b340f340ab6b8d9c13b27d52a782ce3268b2a
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 11 21:24:34 2007 -0800
-
- Update CI excludes
-
-commit f7ba96f6b41de9a3696a03e9efe25c8b037a4f07
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sat Nov 10 11:24:12 2007 -0800
-
- Adds spec for File.open
-
- * In resonse to Lighthouse Ticket #102
- "File.open should throw Errno::EACCES opening non-permitted file"
- * Passes MRI, doesn't yet pass RBX
-
-commit 719329b3f5179766e23a27e427cd0c0846c85ffa
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Mon Nov 12 10:38:42 2007 +1100
-
- Added IO#to_i implementation and spec.
-
-commit cc100fc08be101ecdf0daba1966977fb8e39fa6e
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Mon Nov 12 10:30:25 2007 +1100
-
- Added IO#fileno implementation and spec.
-
-commit d036f5c16a4836d638be83108be35df532d9221a
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Nov 11 23:17:12 2007 +0100
-
- Made SystemStackError subclass of StandardError.
-
-commit bf1c3dc3e463aeaf4e0cee1cbd46b15e7693a395
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Nov 11 20:36:25 2007 +0100
-
- Removed an old Method#arity spec exclude.
-
-commit 72c3495f3513e54c2488292bcdaca9208b6f0339
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 11 10:44:53 2007 -0800
-
- Removed transient dirs from Dir specs.
-
-commit 11f0ed51b4bfb3bea2b544a82b3158fd3daf2ad8
-Author: Victor Hugo Borja <vic.borja@gmail.com>
-Date: Fri Nov 2 03:02:28 2007 -0600
-
- Specs for Module#remove_const
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit e8158f14f0f02e3b0cdcb4182e1277928324cc0c
-Author: Nathan Witmer <nwitmer@gmail.com>
-Date: Sun Nov 11 08:19:10 2007 -0700
-
- Fixes for UDPSocket spec
-
- * Renamed the description to match what was actually being tested
- * Uncommented the code and wrapped it in an "it" block, to prevent
- conflicts/hangs with bin/completeness runs.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 9b973a98d2ebddacd50f0fcb58903bb53bdff3f5
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Nov 11 13:30:22 2007 +0100
-
- Ticket #98: Dir includes Enumerable now.
-
-commit 8d957f186cd4d2c5e6b236de4a0878d38b464848
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Nov 11 13:26:00 2007 +0100
-
- Implemented Module#included_modules.
-
-commit 0021b24ba490fe01f96ef17957328feeedfc4c29
-Author: Nathan Witmer <nwitmer@gmail.com>
-Date: Thu Nov 8 21:42:41 2007 -0700
-
- Commented out code in UDPSocket spec so bin/completeness doesn't hang
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 56687aed201fb864587807cca893268a9f1e2050
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 11 00:10:14 2007 -0800
-
- Method fixture for yield specs.
-
-commit 421aa58f9135807487864adcdcac79f7b6da33c1
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 11 00:08:35 2007 -0800
-
- Specs for yield keyword based on patch in #114.
-
-commit 5ba0b2030c55474f9d8a096d309678ca24a4699b
-Author: Jeremy Durham <jeremydurham@gmail.com>
-Date: Sun Nov 11 01:35:08 2007 +0100
-
- Ticket #105: Implemented Bignum#eql?.
-
-commit 47356fe39033f8571559a4fef933681fda871efd
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Nov 11 01:14:26 2007 +0100
-
- Made specs for Kernel#respond_to? and Kernel#method pass.
-
- KernelSpecs::Foo#baz is defined in another spec, so these two specs
- may not rely on #baz being undefined. This is a horrible workaround
- for the problem that multiple specs make use of the same module and modify
- it freely.
-
-commit 68b4fc7c0192f537fe9727927ac35c440dbdc03a
-Author: Akshay Rawat <akshay.rawat@gmail.com>
-Date: Thu Nov 8 18:21:03 2007 +0530
-
- Updated CI excludes.
-
-commit a1eee3814a5d054cd00e26b40c063d41880bf6c7
-Author: Chris Pettitt <cpettitt@gmail.com>
-Date: Sat Nov 10 14:10:47 2007 -0800
-
- Refactor IO.gets spec to have less duplication.
-
-commit 56497d27bdb3a82d549f89b9fc9fcf0709f99b3e
-Author: Chris Pettitt <cpettitt@gmail.com>
-Date: Sat Nov 10 14:07:21 2007 -0800
-
- New spec: IO.gets('') should advance the file position to the next non $/ character.
-
-commit 95158f5a4141d5d3e2893304e49bfeb62cc7b226
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 10 13:35:03 2007 -0800
-
- Added rescue to prevent meltdown until rbx begin/rescue/ensure is fixed.
-
-commit a39155cb029ca3c1e5e5d69e0e269c685c040f6e
-Author: Chen Yufei <cyfdecyf@gmail.com>
-Date: Sat Nov 10 12:24:38 2007 +0000
-
- Fixed IO#gets when separator is empty.
-
-commit f9c31ce1d2a68c15def98aad6c6ff35eb56cd523
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Fri Nov 9 20:24:40 2007 -0800
-
- Clean up Enumerable#include? specs
-
-commit f017fad69be5d4034a4c5437acf77ec4749b0d75
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 4 20:54:06 2007 -0500
-
- Clean up Enumerable#(collect, entries, find, find_all) specs
-
-commit 81550f082396b4455c3681ae966be1371be0a5db
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 4 13:18:52 2007 -0500
-
- Update excludes
-
-commit d5fd2ee893ea608c7e19cb674a4da7b9f49542e6
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 4 12:16:58 2007 -0500
-
- Cleanup/rewrite Enumerable#find tests for sanity and clarity
-
-commit 39f21aa76f6ddc45be79e4e4e978b4c1c2beed71
-Merge: 17d2e4c... c1b9f74...
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Fri Nov 9 20:25:13 2007 -0800
-
- Merge branch 'master' of http://git.rubini.us/code
-
-commit c1b9f74f88be963e72de763da9130f46869d89fb
-Author: Chris Pettitt <cpettitt@gmail.com>
-Date: Fri Nov 9 12:36:04 2007 -0800
-
- Fix some failing specs for IO#each and IO#each_line.
-
- Also refactor some common code into a helper method.
-
-commit 74af37b849507e504503359a08245effaad7634a
-Author: Chris Pettitt <cpettitt@gmail.com>
-Date: Fri Nov 9 10:58:33 2007 -0800
-
- New specs for IO#each and IO#each_line
-
- This change adds some new specs for IO#each and IO#each_line factored into
- a shared .rb, because one is the alias of the other. Added failing specs to
- excludes.
-
-commit d162a396b566846445328d6c42d3d5f10fcf7ee6
-Author: Matt Pelletier <matt@eastmedia.com>
-Date: Fri Nov 9 02:32:25 2007 -0500
-
- Add and refactor patches from Andrea OK regarding #send
-
-commit 63f0ed010e65549597f6bddb0686ba04157ca478
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Nov 7 09:52:25 2007 -0800
-
- Fixed Method#call spec failing from renamed fixture method name.
-
-commit 1ef46468d7808c52b07388130069cb2e7854bff8
-Author: Matt Pelletier <matt@eastmedia.com>
-Date: Wed Nov 7 04:48:39 2007 -0500
-
- * Update CompiledMethod#arity to be accurate for cases of required and/or optional arguments, with or without blocks
- * CompiledMethod#arity is still inaccurate when splat argument is present (the presence of splat overrides #required)
- * Add specs for more thorough coverage of various argument use cases
- * Includes known Rubinius-failing specs for splat-related arity
-
-commit b7726f26dae95936aa1c3fdf2c52dd18ef7413cf
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 17:48:51 2007 -0800
-
- Updated CI excludes for fixes to public|private_class_method.
-
-commit eb18f898e3ae8e5a1bf3b01291a12516c6a22301
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 17:18:22 2007 -0800
-
- Added Module#protected_method_defined?. Updated CI excludes.
-
-commit aa8904cdbd8b4851be4f05cec3000b04cfc9f6c1
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 17:14:12 2007 -0800
-
- Added Module#private_method_defined?.
-
- Fixed specs for Module#public_method_defined? and
- private_method_defined?. Updated CI excludes.
-
-commit 063b61759ee86f5def2422d16f1eb854c8b9eb76
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 13:39:21 2007 -0800
-
- Updated CI excludes for StringIO.
-
-commit 3c79f871379d2d4b5431138033f723efbf4a795d
-Author: Dr Nic <drnicwilliams@gmail.com>
-Date: Sun Nov 4 16:45:30 2007 -0500
-
- Extended StringIO spec "flattens a nested array before writing it" to ensure deeper test scenario
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 916d617a60cf83ac26c3090310236193f5842ff6
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 13:11:54 2007 -0800
-
- Updated CI excludes for String#scan.
-
-commit fee1d904197c369c561ae3b11aaf582f1b87d1b0
-Author: Matt Pelletier <matt@eastmedia.com>
-Date: Sat Nov 3 16:06:16 2007 -0400
-
- Fix test of String#scan. Do not force matches into array using splat.
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit cc9182cfcde60a63bf566f73c6004b7e46347e77
-Author: Daniel Lucraft <dan@fluentradical.com>
-Date: Thu Nov 1 17:01:03 2007 +0000
-
- Added File.rename
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit fc2b7aa65ab338d8ff543552659046c93659c3ce
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 12:06:13 2007 -0800
-
- Commit rework of Carl Drinkwater's patch from #72.
-
-commit 7f6564b96762d7b3deb9f021789182f5c664a766
-Author: Chris Pettitt <cpettitt@gmail.com>
-Date: Sun Nov 4 10:38:04 2007 -0800
-
- Fixes for two IO#gets spec failures.
-
- This patch fixes the following two IO#gets spec failures:
-
- IO#gets assigns the returned line to $_
- IO#gets returns the entire content if the separator is nil
-
- Signed-off-by: Brian Ford <brixen@gmail.com>
-
-commit 705e8e05496167b1af3a1e3ff3446d325ca54e07
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Nov 5 02:10:56 2007 -0800
-
- Added Module#public_method_defined?.
-
- Updated CI specs for #public_method_defined?.
- Small fix to find_method_in_hierarchy to symbolize arg.
- Updated some spec wording and removed spec'ing exception string.
-
-commit 17d2e4c6ae0c40376fe121786a362c8bc8ce951c
-Merge: 2b77ee8... c07472c...
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 4 20:58:42 2007 -0500
-
- Merge branch 'master' of http://git.rubini.us/code
-
-commit bd6c27f4724bdc461a7036e6373a0ad23060020a
-Author: Trotter Cashion <cashion@gmail.com>
-Date: Sat Nov 3 15:57:21 2007 -0400
-
- Added operator precedence specs for '&&' and 'and'.
-
-commit 2b77ee8b74373a3251973d96c931422909605e29
-Merge: 30d7618... 76aa72e...
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sun Nov 4 13:43:23 2007 -0500
-
- Merge branch 'master' of http://git.rubini.us/code
-
-commit 2c90ce28cc73e08d9fb74b5c7e815807314ba269
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 4 07:18:09 2007 -0800
-
- Updated CI excludes from 85d63b676e.
-
-commit 85d63b676e463a2bec9a322bc8eeffd2daee433b
-Author: Chen Yufei <cyfdecyf@gmail.com>
-Date: Sat Nov 3 23:39:23 2007 +0000
-
- Added specs for IO#gets
-
-commit be5b9595f2077080c0c1179ab9689352d8faea3a
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 4 00:31:12 2007 -0700
-
- Updated CI excludes.
-
-commit d46ad4b63d4a5f77609b0880b7f24e8e27404805
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 4 00:11:52 2007 -0700
-
- Updated CI excludes.
-
-commit 1f307223c673c6744f8b85fc3e707a3419b1a0e8
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Nov 4 00:06:48 2007 -0700
-
- Guarded #freeze specs for MRI and JRuby.
-
-commit ca50fd7d979c36f8af306e0e1474aac5408dd66d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 3 23:22:31 2007 -0700
-
- Guarded specs for #frozen? for MRI and JRuby.
-
-commit 16b36030a796b877809d5d6ea556266c4b4a6413
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 3 20:53:26 2007 -0700
-
- Removed NULL characters from language/precedence.
-
- Enhanced rescue output when loading spec files.
-
-commit 10510ece16ebb5e0ba921e0be631a4740f3e4453
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sat Nov 3 23:09:30 2007 -0400
-
- Fix a method_missing cache error.
-
-commit b313c5632b039c03a448ae3b1046701c8b3243a2
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 3 14:10:29 2007 -0700
-
- Changed shared spec behavior to be compatible with RSpec.
-
-commit 7b825b89e96b3c8e38f9b8bcc8edf2bc6ec6ff22
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 3 14:09:47 2007 -0700
-
- Fixed language/class specs.
-
-commit 30d76181b0b3a9c5ac99c9d0e22a6a451346eff4
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Sat Nov 3 16:47:49 2007 -0400
-
- Fix Dir#each/Dir#entries/Dir.foreach specs. They weren't updated for fixtures
-
-commit f44a8cceb9a186a7127276db2207dfc79957ee8d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Nov 3 13:06:35 2007 -0700
-
- Guard File.(un)link for jruby.
-
-commit 1ec2c3a99ca562c8944aac1f4a60f8e0af0aaf17
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Nov 3 18:20:48 2007 +0100
-
- Properly resize the array in Array#<<.
-
-commit 8dec9918d8a6233ec2cde29d54687a5d950dc8df
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Nov 3 17:13:57 2007 +0100
-
- Fixed Array#unshift for the case when @start > 0 && @start < values.size.
-
- Also extended the Array#unshift specs to cover this case.
-
-commit 50b90918cd5a9a05e475690703c7867b443d191b
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Nov 2 13:47:53 2007 -0500
-
- added IO::foreach, fixed gets to use string separator, and fixed IO::readlines to use File.open
-
-commit 3efc01e110473d003ffb0a1376ec179f30e600de
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Nov 2 13:30:44 2007 -0500
-
- specs for IO::foreach and specs to test IO::readlines,IO.readlines with string separator
-
-commit fad18610b4416dfcfaf35db5029e880dff7e9820
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 29 14:10:11 2007 -0500
-
- basic exec implementation and a single basic spec (not sure how test test exec)
-
-commit 730fc3ed9afc54612d14093148fb8583c9e39fe3
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 21:41:25 2007 +0100
-
- Return mkdir()'s return value from Dir.mkdir.
-
-commit f5766696e701a069f908b3b5d5cfbccfee15ef1f
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 20:46:11 2007 +0100
-
- Implemented Dir.foreach.
-
-commit c696f1edc50c58b87270811c0c9aa0e49b356fe7
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 20:38:36 2007 +0100
-
- Implemented Dir.entries.
-
-commit e8e6188b252172690c1b584e528e3c71035897cd
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 18:16:13 2007 +0100
-
- Raise an error if the opendir() call in Dir#initialize fails.
-
-commit 024309b560c6c69f6f331c614df1da221be7054c
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 16:15:19 2007 +0100
-
- The Array#[]= spec seems to work now, so enable it.
-
-commit 76f118e62a0784326f5edf1c0fe46f6b6e682eee
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 14:28:49 2007 +0100
-
- Made Math.ldexp only accept integers as the second argument.
-
-commit 22bd7369efd1f738835e9c0a6a4624a26dae02d1
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Nov 2 13:30:50 2007 +0100
-
- Implemented some missing File::Stat methods.
-
-commit d6dc42d9085fed5f8bf482d7f84dd9c5fbd4423c
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Nov 1 12:24:53 2007 -0700
-
- Fixed specs failing MRI for File.stat and File.basename.
-
-commit 46f4de189e987f3071ede57f2bb1f7c892d67bd4
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 1 17:30:47 2007 +0100
-
- Fixed ticket #83: Array#push doesn't die anymore after calling Array#shift.
-
-commit 8debed24e957e48b10d60885d9a43083aab4d923
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Nov 1 11:14:22 2007 +0100
-
- In the Numeric#coerce spec, coercing strings to numerics should work.
-
- We can remove the TypeError checks from this spec, since those
- are included in the specs for the Numeric operators.
-
-commit 28cf656fb25ce38453acb2efdcf2e9ac16bb4460
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Nov 1 01:33:31 2007 -0700
-
- Removed Hash#fetch definition from fetch spec.
-
- Fixed spelling of Hash#find_unambiguous.
- Updated CI excludes.
-
-commit a6a69b469d94d0912ccbf123fdb9f53cbaf32830
-Author: Akshay Rawat <akshay.rawat@gmail.com>
-Date: Tue Oct 30 21:47:51 2007 +0530
-
- In the Time#isdst spec, don't depend on the system's current time zone.
-
-commit 1be129f98e0d548a023cc32f5ab763361e2a9c6b
-Author: Daniel Lucraft <dan@fluentradical.com>
-Date: Wed Oct 31 21:05:04 2007 +0000
-
- Fixed String#split to not return non-matching captures anymore.
-
-commit 5f7f798ef26fc8ee1e83c5e392c1fb2e60e31382
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Oct 31 21:54:56 2007 +0100
-
- In the Numeric#coerce spec, don't try to coerce strings to numerics.
-
-commit e26b7645af27d5bfc250c2c11f7e72349750f5c7
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Oct 31 10:52:13 2007 +0100
-
- Added a failing spec for Ticket #83.
-
-commit 9144f0c55eb5f40409bec514f08f89bdba61f800
-Author: Daniel Lucraft <dan@fluentradical.com>
-Date: Wed Oct 31 13:57:54 2007 +0100
-
- Fixed math/constants_spec.rb.
-
-commit 4b521cacb667ca5245954bc03ebfec67c0ac235c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Wed Oct 31 23:26:45 2007 +1100
-
- Modified spec to reflect expected differences in masgn retval behavior
- between rbx (true) and MRI (array of rhs vals).
-
-commit 1f6c50f5c77566e66cb0b842733b7f4f4b24e937
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 30 18:13:47 2007 +0100
-
- Use a fixed timezone for the Time#strftime spec.
-
-commit 60a25e997def085f3ae29773ce70ddc5b7c38d46
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 30 00:47:38 2007 -0700
-
- Fixed Kernel#raise to not output if $VERBOSE == nil.
-
- Guard Marshal.dump specs to eliminate error output until
- a proper Marshal is implemented.
-
-commit e446f2e329a6dfaacb45b5b86ba43ebd9ec606a3
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 29 23:17:49 2007 -0700
-
- Added IO::SEEK_SET, SEEK_CUR, SEEK_END with FFI.
-
- Fixed IO#close to raise IOError if already closed.
-
-commit fcb1ac4d076c07065878c2e65bf7bb44ddef400c
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 29 22:37:23 2007 -0700
-
- Specs for IO#seek and IO::SEEK_SET, SEEK_CUR, SEEK_END.
-
-commit a3570f6702dabd303fcd10d4cfc0e753cff69bb5
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Oct 29 22:33:34 2007 +0100
-
- Make Module.new actually work.
-
-commit 9709fa96b91afe5140f76726f1f7d4b89f8a6d54
-Author: Brian Donovan <brian.donovan@gmail.com>
-Date: Mon Oct 29 11:30:32 2007 -0700
-
- Ticket #75: Fixed Enumerable#sort_by.
-
- We must not call the comparison proc when the object and pivot are
- identical.
-
-commit 52e97da6bbcd28ec4349abcf25b089648d085652
-Author: Akshay Rawat <akshay.rawat@gmail.com>
-Date: Tue Oct 30 02:18:56 2007 +0530
-
- Enabled Math specs that were fixed by Ticket #59.
-
-commit 0f98800d4ab1db526304f1d26597ca3880c811da
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Oct 29 19:29:16 2007 +0100
-
- Ticket #59: Kernel#send now calls private methods, too.
-
-commit 754e48c223c3464c7d048452585c07b8d0b3d8c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 29 00:11:41 2007 -0700
-
- Specs for IO#rewind.
-
-commit 0bfd6bcca8fb287899fadeae81dd7c00b05d07e9
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Oct 28 23:40:37 2007 +0100
-
- Module#public_instance_methods now handles attribute accessor methods.
-
-commit 0a22b36b9bc50a34f1da1d0e994f1a6689195652
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Oct 28 23:26:17 2007 +0100
-
- Added a failing spec for Enumerable#sort_by.
-
-commit 006534b173a186c25c228b653d5ac9d81b20f57e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 21:51:40 2007 +0100
-
- Update Module spec excludes.
-
-commit 496df827eeeb600858fa8c7b26482aa3f653fee1
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 21:50:47 2007 +0100
-
- Make Module#ancestors specs pass.
-
-commit 18185cde2b47374c304e2528a084ea1f7b5178d2
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sun Oct 28 19:46:22 2007 +0100
-
- Added a failing spec for building an array that includes a splatted array.
-
-commit f120a470a5e07a7e53b1e006173942d58956e86b
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 19:33:10 2007 +0100
-
- Extended Kernel#` specs.
-
-commit 7e184c5bbc7be16cc8f7be01713543f222edd267
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 19:00:52 2007 +0100
-
- Removed Exception message dependencies and extended Kernel.String specs.
-
-commit 2853dc58209b3b8d122cee66c7d83e967d0879de
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Sun Oct 28 23:01:54 2007 +1100
-
- Fix for multi-arg operator assign through [], e.g. x[0,3] += 5
-
-commit 91b88710ddc1e8553e51c404cee4039f4d6abf24
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 13:05:08 2007 +0100
-
- Fixed File.ftype specs.
-
-commit 448fdc2def3a9ab249dadf9335568ca30b76f70e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Oct 28 00:36:11 2007 -0700
-
- Updated compiler specs.
-
-commit 0fb510c14ee8787b5965d5665e50da92a988faa6
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Oct 28 00:32:41 2007 -0700
-
- Fixed Bignum#coerce specs.
-
-commit 5e52a259b91e81fe5497f44107dee6ffd613b3be
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Oct 28 00:22:40 2007 -0700
-
- Fixed wording on Rubinius Bignum#coerce extension specs.
-
-commit 19e0259ca51691afe341b1217ab92862b307fe17
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Oct 28 00:15:18 2007 -0700
-
- Revert "Remove invalid and failing Bignum#coerce spec."
-
- This reverts commit 2371b920ca3f956213ab9e406a3b5d2afab4f18e.
-
-commit 4986ec283ee5aa9e392065c74d64952d36554b91
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Oct 27 23:50:05 2007 -0700
-
- Updated CI excludes for Array#pack.
-
-commit 5472f30201d7cddd4465adb246fa32927fe03d91
-Author: Alan Hurdle <alan.hurdle@gmail.com>
-Date: Sat Oct 27 18:38:30 2007 +1000
-
- Bunch of fixes to Array#pack to pass the current set of pack specs
-
-commit 20210a617a3f31c5dc0eda9fa371c49200c11f67
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 02:30:02 2007 +0100
-
- Updated spec excludes for Module specs.
-
-commit 712e3cc6a5d8a69834449e1039dfae3e07fcdcc2
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 28 02:18:00 2007 +0100
-
- Removed the dependency on some Exception messages.
-
-commit 2371b920ca3f956213ab9e406a3b5d2afab4f18e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 27 16:15:33 2007 +0200
-
- Remove invalid and failing Bignum#coerce spec.
-
-commit e1e62e7749d47c838d6b7cd1e95863c0c90d3de0
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 27 20:59:49 2007 +0200
-
- Fixnum#div now always rounds towards negative infinity.
-
-commit 9a4ccbe8381db5b6280c9d1dfcf6fa21a4838c4e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 27 15:09:57 2007 +0200
-
- Updated Spec excludes for Bignum and Fixnum specs.
-
-commit 889c939a668b9b1a4fd8f5a0cfd8bad85c3a5977
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 27 14:24:27 2007 +0200
-
- Fix Integer#[] when given a Bignum.
-
-commit 45d97332f4ec5a174884024c954ceeb6eb852f5f
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 27 13:46:51 2007 +0200
-
- Partial fix for #68: Fix Hash#fetch to correctly handle yielding with a default value passed.
-
-commit a785ea28f39c71a98007a7fafc23985dd21b596f
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 27 13:39:42 2007 +0200
-
- Updated CI excludes for recent Hash fixes.
-
-commit 6dd909fede466ed813ec7c5d207c5deeb69c9eb7
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 27 11:33:22 2007 +0200
-
- Fix for #67: Enumerable#sort should not depend on #size.
-
-commit 720489aa52bfabd492c307330204772b5eba6755
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 26 00:21:37 2007 -0700
-
- Updated CI excludes for spec/language.
-
-commit 41e8a07252b2df9c1e858922195a72f9a40c882c
-Author: Akshay Rawat <akshay.rawat@gmail.com>
-Date: Fri Oct 26 02:37:18 2007 +0530
-
- private keyword should mark a Module method private
-
-commit a201e631cbaabcc5964cfa3eb28a9fa8be1bf347
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 26 00:11:01 2007 -0700
-
- Added spec/language into CI specs.
-
- Updated CI excludes for spec/language.
-
-commit 833fe76de0c0b900ef5255b2abecd19943404c0c
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 25 23:53:35 2007 -0700
-
- Updated compiler specs and CI excludes.
-
-commit f31e5af358d2b5c3ff4afd3819b3a3e571427f8e
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 25 23:28:13 2007 -0700
-
- Migrated Adam Gardiner's compiler patch 236d213de8 to stable.
-
- Updated CI excludes for language/variables specs.
-
-commit bd9e47b1b7624df5e2ae0f31a7fd53c787ecc7e4
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 25 22:50:22 2007 -0700
-
- Fixed language/variables spec to use fixture class.
-
- Added CI exclude file for language/variables specs.
-
-commit 688f03ac452f698105812c28c29dcc7162b7037c
-Author: Adam Gardiner <adam.b.gardiner@gmail.com>
-Date: Thu Oct 25 22:43:20 2007 +1000
-
- Added specs for operator assignment, i.e. +=, *=, ||= etc
-
-commit 982dfee01bedb55e8dbf62d279bc4a375e58ec50
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Oct 25 16:53:45 2007 +0200
-
- Don't hardcode the result of Hash#to_a in the Hash#shift spec.
-
-commit 4bf7c8d2d387c002004da5df9f9c2a06fb65e61e
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 25 01:42:32 2007 -0700
-
- Commit tilman's language block spec additions with some modifications.
-
-commit ff8f6f5b5f5285b0fcf361d84523bf21320074b2
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Oct 24 20:20:12 2007 +0200
-
- Extended the Hash#[] spec with a test case for ticket #65.
-
-commit dc61b1e771c70e54f98859da3dd31a4ea61384e1
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Oct 24 07:11:07 2007 -0700
-
- Specs after(:each) MUST come before it blocks.
-
- Updated CI excludes for IO.read specs.
-
-commit 06539bad037e0ef7368ea5cbb5780fce7bbea443
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Wed Oct 24 21:26:49 2007 +1000
-
- Initial IO::read specs.
-
-commit a2f26d7a7b1997510edff1792eaec6507ba38208
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 23 19:30:46 2007 +0200
-
- Implemented Numeric#remainder.
-
-commit 2bc5fcee6be4db3e0e0c46aa7c1b8ef5a5c57957
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 23 19:10:54 2007 +0200
-
- Fixed Bignum#modulo(0.0).
-
-commit 68965dc12ea369f6db64c208cb2ce123c1398bb8
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 23 10:20:04 2007 +0200
-
- Extended the Numeric#nonzero? spec a bit.
-
-commit 290ddde29d6c64e9c81f69780b7b0c967b2b4901
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 23 10:15:57 2007 +0200
-
- Added Numeric#nonzero? and killed bad Fixnum#nonzero? in bootstrap.
-
- This fixes the Numeric#nonzero? specs.
-
-commit e9a1b257fc95c181e46c679d301a324134a725d4
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 23 16:07:58 2007 +0200
-
- Enabled the Numeric#step spec now that it works fine.
-
-commit f4016db94eee2ec93a2cc487181c9ec2fa0d59d0
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Oct 17 13:51:04 2007 -0700
-
- A number of fixes found while debugging test/unit and optparse
-
-commit 7c7920c3e7727c3514b493ba299a52c5e5cde8f6
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 22 18:12:42 2007 -0500
-
- Numeric#step is capable of floats and passes all tests
-
-commit ebc6ec5be0239bba544c55ff77fdc88903f4bb28
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Oct 22 20:56:33 2007 +0200
-
- Made the Symbol#inspect spec pass.
-
-commit f0db8c3d1bb5dc444fc72ed5ca222f4cf5df8b35
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 21 14:00:30 2007 +0200
-
- Fixed a bug in process_op_asgn1 and added a simple spec for it.
-
-commit 4fbce6e8a6ab8fbb6b69944677678611db68bcf2
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 20 20:03:50 2007 +0200
-
- Fixed a failure in String#sub specs
-
-commit ca0332f9edb9e01ae216dee90674fb6f9809951c
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 20 22:33:42 2007 +0200
-
- Fixed the Bignum#size spec for Rubinius' implementation.
-
-commit ae9c2ac3fe9dc59a027af7571d6d3083bcccb490
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 20 14:14:49 2007 +0200
-
- Don't rely on #respond_to? calls.
-
-commit 94938622aaf74e1f068c3b7ec8bfeccf763792ba
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Fri Oct 19 20:56:50 2007 +0200
-
- Extended the private spec.
-
-commit bf000a15edcfdd30c43ae6563b5766617f245a60
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 19 00:49:16 2007 -0700
-
- Updated CI excludes.
-
-commit ad146fc7ae22bfc26a536a40cf8dc4c0338cf25c
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Oct 18 19:45:27 2007 +0200
-
- Added a spec for the 'private' keyword.
-
-commit f15b5a8c818932d0ab5bea46f48a326e468b3511
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Thu Oct 18 19:44:54 2007 +0200
-
- Added Object#should_not_include.
-
-commit 80fdbd626d8ff99dc7ba4cf23a05d44ad98bd0cb
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Oct 18 09:31:51 2007 -0700
-
- Updates Hash so:
- * No longer freezes keys
- * Specs reflect the lack of freezing
- * shift spec doesn't fail purely because to_a is broken
-
-commit 197f36b6626b61203709704db869324a539764d5
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 20:11:50 2007 -0500
-
- moved File::expand_path to platform and made several fixes + new specs
-
-commit 7e8506fd510ab4e6f07e6d36456fdfef6e5b080a
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Wed Oct 17 21:07:44 2007 +0200
-
- Make sure that File.dirname doesn't modify its argument.
-
-commit 271bc31ba814e68fb414ebf29cf9648f57fe4cb6
-Author: David Altenburg <david@gensym.org>
-Date: Wed Oct 17 00:39:59 2007 -0500
-
- Added to fork spec: check that fork returns a nil pid for the child process
-
-commit 5d45341c55400a51d8cae3128bba265e7d441fab
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 05:19:49 2007 -0500
-
- moved File.basename to platform, added specs, and fixed specs for all but a disputable behavior
-
-commit ae7afd794881a4dedadf876f61369e5e88da695b
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 04:47:24 2007 -0500
-
- added platform/file.rb and fixed File.dirname for all and updated specs
-
-commit 71bf9b1c9cd7fb81692186d21b133fde43e8a6b7
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 03:44:33 2007 -0500
-
- spec to check if break exits all types of yields and loops correctly
-
-commit 3a546b40271d35bf7c60bb56a68ca49089ac9a34
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 03:01:40 2007 -0500
-
- clarified include_spec
-
-commit 40d8ed96fa689daf31039e71f91ed5520a821aa2
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 02:38:46 2007 -0500
-
- specs Module#include and Class#include that check to see if constants, public_methods and instance_methods are imported correctly
-
-commit ff462080a58aaa61759830e18f3a5757a883980d
-Merge: 5a2c858... 5cf41ab...
-Author: Jon Guymon <gnarg@kiryo.(none)>
-Date: Wed Oct 17 01:55:33 2007 -0400
-
- Merge branch 'puts_specs'
-
-commit 5cf41abaff9dc04cdba5fe50492d4ebfdde2a274
-Author: Jon Guymon <gnarg@kiryo.(none)>
-Date: Wed Oct 17 01:55:01 2007 -0400
-
- normalized specs for IO#puts StringIO#puts and Kernel#puts
-
-commit 5a2c858086c1b02a54864ff82c12d4bf3a559535
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 17 00:43:24 2007 -0500
-
- fixed posix File.join and added edge cases to specs
-
-commit e7972b8617b8b0ef2a19a1f7ddedd4d93ab80f5c
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 16 21:17:21 2007 -0700
-
- Commit gnarg's loop specs (#49).
-
-commit 3fcdd60b4c9fc20081987bb13aab37b9419939a3
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Tue Oct 16 19:46:36 2007 +0200
-
- Make this spec usable by loading pathname.
-
-commit 276b6cc5620a5a3629d56b04ade7c397a48c2488
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 16 00:53:11 2007 -0700
-
- Exclude metaclass instances from Module#ancestors list.
-
-commit e108e7f3f8a6ef7cf2acf4bb7e7a6609900a3ebc
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 16 00:06:54 2007 -0700
-
- Updated CI excludes.
-
- Updated compiler specs to match recent changes.
- Added compiled core/string.rb from changes in edeffe90517.
-
-commit 1a1410f394b3de23b63560f2a5c1312cc6451d2e
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 15 19:49:40 2007 -0500
-
- spec for __FILE__ added
-
-commit e158c3130f033a1029ae26888b8e7e541f2b388a
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 15 19:46:58 2007 -0500
-
- spec for __LINE__ added
-
-commit d09ad9e6b28c91f5d00db5d0b369c4932eabbe2b
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 15 18:45:48 2007 -0500
-
- spec for throw/catch inside of ensure reverted and clarified
-
-commit 0e5336f1572fc1ad766cff61d8843410d28df9db
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 15 18:33:27 2007 -0500
-
- spec super refactored into fixtures and expanded to test all methods on each class
-
-commit b998ec8e682c3a0f2160066bb84f40b68f748407
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Oct 15 16:26:58 2007 -0700
-
- Implement undef and Module#undef_method
-
-commit fed8486110930cabce64e0421638a867740e4d21
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon Oct 15 15:54:44 2007 -0700
-
- A bunch more language spec cleanups.
-
-commit 66086cb333432a29d4c4ce4fec6a01c0ac88c5a5
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Oct 12 19:33:59 2007 -0700
-
- Bunch of compiler fixes to pass more language specs
-
-commit 680e0ca4cafb20fa053f0dd5cd72915da9fbc86f
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Mon Oct 15 17:36:09 2007 -0500
-
- specs for super involving inheritence, modules and metaclasses
-
-commit 167febd232f5cf4696cf8e81a96d1c9d80744e36
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 15 15:32:48 2007 -0700
-
- Update CI excludes on OS X.
-
-commit 948e2573800859931e8c61e72069c21e9a50193b
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 15 14:23:02 2007 -0700
-
- Update compiler specs to match recent changes.
-
-commit a015bac050e1080548bd947c5f59b344175a809d
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Oct 15 23:51:01 2007 +0200
-
- Enabled the remaining Bignum#& spec.
-
-commit 0b37b2946772ea41fe7b14c762be7fdbaa4a6f8d
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Oct 15 18:20:56 2007 +0200
-
- Updated Spec excludes for Bignum.
-
-commit ae613272bcf0c260ad3da00ffd14d4a76422ac46
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Mon Oct 15 08:30:11 2007 +0200
-
- Added the beginnings of a File.stat spec.
-
-commit 81147d2eadb0397c2bcc1b9dd620bb55b6e0e53d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Oct 14 11:33:21 2007 -0700
-
- Fixed Float#to_s for numbers of the form "\d+.0".
-
-commit 2f9ba53190ca19ca425126d1319f47b3bbce12f6
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 14 18:57:04 2007 +0200
-
- Updated Bignum excludes.
-
-commit 0c81822cf703da13f6a8783cc6cd4ad453d2ff74
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 14 18:05:45 2007 +0200
-
- Add some OpenStruct specs.
-
-commit add2a900029530cb35b6463525313f432b7f36f4
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 14 17:29:38 2007 +0200
-
- Extended some more Bignum specs.
-
-commit 45cf3a275d390d4ae1d995eca89e10ba82d2288f
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 14 17:29:01 2007 +0200
-
- Extended the Fixnum#to_s specs a bit.
-
-commit d8a42cdd57967ee07cccfa5f3f814d97353c48c9
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 13 23:16:37 2007 +0200
-
- Fixed the bug that broke 'case' blocks with a single 'when' statement.
-
- Acked-by: Wilson Bilkovich <wilson@supremetyrant.com>
-
-commit 5624627fd61378fce65aebf2ffacc39c45ac5ee6
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 13 23:48:32 2007 +0200
-
- Ticket #37: Fixed Bignum#& segfaults when the argument isn't a bignum.
-
-commit 2081e5f53ba80cb9aa2ee272d4e543db1d4e732e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 23:43:08 2007 +0200
-
- Modify and extend Bignum specs a bit.
-
-commit 7917f4f8a538a3251e3cb17d55e4cf2a523af8d5
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 23:42:44 2007 +0200
-
- Modify the fixnum specs a bit.
-
- Remove dependencies on Exception messages.
-
-commit 171f25c25865da618c2e2a9a7b221abda613efa4
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 02:02:12 2007 +0200
-
- Extended Fixnum#<=> specs a bit.
-
-commit f708429a161c52dd713b4239527247c57fa158af
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 13 23:30:37 2007 +0200
-
- Guard bin/ci from running the new Bignum#& specs, which segfault (on OS X at least).
-
-commit 19f40e0ae1b60c037d0c38537a0924ad5726902a
-Author: Ben Curren <ben@esomnie.com>
-Date: Sat Oct 13 13:46:35 2007 -0700
-
- Refactored const_name_to_sym to share logic with Class#attr.
-
-commit ee9daad614fa746a3fe2fc1b9123c65dbb0814c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Oct 13 11:52:08 2007 -0700
-
- Identify which ruby platform and version before changing this spec!
-
- Revert "Fix spec to expect correct result."
-
- This reverts commit 8268469c563943cba6c1afce5d84defbc35f1789.
-
-commit 14a7781944491e5a1c3f5c664adcac4e1c383f2f
-Author: Tilman Sauerbeck <tilman@code-monkey.de>
-Date: Sat Oct 13 17:15:24 2007 +0200
-
- Added a failing spec for 'case' with only one 'when' statement.
-
-commit 8268469c563943cba6c1afce5d84defbc35f1789
-Author: Tom Mornini <tmornini@engineyard.com>
-Date: Sat Oct 13 03:22:47 2007 -0700
-
- Fix spec to expect correct result.
-
-commit 671f93c69e74976c3f5886c7fe8eb32402ccd338
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Oct 12 19:06:07 2007 -0500
-
- specs exiting threads using return, raise, and throw
-
-commit 119154a3ea5ecee20e77726b38fb58ee4b536d48
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Oct 12 18:59:47 2007 -0500
-
- spec to ensure throw exits from correct nesting and can return a value
-
-commit f36f68f075b34b5436257aba1ae41c14c04adcae
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 01:54:42 2007 +0200
-
- Method#[] specs should include the fixture classes.
-
-commit 22d32a24eb799307e42af55b04752c74ff500080
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 01:40:01 2007 +0200
-
- Extend Bignum#coerce, Bignum#&, Bignum#| and Bignum#^ specs.
-
-commit e1f682e27d2486d65297cf2121c354a99954a56e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 13 01:38:55 2007 +0200
-
- Removed a dependency on an exception message in Fixnum#coerce specs.
-
-commit 9754ed5e74eeb6d62f0015f3615d077aa2e58a6f
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Fri Oct 12 21:41:56 2007 +0200
-
- Fixed File.chmod and File#chmod specs on win32.
-
-commit 5ad3a4b7035bdade48586191c6e26cde1e74976c
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 13 01:37:46 2007 +0200
-
- Remove wrong spec from Bignum#divmod.
- Update CI excludes.
-
-commit b068c8634b56cd9129f9fc7c309bfa81869209c8
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Oct 12 18:21:52 2007 -0500
-
- specs for behavior of throw/catch and how they interact with ensure
-
-commit 45d4a8be8f20b2b70d32d0fdd340feb8897a1ad7
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 13 01:21:21 2007 +0200
-
- Add (skeletal) Process::Status.
- Set $? in Kernel#system and Kernel#`.
-
-commit ef1499962a16a7ce85bffe9e61863d2806caf6ec
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 23:52:16 2007 +0200
-
- Regenerate core/dir.rbc and CI excludes for Dir.
-
-commit b999f31ded2a7eccb856d95653a2826a3a190204
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 23:02:39 2007 +0200
-
- Fix typo in Dir.mkdir.
-
-commit de235630aa08df803be0420084b0a61ee35f5448
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 12 13:56:13 2007 -0700
-
- Added dev_null spec helper for capturing or silencing $stderr, etc.
-
- Fixed failing specs on OS X MRI 1.8.5.
-
-commit 01e27ea5fa0e0f0d170cd88f128adfbb2a2703bd
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 22:01:43 2007 +0200
-
- Add spec for backticks and their setting of $?.
-
-commit f7b18c19e47c15f3ab05f8fa548eff034206b0d8
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 12 13:21:03 2007 -0700
-
- Added guards to make specs pass on ubuntu feisty MRI 1.8.5.
-
- Fixed rspec_helper should_include to take multiple args.
-
-commit b2d25d4a502dca79ea98f60d937be7dbd8f496d2
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Oct 12 14:19:55 2007 -0500
-
- spec for retry/redo to control order of an enumeration
-
-commit eec535a19dc2b20156349720dc3bb526c9fa4f1e
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 18:53:33 2007 +0200
-
- Revert "Fix Kernel#`: set $? to the subprocesses exit status. Add a spec to check that."
-
- This reverts commit 40da2d5c68196c3c9002c4ca75ead0fefc520bef.
-
-commit 40da2d5c68196c3c9002c4ca75ead0fefc520bef
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 18:43:44 2007 +0200
-
- Fix Kernel#`: set $? to the subprocesses exit status. Add a spec to check that.
-
-commit 5da57253750e854bd9baf5378684222a895e7fd9
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 16:24:18 2007 +0200
-
- Shield "strange block args" spec from being run by mspec.
-
-commit 2a8f7d7dd6b0f7f800320f84d16d5d089357e085
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 12 14:48:42 2007 +0200
-
- Fix block specs for MRI.
-
-commit ade6c39f6199198e0015558698bc7d0333f7bcd0
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Fri Oct 12 12:07:49 2007 +0200
-
- Fix Array#delete specs.
-
-commit 825af45d5effb6909bb0832f92621b96e51dc380
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 12 01:15:23 2007 -0700
-
- Updated CI excludes.
-
-commit e1bfb47d3560929512cbdf5c27f56c92435ce29f
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 12 00:40:53 2007 -0700
-
- Removed printing summary at exit in mini_rspec.
-
- Set $VERBOSE=nil when running the specs.
- Fixed specs failing MRI.
-
-commit 1f1a041d8bcfaeb8dd3cb17f7d31b21281e690a2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 11 18:26:14 2007 -0700
-
- Moved shared specs to shared directories.
-
- Rewrote Module#method_missing specs.
-
-commit f9177eb198003b495f485a13910808fe603030ad
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 20:54:22 2007 -0700
-
- Added a failing test for setting and getting constants on an instance of a module.
-
-commit d9cbad87fd4d578e4f637627fa03cab312882a36
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 20:51:27 2007 -0700
-
- Updated the excludes for module tests.
-
-commit 938f034bad41f4fe3391b941e536bce9e1be0af6
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 20:49:57 2007 -0700
-
- Updated const_set_spec to not create a new instance of Module for testing purposes.
-
-commit 550caaf78723b00f95c5f8f38215b15a0940698a
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 18:21:01 2007 -0700
-
- Updated the excludes for the tests that are now passing.
-
-commit 82c51fc652e215f0dc421099329c03a37af8e8f8
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 17:56:48 2007 -0700
-
- Updated const_set and refactored the valid_const_name? further.
-
-commit c6323c74d0ee7b554d2cfbff3bd8d85ea910e0c9
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 12:01:27 2007 -0700
-
- Added logic to remove Object and empty from a recursive string for const_get and const_defined?
-
-commit c108d2a623f5041f46b6efa32d0b331f4f91d669
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 11:58:04 2007 -0700
-
- Added back the recursive case for const_get and const_defined?
-
-commit b976f184d8ade3b5d32d3e7ec11027c21c2bce2a
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 11:33:41 2007 -0700
-
- Refactored const_defined to use const_get.
-
-commit 82c5c14b948cedbf3bed5f7996634b0238e4de55
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Oct 11 17:38:05 2007 -0700
-
- Bunch of compiler fixes, almost have test/unit and optparse running.
-
- * Adds support for /ao#{name}/o (aka dregx_once)
- * Invalid redo's raise an exception at runtime instead of compile time
- * defined?(a.foo) works
- * Lots of work on getting the block arg semantics right, including a new
- instruction, passed_blockarg which is used to detect at runtime how
- many block args were passed in.
- * bug in 'yield 1, 2' versus 'yield [1, 2]' fixed
- * A little better error reporting on compile errors
- * Fixed Class#<, added #>, #<=, and #>=
- * Fixed Hash.new
- * Fixed nested case problem
-
-commit 1369b104a3f966dd4d279362afdc6ccb72f06de3
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Oct 11 22:47:16 2007 +0200
-
- Fix String#eql? specs.
-
-commit b190009707c120edb257a9ad92697145092c5612
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Oct 11 10:57:10 2007 -0700
-
- Shield parse errors in block args properly
-
-commit 0509ecbd6aeb973061866c5e04c590f975174b41
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 10:21:08 2007 -0700
-
- Updated tests to test FixNum being passed to const_defined?
-
-commit 80116298779dc5afd3294cd83d758d76d0dcdf50
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 10:16:46 2007 -0700
-
- Added error checking to const_defined?
-
-commit eed3ae097b1dae17e45cdb959b75d1fa7cf21c1b
-Author: Ben Curren <ben@esomnie.com>
-Date: Thu Oct 11 09:25:53 2007 -0700
-
- Convert paramter to_str if it responds to the method.
-
-commit 348df85a082eee56c301bce594d6c522050e34dd
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 10 18:49:34 2007 -0500
-
- specs for language/retry and updated redo to show differences between them
-
-commit e924e2bb206317e8f5375c979f5e4e1046fccca9
-Author: Tom Mornini <tmornini@engineyard.com>
-Date: Wed Oct 10 00:55:47 2007 -0700
-
- Add Class#attr, refactor Class#attr_reader, Class#attr_writer and
- Class#attr_accessor, pass all specs for Class#attr_*, fix a couple of issues
- with said specs.
-
-commit 21b0bdc67c6a8cc4ad4b9d3942a2608fb45da31d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 9 15:10:04 2007 -0700
-
- Commit #198, patch from Will for Module#(private|public)_class_method.
-
-commit 2cf5f0b4683d0a65181c1450d0714c4e165db1cd
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Oct 9 21:00:13 2007 +0200
-
- Moved shared specs.
-
- Moved shared specs into the 'shared'-subdirectory so specs don't depend on each other anymore. Added some more shared specs.
-
-commit e558fab61ce9f7c5211d005aff2c5e8fc1b39931
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Oct 9 19:53:46 2007 +0200
-
- Fixed a failing Array#each spec. Closes #14.
-
-commit 0d77eefd718c826e02376edc8643364eb511773d
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Oct 9 19:09:17 2007 +0200
-
- Removed remaining dependencies on Exception messages in Fixnum specs.
-
-commit dd4063ba46eb313a57957d76dce3608dd8e5c161
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Oct 9 18:58:01 2007 +0200
-
- Fixed String#crypt spec.
-
-commit d5a2bb2b000fae7391e512c5bcab054ce967de3b
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 9 09:35:51 2007 -0700
-
- Updated CI excludes after applying Akshay's Precision specs patch.
-
-commit 10cd5764bbf51f1defa6815f8b07fcdce0de8875
-Author: Akshay Rawat <akshay.rawat@gmail.com>
-Date: Thu Oct 4 21:48:15 2007 +0530
-
- Specs for the module Precision
-
-commit 2e711c30e4e9ce50d9c20ab14a3b99ea47be32e9
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 13:56:45 2007 +0200
-
- Make IO#puts specs pass in MRI.
-
-commit 13dc28c47c3211f01663d002847badb50277f277
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 13:44:51 2007 +0200
-
- Silence warnings when running Hash specs in MRI.
-
-commit 52f903938f4eacf4465f7a36cacb25aa662aa559
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 13:44:02 2007 +0200
-
- Turn Hash#values_at into a shared spec.
-
-commit 1e02ced5a68f16b8a65809136d954c68c9fdc590
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 12:59:58 2007 +0200
-
- Add a few more specs for Struct#new.
- Regenerate CI excludes for Struct.
-
-commit 94ea8c1f25761384796e9499e0b4b3faeba9da66
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 12:48:03 2007 +0200
-
- Silence warnings when running Struct specs in MRI.
-
-commit 5ea6b219a8465cfad86dae9ae12d6a8d85812532
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 9 12:42:58 2007 +0200
-
- Apply patch from ticker #23 by Jon Guymon (gnarg).
- Make Struct specs not depend on method argument evaluation order.
-
-commit 8cbf7b94300e6ebcc0ee3cbe0de8123ef3563e96
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 8 22:08:29 2007 -0700
-
- Fixed that including a module includes the whole chain.
-
- Fixed that Module#include only allows modules.
- Simplified some module fixtures.
- Updated CI specs for module.
-
-commit 4e7e2768d50392831a4d26f236d4cff733418225
-Author: Ben Curren <ben@esomnie.com>
-Date: Mon Oct 8 11:54:51 2007 -0700
-
- Added puts spec for io and updated IO implementation to match MRI's. Updated Kernal#puts to delegate to $stdout.puts.
-
-commit edc724086e84725995ed1720d4fa7a781fd9c3c6
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 8 09:24:40 2007 -0700
-
- Updated CI excludes for Module#define_method.
-
-commit a53ddb723a10d692223f05a49679e17f403fa128
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Oct 8 01:05:04 2007 +0200
-
- Fixed some Fixnum specs to not depend on error messages.
-
-commit d6bc4b47f3f395980c92f323cf029da1ccdba709
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 7 23:42:12 2007 +0200
-
- Added another failing spec for Module#define_method.
-
-commit 49435e31289f593a118377b3513ec9e7cdfea06b
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 7 23:37:19 2007 +0200
-
- Added failing specs for Module#define_method when given an UnboundMethod.
-
-commit 821c0114777fb2a77f1c85f216ee54e4c5340943
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Oct 7 22:29:47 2007 +0200
-
- Apply patch from ticket #15 by Jon Guymon (gnarg).
- Add Struct#eql?.
- Rebuild core/struct.rbc.
- Add more struct specs.
- Update CI excludes for Struct.
-
-commit 1f14c3510d4563930d11155f36717c0fb851c678
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Oct 7 18:13:33 2007 +0200
-
- Added some GetoptLong Specs.
-
-commit f9c8c00649212b924561300abbd0cb037c1d278d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Oct 6 23:00:05 2007 -0700
-
- Update CI excludes for File#executable.
-
-commit 6d4427d07fc474e2404cdd2b6f3b925d99d90e67
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Oct 6 22:50:45 2007 -0700
-
- Updated spec/excludes.txt from 72 items to 17.
-
- Added -V | --verbose flag to bin/mspec.
- Updated CI excludes.
-
-commit d4f5e44a8e2f8e682b779f45d12d060e83eb9fc7
-Merge: a035e9d... 42abc5e...
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 15:18:45 2007 -0400
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit a035e9d3d204cf7e5ddb2fec72ca471ff33c3b9b
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 15:13:28 2007 -0400
-
- fix a bug in the File.executable? spec
-
-commit 3c23c945aaf143aa8706b1cd2956908a71940e26
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 15:09:55 2007 -0400
-
- fix bug in File.executable? spec
-
-commit 94e59065bf921ae167a6b04edfef40de336978a1
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 15:03:14 2007 -0400
-
- Revert "Revert "Add a few more Proc#call specs. And CI excludes.""
-
- This reverts commit 7658362c3882c6be2ef67f6b57d6c6796ff5de98.
-
-commit 42abc5ed6e1ced2fa86e9dc9379c6bed4da4537e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Oct 6 11:40:49 2007 -0700
-
- Updated CI excludes for Kernel specs.
-
-commit 7658362c3882c6be2ef67f6b57d6c6796ff5de98
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 14:29:28 2007 -0400
-
- Revert "Add a few more Proc#call specs. And CI excludes."
-
- This reverts commit 567659dee34014d037d4797bf0c171597e0ac05d.
-
-commit 567659dee34014d037d4797bf0c171597e0ac05d
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 16:23:54 2007 +0200
-
- Add a few more Proc#call specs. And CI excludes.
-
-commit d8e737b09f8ed984e57b4fbbd5c016a7643aa67d
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 15:56:33 2007 +0200
-
- Fix Array#slice specs. Regenerate CI excludes.
-
-commit c79eeb620296a1802e6d194463063555638911bf
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 14:34:05 2007 +0200
-
- Fix Array specs that depended on respond_to? being called on coercion.
- Regenerate CI excludes for core/array.
-
-commit 8a60522fd8237fdfa36ef5518c9642216c66f8d6
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 14:08:22 2007 +0200
-
- Guard Array specs for #freeze. Fix MRI Array specs for #freeze.
- Regenerate CI excludes.
-
-commit eaaab65c54c3b81397441169761774ef95867297
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 12:47:55 2007 +0200
-
- Add specs for Proc#call. Regenerate CI excludes.
- (Most of these seem to be from e6cf8978.)
-
-commit 19bcb0f6ec1b2247985823492f0c25f0aa5d94ab
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 12:09:29 2007 +0200
-
- Slightly amend the core/hash specs.
- Regenerate CI excludes.
-
-commit 6d1afe325098a73757980bb208fb2c8c64bd016b
-Merge: ac9365e... 0d22ef5...
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 01:13:59 2007 -0400
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit ac9365e384263b6f062353f2afab3e33d8f84f3e
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 01:13:23 2007 -0400
-
- added spec for OpenStruct
-
-commit e6cf8978a6dd441d5d4793c48438fab4150ca750
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Sat Oct 6 00:14:01 2007 -0400
-
- added several tests to Proc
- added tests for Kernel#lambda and Kernel#proc
-
-commit 7b69ae066cab2252375d1ad19c6f17b365c47c32
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 18:51:11 2007 -0700
-
- Updated CI excludes for Array.
-
-commit f216e89033d10f3500798561282e48aa0e5b5537
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Fri Oct 5 20:45:41 2007 -0400
-
- really simple spec for the Singleton class.
-
-commit d682b176237a988afa7ebdb3460d64ea41fab919
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Oct 6 01:54:31 2007 +0200
-
- Applied esomnies
-
-commit b3018362c0cad86a5a026eb39b5f6ea4a8af1192
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 01:24:05 2007 +0200
-
- Guard Hash specs for #freeze.
-
-commit a185f463adbab1d6f82126dde9abe88a29e83283
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 01:15:23 2007 +0200
-
- Fix workarounds in core/hash specs.
-
-commit d796eb3d8a5d9a070b105f1fe0e9f46be5bfaaee
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Fri Oct 5 17:09:48 2007 -0500
-
- specs for UDPSocket client/server
-
-commit 46a9c1a0d0610865b659c289293b444f0b3d6ae9
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 15:32:56 2007 -0700
-
- Fixed bin/ci to not load spec/excludes.txt for every file.
-
- Fixed bin/mkspec to not overwrite an existing spec file.
- Updated Fixnum CI excludes.
-
-commit 1099f49c06de5621aff36216179f46c308e60a38
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 14:40:24 2007 -0700
-
- Added basic IO#readlines spec and implementation.
-
-commit edc438039ee503c7b9d1fb83b04bd9bc1664cda5
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sat Oct 6 00:09:41 2007 +0200
-
- Regenerate core/hash.rbc, core/hash CI excludes.
-
-commit 2ad7d015a316620a488ed1cdeb45fe696b9d410a
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 5 23:56:59 2007 +0200
-
- Extend core/hash specs to check for LocalJumpErrors.
-
-commit 42d961f0ab8a7e23a822b41ca82aaed5a48da2bf
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 5 23:21:20 2007 +0200
-
- Refactor and fix Hash#inspect.
-
-commit b51402d8724478b85789d19857a2a48442470fcb
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 11:29:08 2007 -0700
-
- Fixed bin/mkspec to not create the spec file stub if the file exists.
-
-commit efe79de398db491ce97666a3f4f3b38265c1ab95
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 10:55:52 2007 -0700
-
- Updated CI specs. Guarded String specs for #freeze.
-
-commit 8647951df433d427be31bec060edf5b7efb46e46
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Fri Oct 5 17:04:25 2007 +0200
-
- Replaced all occurrences of Object#coerce_to with Type.coerce_to and removed Object#coerce_to.
-
-commit 778e11d2df647cf91a712bb30df34152c71dbc3f
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 5 11:42:40 2007 +0200
-
- Don't work around rbx bugs in Hash specs.
-
-commit 4b42923eb2cdebe43f9e9dd80fff98d9ded26e4b
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 5 11:29:33 2007 +0200
-
- Fix Hash specs to pass in MRI again. (Doh!)
-
-commit 8a4f0b1c0d95b7a87ed99583797cf7d3710fb15a
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 02:24:30 2007 -0700
-
- Updated CI excludes for Hash.
-
-commit cecbf342546f37f4923728e8381e7fafcb039633
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Oct 5 02:22:41 2007 -0700
-
- Changed bin/ci to run in a single process. Updated CI excludes.
-
-commit ba0f4ef5405665c84af4410d70be5ef911a93195
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Oct 4 22:58:50 2007 -0700
-
- Adds the intern spec from Ticket #8
-
-commit 0721f6ea40f51202ec9d2d421061be92e05a18b9
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 22:39:00 2007 -0400
-
- Commit #207 Xavier Shay Enhanced specs for Hash
- fixed Binding#dup spec
-
-commit ce4a1866ef65e041fbed224c3f694ca534d0a0d1
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Oct 4 18:24:21 2007 -0700
-
- makes String#delete faster
-
-commit 7ec0eeadf554150159f0a04468b16de8f06c2e8a
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Fri Oct 5 00:32:25 2007 +0200
-
- Whoops, two more frozen TypeErrors I forgot.
-
-commit 78a3de42bf0e6f1478b2aac903c25143fd56195a
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Thu Oct 4 23:17:42 2007 +0200
-
- Regenerate CI excludes and core/hash.rbc after revert.
-
-commit beaa5d022b19cb70213d4fe14e10d7f1a5f90a3a
-Merge: c7ea881... 8cb4b0b...
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Oct 4 16:12:41 2007 -0500
-
- Merge branch 'spec_block_parameters'
-
-commit 8cb4b0b2c3c766618a523a0ef9a83106761ee2f8
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Thu Oct 4 16:11:15 2007 -0500
-
- specs for setting variables in block parameters
-
-commit c7ea8812f74184e6ee33bb236766f32fface2f95
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Thu Oct 4 22:57:09 2007 +0200
-
- Regenerate CI excludes for spec/core/hash. New hash.rbc.
-
-commit 939e8c533fb70586f8c7c6f3506d6be13f492d78
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Thu Oct 4 22:11:18 2007 +0200
-
- Fix Hash specs: don't depend on coercion to call respond_to?
-
-commit 422e45f210ec9dc2438ae3b11544823bb6ffdd50
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 16:21:27 2007 -0400
-
- added specs for FileTest#exists? and FileTest#exist?
-
-commit e43466b52184a042bd38d33273acf7afa4580a96
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 16:12:58 2007 -0400
-
- added spec for File.exists?
-
-commit 9f69c8193d92752a2be7c21d23dfe90fb9765f11
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 16:03:33 2007 -0400
-
- fixed grammar error in Method#clone
-
-commit 9321aacf703eaec6d6bc26cce83ed7475cb27d46
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 16:00:31 2007 -0400
-
- added several specs for Module
-
-commit a282c1c4c137e1bdeae34f2f9cd58bc73f257809
-Author: Jason Yates <jaywhy@gmail.com>
-Date: Thu Oct 4 14:19:07 2007 -0400
-
- added specs for Kernel#binding and Binding
-
-commit 3e92b4528dbf47b80a25232979554f7e4309460a
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Oct 4 10:45:10 2007 -0700
-
- Fixed ffi_sprintf_[fd]. Updated String spec CI excludes.
-
-commit 9e9a292a8a4befeb8a928d476119b02ac0df976e
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Thu Oct 4 18:53:47 2007 +0200
-
- Alias Object#object_id to Object#__id__
- Regenerate CI excludes for spec/core/kernel
-
-commit 8790e93c6d231baf7da07f11d02b91a38d28375e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Oct 3 18:23:42 2007 -0700
-
- Superclass checking and loop {} fix.
-
-commit 718ae6f28223e94b8ca0f3af7ce321c81a597804
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Thu Oct 4 15:05:59 2007 +0200
-
- Slightly extend Object#kind_of? specs.
-
-commit 7fa087a7058fe8872bb9743abd6dd472cd2119d7
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Oct 4 08:43:55 2007 +0200
-
- Fixed some String#slice specs.
-
-commit b9be176a9e64669f2a787c9bdebc1ba30e344d97
-Author: Paul Meserve <pmeserve@gmail.com>
-Date: Thu Oct 4 01:37:56 2007 -0400
-
- adding String#each_char
-
-commit c1b17108a78a4dc5d3e224158f8f9d76232003e6
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 3 17:42:06 2007 -0500
-
- basic specs for Kernel#sleep
-
-commit 1fe895518bdccb93991f85a92f53876ed3d4df13
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 3 14:16:14 2007 -0500
-
- added spec for Kernel.local_variables
-
-commit 00417283b36dcb58da82c6fc2e9be7580de945b0
-Author: Charles Comstock <dgtized@gmail.com>
-Date: Wed Oct 3 14:15:25 2007 -0500
-
- added specs for Kernel#global_variables
-
-commit 5b944520099f129462c3b03fa6ee7d1bb0636fc0
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Oct 3 14:07:09 2007 +0200
-
- Fix String#index specs.
-
-commit c9cdef77c7fa8dda92c91cee5a47624b9c9dc9e8
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Oct 3 14:05:34 2007 +0200
-
- Fix String#hex specs
-
-commit 4625a7afe509545f782cd4631632b4d7a58011aa
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Tue Oct 2 23:53:20 2007 -0700
-
- String#% works with a few exceptions:
-
- * %u doesn't work (it's aliased to %d for now, as in 1.9)
- * There's a weird glitch in Float(10_1_0.5_5_5) that I can't track down
-
-commit 54ab6f559093e66f78cfa30db8aa6587061552d6
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 02:05:41 2007 +0200
-
- Extend Kernel#kind_of? specs.
- Regenerate CI excludes.
-
-commit 4583be7e7ed76e5843dcb396f8bae735f341de73
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 02:03:58 2007 +0200
-
- Remove superfluous whitespace from Object#kind_of? specs.
-
-commit 5c237626469f4b0f4d227916752dd2e03510fcf9
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:50:33 2007 +0200
-
- Remove superfluous comment from Object#kind_of? specs.
-
-commit 7a2c673d04b0d0506e89073ff231104e21c3304c
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:47:56 2007 +0200
-
- Simplify Kernel#freeze specs.
- Move Object#extend vs. frozen? spec to extend_spec.
- Rebuild CI excludes for Object#extend specs.
-
-commit 3f6a27603b0b1f91ce32b9ff2a5fe3222fa7220b
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 2 17:03:37 2007 -0700
-
- Commit Charles Comstock's language return specs.
-
-commit ad4e7affcbaae4f0e967c97da485313168595a5e
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:36:27 2007 +0200
-
- Fix Kernel#caller.
- New core/kernel.rbc.
- Regenerate CI excludes for Kernel#caller.
-
-commit 73b2ef1c889c940d22da6ad6bb8882eef66592fa
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:34:10 2007 +0200
-
- Add spec for checking the default argument value for Kernel#caller.
-
-commit 180ecd6a7fa1d32e1932a322b1f8f82efd558e7f
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:32:29 2007 +0200
-
- Add spec for checking that Kernel#caller returns nil.
-
-commit 9ad0c1428df70c9fd9e0081651e3b60cf5773267
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:30:46 2007 +0200
-
- Add spec for checking the argument handling of Kernel#caller.
-
-commit 7a9483b823115b3122a4e42b21dfcb5b0f369a54
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:23:17 2007 +0200
-
- Refactor the tedious part of the Kernel#caller specs.
-
-commit e204755859e4dc147217816ab3bf587db3d51dd6
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Wed Oct 3 01:22:26 2007 +0200
-
- Cleanup description of Kernel#caller specs.
-
-commit dadbbb7930b62a4a6e47c8c32a4d9f26fcea38b4
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 23:52:49 2007 +0200
-
- Regenerate CI excludes for spec/core/kernel. Again. Because I fixed the typos.
-
-commit 4a3587da37fd27effb30356fdd2e496f8c898be7
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 23:45:33 2007 +0200
-
- Fix CI specs to pass in MRI 1.8.6.
-
-commit a46f5085f3c2a4849fe709044e447e5d6dacda4f
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 23:27:51 2007 +0200
-
- Fix typos in spec/core/kernel specs.
-
-commit cb3d5867ec91a59a2a75136eb5210a10540b0ce0
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 23:27:23 2007 +0200
-
- Regenerate spec/core/kernel excludes.
-
-commit 22e6fe0ef8dbf13aa01124447e09c9dc96f63fe3
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 23:26:51 2007 +0200
-
- Fix Kernel#Array spec: don't depend on the exception message.
-
-commit 7b79130f38925cb48712be617cef5a80c71f0ba4
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 2 14:29:42 2007 -0700
-
- Commit #5 (LH) Charles Comstock Process.wait2 spec.
-
-commit 859c119a48909030f29a2085fbe0a80ed96d2408
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Oct 2 20:57:31 2007 +0200
-
- Fix Float#to_i and add a spec to catch the old misbehaviour.
-
-commit f2b5b2304588b4fb0efd9818c79a4b9774b2c850
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Oct 2 19:07:49 2007 +0200
-
- Fix some String#scan specs.
-
-commit 8e0ce11df329181efa440cbd55f29848e12188bf
-Author: Kevin Clark <kevin.clark@gmail.com>
-Date: Tue Oct 2 00:39:15 2007 -0700
-
- Add error handling for Dir.mkdir/rmdir
-
- Add aliases for Dir.delete/unlink
-
-commit 20e66dd965bfceb29e4939090a0fd543d05392a3
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Oct 2 00:21:49 2007 -0700
-
- Commit #206 Jason Yates' UnboundMethod specs.
-
-commit 00d7d22b7d106c6aac5d9664cb444e14811171b0
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Mon Oct 1 17:57:29 2007 -0700
-
- First pass at actually getting my modulo impl working
-
-commit c90766a09c7e1fe7a2261f8b09d9caa8eaf2214e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Oct 1 21:21:34 2007 +0200
-
- Fix the String#crypt spec.
-
-commit a0f6f8e51a6f7a65230f8f2ea53587ccb09f9270
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Oct 1 20:18:29 2007 +0200
-
- Changed the String#to_f specs a bit.
-
-commit 21d43e565bb55a31b45dc9fabbefface156ec516
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Oct 1 16:13:28 2007 -0400
-
- Add failing Array#pack spec for use case taken from Mongrel
-
-commit b1d70b4a847fc1c8df3eb4a219c4318420121e82
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Oct 1 09:04:03 2007 -0700
-
- Commit #205 Jason Yates' Method specs.
-
-commit de7e0f0183d072f101e0781635fc2fdb1af1b851
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Mon Oct 1 00:11:12 2007 +0200
-
- Fix compiler specs to expect sret when appropriate.
- Rewrite compiler specs for multiple assignments.
- Regenerate CI excludes for compiler specs.
-
-commit 1d1e704306fca4453d600259e87175dcdc9de314
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 23:27:12 2007 +0200
-
- Add edge cases for File#extname specs.
-
-commit 108d757e6c24447b89fa785b2bf091b72d29933d
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 22:34:15 2007 +0200
-
- Regenerate CI excludes for Dir specs.
-
-commit 20c6c3cd9b5d59b9782b702ac6afeb828e895d5f
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 21:49:52 2007 +0200
-
- Make Dir specs pass in MRI.
-
-commit dcd172338bce5b70cb367db3c1e6f4653c05f9e8
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 21:10:36 2007 +0200
-
- Fix case comparison with Symbols.
-
-commit 2a45cd71d1eb90a7c11ff62d81371df9479b0d43
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:28:32 2007 +0200
-
- Add specs for String#tr! and String#tr_s!.
- Cleanup specs for String#tr! and String#tr_s!.
- Regenerate CI excludes for String#tr! and String#tr_s!.
-
-commit 6418bd672c8ea031d8ac2364c8a98bb631e53deb
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:26:19 2007 +0200
-
- Add specs for multiple asignments with splats vs. Array#dup.
-
-commit 10b04881d286acab9dc97147750743e03ee4509f
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:25:14 2007 +0200
-
- Fix Class.new to raise TypeError when the superclass is not a class.
-
-commit 0b9debba0672305f8551f5d5f35cdd3aaf16c1f1
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:20:49 2007 +0200
-
- Add specs for the names of classes generated with Class.new.
-
-commit e15cef6eb851318838351a4d8717b708bb09d31d
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:15:43 2007 +0200
-
- Remove debugging output from spec/core/dir/chdir_spec.rb
-
-commit f3251ba0e8ade79f157bc02dca550481488bf888
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Sun Sep 30 13:15:17 2007 +0200
-
- Remove debugging output from spec/core/extensions/rubinius/options_spec.rb
-
-commit 5d4d2abaf02aef6caa7e532208da5e5f57bc6373
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Sep 30 20:54:14 2007 -0400
-
- Working Socket implementation and specs. Still needs readpartial to support Mongrel.
-
-commit b514e53f589d509c287516d8dd985f96e66d9a1c
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat Sep 29 15:44:06 2007 -0400
-
- Working IPSocket#peername implementation
-
-commit 965ed2d88527ae8aa4ac962e8ca84180f61e6345
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Sep 24 02:34:26 2007 -0400
-
- Yet another interim socket commit
-
-commit ecd54e981a1098c4b3abf14587212e7d1d9049a6
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Sep 20 16:29:21 2007 -0400
-
- Another interim Socket commit
-
-commit 351bbdf08f190e24328328df7b3f995b8dc27a9f
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Sep 19 22:17:52 2007 -0400
-
- Interim commit of Socket work so I can generate a patch
-
-commit 65a73cdfea95c5991f2044bee150e53643216ad3
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Sep 26 13:15:45 2007 +0200
-
- Added some Marshal#load and Marshal#dump specs.
-
-commit 89e1b91c606dfe18581c3ed3923340b952471d8e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Sep 26 13:15:19 2007 +0200
-
- Extended Specs for Kernel.Float and Kernel.Array
-
-commit 5d46933362b8c54cb5d0370bbf61e063459de514
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Wed Sep 26 13:14:41 2007 +0200
-
- Added specs for Symbol.all_symbols.
-
-commit b3324808584d7b4ee6af58d98eeb7c2162c31208
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Sep 27 10:57:46 2007 -0700
-
- Commit #180, Jason Barton's specs for Module#undef_method, #remove_method.
-
-commit 2e1219fc03d9cb673074ee34b1f8af4bdffe9c0e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Sep 27 18:49:26 2007 +0200
-
- Fix Kernel.Integer by making use of String#to_inum. Add some more Kernel.Integer specs.
-
-commit b0d4747cab49f4a17e9899392171087d7b67f687
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Sep 27 18:23:42 2007 +0200
-
- Fixed String#to_i. Added String#to_inum. Extended String#to_i specs.
-
-commit 2799c392b3f5383e9e74745ceb9cf7a52f82918b
-Author: Paul Meserve <pmeserve@gmail.com>
-Date: Thu Sep 27 01:20:00 2007 -0400
-
- fix for Struct#new and a small struct spec changes
-
- (also re-ran bin/ci on struct specs - most of the changes were from previous commits though)
-
-commit 30d9bf1f6ef9dcff067d427d6226bbce985f5e69
-Author: Paul Meserve <pmeserve@gmail.com>
-Date: Wed Sep 26 19:08:37 2007 -0400
-
- raise proper error when passing non-block args to Enumerable#all?
-
-commit 1ef1e0ef65ef3c86558da3d313dee5cada6dd4c5
-Author: Paul Meserve <pmeserve@gmail.com>
-Date: Wed Sep 26 17:25:17 2007 -0400
-
- adding alias for Float#quo to fix a couple number specs, and some modifications to Enumerable#min/#max, along with a couple new spec assertions. fixes failing specs and implementation should be a lot closer to MRI
-
-commit 547dd89791d92f061afcaef7184f054affae871d
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 26 09:46:50 2007 -0700
-
- Fixed placement of after(:each) block in numerous File specs.
-
-commit fa3dcbfdd623a7a7cdb15bc29b38ae47bb4056d5
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Sep 25 20:25:36 2007 +0200
-
- Added specs for UnboundMethod#arity
-
-commit 33783408b8ce1bdfcd205fd02bc3848119a632cc
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Sep 25 18:00:10 2007 +0200
-
- Added specs for Class.
-
-commit 0edea3c3a7dda5c453c527b2cef3ffba1eef1396
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Tue Sep 25 17:25:40 2007 +0200
-
- Created some specs for Proc.
-
-commit 62c92f1c3aef6c2ff7ab8cbcd49eefb236d5caed
-Merge: b79d04d... 2d9c698...
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 26 01:09:42 2007 -0700
-
- Merge branch 'dir'
-
-commit 2d9c69848f4ca34685b95b07e17d1b5fe1ec2391
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 26 01:09:28 2007 -0700
-
- Updated CI spec excludes for Array, Dir, Fixnum, Enumerable, Hash.
-
-commit b79d04db673d9b7b5cc47f2918bccf1b0400bdbd
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 26 00:56:01 2007 -0700
-
- Commit crayz's patch from #195, #196, #197.
-
-commit ec960578671a327469d9545d6ced827736ceafa0
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Sep 25 19:40:54 2007 -0700
-
- Fixed Dir specs failing MRI after conversion.
-
-commit 00b398352ed0f4cbcd326d56b7f8a4469056ee0d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Sep 25 00:54:06 2007 -0700
-
- Many cleanups of Dir specs.
-
- Added Dir specs fixture directories and files.
-
-commit b75cfa7c0a9871dc34b8b315ca2311e65000b2f3
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Sep 23 00:41:36 2007 -0700
-
- Converted Dir.glob specs.
-
-commit 3d8ea2a55e67cc6cfb85d2f4f7845a45984f6504
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Sep 25 21:52:54 2007 +0200
-
- Fix a few Struct specs. Failures are down to 15.
-
-commit a477ff678e9f5f39d3d2b94e559c77b34f0c56c5
-Author: Martin Kuehl <martin.kuehl@gmail.com>
-Date: Tue Sep 25 20:51:38 2007 +0200
-
- Fix compiler warnings in Subtend spec extensions.
-
-commit db3e1be4e25b7e8cc463443d050afe9a5acaa7de
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Mon Sep 24 22:31:03 2007 +0200
-
- Extended Fixnum specs.
-
-commit d136b779736af52d1eac08a40814ab4a47de93b3
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Sun Sep 23 17:47:30 2007 -0700
-
- Array#each explosion spec
-
-commit 8a24a71ff13aac465f7f4a14587981c3c23dc800
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 23 20:06:04 2007 +0200
-
- Extended Comparable specs.
-
-commit ea9ba046ddfe91601d4453972a6d6f8fce96c392
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 23 12:17:17 2007 +0200
-
- Fix Numeric#divmod and Fixnum#divmod.
-
-commit 1c5ecb9d2e9066c66b9f0625d65cc4cefaee1f83
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 23 12:00:16 2007 +0200
-
- Fix Float#to_i for infinite, negative values. Fix Numeric#/ and Numeric#div. Add Numeric#do_coerce.
-
-commit 2d67d024e11e887eb07622963bfc36b0ec377746
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Sat Sep 22 20:08:38 2007 -0700
-
- Added Onig 5 and got rindex working with it
-
-commit adc26eb525447010e28fc884eaa54b9d2228f4d6
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 23 01:35:11 2007 +0200
-
- Fix Kernel.Float specs
-
-commit 9a2ecf258fee3bda410776b3d3b77366590d64fe
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Sep 22 23:18:46 2007 +0200
-
- Extended more Fixnum specs. Removed the spec/fixnum/induced_from_spec.rb.
-
-commit 53b0042824bb1b1c523d790cb3645aec6b789abe
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Sep 22 22:35:53 2007 +0200
-
- Extended many Fixnum specs.
-
-commit 8661cdb78cd2c4afa0fb231aa9cc959e338e097e
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Sep 22 22:35:11 2007 +0200
-
- Extended nil#to_s spec.
-
-commit 4008d8b39032ffa5667e95fb445ff816b1428330
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Sep 22 14:25:27 2007 +0200
-
- Added some more specs and fixed some bugs in Range#initialize, Range#step and Range#each.
-
-commit 254e3d57dc6e859616ca7e0c44058d4b73211f68
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sat Sep 22 11:31:02 2007 +0200
-
- Some updates to Range specs.
-
-commit b87e28bfc06e81fe5c4c3d6e285947f635f79f61
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Sep 21 20:12:18 2007 -0700
-
- Commit wycats Regexp.regexp_match_region primitive.
-
-commit eaa56811836b4b5ed09a5e26d00f26eb004f2853
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Sep 21 18:44:25 2007 -0700
-
- Added StringValue to some File methods.
-
- Upated File CI spec excludes.
-
-commit 83f7b6020dbc881fbd6bd13da6ebb049d6080c2c
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Sep 21 17:54:53 2007 -0700
-
- Upated spec excludes for Float, Fixnum, and Math.
-
-commit af0b0c8da8357fcae7437f6cdfd7797f03ffd73b
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 20 22:10:54 2007 -0700
-
- Fixed a number of string-related issues:
-
- String#inspect respects $KCODE
- String#inspect returns tainted subclass
- String#dump is no longer a copy of inspect, and does not respect $KCODE
- String#match tries to call #to_str if it can before throwing an error
-
-commit 9409ace6d3e97946d10f9f7fcefa69ebcae43c47
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 20 16:55:11 2007 -0700
-
- String#index works
-
- Tweaked spec because [[x,y], [x,y]].each{|x,y| ... } wasn't working
-
-commit 6a72e4c4defef170f53a31c930c112022934dbc4
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Sep 20 15:22:28 2007 -0400
-
- Correct StringIO#reopen specs and implementation. Submitted patch for 1.8.x stable.
-
-commit 2b10dd99c2de4f97b5faa45060eba929d02052c4
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Wed Sep 19 22:20:33 2007 +0200
-
- Implemented File.identical?
-
-commit 2c3c1fc7bd2f6365b28262cae46872eb0925c2e7
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Wed Sep 19 21:48:13 2007 +0200
-
- Implemented File.link.
-
- Kudos to the Frankfurt Rails User Group! :)
-
-commit 0330b22006e39b5b173c78800f412831296de59a
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 20 01:32:43 2007 -0700
-
- String#gsub works correctly
-
- There was a weird segfault issue which I tracked down to a use of gsub inside of gsub.
- I got things working by extracting that functionality into a mini-gsub for just that
- use case, but we should fix it.
-
-commit 6c825ce63ca0eb7d6f882a767ee0e6a597219883
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Sep 19 22:14:31 2007 -0400
-
- Discover and fix an edge case in StringIO
-
-commit 6bd7adcfa115f11829a7efe8f526fabbb56d5c4c
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Sep 18 19:00:20 2007 -0700
-
- File.fnmatch(?) now passes all existing specs.
-
-commit f626f4199b88ca09a2ba75127270c0bec2ec2c86
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Mon Sep 17 15:04:44 2007 -0700
-
- Adds a new match_all primitive
-
- * will be used as the base of regex-related String functions
- * is called match_all instead of scan because it's more primitive than Ruby's scan
-
-commit 0b42d4d2610ec36a4ae5e21c37d5b587f2b9dcf8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Sep 17 02:06:50 2007 -0400
-
- Avoid using $/ in IO#puts and StringIO#puts
- Additional StringIO specs and fixes for failures
-
-commit 75969031a57bea50e4a6450bbc9ae9e5adf76fa7
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Sep 16 18:26:29 2007 -0700
-
- Replaced File.fnmatch FFI version with custom version.
-
- The custom version is needed to be as compliant as possible
- with MRI on different platforms.
-
- Lots of fixups to File.fnmatch specs.
-
-commit 18d098062cb1b996a571a946740eea7c52421e12
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Sep 17 01:11:45 2007 -0400
-
- Some failing sprintf specs and then the fixes for said failures
-
-commit 84f94ab41d72012e4ec3d0d236b183fd8a51fbe0
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon Sep 17 00:53:30 2007 -0400
-
- Additional StringIO specs and fixes for the failures that arose
-
-commit 9b44df55c682f239f036d46efe45edc2190a7345
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Sep 16 12:55:27 2007 -0400
-
- Add StringIO spec for $/ global handling
-
-commit dfcba62eb69f88d373359c75c3fa7fe827e24c69
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Sun Sep 16 00:43:41 2007 -0700
-
- Fixes string/equal_spec to pass
-
-commit 5026350a166b94fc5fffff70dae510fa2abf2094
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Sun Sep 16 00:20:52 2007 -0700
-
- String#slice works
-
-commit a4f3aa09d3aeb8d2b0a640ca9f659a5945692e04
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Sep 15 13:49:42 2007 -0700
-
- Added ability to read/write to pointer to int or double in FFI.
-
- * Fixed Math.frexp to use pointer to int to return exponent.
- * Completed Math specs.
-
-commit 1a88ca4def8d7aa566a4254eebee3236a1359fc8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Sep 14 20:57:01 2007 -0400
-
- mini_rspec.expectation_messages.yak_shave!
-
-commit 64f53c8b40b3a80b41a2c27b4ac7255b7aad5f4d
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Sep 14 02:18:16 2007 -0400
-
- Hopefully full StringIO coverage now
-
-commit 7cf9fe62bc9a5a00ae69ed3cac82e50012f3bb69
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Sep 14 00:54:33 2007 -0400
-
- Yet more StringIO specs
-
-commit 92da0550bd32db984fbb54f105b9701867d4faf9
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Sep 14 00:38:55 2007 -0400
-
- More StringIO specs
-
-commit 29826669197f44850d323910c7e60897e1ef7796
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Sep 14 00:23:45 2007 -0400
-
- Beginnings of StringIO specs
-
-commit 0c19e3557125dd366ddd119a34451715bfe5e7a1
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Wed Sep 12 18:11:49 2007 -0700
-
- Fixed object allocation bug and Bignum spec
-
-commit e42a1b960f530a987527d8795a98b2de18fea824
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Sep 13 19:19:03 2007 -0400
-
- Re-implement Module#define_method. Passes existing specs.
-
-commit a8b1a148e5fbfeb3c91558fd6caccc95006a5617
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Thu Sep 13 03:55:15 2007 -0500
-
- Adding a non-compiling spec to case_spec and updating core.rba that didn't seem to get updated correctly.
-
-commit bbd682ba2e12ba5907fe2edf2f14f11fb110cac8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Sep 13 04:04:33 2007 -0400
-
- Fix anonymous 'rest' arguments
- Suppress stray STDOUT traffic from 'defined?'
-
-commit 8f11498019eb49a4dd8bf52c4361432ebb1175d5
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 22:21:30 2007 -0700
-
- Updated CI process.
-
- * Changed bin/ci to generate an exclude file per file put
- in .spec directory.
- * Generated CI spec excludes files.
- * Updated .gitignore to not exclude .spec directory.
- * Moved the critical excludes file to spec/excludes.txt
-
-commit b736263ff325efabb907f300c1c69a2e63bd5620
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 22:21:30 2007 -0700
-
- Updated CI process.
-
- * Changed bin/ci to generate an exclude file per file put
- in .spec directory.
- * Generated CI spec excludes files.
- * Updated .gitignore to not exclude .spec directory.
- * Moved the critical excludes file to spec/excludes.txt
-
-commit 58ff9428a2a20e93e3682f834e32f754ed2c47d4
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 18:39:48 2007 -0700
-
- Fixed specs failing MRI.
-
-commit f54b1dffb9372e5cb1c71d93c67f2407fce0a1d0
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 17:17:46 2007 -0700
-
- Fixes to specs failing MRI for hash, float, fixnum, file, enumerable.
-
-commit e1d359eec451a69deb67ffdedd09b86d00774cc2
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 14:34:50 2007 -0700
-
- Fixes to Hash specs based on Ruby version differences.
-
-commit ee5eec5d32bb42fbf549068905ddebe215fbcf70
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 08:53:47 2007 -0700
-
- Fixed failing specs in kernel, module, numeric, string.
-
-commit 4f0af824f132428762f1e06409ca16c1022867bc
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Sep 12 06:24:16 2007 -0700
-
- Added #platform and #version guards for specs.
-
-commit 355c602704cd402a1d7cbadc9b4d8fae0b34f1f4
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Sep 11 00:35:03 2007 -0700
-
- Misc changes to specs to cleanup after the breakup.
-
-commit 85336c6a83736b01d63b645baf0e7e18bb5ce569
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 23:21:24 2007 -0700
-
- Converted exception, kernel, struct, object specs.
-
-commit e10bc8cbbaa26123724dad9f97f44d82e8cbf600
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 21:48:15 2007 -0700
-
- Converted string and numeric specs.
-
-commit 8ec64d24811a7951756c840c98a66a7c7d2ae7c8
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 18:35:18 2007 -0700
-
- Converted array and module specs.
-
-commit 2849f4a41b3fbda6c626d934bbf3d7476ea31848
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 15:22:36 2007 -0700
-
- Converted enumerable, file, hash, process, regexp, thread.
-
- Fixed bin/mkspec to remove '=' from string for file name.
-
-commit ffa5328aa8ed7ea079c0cc8b4228ababa5919cf6
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 13:16:14 2007 -0700
-
- Converted time and bignum specs.
-
-commit 7798952047471d28a8e12a796092c4df7ae002f2
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Sep 10 01:21:38 2007 -0700
-
- Converted range, math, matchdata, integer, float, fixnum, comparable, io.
-
-commit 423d85f4a7eb4b40d2eea83a462f5c38c4a6aee3
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Sep 9 23:43:14 2007 -0700
-
- Added dir and files for ENV. Converted true, false, nil, symbol, process.
-
- Added .spec to .gitignore.
-
-commit 8274bdcd0c747c21806065feb743e7794231f48f
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Sep 9 22:40:37 2007 -0700
-
- Converted kernel specs.
-
-commit bc1917d630d7938b62a866c3825dfa08e5ec99e1
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Sep 9 21:57:03 2007 -0700
-
- Initial create of spec/core subdirectories and files.
-
- Updated bin/mkspec to exclude Exception subclasses and
- OptionParser (which is in Object.constants because of
- the script requiring it). Also normalize TrueClass etc.
- to directory 'true'.
-
-commit b941eceb681c57d23d35f952b11b2a2d3a1ea4dd
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Sep 13 01:00:22 2007 -0400
-
- Add a minimal spec for the 'undef' keyword
-
-commit 3af389594f3828763a85d8eef65f773b183e1b46
-Author: Charles Nutter <headius@charles-nutters-computer.local>
-Date: Wed Sep 12 19:33:36 2007 -0500
-
- Adding a bunch of default argument specs to language/def_spec.
-
-commit 6b4936e834a2814602be54f01e08dcdc1f9433b5
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 9 16:58:35 2007 +0200
-
- Another fix for multiple mock expectations on the same method.
-
-commit f686ff256289263eb473249dd734cf2214c41cc2
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Sun Sep 9 16:13:53 2007 +0200
-
- Mocks now support multiple expectations of the same method with different arguments.
-
-commit 860e0d08adc8cdee9ac4d9ff3bd0e30d5d3aaa49
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Sep 8 02:36:19 2007 -0700
-
- Added to critical-excludes and ci-excludes. bin/ci -f s -C runs to completion.
-
- rake build:core compiled string.rb, so checking in core.rba.
-
-commit c9c79c910a57e5628d1743f3b440c0066875500e
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Sep 7 23:24:44 2007 -0700
-
- Added Math methods using FFI.
-
- Added Kernel.coerce_to and rewrote Float(), Integer(),
- Array(), and String() with it. Float() needs to be fixed
- to raise on strings like rb_cstr_to_dbl does.
-
- Fixed -C options for bin/ci and bin/mspec.
-
-commit b8d8b8c8475fde1ce3519e29788a34780dffae8c
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 19:40:02 2007 -0700
-
- Fixes String#<<
-
- * Added taint if other has taint
- * Fixed 10 spec failures
-
-commit b0b85547ab9dd16ba88a75c64a91c3ae0d079b27
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 15:36:44 2007 -0700
-
- Added bus error to critical-excludes
-
-commit ed13a10112d0a262a48c8e5db7d1eaaa3e076e55
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 15:19:51 2007 -0700
-
- String specs work in 1.8.6 MRI
-
-commit 6fc507c96e990139c311900c73c7e31447879071
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Sep 7 12:03:09 2007 -0700
-
- Changed VERSION and RUBY_VERSION to shadow MRI (currently 1.8.6).
-
- Added RBX_VERSION (currently 0.8.0). Updated loader -v to display
- RBX_VERSION and RUBY_VERSION and truncated BUILDREV.
-
- Enabled before|after(:all) for mini_rspec.
-
-commit 8ce602f80b35f5859c58730968a9a7053a87bd59
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Sep 7 11:16:16 2007 -0400
-
- Array#uniq, #uniq! simplified. 72 failures.
-
-commit 38f271a1b7d49074d8db9285553756fb75ffe78b
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 11:23:36 2007 -0700
-
- define_attr added to subtend
-
-commit 843706d585334c30943c8bbdd3ef6ca22297d42d
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 10:48:51 2007 -0700
-
- Added rb_cstr2inum to subtend
-
-commit 97a22e2144b623a62780995333d65986c98c4ba2
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 10:42:30 2007 -0700
-
- Added rb_const_defined to subtend
-
- It also seems that my fixture for require didn't make it in; adding that as well
-
-commit 0ac9ec2b0f381bf2fb3a36cd0b6f30748771e818
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 10:21:28 2007 -0700
-
- Added check_*_type to subtend
-
- * check_array_type
- * check_string_type
- * check_convert_type
-
-commit b2bf1c44fa7c2663e6fc0b27127aa4f5e38e073f
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 09:45:03 2007 -0700
-
- Added rb_attr_get to subtend
-
-commit 81605662ab8acc5a50536f1fc613e7d24e142df1
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 00:27:38 2007 -0700
-
- int2inum added to subtend as well as INT2NUM
-
-commit e80084e6b245173c17403891c65d86db1e6b3022
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Fri Sep 7 00:02:06 2007 -0700
-
- rb_str_split added to subtend
-
-commit 90f1fa95825caa8b21e147248d1a7d999579b937
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 23:51:56 2007 -0700
-
- rb_require in subtend added
-
-commit 5bb87f516b2a26f77a864a15636331102d6d8499
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 22:58:29 2007 -0700
-
- rb_to_id added
-
-commit e0532b3fb62089da7b7362ec2232997878a1221d
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 22:31:30 2007 -0700
-
- Added specs
-
-commit 75f7a1d2b37067f55099dd117e8fcd905baa748d
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 21:59:12 2007 -0700
-
- string subtend fixes
-
- * rb_str_cmp added
- * rb_str_cat fixed with working spec
-
-commit f058cea3e5291c349f5b2b1cfbdad4d734240f95
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 21:34:52 2007 -0700
-
- added rb_define_const
-
-commit ec7ca7f45ef32794afb919851e4bfd5e8d7aa46d
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 21:03:44 2007 -0700
-
- rb_include_module added
-
-commit 5b3471544508e973ba6afbd16daf47f5796f8b30
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Sep 6 20:41:09 2007 -0700
-
- float_new added and some functions missing in ruby.h added
-
-commit cd2af0bae996a4addfe23baa0558125a8a5523e7
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Sep 6 17:09:06 2007 -0700
-
- Fixed subtend. Added diagram of the context chain.
-
- NMCs (NativeMethodContext) now use the proper context stack.
- The stack maintenance was all screwed up when calling in and out of
- native methods, which was the source of a few problems.
-
-commit da5f9e6f942c11d906760e952debae4d05b3d872
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Sep 4 22:26:48 2007 -0700
-
- Added load-order dependency generation to rake build:(core|platform) task.
-
- Added 'depends on:' declarations to kernel/platform and kernel/core files.
-
- Updated ci-excludes.txt to reflect recent spec checkins.
-
-commit 7b1ca6f305e33b34a99e8c9e049843a76cceeca7
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Sep 2 21:29:49 2007 -0400
-
- Add more 'alias' specs. Show singleton methods in 'public_methods' output.
-
-commit 5c0b5fcb2a0c9f47a04e6a5d5027484224d0a942
-Merge: 4896039... 01c2126...
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Sep 2 18:58:53 2007 -0400
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 48960394ab7f36ccd1b18609677b40721c30d7a2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun Sep 2 18:57:29 2007 -0400
-
- Add some 'alias' specs that fail on rbx and pass on MRI
-
-commit 01c2126b705327d99aa183d51dc014169e8b4e07
-Merge: 04602c6... b6d92ec...
-Author: Florian Gross <flgr@ccan.de>
-Date: Sun Sep 2 19:45:25 2007 +0200
-
- Merge branch 'master' of git@git.rubini.us:code
-
- Conflicts:
-
- spec/core/string_spec.rb
-
-commit 04602c6756a9199b64e7d909c01dc995b25fa8a7
-Author: Florian Gross <flgr@ccan.de>
-Date: Sun Sep 2 19:32:47 2007 +0200
-
- * New specs for String#tr_s(!) and upcase(!)
- * Improved specs for String#capitalize!, downcase(!) and swapcase
-
-commit c94f83b20f7b11dc48c523c84de59b9ac6f76cce
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 23:15:07 2007 -0400
-
- Array#reverse_each, #rindex fixed and cleaned. 80 failures.
-
-commit f531f812f87283b950c62648e3cf08a7400c2779
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 22:03:05 2007 -0400
-
- Array#replace fixed, specs. 88 failures. * Disabled specs for #initialize_copy which is private.
-
-commit 1656b8a04a40bc5a43adec88ffd1480d9da6ba28
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 11:50:56 2007 -0400
-
- Array#reject, #reject!, specs fixed and cleaned * Added spec to check #reject returning Array and corrected implementation.
-
-commit e1c499c6feafc19788addd098a6da052904cb09c
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 11:25:45 2007 -0400
-
- Fixed logic in Array#rassoc, specs. 91 failures.
-
-commit da79b116d3fdc5fd4cd04f5ad1ad44b2c269ad77
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 10:38:39 2007 -0400
-
- Array#push checks frozenness, specs. 92 failures.
-
-commit 290aa6fe561453821f59be3fa92695d0b0d77c04
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 10:26:25 2007 -0400
-
- Uncommented most of Array#pack specs. * float -> int conversions still hang both C and c and are therefore disabled.
-
-commit 885f2522244c1792f45260194aba085028d5c919
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Fri Aug 31 09:59:30 2007 -0400
-
- Fixed logic errors in Array#assoc, Array#include? * Both, contrary to docs, compare elem == obj, not the other way around.
-
-commit d825038a409f4d931e80736e2de49ff0752857a9
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Aug 31 00:12:06 2007 -0700
-
- bin/ci supports options for separately running spec files
-
- Use bin/ci -s to separately process each spec file. Use
- bin/ci -m to run all the spec files in a single VM process.
- -s is the default for --create, but -m is the default for
- everything else.
-
- Updated ci-excludes.txt and critical-excludes.txt.
-
-commit 7dfe5cb7936051685a2c79effb6295b9aa179810
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Aug 30 23:44:28 2007 -0700
-
- Updated ci-excludes.txt to only exclude failing specs.
-
-commit fb09f0a7a6969adffd8d99bf869eb50c91eef097
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu Aug 30 20:31:20 2007 -0400
-
- Fix object and array specs that failed under MRI
-
-commit 6fb73244537b61a20538c1f3d5a060a40a358be5
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Thu Aug 30 17:08:12 2007 -0700
-
- Fixed two typos in the subtend string specs
-
-commit 00256f41d4e3ebfcdafdc25e27bfbf4bc7d3de3f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 11:19:09 2007 -0400
-
- Array#last fixed. 48 failures.
-
-commit 887d41c64c6bdff693f6ecd8d3078f8453669648
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 11:02:27 2007 -0400
-
- Array#insert, specs corrected. 49 failures.
- * Fixed Array#insert
- * Re-complianced frozenness specs for Array#inspect.
-
-commit 1bc536e1128bc76b1c9efae593340f67bdcb5fb5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 10:42:05 2007 -0400
-
- Array#indexes correct implementation. 51 failures.
- * Array#indexes and #indices is now correct although
- both methods are deprecated in favour of #values_at.
-
-commit 5de09c707b1ce43bf689e8ded9ea19784e77a49e
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 10:09:27 2007 -0400
-
- Array#include? implemented. 53 failures.
- * Replaced use of Enumerable#include?
- * Re-complianced to a simpler Array#include? spec to
- avoid implementation-dependedness.
-
-commit 14ca6c2533764eea508b24b0ec89475a7aae5e94
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 09:32:40 2007 -0400
-
- Array#hash spec compliance change. 54 failures.
- * Disabled an Array#hash spec for Rubinius because it
- relies too much on implementation details.
-
-commit fc4f392fa7fba88b36bfdec61db3acaa1f1fadc2
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Thu Aug 30 00:42:03 2007 -0400
-
- Array#flatten, #flatten!. Improved Array specs. 384 ex, 55 failures.
- * Array#flatten, #flatten! implementation improved, they
- also work recursively now.
- * Re-enabled Array#flatten, #flatten! specs and the
- recursive test for Array#inspect.
-
-commit efeaa622994e9868b9324247b0ff1fd5743792ac
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Wed Aug 29 23:29:36 2007 -0700
-
- A series of rb_str functions in subtend, plus fixes to some of the tests earlier committed
-
-commit e4f5281148799ed716065c489d384a42d208290d
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Wed Aug 29 19:16:26 2007 -0700
-
- rb_str_append() added
-
-commit a05c376478f7407da4e0aa2a6a7e3de98176a63b
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Wed Aug 29 13:25:17 2007 -0700
-
- Updated subtend array functions
-
- * rb_ary_reverse() added
- * tests added for rb_ary_join() and rb_ary_reverse()
-
-commit 779fb97c35b78b9749cbb118fcb555096957e4c6
-Merge: 2793a99... e17987e...
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Wed Aug 29 12:40:33 2007 -0700
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 2793a9917f8f5cc2f0fc14ba605cec499532e680
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Wed Aug 29 12:40:21 2007 -0700
-
- Slightly improved rb_ary_pop() test
-
-commit c196c60b6cd32c85b18bdab31ee000cf097309b5
-Author: Me <rue@meow.kittensoft.org>
-Date: Tue Aug 28 23:49:46 2007 -0400
-
- Array#fill fixed, cleaned up. 375 examples, 59 failures.
-
-commit 7736413f262357479c2f3354a73533fd89b3c9a6
-Author: Yehuda Katz <wycats@gmail.com>
-Date: Tue Aug 28 17:54:28 2007 -0700
-
- added rb_ary_join() to subtend
-
- Trying to get tests working but it's hard to see if I'm correct without the ability to run them.
- I'll take care of making sure there are passing tests as soon as I can.
-
-commit 0effcaf3e948d80ae3ad17b33f0483313d85cdbe
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Tue Aug 28 00:24:41 2007 -0400
-
- Array#fetch, specs, slightly cleaned array.rb. 62 failures.
- * Array#fetch uses to_int.
- * Specs for Array#fetch check for correct block var.
- * Removed extra comments from array.rb.
- * Removed old implementations from array.rb.
-
-commit 51737d35c24f853a23e14f7a227138d4d0f6b457
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Aug 27 21:46:30 2007 -0700
-
- Added failing File specs to ci-excludes
-
-commit a195970e2b2d34fa4388e6a72e91ada13b4b0d32
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Tue Aug 28 09:20:33 2007 +1000
-
- Ensure exists? is prefixed by File.
-
-commit 804b6f3358c1bb73492beaa0e978d4df8dbac138
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Tue Aug 28 00:18:41 2007 +1000
-
- Minor refactoring work on file spec.
-
- Removed duplicated constant tests.
-
-commit ef18eaaaa1a79b964667900b19f3f10e1b67032b
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Aug 27 14:25:06 2007 -0700
-
- Updates to enable bin/ci to run to completion.
-
- Changed mini_rspec to not use File.open with a block to work
- around IO#read failing to catch EOFError.
-
- Commented out object_spec.rb specs that need to be completely redone.
-
- Updated spec/reports exclude files to enable bin/ci to work.
-
-commit 505617b26829d5f489c4488ed934a6dc720f64f0
-Author: Florian Gross <flgr@ccan.de>
-Date: Sun Aug 26 22:53:42 2007 +0200
-
- A few new specs for String#sum, #to_i, #to_s, #to_str, #tr and #tr!
-
-commit a6a24a97dce2a4072a6ea17e48259b76f0c3681a
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Aug 26 02:52:55 2007 -0400
-
- Array#delete, Array#delete_at, Array#delete_if. 63 failures.
- * Fixed the three delete* methods, they still need clean-up
- * The specs reflect difference in frozen handling for rbx and r18
-
-commit 063f8c25d45e0934bca236ecb8af36dcb517187f
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Aug 26 02:26:15 2007 -0400
-
- Array#concat fixed. 69 failures.
- * Array#concat checks frozenness and cleaned up
- * Improved specs for #concat
-
-commit a9f3593593948cf72d94712765d05bfcc27f2e78
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sun Aug 26 01:53:05 2007 -0400
-
- Array#dup, Array#compact, Array#compact!. 71 failing.
- * Array#dup properly returns subclass
- * Array#compact(!) improved to pass specs
-
-commit 7be3bc12ea2e5432e442cb44103b4b1c6d981163
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 23:57:38 2007 -0400
-
- Array#clear, Array#frozen?. 372 examples, 73 failures. * Array#frozen? checks for sorting freezes * Array#clear fails on frozen Arrays
-
-commit 5c958242fe25f8a18cd8d315f81fb3db80dc7a40
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 17:19:23 2007 -0400
-
- Array#==, Array#assoc improvements. 75 failures
- * Cleaned up Array#==
- * Array#assoc processes correctly
-
-commit f82f8a300ee394f9f1038cc84de1cf6b132d7ef5
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 16:24:22 2007 -0400
-
- Array#* improved. 371 specs, 81 failures
- * Array#* processes to_int and to_ary correctly and forwards
- to #join when needed.
-
-commit 91e16f06d5b5b16f1fa7ffc1d3673d7f1c681587
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 15:54:12 2007 -0400
-
- Array#join can process recursive Arrays.
- * Rubinius cannot create recursive Arrays so this is somewhat moot.
-
-commit 2d7427bb638f1af6d7437beed4beafde5274dbdf
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 13:46:45 2007 -0400
-
- Array#|, better Array#&. 371 examples, 86 failures.
- * Array#& explicitly uses #eql? semantics
- * Cleaned up Array#|, uses to_ary
-
-commit 2b8707466f763662d52efaeab71b4789b132bb40
-Merge: c61b1e5... 76be87f...
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 12:41:06 2007 -0400
-
- Merge branch 'array'
-
-commit 76be87f74d352d79425e9c46d3df55678257fda9
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 12:28:32 2007 -0400
-
- Array#<< improvements. 371 examples, 89 failures.
- * Specced and fixed resizing bug in Array#<<
-
-commit c61b1e54cc11c297b9e9a9eca70cb6a354ed21d9
-Merge: 3618a8b... c6cc98f...
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Sat Aug 25 18:16:45 2007 +0200
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 3618a8bc588588ef8fb0dcc4753bc42606b86c13
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Sat Aug 25 18:16:05 2007 +0200
-
- Update object specs
- Update the object_spec.rb file
- * add more specs
- * refactor using it_behave_like
-
-commit 294e5aacda8a74a9d8f57d05bb433f2fadcd08f1
-Author: Eero Saynatkari <rubinius@projects.kittensoft.org>
-Date: Sat Aug 25 12:07:06 2007 -0400
-
- Array#[], modified parts of array_spec. 369 examples, 90 failures.
- * Array#[] passes its specs
- * Disabled some parts of array_spec while fixing Array. These
- will be re-enabled as soon as possible.
-
-commit 1369465aefcd1d50ddd268ba9af968c62137e2b2
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Fri Aug 24 11:14:20 2007 +0200
-
- Array#new correct implementation
-
-commit e321427a52878ef9d9c7c04aa7c3c4f1e3a6c940
-Merge: bff7c05... 69c0407...
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Fri Aug 24 11:14:20 2007 +0200
-
- Merge branch 'master' of git@git.rubini.us:code
-
-commit 07c7f93a64fc37f3cf94a0a2c272468d015a7fb3
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Aug 23 21:18:13 2007 -0700
-
- Converted Regexp specs to new describe style.
-
- Fixed String specs to be compatible with bin/completeness.
- Fixed bin/completeness to use dotted reporter instead of CI
- reporter since the latter no longer outputs summary info.
-
-commit 6776e1478fa7e78a0944a1ee59c55c3839f51ea4
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Fri Aug 24 13:14:47 2007 +1000
-
- Added implementation of File.split and updated specs.
-
-commit 4053b9076b4b996f544095a75317453967723faa
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Wed Aug 22 21:58:13 2007 +1000
-
- Added spec for mocking methods on a class
-
-commit 54cae1196db08f6a734c35079db8df62e491f300
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Thu Aug 23 17:38:40 2007 -0700
-
- Added more IO stuff and platform methods.
-
- I'm still a little unhappy with the input buffer situation.
- (ie, there is none.)
-
- Adds IO#sysread and IO#syswrite as well as a bunch of POSIX stuff.
-
-commit 12a755004c0a8a0319212965da61385738166f98
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Aug 21 12:44:48 2007 -0700
-
- Beginnings of ftools spec, fix backtrace generation.
-
- Backtraces were failing to be properly built if the sender was a Block.
-
-commit bff7c05ce12c79ef111422ecf4525f1a65e7a5f0
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Fri Aug 24 01:15:41 2007 +0200
-
- More specs dor enumerable
- * add inject, min, grep, find, detect, find_all, select
-
-commit ed9a8fefcc384bb6548a7f66bbafb97192ec8fd3
-Merge: 4ef0b9f... 8dd800e...
-Author: Arthur Schreiber <schreiber.arthur@gmail.com>
-Date: Thu Aug 23 11:01:25 2007 +0200
-
- Merge branch 'specs'
-
-commit 8dd800e8189f616dc54390c0ebf96c331de41230
-Author: schreiber.arthur@gmail.com <arthur@arthur-desktop.(none)>
-Date: Thu Aug 23 10:45:56 2007 +0200
-
- * Some more Module Specs.
-
-commit 0f414f56f9050d86011df75e7fd23428fe378996
-Author: schreiber.arthur@gmail.com <arthur@arthur-desktop.(none)>
-Date: Thu Aug 23 10:44:59 2007 +0200
-
- * Added :count => :any option to mock expectations
-
-commit 4ef0b9feddfebfd1b6177fce6e3a1a4077f4f098
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Aug 22 23:10:22 2007 -0700
-
- Updated exclusion list for CI specs.
- Updated rake spec:ci task.
- Changed ci spec run action to execute all specs in one process.
- Added guard on file specs to prevent compilation exception.
-
-commit c3b61b239fa6a02327e5651513986d998d826eaf
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Aug 22 21:48:08 2007 -0700
-
- Updated CI spec process to exclude specs failing on compilation.
-
- Added critical failures to enable running especially spec/core.
- Added failure guards to struct specs.
-
-commit f339a284c66357bc52749e5fe9c0d59bbbdc7ade
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Aug 20 22:31:56 2007 -0700
-
- Fleshed out bin/ci constructs for running specs.
-
-commit 4f750d59adfff6c1751372c0d2853778dc7ae16d
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Tue Aug 21 22:40:33 2007 +0200
-
- * more enumerable specs
- * refactor to it_behaves_like
-
-commit 3c79d5cf67b40b945602d5c5fa77589e0d7bae2c
-Author: Pedro Del Gallego Vida <pedro@la-vaca-roja.(none)>
-Date: Tue Aug 21 20:52:16 2007 +0200
-
- update file_spec.rb
-
-commit b2a64089bffe5afb9148a665ecb6e70c3bc62b67
-Merge: 6865b97... 1b6a8a1...
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 19 16:22:53 2007 -0700
-
- merge 1b6a8a157
-
-commit bf54767922eb8d494c683ed8d57c6ffb5164fc29
-Merge: 6c6032e... 37d71c9...
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 19 15:24:21 2007 -0700
-
- merge from e83bcd022
-
-commit 05db33909c319231ac375812025ea2378710a299
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sun Aug 19 21:26:15 2007 +1000
-
- Add conditional when deleting a file in after(:each) block to prevent an exception if the file is missing.
-
-commit 138ab001175987cd38aff092a850e515745f9292
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sun Aug 19 21:18:22 2007 +1000
-
- Converted remaining context/specify spec's into describe/it, and followed class/method naming convention.
-
-commit 749b883d0260326573c581cc63eab67e1a4bc590
-Author: Marcus Crafter <crafterm@redartisan.com>
-Date: Sun Aug 19 20:23:11 2007 +1000
-
- Added implementation of exists? blockdev? chardev? zero? size size? writable_real? executable_real? readable_real? unlink delete and chmod using ffi where needed. Specs for most of these methods existed already, added specs for those that weren't. Fixed a few typos.
-
-commit ddcb14f9f2311ec843a1f1f8d2b3fa868384ff0d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 18 23:19:32 2007 -0700
-
- more misc changes to get ci specs working
- added alias for File.exists? and File.exist?
- added Dir.getcwd
- added empty File.delete
-
-commit afb252fd6170ed051e97f1911e5f1200414ebf98
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 18 22:20:10 2007 -0700
-
- updated compiler specs.
-
-commit d0e6b658d9065b0fbc9180cd5d19139834f64f59
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 18 21:04:18 2007 -0700
-
- changes to support better CI specs
- hat mini_rspec will take a filename as an exclude/include argument and read the actual excludes/includes from the file.
- added that mspec will take -o FILE to use an alternate to STDOUT for the spec reporter output.
- updated spec tasks. misc spec changes.
- added naive implementation of IO#each.
-
-commit 541bcb521a8ee589c7d28c095ad7ee1489af42db
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri Aug 17 19:30:05 2007 -0700
-
- Complete reorganization of bootstrap. Addition of kernel/platform. FFI fixed.
-
- New restrictions for meta-programming in core bodies (not in methods).
- kernel/platform is now where platform specific code, mainly related to FFI, lives.
- A bunch of FFI bugs have been fixed and it should be working much better now.
-
- FFI Note: you may now only specify :state as your first argument, and you must
- leave it off when you call the method (rather than passing nil like before).
-
-commit af245dfbc80ff942de62408e70db7499a798fb0a
-Author: schreiber.arthur@gmail.com <arthur@arthur-desktop.(none)>
-Date: Tue Aug 14 01:30:09 2007 +0200
-
- Forgot to add the autoloaded file for Module#autoload
-
-commit b946940f463028de067ef2e082c96fe431c94b0a
-Author: schreiber.arthur@gmail.com <arthur@arthur-desktop.(none)>
-Date: Tue Aug 14 01:09:10 2007 +0200
-
- Updated Module Specs
-
-commit 6cd6aa53a5d20c78941442f7e367ef8c7aee17c2
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Aug 10 00:14:09 2007 +0000
-
- converted array specs with a few edits.
-
-commit c075f7f70da2a029c69f3fff1f9caec419db64d5
-Author: Arthur <arthur@unknown>
-Date: Wed Aug 8 12:47:18 2007 +0000
-
- fix a small typo
-
-commit c7262df9ee1c2544890b001574c8cb0f8ae26a75
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Aug 8 01:24:25 2007 +0000
-
- converted exception specs. added #should_be_ancestor_of. use ExpectationNotMetError in mini_rspec like rspec does.
-
-commit f591e18978b73c508505db73f274f4bd69c372c5
-Author: Arthur <arthur@unknown>
-Date: Tue Aug 7 08:36:15 2007 +0000
-
- * String#to_str specs should actually use String#to_str
-
-commit 80f69571c5378d6bbb2e7a118ada00db66226797
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Aug 7 06:47:53 2007 +0000
-
- converted range specs.
-
-commit aca62d253a6b2df891ca4ec4b177ea95b621d636
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Aug 7 03:52:46 2007 +0000
-
- fixed mini_rspec -e option, allows multiples. converted hash specs.
-
-commit 928c9a392102fa7b7945f332480a7477ec203467
-Author: Florian Gross <florgro@gmail.com>
-Date: Mon Aug 6 22:04:16 2007 +0000
-
- New specs for String#swapcase(!), to_f, to_i, to_str, to_sym
-
-commit 6d0a6b0051a55af32743d9d98d6425489a622ebe
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Mon Aug 6 21:58:55 2007 +0000
-
- * more specs for File.open. Specs for File.truncate
-
-commit 8b19b683a8593b4dd5024841d8023df827a44875
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 5 23:39:36 2007 +0000
-
- fixed completeness to not over match methods. converted comparable specs.
-
-commit c6f4d90df72b103884fa5470a433f5513d2c524d
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Sun Aug 5 22:52:17 2007 +0000
-
- * more specs for File.open. Some of them are plataform dependent
-
-commit 38bfff9d014b90409e272ddf041dc63f53d48f5d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 5 22:45:31 2007 +0000
-
- converted bignum specs. misc cleanup.
-
-commit 14890b68c447731417ce53ca2e4310175e39b440
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Aug 5 22:00:04 2007 +0000
-
- Small spec fix
-
-commit b6c3cfca5cf1b2cb85dc216180ad21a6bf653a10
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 5 17:20:32 2007 +0000
-
- converted time specs. according to completeness, need to spec 9 more methods.
-
-commit 8829cf7e94ec0434f642fafa7dbf117a860045b9
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 5 07:53:47 2007 +0000
-
- more converted specs.
-
-commit 5bf174780e893b7ee9b82b6ca3964db7cad84e30
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Aug 5 07:08:08 2007 +0000
-
- converted fixnum specs to describe per method.
-
-commit 88023701a88c1113e4874c193d26c6bf21fad383
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 4 22:19:18 2007 +0000
-
- misc noise cleanup in specs. use bin/completeness to find missing specs rather than warns.
-
-commit 3d960a021cb9ac2bdc2a204f94b4f024f3ef60a4
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 4 22:06:12 2007 +0000
-
- fixed completeness to pass correct spec example string for class methods. changed float specs to describe per method.
-
-commit 8a7abb5996e5bdf8b9d6c5884e0e0d8ae73d060e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 4 20:10:38 2007 +0000
-
- beginning of a completeness reporter. use 'bin/completeness -t ruby' to report on the completeness of the specs against MRI. use 'bin/completeness' to report on the completeness of rbx relative to MRI. use -t target for other implementations. updated some specs to the 'describe Class#method' style.
-
-commit 463f13be4462e22bc3f4491a475658624c5832ab
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Sat Aug 4 17:09:25 2007 +0000
-
- * fix some bugs in bignum_spec
- * changed the File::Foo.shouid == bar assert to defined?(File::Foo).should == "constant". The specific value dependence on OS.
-
-commit 989d72394f1e175b058f55ccf3e60f09a2c76401
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Aug 4 04:15:01 2007 +0000
-
- fixed mini_rspec specdox reporter to not output describe message until examples are executed. fixed specdox and dotted reporter to distinguish between errors and failures.
-
-commit f98fe7f211e5784a35e99643fb52c9350b20d7ae
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Aug 4 01:40:52 2007 +0000
-
- More compatibility and a few small fixes
-
-commit c78ba9f96d7d4d229d6b1b1b11cf314fb5a0271d
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Aug 4 00:40:42 2007 +0000
-
- Compatibility for USE_RSPEC=1, sanity, some clean-up
-
-commit 761d05b5cbd92339f9d02e65d005a65c5155618e
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Aug 3 21:49:26 2007 +0000
-
- * Compiler and Normalizer fixes for method definitions without bodies
-
-commit ad7abe4d61171f9650d08b277d45c7f680f37950
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Aug 3 17:07:19 2007 +0000
-
- fixed mini_rspec shared behavior to be compatible with rspec.
-
-commit 1e1ccb902d11547e9f67db82c31a5898e6227d67
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Aug 3 16:39:07 2007 +0000
-
- added an implementation of shared behavior for mini_rspec. altered Array#[] and Array#slice specs to use shared behavior.
-
-commit 7697b2ae3db6ed1d8697010a7e0f52f8e3587c8a
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Aug 2 20:41:43 2007 +0000
-
- added SpecRunner class to mini_rspec to properly encapsulate behavior. added --example option to specify a regexp to match examples to execute.
-
-commit b80bb3d295d3648988b15a29553189f219d8ac0a
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Thu Aug 2 15:56:07 2007 +0000
-
- * added specs for file_spec
-
-commit c277fd3de82678f055693422af19c3f45ffc2a88
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Aug 2 00:46:27 2007 +0000
-
- mspec: Add -x option for excluding specs by RE
-
-commit aa53967c694ed7621aa1a8a8b542d067d9e58925
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Aug 2 00:05:53 2007 +0000
-
- New specs for String#succ(!)
-
-commit eafa5b0fd43168b4ae649b145f9528f7deae3aa7
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Aug 1 22:59:38 2007 +0000
-
- New specs for String#sub(!)
-
-commit 3406e64032251a2a9849da3f6c27d872dd339175
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Aug 1 22:17:18 2007 +0000
-
- New specs for String#squeeze(!) and String#strip(!)
-
-commit fa4d66576528725085ef47cca27c5c85c55b3150
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Aug 1 21:08:26 2007 +0000
-
- added Object#(public|private|protected)_methods and Module#(public|private|protected)_instance_methods. added Tuple#first, last.
-
-commit 4ca071ba4a48aa984308e0ba9448718a6e214d7a
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jul 31 20:56:37 2007 +0000
-
- Some Object#methods et al specs.
-
-commit 67be404ac0714ec01c1c92c77465915d90fd794b
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 31 18:41:54 2007 +0000
-
- Renamed variables_spec.rb to assignment_spec.rb
-
-commit c0187db3e51297dfffabebe9acb6d6321bd04578
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 31 18:22:41 2007 +0000
-
- New specs for String#split
-
-commit 06cb5ab7c39866c99bb8d9a5fbb678f2f8a19cf2
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jul 22 06:47:54 2007 +0000
-
- Removed the .rbc files from externals dir and set svn:ignore. Added Tuple specs, fixed a couple small problems with Tuple. Modified mspec to pass -I, -r to the target; added -n RUBY_NAME to affect which specs are run. Added hashi dir as an experiment to implement a bootstrap that could be run on e.g. MRI or JRuby to allow the core libs to be run and tested against the specs.
-
-commit 567d4f710bc232fc9223972e22a7d92e4abe940d
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue Jul 17 17:49:53 2007 +0000
-
- Stack allocated lvars, GC fixes, compiler changes, oh my!
-
- This is a biggy (too big in fact). It started as a change to allow
- arguments to be accessed directly from the stack, and turned into a
- monster.
-
- Arguments and some lvars can now be accessed directly from the stack,
- making them cheaper to create and use. This turned out to expose
- a large number of bugs in the VM related to stack access, as well
- as some in the GC.
-
- The big GC change here is that the mark/sweep GC is actually run now,
- as opposed to before when it would just allocated more and more memory
- (the source of memory issues I suspect).
-
-commit 564ac024e14a790f4a3d257ddf1d9fa0cb93ee3b
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 17 00:20:52 2007 +0000
-
- $~ specs all over the place;
- Revised % format string specs (match MRI trunk);
- Revised hex and oct specs (match MRI trunk);
- Merged slice together with [];
- New specs for scan and slice!
-
-commit 2389eb4b36d86732dbb621be1cad3edca0e36aa5
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Mon Jul 16 09:26:20 2007 +0000
-
- * added specs for file_spec
-
-commit a6453b6184353633d14c271533c2e2af7a6c4b12
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jul 15 17:53:58 2007 +0000
-
- A few specs for char numbers outside of 0..255;
- A few specs for modifying strings while iterating;
- New specs for hex, index, initialize(_copy), ljust, lstrip(!), match, next(!), oct, replace, reverse(!), rindex, rjust, rstrip(!);
- Small additions, fixes & refactoring
-
-commit 217dd5dae127c146559dd1512edac23a94565ae9
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Jul 14 23:52:52 2007 +0000
-
- Taintedness specs all over the place;
- String subclass specs for String#%;
- Range subclass specs for access methods;
- str[idx, count] = str specs (contributed by John Lam);
- New cases for capitalize(!) / center / gsub(!);
- Refactoring
-
-commit b8b0c3dd380335260c3870934ca51dce736ce15d
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Jul 14 23:39:38 2007 +0000
-
- Added custom range subclass cases for access methods
-
-commit 558552ec549fd605bed2c8f5c384e8c944e780a2
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Fri Jul 13 14:40:15 2007 +0000
-
- * added cases for file_spec
-
-commit 5218708c630bd8a631522a00aa6cba4e91cbec54
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Fri Jul 13 13:36:53 2007 +0000
-
- * added cases for file_spec
- * refactoring numeric_spec.rb
-
-commit 3e9dbc15a81950e55a15a7fcca0ab04a5fd5353f
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jul 11 22:09:49 2007 +0000
-
- Add specs for to_* calls having correct semantics with method_missing() and respond_to?();
- Small clean up
-
-commit 23961f46af6f74d2d6b9019972e451a5ae12b728
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jul 11 22:00:26 2007 +0000
-
- Add specs for to_* calls having correct semantics with method_missing() and respond_to?();
- Removed a few duplicate specs (probably resulting from a mismerge)
-
-commit 639c64ca0965ff79401989ca7dbde862815f13fb
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jul 11 21:09:33 2007 +0000
-
- Add specs for to_* calls having correct semantics with method_missing() and respond_to?();
- Fixed String#%'s %E/e/f/G/g and %b/d/i/o/u/X/x specs to verify Kernel#Float / Kernel#Integer semantics instead of to_f / to_i ones
-
-commit e97879670bbc8425810a3c83f15a523066899a89
-Author: Arthur <arthur@unknown>
-Date: Tue Jul 10 20:04:48 2007 +0000
-
- * fix a typo
-
-commit 1e8890613a215c61ef90629b8b6023ac4612c499
-Author: Arthur <arthur@unknown>
-Date: Tue Jul 10 20:03:44 2007 +0000
-
- * Update Symbol Specs to the new format.
- * make Symbol#to_int show a warning as in MRI.
-
-commit 1262f24460463628c7cc4e275b7c814048937b57
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 10 18:28:06 2007 +0000
-
- New specs for gsub() without block
-
-commit 0ba87f6edc183385551e4cf8c05212fadaf36427
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 10 16:48:46 2007 +0000
-
- New specs for capitalize, chomp, concat, crypt, eql?;
- Added missing methods chop, chop!, count;
- Small improvements and refactoring
-
-commit 226942caef6bd217a13dc235a89c5ccf4a18f98b
-Author: Florian Gross <florgro@gmail.com>
-Date: Mon Jul 9 21:29:19 2007 +0000
-
- Strings specs for letters c through e
-
-commit e41c027537f1e4f8ea4b8b5b6fe90df9a21e3aff
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Fri Jul 6 17:13:39 2007 +0000
-
- * added 62 cases for file_spec
- * remove a bug from obejct#method_missing_spec that break the specs
-
-commit 06d2fd71b847e139a39ab3b7a132ab041a8d4c1e
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Wed Jul 4 16:05:21 2007 +0000
-
- * add 84 cases to the numeric_spec.rb
-
-commit b8d334f575322c65932279346bba61caead61555
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Wed Jul 4 10:28:27 2007 +0000
-
- * 14 cases for Object.method_missing
- * Add File#atime, File.atime, File#ctime, File.ctime, File.delete, File.executable?, File.executable?
-
-commit f2276130c4bf1894ffb6efb451203dcbfe9322bb
-Author: Charles Nutter <charles.nutter@sun.com>
-Date: Wed Jul 4 08:48:57 2007 +0000
-
- Added a spec for Process::times...it's not great, but it's something.
-
-commit f71bb57b3fc69c35d34abdb9959e27efb71bbdff
-Author: Charles Nutter <charles.nutter@sun.com>
-Date: Wed Jul 4 06:14:06 2007 +0000
-
- Fixes for #150; handle Time - Time correctly, don't assume it's a number of seconds.
-
-commit 895f1abdc0bfcdb213f97067704b1bb87a7e6d17
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 3 17:01:27 2007 +0000
-
- New specs for casecmp
-
-commit 2aa7cb37925cd92c3b23d4a33a6d7bc7c2b66737
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jul 3 14:07:56 2007 +0000
-
- New #[] and #[]=, capitalize and casecmp specs;
- Converted "should work" messages to "works" using a few regular expressions -- I'm still going through the file so bad replacements (if any) will be fixed
-
-commit 719ff3b8959d93d7da8165d6e5b44989afde92d7
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Tue Jul 3 00:33:59 2007 +0000
-
- * new NoMethodErro_spec.rb
-
-commit 5363324044fdc1457cfbf1b738dd931d3255b191
-Author: Florian Gross <florgro@gmail.com>
-Date: Mon Jul 2 23:58:09 2007 +0000
-
- Some more new specs
-
-commit fa1b3694e366bf087a8d1ac107257c38ce447251
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Mon Jul 2 20:29:20 2007 +0000
-
- * Add to_s with a base spec
- * Change foo.aMethod.to_s.should == "bar" with foo.aMethod.should_be_close(bar,TOLERANCE) because floats representation are plataform/implementation dependents, but not changed aBignum.to_s.should = ...
-
-commit 2a5c93afd4ddfef7c30de17c531f49849e9bb957
-Author: Pedro Del Gallego <pedro.delgallego@gmail.com>
-Date: Mon Jul 2 00:10:06 2007 +0000
-
- * Add Float::Constant specs
- * Change foo.aMethod.to_s.should == "bar" with foo.aMethod.should_be_close(bar,TOLERANCE) because floats representation are plataform/implementation dependents
-
-commit 7d3dcc24cb72d6548cf44d8519691f4cd7344801
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jul 1 21:00:37 2007 +0000
-
- Heavily extended and refactored String#% specs;
- some cleanup
-
-commit 79ce6628df39d20d03efcd715ea42ba70ae9f03e
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jul 1 20:59:38 2007 +0000
-
- Add support for MRI as :mri for failure() and similar methods
-
-commit 7e43cd858c0380aaf17dd7bacd8a24cef96bb309
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jul 1 17:11:08 2007 +0000
-
- rindex terror specs
-
-commit e5b7cf88092cf59357124e3d8f35bc19f8ee589a
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jul 1 01:14:09 2007 +0000
-
- Added a few new format specs (Most of these should probably be moved to Kernel::format later)
-
-commit a533693824608a03ab6a66882b607fecab3a3a75
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Jun 30 00:29:29 2007 +0000
-
- A few more specs, clean up and compatibility with MRI 1.9 head
-
-commit b9e8936562ec23db63879f9c127dadeadd8adf2e
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 29 02:41:40 2007 +0000
-
- New specs for [], default(), delete(), shift(), yield argument count semantics and modifying hashes while iterating over them;
- Also removed some warnings and cleaned up the code a bit
-
-commit 72d1b106c1de4b00b9af184eb890e950854a9c77
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 29 02:37:55 2007 +0000
-
- Adding spec for join passing along separator argument for nested arrays
-
-commit 6e2848b7143cd0ae47a7b9ac632a567df7fd30fc
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 29 02:35:09 2007 +0000
-
- Adding message argument for should_raise()
-
-commit 31591886dde4bfd9b4e9de34c26960e45566b7ee
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jun 27 05:15:15 2007 +0000
-
- Commiting (#147) math specs by pedro (modified for style, structure, and legibility).
-
-commit c7d623ee836363d0f3d443ba1c676ef0f86e34f7
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jun 26 04:06:49 2007 +0000
-
- enhanced spec:ci to take a target on the command line, invoke like: SPEC_TARGET=jruby rake spec:ci. removed deprecated #only and #except from spec_helper.
-
-commit c13a588cb7e37c20ce7e8a9430d854cc51be7b00
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 25 08:28:10 2007 +0000
-
- misc cleanups to specs to eliminate interaction effects.
-
-commit 280296208bd699cb574c662f92b585519a739c6b
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 25 02:42:07 2007 +0000
-
- removed extension dir and added README for subtend specs.
-
-commit 7ce8d4addc77ea9da0daf3ea3dc1fc7b00030b29
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 25 02:30:15 2007 +0000
-
- reorganized subtend specs. stragglers from spec/language reorg.
-
-commit d499ebfd98d8fb9bd50c0f7a46b3587aa1f28c8a
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jun 24 19:44:12 2007 +0000
-
- significant reorganization of spec/language, added files that correspond to the desired layout of this section. there remains to be done a large amount of cleanup for existing language specs, and especially spec description strings.
-
-commit bc0d0965bb5a6b3966884b63edd37218359aa46d
-Author: Tilman <tilman@unknown>
-Date: Sun Jun 24 14:52:15 2007 +0000
-
- Extended specs for File.join.
-
-commit a4e189f31a8c256821564041c4dbce2a832ba78e
-Author: Tilman <tilman@unknown>
-Date: Sun Jun 24 13:00:33 2007 +0000
-
- Fixed a typo.
-
-commit ecaf1abafeb69994b05463742ca4220797f62ad3
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Fri Jun 22 23:25:13 2007 +0000
-
- * Array specs by Josh Susser (hasmanyjosh)
-
-commit 1c8987b6195d356126ebc3cc9c21e473be915240
-Author: Arthur <arthur@unknown>
-Date: Fri Jun 22 21:22:30 2007 +0000
-
- * Heavily extended String specs
-
-commit 663e2cbe0c026aa7e792b6aab682301570ccd766
-Author: Tilman <tilman@unknown>
-Date: Fri Jun 22 08:59:42 2007 +0000
-
- Added specs for Time#dup.
-
-commit f9dd8149bd7d794e8686053e8dca010ea71eacba
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jun 21 06:47:57 2007 +0000
-
- added methods #compliant, #noncompliant, #extension, #failure. Please read the comments for them in spec_helper.rb. #only, #except are deprecated but have not yet been removed.
-
-commit 389b3cef5176b0244f78294a3c820cc84797e0df
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jun 21 05:22:36 2007 +0000
-
- added -f i (immediate) reporter for mini_rspec.
-
-commit d113f855e32d09abaa74bb0ccafa4a65ffce66b1
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jun 20 21:59:27 2007 +0000
-
- A few more hash order consistency specs
-
-commit 8df2a605937c29b0ca4e89fae37b725e7244fbee
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jun 20 21:24:01 2007 +0000
-
- Small spec improvements all over the place
-
-commit 5c2472584637b6f5accaaf2450d4c23904b0bbd7
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 23:06:33 2007 +0000
-
- Small tweaks to let us run specs against Ruby 1.9
-
-commit 18b06659146f00f0ecf72846c445b03268305328
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 15:56:02 2007 +0000
-
- More specs, including frozen hash ones
-
-commit 3cc17a6c7d4c4e4d13b67da4e2bd8937160916f0
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 15:02:21 2007 +0000
-
- Specs for methods involving to_hash and more
-
-commit a33e72ba27dc7c80fb7c3947d4fe86521b8987e0
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 13:35:14 2007 +0000
-
- New specs for each, each_key, each_pair, each_value, fetch, has_value?, index, initialize_copy, inspect, invert, key?, keys, length, merge, merge!, rehash, to_a and value?
-
-commit f5ec55b0233fd6b7825b04afc6157caac0c529ce
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 13:18:33 2007 +0000
-
- Using except(:rbx) for "inspect should handle recursive arrays" instead of commenting it out
-
-commit 7fec6cb5534d22dbfa4dd245cf3b0c0776b3b465
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 00:56:35 2007 +0000
-
- New specs for Hash.new, #==, #[], #[]=, #clear, #default=, #delete and #empty?
-
-commit e3085af8e97177f8b7e4ff1c2aad2f306a4f474d
-Author: Florian Gross <florgro@gmail.com>
-Date: Tue Jun 19 00:53:43 2007 +0000
-
- Specs for how Array#uniq should use eql?() and hash()
-
-commit 01799e95c71453e8dff9730dd283bf76989e75e5
-Author: Florian Gross <florgro@gmail.com>
-Date: Mon Jun 18 11:22:47 2007 +0000
-
- Adding new specs from rue plus more. The diff is a bit chaotic, but everything should be OK.
-
-commit 890deed76153d05c6874b46ec29c474eb4e36e41
-Author: Florian Gross <florgro@gmail.com>
-Date: Mon Jun 18 11:12:04 2007 +0000
-
- Moving only() to general spec helpers, adding expect()
-
-commit bf89af6c3b632b88e3cc74bead42f21561da58a7
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 18 07:19:15 2007 +0000
-
- (Jason Toy) added some specs for File (with some modifications) (#130).
-
-commit a7a6d8e336f8d331c60e973fb8f9e0aac1fb61ac
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 18 05:20:29 2007 +0000
-
- (Jason Toy) initial specs for YAML (#123).
-
-commit 4c2f70040050e35da28a8684296f913a3dd4a198
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 18 05:14:41 2007 +0000
-
- (nitay) patch for Bignum#size (#120).
-
-commit b1e57c9c718acfc7f1e61ae1fb60f10b918f8e5c
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 18 01:40:29 2007 +0000
-
- Range specs and code from Ryan Mulligan (#141).
-
-commit 9fa70f392bf83c55d67e682c36d9ebd247cff62c
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jun 17 22:02:48 2007 +0000
-
- New specs from Ryan Mulligan (#140)
-
-commit 64c970bddeb754115ed193d2f786c797ea90dab3
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jun 17 20:08:40 2007 +0000
-
- reorganized specs to put implementation-specific extensions in a subdirectory within the logical division of the specs into core, library, language.
-
-commit 8d437f0f63d4d3f9eea6e4436a28f437e6e76053
-Author: Florian Gross <florgro@gmail.com>
-Date: Sun Jun 17 19:39:37 2007 +0000
-
- Initial work on hash specs -- a few new cases and a bit of reorganization
-
-commit d8222049004ba0d6ec51db0c962b5200bb180aec
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jun 17 03:53:45 2007 +0000
-
- (yipstar) module specs for undef_method, define_method, remove_method. all pass MRI.
-
-commit 0162cfe6a443ded5d6c8e01a866f5a8d1fbce901
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Jun 16 23:11:31 2007 +0000
-
- Added specs for * / join / to_s with recursive arrays
-
-commit 0744e57d7860b9f6eefcc8e14962d7ee777d2ec4
-Author: Florian Gross <florgro@gmail.com>
-Date: Sat Jun 16 22:05:32 2007 +0000
-
- A few more specs for array sub classes with to_ary [ruby-core:11472]
-
-commit 07e0df5111c8ceeda83e50ef434948ee17e92aae
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jun 16 19:09:19 2007 +0000
-
- commented out specs that cause the VM to seriously misbehave allocating memory without bound or causing SIGBUS. currently 434 examples, 130 failures at r1357 on MBP.
-
-commit 2abc6e6dc5df662e8f0587636bd1cf3573e39f28
-Author: Tilman <tilman@unknown>
-Date: Sat Jun 16 16:41:07 2007 +0000
-
- Don't use timezone names that aren't portable.
- Instead, specify timezones by their standard name and the offset from GMT.
- This makes the specs pass on FreeBSD w/ MRI.
-
-commit d4106115c2ca9a4678b7060b6ac0091d66312624
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jun 16 08:20:29 2007 +0000
-
- a first, big step to making the entire set of specs more agnostic about the ruby implementation/engine by, paradoxically, qualifying certain specs to only run under certain ruby engines. removed incompatible and rubinius directories. folded in specs where appropriate and moved spec files (e.g. bytearray, tuple, compression) into the appropriate directories. the spec/parser and spec/compiler dividing line is not clearly defined given the range of types of implementations and perhaps should be merged.
-
-commit 3de0340e693e20b5e32c643f1f4dae7e1943e077
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jun 16 07:07:41 2007 +0000
-
- migrated more tests from shotgun-tests to specs.
-
-commit 369813306643d98c277841c1e9b400f6b60d3316
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 15 22:43:05 2007 +0000
-
- Add spec for elements returning odd stuff on <=>
-
-commit d70ab64def5ebdcb0e1946618b06e810270eb2aa
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 15 22:17:03 2007 +0000
-
- New specs for frozen arrays
-
-commit fda7128521254d2db2668fec55ef7ce9337ecf1a
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 15 21:55:30 2007 +0000
-
- More specs, mostly for array subclasses
-
-commit 2d57166d2ef2ff63f333b7ee0c196f5c4e10b8cf
-Author: Florian Gross <florgro@gmail.com>
-Date: Fri Jun 15 16:56:25 2007 +0000
-
- More than five bazillion new specs including a ton for the very evil []= method (letters i through s)
-
-commit b905a952af41a96f72499750c4635b1352b237ba
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 14 23:06:33 2007 +0000
-
- A few more specs.
-
-commit e17aa3690f7dcd2dab346bf7def0dd26b38072f1
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 14 22:16:54 2007 +0000
-
- A bunch of new specs. Includes highly exotic corner cases.
-
-commit 7845d8928d138353ad03bd496d1800c03e82b538
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 14 20:52:23 2007 +0000
-
- Fix cleanup to work with symbolic method names like ==
-
-commit c677ac036baa847cef3de6a34b2b56c9fd09213c
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 14 18:04:43 2007 +0000
-
- Fixed the test for DATA to match MRI (it's only supposed to be defined when the main file contains __END__);
- Added test for TOPLEVEL_BINDING
-
-commit 27b2767cd21b5a69ee10a2a629a68de64fd8ae5a
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 14 18:03:26 2007 +0000
-
- Introducing RUBY_NAME so we can spawn a new Ruby for things that can't be tested otherwise
-
-commit 4c4a96f51b4c06dd6896f996ae0e87a68152a3bc
-Author: Tilman <tilman@unknown>
-Date: Thu Jun 14 15:15:56 2007 +0000
-
- Don't call Time.now multiple times when comparing their values.
-
-commit cde774be8b188f5870b1ee387b5e5fffd9948163
-Author: Tilman <tilman@unknown>
-Date: Thu Jun 14 15:00:17 2007 +0000
-
- Fixed a typo.
-
-commit 6e51eee65c310255183d81d97a98be313ca68afc
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 11 04:07:03 2007 +0000
-
- put guards on imcompatible specs to prevent ruby, jruby from running them. work around for Dir ** globbing being broken.
-
-commit 03dfae6b896a6b67ac6066e94284d992833afac5
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jun 11 02:00:25 2007 +0000
-
- Added rake task spec:ci. added svn:executable for bin/mspec. enhanced readability of system command in mspec. added globbing across directories to mspec command.
-
-commit 96425667fbff044333c13c5a88c3b8cad156504f
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jun 10 21:45:52 2007 +0000
-
- modified mini_rspec to include proper reporters. converted mspec to use ruby to generate a command line to run specs. mspec usage should be similar to spec: mspec spec/core spec/language/class_spec.rb will execute any spec/core/*_spec.rb plus spec/language/class_spec.rb and output a single summary of exceptions, examples, failures.
-
-commit 1075f2cf34a81c00a1b06d2474c78300ae013161
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sun Jun 10 06:59:40 2007 +0000
-
- Cleaned up MatchData, added support for accessing named groups.
-
-commit c678d79f125d67328e267001e5fe353f5ef38a2c
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sat Jun 9 04:20:51 2007 +0000
-
- * =~ for regexps to mini_rspec by dean (Ticket #136)
- * Kernel.caller spec relocation for reliability
-
-commit 00eec364dbf3cef03915a68a359ed06b7e501553
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jun 8 07:10:56 2007 +0000
-
- reintegrated String specs. all specs in core follow the convention that there is one file named <class>_spec.
-
-commit 9f9817bbb9fea5cc02eb280f01eb50e45ea03118
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:49:47 2007 +0000
-
- * String#replace, String#chop! and String#chop behave now as in MRI.
- * Specs
-
-commit 129e492fcacf937473bb1c602176b48a352f8572
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:39:00 2007 +0000
-
- * Fix String#<=> when the given object is not a String.
- * Fix String#to_sym for invalid symbols.
- * String#to_i raises an error when invalid radix is given.
- * More specs.
-
-commit 8d7a9e21874d9e44c63d17dd8f6832b942805707
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:31:25 2007 +0000
-
- * Make String#capitalize!, String#downcase! and String#upcase! check for the 'frozenness' of self
- * Specs
-
-commit 10087a0c92217d1fbadfede9fdb0099c7eb195e6
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:25:08 2007 +0000
-
- * Spec for String#==
-
-commit e51ca54f6f4e9e3dabd48895fa2cb746fb0d3c17
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:23:23 2007 +0000
-
- * Fix String#=~ to work as in MRI.
- * Specs
-
-commit d2c7d6e6bb624c23e994888b6a235022486e0c69
-Author: Arthur <arthur@unknown>
-Date: Thu Jun 7 23:16:35 2007 +0000
-
- * Alias String#size to String#length.
- * String#<< now correctly checks and converts (where applicable) arguments.
- * String#<< raises an error if used on frozen string.
- * Added extended specs for String#<<.
-
-commit c389493556e3394cce846698aa4fc6a67a5f4b40
-Author: Tilman <tilman@unknown>
-Date: Thu Jun 7 18:14:02 2007 +0000
-
- Time#zone_offset and #zone_utc? are also in stdlib already.
-
-commit 7dcd86dca123edaec7edec2853cba2af27ca6d52
-Author: Tilman <tilman@unknown>
-Date: Thu Jun 7 18:07:59 2007 +0000
-
- Moved the specs for Time methods that should be in stdlib rather than in core to spec/lib/time_spec.rb
-
-commit 953dfdfdea395ead465a9e19339d94f8b8c7d684
-Author: Hapk <hapk@unknown>
-Date: Thu Jun 7 17:36:20 2007 +0000
-
- Added more specs for Array#pack: covering %#bB.
-
-commit 7aa84bc102ad6943aed46cbb357f233ac4b6d3f9
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 7 16:47:03 2007 +0000
-
- Make next with arg match MRI; Fixed typos and a copy&paste error
-
-commit 40c354444d6d7a2fd3aeb940c3bdcf6fd2a28940
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 7 16:43:17 2007 +0000
-
- Fixed to run on MRI (uses Object.const_get now)
-
-commit 95dd0ca698d0b1f79a11f4a556c171bea33ba176
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 7 12:52:40 2007 +0000
-
- Make behaviour match MRI, fixed copy&paste errors, did some refactoring
-
-commit 191d4e80406a6e4ffd08594ddeada47fb3219bf0
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 7 01:41:08 2007 +0000
-
- Fix chaos introduced in rev 1283
-
-commit e0f5184493607f7d9c216146207dc298893a744c
-Author: Florian Gross <florgro@gmail.com>
-Date: Thu Jun 7 01:28:55 2007 +0000
-
- Fix Dir.chdir test on OS X (/tmp is symlinked to /private/tmp)
-
-commit a32062d6099556a93afee61f0b0000a28675fbb6
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 21:44:00 2007 +0000
-
- Deleted old specs.
-
-commit de7b3ecaa61c4d3514c8a3534805e9c8d0d1bb2f
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 21:09:48 2007 +0000
-
- Made the Time#to_a spec pass with any time zone, too. MRI passes all the specs for me now.
-
-commit ac1e295da36f23184e583f5e62a4909959550dbd
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 21:06:32 2007 +0000
-
- Fixed specs for Time#localtime, #gmtime and friends.
-
-commit 064a5967f5550cf4a2e10885ab2c9f22afa59da2
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:56:41 2007 +0000
-
- Fixed a few more Time specs. Instead of the imaginary time zone "PDT"
- I'm now using Asia/Kuwait for some specs, because those lucky people
- don't have DST, which means we don't have to flip the spec expectations
- every 6 months.
-
-commit 8f6b6a5a5f8e62631a58061b6cdeeaff5654aeb0
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jun 6 20:41:32 2007 +0000
-
- module_function specs matched to MRI (module_function makes the instance methods private)
-
-commit 8cc656b95cb71ea476e787ce635df889090f8050
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:41:02 2007 +0000
-
- Fixed the Time#year spec. Using CET, too, since specc'ing using 1969 just feels wrong.
-
-commit ed7be9eaa73b8b1d85964f5c8fdfc250e2e8f62f
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:38:43 2007 +0000
-
- Oops, fixed a stupid error in r1281.
-
-commit e81d716092e0c6a8b52775ca2b9e0d44c4e3ef7f
-Author: Florian Gross <florgro@gmail.com>
-Date: Wed Jun 6 20:35:42 2007 +0000
-
- Divmod matched to MRI (Special casing darwin on MRI because it doesn't raise FloatDomainError exceptions in some cases)
-
-commit fc5f461c47b7212f05f8699110e313aeab46d46d
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:35:34 2007 +0000
-
- Fixed the Time#hour, #min and #day specs.
-
-commit 6847a1e49ff4ad4dfe7c6e9e4d7352f92d72b4cd
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:26:26 2007 +0000
-
- Don't call Time#seconds as MRI doesn't have it and it doesn't seem to be needed anyway.
-
-commit b9a6ccc89d46ffa910c9bdc0fece9d013440872d
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:14:15 2007 +0000
-
- Time#asctime needs to use %e to print the day of the month.
-
-commit 7311fdf31481ba7a4373d5b007efb62c1f84c389
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 20:03:30 2007 +0000
-
- Hardcode output for Time.gm(...).inspect. This makes utctime superfluous for now.
-
-commit 229e7eefe7944df92ab2f84e553992fc0c868dbd
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 19:19:38 2007 +0000
-
- Fixed two more Time specs.
-
-commit 7f490d752ed97bfb9b830d24f4e2c2f44107c141
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 18:41:47 2007 +0000
-
- Make sure that with_timezone resets .
-
-commit 9c8d25c4d072510215407209fa52a06b85e95d35
-Author: Tilman <tilman@unknown>
-Date: Wed Jun 6 15:57:32 2007 +0000
-
- Made the wday spec work with any timezone.
-
-commit 4882f8a676d5234339296d6a4489f3a7134cf5fd
-Author: Tilman <tilman@unknown>
-Date: Tue Jun 5 20:08:22 2007 +0000
-
- Fixed a typo.
-
-commit fb63faa2165cafdc7907f173344638609f884833
-Author: Tilman <tilman@unknown>
-Date: Tue Jun 5 20:03:06 2007 +0000
-
- Make sure that a GMT Time object returns true from gmt?
-
-commit deae4911588b555264f529e765dc5baf7a2c6e69
-Author: Tilman <tilman@unknown>
-Date: Tue Jun 5 20:00:45 2007 +0000
-
- Use with_timezone for the gmtoff specs.
-
-commit 625dd8e366f846cf15165e323a719199627ae422
-Author: Tilman <tilman@unknown>
-Date: Tue Jun 5 19:47:29 2007 +0000
-
- Added a helper method to temporarily override the TZ env var and fixed one of the specs by using it.
-
-commit b359eb74d41749919c6177ec2af6b5b516308bd8
-Author: Tilman <tilman@unknown>
-Date: Tue Jun 5 19:33:01 2007 +0000
-
- Provided 'date' calls for coreutils' date program.
- Checking for coreutils using RUBY_PLATFORM isn't the right way,
- but it will do for now.
-
-commit b19c3c8d886885adc08ac69469792b14e47ba265
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Mon Jun 4 23:42:20 2007 +0000
-
- * Improved Array#sort with additional spec by wycats (ticket #135)
-
-commit 8513e72a5af7596c8782ee45dff39607489dbf12
-Author: Tilman <tilman@unknown>
-Date: Mon Jun 4 16:39:53 2007 +0000
-
- Ticket #132: Implemented ENV in core and removed read-only ENV from shotgun.
-
-commit 03d75a78855213f6267fb8f80f9c71d0a031641f
-Author: Mojombo <mojombo@unknown>
-Date: Sun Jun 3 20:49:41 2007 +0000
-
- Implemented most of Time, updated time specs accordingly
-
-commit 36975b1b79abbd38de68223cdc8ecbca9ba0feee
-Author: Bremac <bremac@unknown>
-Date: Sun Jun 3 16:20:59 2007 +0000
-
- Add Functions::abort, Functions::printf, and Functions::sprintf, and minimal specs. Closes ticket 87.
-
-commit 9d25d95a4aa3fd22d3f3a340427d40410488a770
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sun Jun 3 12:41:49 2007 +0000
-
- * Lots of new assignment specs by crafterm (Marcus Crafter) (Ticket #133)
- * MatchData#inspect and #to_s now indicate it is an MD object
- * -dc notes which file/method is being compiled
-
-commit ec0fb5beed68155c9e1ff67185cc2c8e4e474c04
-Author: Arthur <arthur@unknown>
-Date: Fri Jun 1 22:23:39 2007 +0000
-
- * Fix String#[] and add some edge cases to the specs
-
-commit 068b48538ec574558ab787d59b14ebd2925f1126
-Author: Tilman <tilman@unknown>
-Date: Fri Jun 1 18:12:10 2007 +0000
-
- Renamed module 'B' to something more meaningful to avoid name clashes.
-
-commit eb3de8af03d070b03216daa4fc0c2216d9d3e2a2
-Author: Arthur <arthur@unknown>
-Date: Fri Jun 1 18:09:52 2007 +0000
-
- * Extend String#slice! specs
-
-commit db4775403d57ea29165165b9cbf0110739d91e2a
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Jun 1 02:26:30 2007 +0000
-
- * Ticket #128 - Patch by Marcus Crafter to enhance assignment specs
-
-commit 6098aa16357ce4261feb51bdf083c02442b1f074
-Author: Tilman <tilman@unknown>
-Date: Thu May 31 19:05:45 2007 +0000
-
- Implemented rb_obj_alloc() and friends in subtend.
- The spec for rb_class_new_instance() is still failing because of strange
- subtend behavior.
-
-commit ae2c3cb4502ba9475111eeef10b2b70780a1b9f4
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu May 31 13:54:24 2007 +0000
-
- * Fixed shotgun compile failure (possibly r1204)
- * Various casts to avoid warnings
-
-commit d317d336412d0c1778d4c015dfe96287c44e1bd9
-Author: Hapk <hapk@unknown>
-Date: Thu May 31 11:12:02 2007 +0000
-
- Added specs for "break", "next" and "redo" keywords.
-
-commit a33f801f8f142d997a553e41cde9f5b10d75ee65
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu May 31 04:23:33 2007 +0000
-
- * Kernel.caller spec by jtoy (Ticket #112)
- (kernel_spec is badly broken still)
-
-commit ce15eb69e721820e75b0f7aeae6488701cbe9555
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu May 31 03:55:27 2007 +0000
-
- * Fixed String#dump spec expectation (Ticket #105)
- * Moved RUBY_ENGINE to rubinius-specific variables_spec (Ticket #109)
-
-commit 7d2c575164dfbbd436d7c6ff400c088a68b29fa8
-Author: Hapk <hapk@unknown>
-Date: Thu May 31 00:42:50 2007 +0000
-
- Added "if" specs for variable scoping.
-
-commit ceb4430f9c713f409f2567a0aa324f19afb09b79
-Author: Hapk <hapk@unknown>
-Date: Thu May 31 00:35:49 2007 +0000
-
- Added specs for while / until condition/block evaluation order.
- Added specs for next and redo statements.
-
-commit 4adeecf9333236800396bd77f928fb902e785692
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 30 22:17:04 2007 +0000
-
- * Fixes to RSpec cleanliness of specs, most patches by zimbatm.
- (Tickets #97 #98 #100 #103, partially #99)
-
-commit bbb0714b6ae60adb0af7445ed56544ceec3bc890
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 30 21:41:03 2007 +0000
-
- * Array specs are RSpec/MRI-clean and pass (Ticket #95)
- * Fix to should_raise for MRI by zimbatm
-
-commit d627ab36d3839745e057d9f5de781269ba7b154a
-Author: Hapk <hapk@unknown>
-Date: Wed May 30 21:15:39 2007 +0000
-
- Added specs for 'while' and 'until' statements.
-
-commit 8a2177c7f23181909c5dcb51dd6df1e5b930fdbe
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 30 20:32:13 2007 +0000
-
- * Enhanced hatefulness of 'for' specs
-
-commit 9f64f2a1c584420fcabfc73a7c464aa3b1ba2e90
-Author: Hapk <hapk@unknown>
-Date: Wed May 30 19:46:57 2007 +0000
-
- Added specs for postfix "if" form.
-
-commit 9dd8a846adf356d75ceac566612f35d1d30840bf
-Author: Hapk <hapk@unknown>
-Date: Wed May 30 19:34:50 2007 +0000
-
- Moved loop specs from spec/language/expressions into spec/core/kernel_spec.rb.
- Added more specs for Kernel#loop.
-
-commit ddf2e3169c3a8b587f9abfb0ddf196635aec5186
-Author: Hapk <hapk@unknown>
-Date: Wed May 30 18:57:38 2007 +0000
-
- Removed obsolete "elsif" statement spec.
-
-commit 3b6dca92ea810aa7866a2c7aa0b8812e72b6630e
-Author: Hapk <hapk@unknown>
-Date: Wed May 30 18:56:00 2007 +0000
-
- Updated specs for "if" statement to cover more cases.
-
-commit 678f609bfe826538ec16e75f7362bcb3f50c8d6d
-Author: Arthur <arthur@unknown>
-Date: Wed May 30 17:09:09 2007 +0000
-
- * Extend Specs for expressions
- * Break the Specs up
-
-commit df60cc21e4213ac8344b5ed91e802d8cbbfa47a0
-Author: Tilman <tilman@unknown>
-Date: Wed May 30 17:00:17 2007 +0000
-
- Implemented rb_ary_store() in subtend. The last spec still fails, but we'll fix that later.
-
-commit 8e0fea820c1683913625dfe95c7d3210d4548814
-Author: Arthur <arthur@unknown>
-Date: Wed May 30 10:09:55 2007 +0000
-
- * Extend Specs for Class Definitions (nested class definitions, class definitions that extend objects, Multiple Definitions of the same class).
- * Lots of them are failing in rbx.
-
-commit ce16f2b568ea89cb5f13660d3175165b105e4233
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 30 01:18:39 2007 +0000
-
- * OK, that should really be in 'rubinius', not 'incompatible'
-
-commit 888b777539baa116eedc14191ac85d57aec54349
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 30 01:15:37 2007 +0000
-
- * 'Options' is a Rubinius-only class, and should therefore be in 'incompatible'. Closes ticket #102
-
-commit 46a58344fa2f03fb4154b78f34239a815b2d9944
-Author: Bremac <bremac@unknown>
-Date: Tue May 29 23:52:52 2007 +0000
-
- Fix typos in specc'ing module_function, and make that spec play nicer with MRI.
-
-commit e0cedb691f76af4554bfc7522a7668ff861492f0
-Author: Bremac <bremac@unknown>
-Date: Tue May 29 20:49:42 2007 +0000
-
- More complete raise implementation and specs: Handle instantiation.
-
-commit 9f3a3bfe9d2610dd7e9e752c86a1b8aba47f7fdf
-Author: Hapk <hapk@unknown>
-Date: Tue May 29 20:39:07 2007 +0000
-
- Added 'case' spec for case with empty 'else' body.
-
-commit 8f888bd3d0a01afc945c45c0502a0b97f3227c48
-Author: Arthur <arthur@unknown>
-Date: Tue May 29 20:34:18 2007 +0000
-
- Extend Class specs. Some specs failing in rbx.
-
-commit f52d9faadc1eac31e7b92c1edb1cf45ca1d42c89
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 20:29:53 2007 +0000
-
- Implemented rb_str_new2() in subtend.
-
-commit d4d5e3d1eb8e5ee44acff6697a29a37b9eca25b2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 29 20:00:51 2007 +0000
-
- * Patch by HaPK - Add specs for 'case', and enhance specs for 'for'
-
-commit f3e736731e852dacbf90e8e3e33d840384909354
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:56:41 2007 +0000
-
- Actually exercise rb_ary_unshift() in the spec.
-
-commit 69d756ae17fce1fb53be5e7a1b5b7169b69c4aa2
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:55:32 2007 +0000
-
- Implemented rb_ary_shift() in subtend.
-
-commit 9f84a5ecddae6c0daf1fd7e46815275c7d7429db
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Tue May 29 18:50:41 2007 +0000
-
- * Fix to Array#to_a for subclasses
-
-commit 2bbc87fc1b5261b57927a02f75915829b398b478
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:50:33 2007 +0000
-
- Implemented rb_ary_unshift() in subtend.
-
-commit 4e69b95ad7991a57fd3f9b7cbf350cb5b13c6a5c
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:46:53 2007 +0000
-
- Implemented rb_ary_dup() in subtend.
-
-commit 122a9cfbe79e872146116c8e045a243fffd333e6
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:31:48 2007 +0000
-
- Marked SubtendArray method functions as static.
-
-commit 0e3319c07aa1d536343343fbbe1004c4cdce2df0
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 18:28:05 2007 +0000
-
- Implemented rb_ary_clear() in subtend.
-
-commit 621f0082fca85140791e2c40aabc8ad3fe3318a6
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 17:58:31 2007 +0000
-
- Implemented rb_ary_entry() in subtend.
-
-commit 9c7d05c0bb19e65f57fc6aab778785e2a727c4a4
-Author: Tilman <tilman@unknown>
-Date: Tue May 29 17:42:40 2007 +0000
-
- Ticket #91: Made spec/subtend/rake_helper.rb more portable.
-
-commit 5dba201079bdf8da63364ea760342f3cef85df74
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 29 15:56:01 2007 +0000
-
- * Add specs for Array#pack, patch by HaPK
-
-commit 2d71e18c6f08144d4fb402904a9226a8500343bd
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 29 15:28:45 2007 +0000
-
- * Better fix to method argument scoping, to support: def foo(a, b=a.length)
-
-commit f9deebb38b80cdea3dff44d7461404e5f501f566
-Author: Defunkt <defunkt@unknown>
-Date: Tue May 29 09:59:00 2007 +0000
-
- * Add spec for Struct subclasses. Closes ticket #110
- * Add failing specs for Class.new. Closes tickets #89 and #94
-
-commit 3be02f950f32a288fac1cd5cff0ae014057c96fb
-Author: Defunkt <defunkt@unknown>
-Date: Tue May 29 09:12:00 2007 +0000
-
- * Add should_include convenience method to make rspec more compatible with mspec. Closes ticket #106
-
-commit 68e716e1874e7dd4186c7eef2aea5e25157a44fd
-Author: Vagabond <vagabond@unknown>
-Date: Tue May 29 03:46:33 2007 +0000
-
- * Add HaPk's fix to Numeric#== to handle failed coersion with corresponding specs
- * Removed duplicate definition of Numeric#==
-
-commit a63e6fcb08e34c625957d8d23bbe602964863c5b
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 29 02:59:43 2007 +0000
-
- * Add Kernel#eval. Probably lacks some crazy MRI semantics at the moment
- * Method definitions should properly create a clean scope for locals
- * Support wacky default arguments, such as blah = lambda {|z| z.foo(another_arg) }
- * Optional label prefixes in assembly output, for easier debugging
-
-commit f1295ac58d2b601f539efe0e660dfed9d043d1d7
-Author: Vagabond <vagabond@unknown>
-Date: Tue May 29 01:39:46 2007 +0000
-
- Change Time specs to use ENV['TZ'] instead of `date` in hopes of being more portable
-
-commit 404faeca93c007f3eb9b3df52c2bde7673565113
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Mon May 28 19:20:27 2007 +0000
-
- * Fix some mistakes in method_spec that caused it not to pass under MRI
-
-commit d336078c02e1306acb4b2664a427b63e93b02788
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun May 27 06:03:25 2007 +0000
-
- * Fix local scoping to allow for method definitions on local variables
- * Pass all the horrible method definition specs
-
-commit 7759a0f91f794d05a32d48dd2e67d05c0b1dace7
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sun May 27 05:03:53 2007 +0000
-
- * Rename Thread.yield to Thread.pass
- * Implementation of 'module_function' by bremac, with minor tweaks
-
-commit 55f30c5e59d16ebbf045be93a7d406fed9a4dcbd
-Author: Vagabond <vagabond@unknown>
-Date: Sun May 27 00:34:44 2007 +0000
-
- Added defunkt's implementation of Module#const_set and const_get and associated specs (Ticket #72)
-
-commit 9cebe0c56fda41b83ab14d39275e327daf0bdcc9
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sun May 27 00:31:47 2007 +0000
-
- * Fixes to mini_mock by bremac (Tickets #85 and #86)
-
-commit f33756f22597bd280e453d5c7ad97685fa284579
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sun May 27 00:24:51 2007 +0000
-
- * Fix typos in splat_spec (Ticket #77) by tilman
-
-commit ea13a828e5fc19694fc24da25b2224a75462a88c
-Author: Vagabond <vagabond@unknown>
-Date: Sun May 27 00:11:58 2007 +0000
-
- Add Chris Wanstrath's (defunkt) Struct patches. Tested working against MRI.
-
-commit 3ca0ddcc2c39fec74f10b75df2af5c1581b9eaa3
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sat May 26 23:56:26 2007 +0000
-
- * Array fixes. Only spec failure remaining is #pack
-
-commit 4d91aa707a47189398455eb1c40b341dc3766ccf
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sat May 26 20:05:13 2007 +0000
-
- * Array fixes to pass specs (including HaPK's code).
- All remaining failing Array specs except #pack are
- not Array bugs. Test this heavily.
-
-commit 6793b34a54ab8e24e8a66a8af026a34315ac9f5b
-Author: Vagabond <vagabond@unknown>
-Date: Sat May 26 07:34:12 2007 +0000
-
- Add cdcarter's Enumerator implementation and specs translated from his test/unit tests
-
-commit fd10c39192825aeef68c8843c2813cf50b8137f2
-Author: Vagabond <vagabond@unknown>
-Date: Fri May 25 20:12:22 2007 +0000
-
- Some fixes to rand with associated specs
-
-commit 60d37d28b715854f5186598c90101824665ce715
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri May 25 19:43:11 2007 +0000
-
- * Properly normalize default method arguments, to support: def(x, y=puts('hi'))
- * Fix 'for' loops so that they use 'create_block' in the proper way
- * Move all 'for' processing out of compiler.rb
-
-commit 3c04a44e8ff9e84f48fbd2d3afabb886494b5a98
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri May 25 06:35:48 2007 +0000
-
- * Patch by HaPK - Fixes String#dump / inspect / upto
-
-commit 9e2442110ec33ff9ca4875407b227f2cf79a606a
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri May 25 05:36:31 2007 +0000
-
- * Use a random pivot point for better worst-case Array#sort performance
- * Add 'rake pristine' task to kill all .rbc files
- * More tricky specs for splats and multiple-assignments
-
-commit 7bea77d8d3e8f190dba4f34fead888551fd07730
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu May 24 23:50:06 2007 +0000
-
- * HaPK's patch to String#<=>, along with its specs
-
-commit 0e6007e7eb9eee5e3ab1acdf55da00f4ab8c4be0
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu May 24 23:29:49 2007 +0000
-
- * Add spec for masgn semantics
- * Fix numerous multiple assignment bugs
-
-commit 6d68d22efd7d2dba75c77cf957edb28dca6df6ef
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu May 24 07:05:00 2007 +0000
-
- * New Array#sort implementation, fixes several Array and Hash specs
- * Add a warning comment to bytearray.rb about some incorrect <=> behavior
- * Prevent unimplemented Array specs from crashing the spec run
-
-commit 0ca089c7354ec96103cb637f861751ca7df01136
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Thu May 24 01:15:40 2007 +0000
-
- * Support all kinda crazy splat syntax
- * Updated some compiler specs, though some TODOs remain
- * Added a comment above unshift_tuple, since it really shifts
-
-commit bbe0b73b07a393f94724964941d2fdd717a2d72e
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 23 19:58:10 2007 +0000
-
- * Add compiler support for: yield(*args)
- * Update some compiler specs to match recent fixes
-
-commit 32a7082205d3d214ad43a477286270a96076b140
-Author: Kev <kev@unknown>
-Date: Wed May 23 17:32:06 2007 +0000
-
- Make spec titles consistent (describing C api behavior)
-
-commit 699c66f8c8304522fbb3589356fe2bcd298277c8
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 23 06:56:25 2007 +0000
-
- * Use yield instead of &prc.call when initializing a thread.
- * Fixes VM crash / closes ticket #68
- * TODO - Why the HELL does this fix it?
-
-commit f8b6e1ff9e19e786b08fee30988eb874eae748b5
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 23 03:18:26 2007 +0000
-
- * Implement Thread.main
- * Prevent Object#inspect from crashing the VM when the inspected object has itself as one of its instance variables
-
-commit f24f573608ee5569b29754a017769db0f866cf4c
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 22 22:35:14 2007 +0000
-
- * Implement 'class_variables' method
- * instance_variables and class_variables now accept an optional argument, causing them to return symbols instead of strings
- * Support defined?(@@class_var)
- * Support defined?(a_vcall)
- * Fix false-positives in defined_spec.rb
-
-commit da540b51c47b2349b0ab8d4ca0bd11124138f9ce
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 22 20:52:30 2007 +0000
-
- * Add compiler support for begin/rescue/else/end syntax
- * Default rescue clause should be StandardError, not RuntimeError
- * Add specs for 'else' and empty begin sections
- * All Exception specs now pass
-
-commit 82abf73fd99ec45f7cb6d98d19b219a61af59a61
-Author: Vagabond <vagabond@unknown>
-Date: Tue May 22 18:39:59 2007 +0000
-
- * Fix Object#instance_eval to bring it into line with the specs and MRI
- * Fix Object#instance_variable_validate to not accept fixnums as instance variable names
- * Add another Object#send spec that tests exception raising for missing singleton method names
-
-commit 3b624f3f49c0433289224baf656b3d7be78cecd8
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue May 22 08:15:48 2007 +0000
-
- Fix the block arg scoping problem, also add a missing file from the compiler specs.
-
-commit 59af7028c060c8e3f9b9c107fb750a71dd37a1d6
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Tue May 22 07:14:54 2007 +0000
-
- A bunch of yummy-ness. Local variables now conform to the 'standard' behavior, ie they're allocated at different depths inside blocks (this is the yarv/jruby behavior).
-
- Cleaned up a couple of subtend things.
-
-commit f8ed63efac6fa661dd39db2c207b66c34d132546
-Author: Vagabond <vagabond@unknown>
-Date: Tue May 22 03:28:17 2007 +0000
-
- Add specs for Object #method, #respond_to? and #__send__. These currently fail with singleton methods on rubinius.
-
-commit 0d6e6b7109014c97d8f8be136166b3279d5a1108
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 22 02:06:19 2007 +0000
-
- * Handle 'call' nodes containing newlines, e.g. x = [5,6,7,8];p Hash[*x]
- * This is probably the wrong implementation, but it does work
-
-commit 518f7d34112e536d726cecfb2473c7b3db9ec33e
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 22 00:52:01 2007 +0000
-
- * Fix mini_mock's cleanup process
- * Add the ParseTree sexp test cases as specs. Currently in serious need of auditing
-
-commit 17ad76c162ff0cfe9662c20d418f455581389b42
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon May 21 21:50:13 2007 +0000
-
- Add a failing spec
-
-commit 1744773b7f57c766c75d188b04e55540d45e19d0
-Author: Vagabond <vagabond@unknown>
-Date: Mon May 21 20:22:04 2007 +0000
-
- Do some env trickery to make Kernel#at_exit testable
- Improve implementation and specs for Kernel#warn
-
-commit 45733aa44e8daee9e8c5e552ac9312f21163fe39
-Author: Vagabond <vagabond@unknown>
-Date: Mon May 21 20:16:18 2007 +0000
-
- Convert time specs to compare against output of the date command
- Change Time#inspect to use %z (GMT offset) instead of %Z (timezone)
-
-commit e58ef35a05d2a565befeaf3600bc00f21203a84c
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon May 21 20:12:34 2007 +0000
-
- Add spec for breakage caused by 1089.
-
-commit a5d54efe9a45f3acc1cdb0183a8c13ce6ed5e327
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Mon May 21 04:57:41 2007 +0000
-
- * Options implements a minimal lightweight option parser
-
-commit b28b77af82d99a7a3ec5a78f6ab8b4e138ac577b
-Author: Kev <kev@unknown>
-Date: Mon May 21 03:54:33 2007 +0000
-
- Add missing hash spec
-
-commit 81496352bdc2b6b27e293b7542908c6be54b9b6b
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon May 21 02:08:57 2007 +0000
-
- added specs from ticket #38 (David Anderson), but not patch because implementation was invalid (e.g. [].first(0) => [] not nil) and superceded by recent patches. fixed Array#[i,0] => [] exposed by the added specs.
-
-commit 4ed6afc81262a4197f1ddc646ada94277cd9abe6
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon May 21 01:07:36 2007 +0000
-
- HaPK's patch to Array#[] with specs. Knocks 14 failures down to 6. Ticket #60.
-
-commit b267aee1c10b6092d954c72d5776f4eafc109e51
-Author: Kev <kev@unknown>
-Date: Sun May 20 21:09:49 2007 +0000
-
- rb_raise, rb_const_get, exception definitions. Wooooo exceptions from C
-
-commit 37793ed650e6ce7352a7547cf4bc68f2ceb2f0b4
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat May 19 08:42:23 2007 +0000
-
- * Added nastier multiple-assignment-with-splat specs
-
-commit 39c9817fa1932f9fe708a8ba78f43cb39e7cb68b
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat May 19 08:30:06 2007 +0000
-
- twifkak's Kernel.fail patch with slightly modified specs.
-
-commit 264a42e8c11d08afa895b415453d59e1e1efe2e1
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Sat May 19 08:01:47 2007 +0000
-
- * Remove a misleading comment in exception_spec
- * Pre-compile bin/*.rb after a make install
-
-commit 7608e585e02283677275aaf5e5283e397ed2d671
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri May 18 23:57:09 2007 +0000
-
- Vagabond's Kernel.warn.
-
-commit 9a41c5a21bbc822ff9ff758eb2962ba80e2d454b
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri May 18 18:52:36 2007 +0000
-
- * Re-enable tr and unpack String specs
- * Change 'Nan' to 'nan' in Sprintf to match MRI
-
-commit fdc7032c6e4823727312cc7e5c33386cf9d91429
-Author: Mental <mental@unknown>
-Date: Fri May 18 06:01:20 2007 +0000
-
- add spec for ensure result elision
-
-commit 37438dc826624c3fee3afc1d30a9f661bbb1ab8d
-Author: Mental <mental@unknown>
-Date: Fri May 18 05:45:28 2007 +0000
-
- basic thread spec
-
-commit d89b7728d148ba8c1ddd74323aa8f9e3dae79691
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri May 18 02:37:55 2007 +0000
-
- * Fix 'should_raise' in mspec and rspec helpers
- * Added some new Module specs, and fixed existing failures
-
-commit f63e0cf797158a239f65714918debf7a6c1bb687
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu May 17 04:12:58 2007 +0000
-
- * First draft of a mock lib for mini_rspec
-
-commit c7fd82a8b4b84088de45463dbc25ae7eea5aabe2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 16 22:38:27 2007 +0000
-
- * at_exit handlers should run in reverse order of registration
-
-commit 2fb5c6e46f1682d927be8a9e116a609c75ec8be5
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 16 22:14:21 2007 +0000
-
- * Fix Kernel.Array(). All core/kernel specs pass now
- * Add Kernel#at_exit specs
- * Fix Kernel#`
- * Move AtExit handler array from Ruby namespace to Rubinius
- * It's spelled 'occurred', not 'occured'
-
-commit 3d1605a3ca731b05b5c03ebd8a6edcf386612930
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed May 16 06:04:16 2007 +0000
-
- added incompatible specs for #instance_methods returning symbols.
-
-commit 8ba8409ae0ab94a33cd082f02a81d4d1eab35b59
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 16 04:27:22 2007 +0000
-
- * Patch by shadowfiend - Enhance Module specs and implement Module#instance_methods
- * Make sure instance_methods always returns symbols, not strings
-
-commit 1e9b0066d712d4507260be02cf2bf116b2519af2
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed May 16 03:24:35 2007 +0000
-
- * MethodTable 'is a' Hash, and does not need its own fields in the bootstrap. Fixes 'Object.methods.keys'
-
-commit 8c57dd0e26cb5468c1b0150c5d9c5d80ae6f2de2
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon May 14 06:18:42 2007 +0000
-
- fixed class specs to pass on MRI. put rbx-specific integer specs in spec/rubinius.
-
-commit 8b43acd25a14f540447a9f958f7671822f836817
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon May 14 05:59:06 2007 +0000
-
- moved rbx-specific proc specs to a new home. made core proc_specs pass MRI.
-
-commit 4feb384d0a02b272bd1a3581dd4070ef475b25af
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon May 14 02:59:22 2007 +0000
-
- added RUBY_ENGINE == 'rbx' to global constants and exposed Rubinius::<const> on Object like MRI. converted sprintf specs.
-
-commit 34ad791d5f60177de7992a24f07992bb0d6c8b09
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Mon May 14 02:25:06 2007 +0000
-
- * Disabled Lightning's dissembler on amd64
- * Split specrunner into bin/mspec and a wrapper
-
-commit 8796b1f00501813c62676266508a6f89a82ec48e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 13 22:47:28 2007 +0000
-
- minor reorganization, cleanup of spec dir.
-
-commit 9be73815e2037dcc5347c2ef9876e76316efc504
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 13 22:06:54 2007 +0000
-
- specrunner outputs summary with 'examples'. converted language/literals, keywords, straggler method_spec.
-
-commit 647fe38ce5f132b7944cca8550233249d8b3c113
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 13 21:21:04 2007 +0000
-
- converted language, parser, library specs.
-
-commit d9e8f1fd3bc70231c89a1bdc17a9af5a46fce819
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 13 08:28:21 2007 +0000
-
- converted incompatible specs.
-
-commit 9a07bb52c526ce8883c53d437077d78510b0ac73
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 13 08:09:34 2007 +0000
-
- added Object#coerce_string that should act like 1.8.x StringValue function. added String#crypt and a couple other String things.
-
-commit 2bae9b5e3baa33da21c1335e84c2eab062eac3a4
-Author: Kev <kev@unknown>
-Date: Sun May 13 06:21:06 2007 +0000
-
- add rb_hash_delete
-
-commit 0ca1a5baa94b5984b0812365a408688420168d24
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Sun May 13 05:31:24 2007 +0000
-
- Imported GNU Lightning. subtend's rb_define_method_ now generates stub's to pop the args and call the function. Next step, add type conversion to call functions that don't take handles.
-
-commit 141e795d5042cb4ea398c9b8eaa9cd7045f5625e
-Author: Kev <kev@unknown>
-Date: Sun May 13 05:15:33 2007 +0000
-
- Add rb_hash_aset
-
-commit 0988a253d8e23b400a738ad74637e8b3655eae8c
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat May 12 19:40:35 2007 +0000
-
- new .rba's with rue's changes. converted spec/shotgun specs. added specs for Tuple. added aliases size, length for Tuple#fields.
-
-commit abd44484b4b2a28a4c7f0bf7acdf12ff30123729
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sat May 12 19:32:06 2007 +0000
-
- * Fixed class variables, should work everywhere now
- * Specs for cvar behaviour
-
-commit 8ec7dac58577cea314ff0fcd976219b23591bc4d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat May 12 07:40:42 2007 +0000
-
- reimplemented Object#instance_variable_get|set and #instance_variables. now works with immediate values, and classes with no __ivars__.
-
-commit 30c4dd441243277ec5b814ad9b4d4697e87641d0
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri May 11 07:56:14 2007 +0000
-
- added primitives for instance_variable_get|set so that methods operate identically on objects that do not have an __ivars__ field (e.g. Array, String). this needs more work because an exception occurs when attempting to set|get instance vars on an immediate value.
-
-commit 998a0ab62542f36f9e36bdd497116349421951ce
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 9 23:07:35 2007 +0000
-
- * Converted rest of spec/core/
- * mini_rspec/specrunner improvements
-
-commit 0cac71dd1e4dbb728bd3401e73fda5b3fbe95e38
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed May 9 08:18:59 2007 +0000
-
- updated expectations to be the actual compiler output. these specs should be carefully reviewed.
-
-commit 8d551887fd1fabc7700f9f0a432b728829dcef96
-Author: Kev <kev@unknown>
-Date: Wed May 9 07:42:15 2007 +0000
-
- Pull out bundle that got caught in the commit
-
-commit 736916decc6d9bfd7096079a0118f41a168d735d
-Author: Kev <kev@unknown>
-Date: Wed May 9 07:41:42 2007 +0000
-
- Add hash specs, and impl of rb_hash_new
-
-commit 2352f0a526be0f277f2e5d60f18acddc216045c1
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed May 9 07:06:45 2007 +0000
-
- converted test/bytecode/test_compiler to specs.
-
-commit 1f1d30f9ca690214a61f299a4bb408c2d28ef004
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 9 06:08:41 2007 +0000
-
- * Converted MatchData specs
- * Default warnings for empty spec files
- * Improved specrunner
-
-commit 04c03e648ca83de2c2aee37f9aef9079d0493bd7
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Tue May 8 06:24:48 2007 +0000
-
- * Converted Integer and Kernel specs
-
-commit a202ef1dfb21cebf3ee33376775d86b9dc89269d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue May 8 05:45:33 2007 +0000
-
- added before, after methods to mini_rspec. started adding compiler specs as conversion from test/bytecode/test_compiler. removed all host/target junk. thanks. bye.
-
-commit 692da2d89089bc94c95915c90da756480a057dc1
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue May 8 03:36:51 2007 +0000
-
- converted object specs. these really blow up rubinius.
-
-commit 714f5df86f583158d73eda366e2f2527156c3b8e
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Mon May 7 17:29:56 2007 +0000
-
- The first compiler spec, testing the masgn assembly. Some are commented out because they don't yet work.
-
-commit 8ccfe13ca0eca4ceae6a201905a64666a75dd6ba
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Mon May 7 05:52:41 2007 +0000
-
- * Converted and reviewed Hash specs
- * specrunner reports specifications and failures
-
-commit aa32b8e94de5c1ccd49a9d6ddca5836d6303c460
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun May 6 06:50:52 2007 +0000
-
- finished converting fixnum specs.
-
-commit 7c55264dc15ed2b8a1b341a5d605701c6626ad34
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Sat May 5 06:22:37 2007 +0000
-
- * Converted Enumerable specs
-
-commit 1c660edd87fa91d8c244289b00eb9252d5654c3d
-Author: Evan Phoenix <evan@fallingsnow.net>
-Date: Fri May 4 23:45:08 2007 +0000
-
- Fix array_append as well as the logic to call the extension function so the arguments are correct.
-
-commit 6b9c27b8f8d12be443d37635e17b23b7f0d76388
-Author: Kev <kev@unknown>
-Date: Fri May 4 07:54:10 2007 +0000
-
- Complete rspec coverage of subtend string compat to date.
-
-commit 32db2e9a157cee24ae883b7b8fd563d98fc2dce5
-Author: Kev <kev@unknown>
-Date: Fri May 4 07:11:21 2007 +0000
-
- Add loading of C extensions via require.
- Stop grammar.c from generating every fricking time
- Cleanup formatting on subtend
- Add proper minispec tests for subtend
- Remove old subtend test extension
-
-commit 851fbe6e587596fd074b4c99e42c43865118ae00
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri May 4 06:58:35 2007 +0000
-
- converted (but not to the new new style) fixnum specs. fixed mini_rspec to rescue backtrace.show on MRI.
-
-commit 3e8deacb57ef80684281b1329778bc52681a8601
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri May 4 06:22:53 2007 +0000
-
- converted module specs. added incompatible spec for const_defined?(Some::Class). made mini_rspec print backtrace on error.
-
-commit 3c1cc4ff4f6bf4fa28f65d9909a74f77f6524aa8
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri May 4 05:45:50 2007 +0000
-
- converted math and exception. added two helper methods: should_be_close, should_include. I think spec_translator should handle converting these to 0.9.x syntax as soon as rspec runs.
-
-commit 28e3cdba63f2853b9e9a084f27ad764437830799
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu May 3 15:26:39 2007 +0000
-
- converted float specs. added ignore for *.rbc on externals/rspec-0.9.1.
-
-commit 69ea5db15fb0562d8a4114d4e8ec54f2e19ad8fd
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu May 3 06:40:17 2007 +0000
-
- converted range, nil, regexp specs. added ignore *.rbc on rspec dirs.
-
-commit 6cc364770406e4e04ef7baf2fdaab7425a7f5a6c
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu May 3 03:27:04 2007 +0000
-
- * Converted Dir specs
-
-commit 5e39be7f97d5cd131b0cf564746d881245030f7d
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu May 3 03:04:24 2007 +0000
-
- okay, rue insists that we use describe ... it now. (see spec_translator with rspec 0.9.1).
-
-commit 99f05b9d6572600ed0bf6a732048c1c4a2d2bb0b
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu May 3 03:00:06 2007 +0000
-
- converted bignum specs. 100% pass on MRI.
-
-commit f9e4df4bdb721eb32c4ac7e5abd4a646daaf20d2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu May 3 00:06:19 2007 +0000
-
- fixed mini_rspec aliases for specify, etc. to work around exception: No method 'alias_method' on an instance of Object. (NoMethodError)
-
-commit 89d3ca0681816afd389907cbb52f7e0372dbecef
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 2 07:13:56 2007 +0000
-
- * Converted spec/core/ binding, class and continuation
-
-commit 086f889a9bae2e40dd6a8b1ffa80113070f3ad46
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed May 2 04:22:12 2007 +0000
-
- * bin/specrunner is a small bash kludge for running mini_rspec over
- a directory (recursively) or a single file
- * Rakefile allows diffing a current spec run against a base run to
- easily see all changes among the thousands of specs as well as
- storing a base run
- * specrunner produces decent output for the minimal spec output
- from mini_rspec
-
-commit ba89b2c015d2754b6470b324a013f018d8202cfe
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Tue May 1 22:57:22 2007 +0000
-
- * Converted spec/core/array_spec.rb to mini_rspec
- * Reviewed and fixed some specs for Array
- * Spec-style output to mini_rspec (manual comment/uncomment to switch)
- * should_raise for slightly more natural exception verification
-
-commit 0330bcc23fa1609db291cd382cb13fc168ec5bf3
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Tue May 1 22:44:40 2007 +0000
-
- * Implement correct behavior for String#split when called with a zero-width Regexp
-
-commit c8e806e2dafd237fa8117ead21553a195900613e
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue May 1 02:29:35 2007 +0000
-
- converted symbol_spec. 100% pass.
-
-commit 76e31065df70ebc5790fdb604f1b07d28ffaa81c
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue May 1 02:19:33 2007 +0000
-
- commented out specs that cause rubinius to hang. String#delete and #tr (and methods that are implemented in terms of these).
-
-commit 2ae8aea13161a71c3fb4ca8e0486acd55c897579
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue May 1 01:17:14 2007 +0000
-
- converted core/string_spec to regular syntax. added mspec_helper.
-
-commit ff84053991295b259ca8b1c17adff95f5d471961
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Apr 30 22:31:26 2007 +0000
-
- converted false_spec. added svn:ignore *.rbc on all spec dirs.
-
-commit 3fc864ba235c56118e1db66dbf9537d6ff8c0c5f
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Apr 30 22:00:12 2007 +0000
-
- Let the breakage begin. Converting all specs to use mini_rspec with 100% compatible syntax with rspec proper. usage: 'USE_RSPEC=1 spec spec/core/false_spec.rb' for any specs that use example {} method. spec spec/core/true_spec.rb OR ./shotgun/rubinius spec/core/true_spec.rb for converted specs.
-
-commit 4c6c7f406d0e5504a72c52b1ae5339a9dba36865
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Apr 29 17:28:11 2007 +0000
-
- added setup method and print to STDERR and STDOUT to support a shell script runner.
-
-commit 958a0e9b1a066cf2d825b960b66788b05c928f36
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Apr 29 08:26:09 2007 +0000
-
- mini rspec implementation. example {} method is dead.
-
-commit a323b3d424f226322cf20e65e87f8a4e962ed497
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Apr 29 03:23:17 2007 +0000
-
- Added Array#first, Array#last that take numeric args to core. Added a bunch of failing specs for Array#[]. #first and #last are implemented using #[] so several of the specs for those fail, but the implementation of #first and #last was tested in MRI.
-
-commit 3897c943069582b1e5d1649a097bd77c0c895e0a
-Author: Hurdlea <hurdlea@unknown>
-Date: Thu Mar 29 13:51:13 2007 +0000
-
- * Support for Floats in Sprintf
- - Sprintf is still missing support for unsigned twos complement
- * String#% now implemented
- * Fixed a minor issue in the Rakefile
-
-commit 5ed87ff88793f8d44cfe34b443eb032d27dc2a4c
-Author: Hurdlea <hurdlea@unknown>
-Date: Thu Mar 15 05:08:34 2007 +0000
-
- * Added Sprintf core module and classes for string % and Kernel
- - Still needs some work with floats and requires a couple of
- primitives to achieve this.
- * Fixed a small issue with String#Index(Fixnum, offset)
-
-commit 982c09b15710429fc97d8d43d9f24a3a0badb6d5
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Mar 10 22:35:18 2007 +0000
-
- Fixed array spec for #sort which improperly depended on the accidental order in which two elements of the array were being compared.
-
-commit 32fe004da7f35e9b7dcc96f8e57e1acb37164748
-Author: Hornbeck <hornbeck@unknown>
-Date: Sat Mar 10 06:38:23 2007 +0000
-
- Two tests in the ObjectSpace spec. It was bare and needed love.
-
-commit e1530bb1999118bf88037dccc27d78f54bdbe5e4
-Author: Tlockney <tlockney@unknown>
-Date: Sat Mar 3 23:28:27 2007 +0000
-
- updated all rspec exceptions. exception specs all pass in MRI. still a few rubinius exception spec issues
-
-commit 2c278533cbfe0efc7076d2c947323640be5f207a
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Mar 3 21:29:55 2007 +0000
-
- Committing tlockney's additions to core/exception_spec.rb. These pass on MRI but illustrate areas to fix on rubinius.
-
-commit fd8993c0996e4524440a6572c45dad4ab112fb2f
-Author: Hornbeck <hornbeck@unknown>
-Date: Fri Feb 23 15:58:33 2007 +0000
-
- committing Aki Reijonen's Hash patches for hash.rb and the hash_spec.rb. Also included is Thomas Lockney's exception_spec.rb patches.
-
-commit 08e6d924b8c0175242c1c40322ed3e45855a86c2
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Feb 18 07:48:46 2007 +0000
-
- Altered Object#instance_variable_[get|set] rearranging flow control. Added specs for instance_variable_[get|set] for Array, IO, String.
-
-commit 2a2385413c03f21dfc038e110f46a7a3bd2fc9c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Feb 18 06:05:47 2007 +0000
-
- Increased time out value when running rspec error report. Minor changes to text in class specs.
-
-commit bd0d7fcf72546a0a3a5a6a59b1a6f2aadd8e4262
-Author: Mae <mae@unknown>
-Date: Sun Feb 18 03:53:00 2007 +0000
-
- Integer#bits for future refactoring of shift
- * added Integer#bits which calculates minimum bit storage required for (signed int) form of the Integer
- * spec'd it too
-
-commit 4e6b39d5e69c04d92ceac76ce5a5bd792fb65f39
-Author: Mae <mae@unknown>
-Date: Sun Feb 18 02:55:55 2007 +0000
-
- Object#extend-a-gogo
- *Fixed Small bug in rubinius_target where failures wouldn't be reported
- *Implemented Object#extend and changed math.rb to use it accordingly
-
-commit 5472c10579cef38f9f28c904710246509633a040
-Author: Mae <mae@unknown>
-Date: Sun Feb 18 01:21:11 2007 +0000
-
- A great Time patch from John Hornbeck <hornbeck@gmail.com>:
-
- A more complete Time diff. This includes many of the instance methods for Time and a new primitive for usec. This diff also includes some failing specs as I went ahead and added the specs for the rest of the class methods. Also included is the constants for Time.
-
- Keep the good work coming John!
-
-commit 83ab11e0ab6679b1c9eefc5095d3f20af9a61661
-Author: Mae <mae@unknown>
-Date: Sat Feb 17 23:26:33 2007 +0000
-
- Patch from Aki Reijonen <aki.reijonen@gmail.com> without the Float.induced_from part
-
- Summary of the changes:
-
- ** Added methods **
-
- Numeric#integer?
- Numeric#div
-
- Integer#to_int
- Integer#round
- Integer#truncate
- Integer#next
- Integer#succ
- Integer#integer?
-
- String#slice!
-
- Object#to_a
-
- Kernel#Array
- Kernel#String
-
- ** Fixed methods **
- Float.induced_from
- - Now return the passed object if it's an Float insted of calling #to_f
-
- ** Removed methods **
- Fixnum#div was broken, the end result should be converted to Integer,
- not the number passed as a argument. (superceded by Numeric#div)
-
- --
- Aki Reijonen
-
-commit 243a4e9ba46149b8ba39c7238f8ff3d5f267689e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Feb 17 06:17:44 2007 +0000
-
- Ditched all the instance vars in array specs since we've got locals now.
-
-commit be5363e22e04b8baf26cb4abd8a8a67e7dd3cc0c
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed Feb 14 01:05:49 2007 +0000
-
- Fixed * varargs to work in method definitions. Currently still
- does not work as the single named parameter (foo(*a)). This
- means that lib/bytecode/encoder.rb now compiles under Shotgun.
-
-commit 3bb810688e848c90d5c20929c630f36a32796d2d
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 13 18:42:09 2007 +0000
-
- Added Object#instance_variable_set and specs.
-
-commit 54392c99dc3db5b58c85799416cc528c60b12533
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 13 18:25:24 2007 +0000
-
- Added Object#instance_variable_get and specs. Uncommented Math module constants specs.
-
-commit 84267901502ca1e8e8b13afa0e3a16e0cdc8e493
-Author: Mae <mae@unknown>
-Date: Sun Feb 11 10:30:13 2007 +0000
-
- * Primitive Specs
- - Added spec for bignum_div (and fixed a problem where it would always fail)
- - Fixed primitive_spec_helper (because it broke the old specs last time)
- - Removed magic method chaining because it sucks
- - DISCLAIMER: primitive specs atm just test functional things, _NOT_ stateful side-effects
- - We can do this properly once rubinius can run rspec
-
- * SIRB
- - Made it so that => wouldn't get printed before the command prompt if you typed "exit"
- - Made Kernel#p, Kernel#puts, Kernel#print return nil (like MRI)
- - added #!shotgun/rubinius to top of sirb and symlinked it to bin/sirb.rb as well (for convenience)
-
- * Removed unused local from __loader
-
-commit efce7d8a56748ab1831a34d21b8c92ff8b2eb977
-Author: Mae <mae@unknown>
-Date: Sun Feb 11 07:25:51 2007 +0000
-
- Moved math to math_spec; added object_spec for primitives; made primitives_spec_helper maybe too smart? -- they chain methods on to the remote target
-
-commit 087a5e5a6e89e4a53a39e025ffe08d21e96b8f6e
-Author: Mae <mae@unknown>
-Date: Sun Feb 11 05:51:30 2007 +0000
-
- * Made rubinius_target and example much more helpful
- - backtraces are shown on failure now
- - you can do this: example { 1 + nil }.should_raise(TypeError) and it works :) (with bt and all)
- - injected some extra code in example snippets so try(exc) syntax still works
- - Float, Nil, True, False specs all pass 100 %
- - made rubinius_target make use of @src (used in bignum)
-
- * Made Kernel.Float() and Kernel.Integer() behave appropriately like MRI _with_ the exception of Float() also checking for to_i method
- - Integer(nil) => 0 and Float(nil) => 0.0
- - lots of spec coverage
-
- * Numeric#coerce was slightly tweaked to use new Float() and Integer() behavior
- - Specifically complains about other being nil (so 1 == nil doesn't work)
-
- * Made Float.induced_from() more anal retentive (only accepts core Fixnum, Bignum, Float types like mri)
- - specs cover it
-
- * Fixed infinite loop on Bignum#& and moved & out of Numeric into Integer (Float doesn't have &)
-
-commit eadf1ead754d3dbfaf703c205f6f5e8f4dc5c430
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Feb 11 03:00:25 2007 +0000
-
- Put object flags values into a single include file. Added Object#taint, tainted?, freeze, frozen?. Neither of these states actually effect execution yet. Fixed up Object specs.
-
-commit 38e7f757e67b4ec985835e0e93ba4d32bbee5ca4
-Author: Mae <mae@unknown>
-Date: Sat Feb 10 23:57:37 2007 +0000
-
- - Created specs for math_sqrt primitive (and created spec/primitives/math_spec.rb)
- - Tweaked primitives_spec_helper to properly transport NaN's to testing environment
- - Removed non-needed self parameter from math_sqrt c function
-
-commit a4267a136d7f0bf7f92421fcebd8011600a1d92e
-Author: Mae <mae@unknown>
-Date: Sat Feb 10 22:29:46 2007 +0000
-
- Float.induced_from love
- - made Float.induced_from work for any to_f item (controversial whether this should be done in Kernel.Float() or not)
- - apparently this fixed some float failures
- - made Float.induced_from safer because it now complains if to_f returns a non-float
- - wrote specs for new induced_from behavior
- - try (spec_helper) needs to be investigated, manual running of the premises of 'Float divmod should raise FloatDomainError if other is zero' show this to be a spec that _should_ pass
-
-commit 65a4e8abfc7f690456e4f44e7e4cc38911288516
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Feb 10 18:54:15 2007 +0000
-
- Added spec files for the rest of the core classes documented in Pickaxe book. Add simple class hierarchy specs for exception classes.
-
-commit c7a2f68c36dd95f51af88e8fa62b24b71d68578a
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Feb 10 17:29:46 2007 +0000
-
- Commit of scoopr's Math module beginnings. Thanks scoopr.
-
-commit b1e8d150460f2ae9ea2e5ef87d0df3b705c1d0d6
-Author: Mae <mae@unknown>
-Date: Fri Feb 9 08:54:25 2007 +0000
-
- Bignum primitive specs
- - Added spec and changed to metaprogramming style for primitives: bignum_add, bignum_compare, bignum_equal, bignum_and, bignum_divmod
- - fixed bug that bignum_divmod spec found where bignum_divmod would always fail on divide by zero GUARD
-
-commit 0487a39ec9995af8eb5a8dff5ec64492261852e7
-Author: Mae <mae@unknown>
-Date: Fri Feb 9 07:48:56 2007 +0000
-
- Primitive Spec Sexiness
- - Added spec and changed to metaprogramming style for primitive fixnum_to_f
- - Made usage of run_primitive(:add, 1, 5) more sexy i.e. 1.prim.add(5)
- - converted fixnum spes to use sexiness
-
-commit 95fa48f29eaa7e3f10ccd63d385fb3f582f57eea
-Author: Hurdlea <hurdlea@unknown>
-Date: Fri Feb 9 01:36:14 2007 +0000
-
- * Added String#delete, delete!, tr, tr!, tr_s, tr_s!
- - String#count and squeeze to follow ...
- * String#<< now accepts Fixnums
-
-commit 017bdc57602e2e5d55705de070c07edba46a347f
-Author: Mae <mae@unknown>
-Date: Thu Feb 8 09:23:55 2007 +0000
-
- - removed noop from primitives (it does nothing)
- - removed noop primitive spec
- - changed CPU::Primitives.name_to_index to offset by +1 (to leave room for special 0 value)
- - still having same closed parens issue with spec:primitives:
- syntax error, unexpected $end, expecting ')' (SyntaxError)
-
-commit 18a3347bb32d8ac5269438376f0100ecce2c9e73
-Author: Mae <mae@unknown>
-Date: Thu Feb 8 08:20:14 2007 +0000
-
- - made shotgun/lib/primitives.rb have less dependencies
- - fixed bug where if a false was popped of the stack it wouldn't be recognized as an argument in primitives_spec_helper (nil will only do this now)
- - fixed regression in primitives_spec_helper where the proper code wasn't showed when shotgun crashes
- - noop_spec works again
-
-commit 16b08e446b69344da1edbc1f793e0161deac8e6c
-Author: Mae <mae@unknown>
-Date: Wed Feb 7 23:59:14 2007 +0000
-
- More Primitive Goodness, Conform to unified rspec standards
- - Added specs and changed to new metaprogramming style for the following primitives: fixnum_and, fixnum_or, fixnum_xor, fixnum_invert, fixnum_neg
-
-commit cb2ac85b45a41a63100cac673919ad8db1f93f43
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed Feb 7 23:16:35 2007 +0000
-
- Basic specs for Symbol literals.
-
-commit 3ab7aced51f3a63c8f76706a2f159d0d5753dc64
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Feb 7 20:35:27 2007 +0000
-
- Changed Fixnum primitives specs to be in a single file, spec/primitives/fixnum_spec.rb. Added back the alternative example of writing specs for others to evaluate or use. Updated the wiki specs page to lay down the law on spec files. Kindly follow it.
-
-commit cf16d691990f43f5bf8807bbef2ba1876892be57
-Author: Mae <mae@unknown>
-Date: Wed Feb 7 18:27:15 2007 +0000
-
- Autotest, C warnings cleanup, and some primitive_spec usage cleanup
- - Added Autotest Facilities for primitive bin/autotest/primitives
- - need to gem install zentest to use this (and some diff gem i can't remember)
- - Removed ugly require statement from cpu/primitives it was causing annoying ruby errors
- - Added missing prototypes to cpu.h and regexp.h (primitives.gen was complaining)
- - Localized bt and bt_size variable declarations to where they would be included by the preprocessor to make more warnings go away
- - Added newlines to the end of numeric.c, numeric.h, float.c
- - Used one of brixens suggestions (injection of primitive spec helper automatically)
- - Removed extraneous primitive helper inclusion in each spec
-
-commit f4bbce9d761d27e1381b95a4ff6076e85577074d
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Feb 7 16:56:21 2007 +0000
-
- This shows an example to 'fix' mae's rubyesquely-challenged (bluntly, ugly) primitive specs. Also, there should be one spec file for a group of related contexts. In this case, the group is the class Fixnum. So, mae, fixnum_spec.rb, NOT fixnum_xxx_spec.rb. Sorry. Cry tyrany, weep and gnash thy teeth, howl in protest, but please fix it. This is non-negotiable. Thank you and good work on the primitive specs. :)
-
-commit e5f6215824a40beb0ca678575596bd06afa8dd3a
-Author: Mae <mae@unknown>
-Date: Wed Feb 7 09:54:54 2007 +0000
-
- - Added specs for primitives: add, sub, fixnum_mul, fixnum_size, fixnum_div, fixnum_modulo, fixnum_divmod, fixnum_to_s
- - Updated primitives to new metaprogramming style: sub, fixnum_mul, fixnum_size, fixnum_div, fixnum_modulo, fixnum_divmod, fixnum_to_s
- - Changed wording in a couple primitive spec files to be more explicit
- - Made reporting by primitive_spec_helper more helpful when shotgun crashes from injected code
-
-commit 3032c6bd869a04c1517508850f94119975c36e54
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Feb 7 02:26:47 2007 +0000
-
- Fixed up String#to_i a bit; added a bunch more specs for it.
-
-commit d8a24ffa8d9983a85b0f03784a89bfa667af1615
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Wed Feb 7 01:46:30 2007 +0000
-
- Added very basic set of specs for assignment and multiple assignment semantics.
-
-commit edb7c82523b36b26e24437de42fd2638eef1653f
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 19:02:46 2007 +0000
-
- Added specs for and methods CType#isalnum, isdigit.
-
-commit e84ba1b12c51331d00bdd06684dcff96ea229322
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 17:30:55 2007 +0000
-
- Added spec/shotgun/bytearray_spec.rb. Added spec for ByteArray#[], []=. Modified various string methods to use BA#[], []= instead of get_byte, set_byte.
-
-commit be9589cc47cbf35edd94ca22407de4b1527a3fdb
-Author: Mae <mae@unknown>
-Date: Tue Feb 6 11:26:31 2007 +0000
-
- Tweaks to primitive metaprogramming and addition of noop spec
- - Added types 'qnil' 'qtrue' 'qfalse' to be used in primitive metaprogramming
- - Added spec for noop primitive
- - Added run_asm method to primitives_spec_helper for those tricky tests
- - Converted noop primitive to new metaprogramming style
-
-commit e31f1af903dd8dd31427e34a718b30f5c63af8df
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 10:33:00 2007 +0000
-
- Some fixes to String#to_i and additions to specs. Added String#oct and hex.
-
-commit 2a157827bd72b6c7ce8a025928cdd9d7f2f8d00f
-Author: Mae <mae@unknown>
-Date: Tue Feb 6 10:18:16 2007 +0000
-
- moved equal and compare to use new primitive technique
- - also updated equal_spec to ask for ArgumentError instead
- - uploaded new rba *glares at brixen*
-
-commit 771d0fede3086ce58d225ac4001ea0934f3bb0e3
-Author: Mae <mae@unknown>
-Date: Tue Feb 6 09:33:03 2007 +0000
-
- ARITY macro raises ArgumentError directly from the primtive now and made specs pass
- - Made ARITY macro raise an argument error exception instead of just ambiguously failing
- - Made _ret return TRUE on arity failure (exception directly raised)
- - Moved GUARD and POP macros to shotgun/lib/cpu_primitives.c where they belong (localized)
- - Removed side-effect printf in cpu_raise_arg_error since stack trace is fine now
- - Tweaked primitives_spec_helper should_raise to work for all exceptions
- - Made specs for equal/compare pass again (expect ArgumentError instead of PrimitiveFailure)
- - New compiler.rba (update these ppl!)
-
-commit e89190c8fdc4a71c7b8cd9c8b873a63b9d1888c5
-Author: Hurdlea <hurdlea@unknown>
-Date: Tue Feb 6 07:51:08 2007 +0000
-
- * Finished String#[]= for string index
- * found odd bug with spec where string[1,2]="foo" is not interpreted correctly
- changed methods to use send(:[]=, ... and the tests pass
-
-commit c6e1bb68e930a537bd51d77afd37cdc8b5d62d31
-Author: Hurdlea <hurdlea@unknown>
-Date: Tue Feb 6 07:18:15 2007 +0000
-
- * Added String#[]= slice functionality
-
-commit e405d4f5f32fd8192c435b3488f394b2635c7db7
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 06:37:31 2007 +0000
-
- Added String#chomp[(bang)].
-
-commit ff48a6c333f34c1b1882c260db7145facce3d71f
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 06:00:56 2007 +0000
-
- Added String#replace_if that calls replace if self != other else returns nil; Added upcase, downcase.
-
-commit f46d747eba82c215fa07b067a30f2a2e8868d284
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 05:31:13 2007 +0000
-
- Implemented String#reverse directly rather than with String#<<. Modified some string specs for [lr]strip but forgot to commit them earlier.
-
-commit d3b0e71e810a985f3b8f2e5f5c7d5c4619f151f9
-Author: Hurdlea <hurdlea@unknown>
-Date: Tue Feb 6 03:00:28 2007 +0000
-
- * Added NilClass specs to detect NilClass coercion
-
-commit c570ca475cabeb3fcfcca26d4c57b8e57f6606b4
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Feb 6 02:01:19 2007 +0000
-
- Added module CType mixin for Integer to provide isspace, isupper and friends. Added specs for CType in spec/shotgun. Implemented String#capitalize[(bang)]. Moved ByteArray into it's own file. Updated various string specs and commented out temporarily index spec.
-
-commit 4694d1511e880e43dfccb3e3f5309f0920395ba0
-Author: Hurdlea <hurdlea@unknown>
-Date: Tue Feb 6 00:22:17 2007 +0000
-
- * Fixed operation of Regexp#=~
- * Updated Regexp spec for =~
- * String#== now works correcly for duck typed objects
-
-commit 8e42aa9c789fcc9bc475d460e7158f2adcc8ab64
-Author: Mae <mae@unknown>
-Date: Mon Feb 5 22:46:21 2007 +0000
-
- Added arity checking for primitives
- -for use in primitives: #define ARITY(length) GUARD( (length) == num_args )
- -for instance if i have a primitive that takes one argument (self + arg) i put ARITY(1) at the top
- -changed specs with regard to arity accordingly
- -made block_given conform to the "self rule for primitives" by padding Qtrue where self would be
- -fixed block_given? to pass the right arity (0) in the compiler
- -specs for compare and equal pass now
- -added primitives_spec_helper (forgot last time)
-
- NOTE: Binary .rbc compatibility is broken now since there are arity checks done on block_given?
- -the rba's i uploaded should be fine but if they arent...
- do find -type f | grep .rbc | grep -v .svn | xargs rm
- then rake build:rubinius
-
-commit 2d5c9bc3170bf959390627def10c0208088b48ee
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Feb 5 22:39:08 2007 +0000
-
- Added Integer#isspace and spec in spec/incompatible. Added spec/incompatible/string_spec to describe behavior of stripping runs of whitespace and nulls from end of a string. Added or modified String#lstrip, lstrip(bang), strip, strip(bang), rstrip, rstrip(bang).
-
-commit d4b07b06ca85543423a308f12b82ae4671bdd0c2
-Author: Mae <mae@unknown>
-Date: Mon Feb 5 21:01:59 2007 +0000
-
- -split out common primitive testing functionality to primitives_spec_helper.rb
- -added spec for primitive "equal"
- -again primitive specs are rake spec:primitives
-
-commit c1a7896f24e018df13af7f0d3d60db9f461130a5
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Feb 5 20:58:21 2007 +0000
-
- Added that Module#include passes off to append_features. Added Module#include that takes multiple args later in the bootstrap sequence. Added specs for include and append_features.
-
-commit d407ecab13722599b75fecc20bdebd86c9f76fa6
-Author: Mae <mae@unknown>
-Date: Mon Feb 5 20:48:02 2007 +0000
-
- Misc Changes to Tweak primitive specs
- -Added spec to test arity restrictions of compare
- -Fixed bug where should_raise for primitives was not catching the error condition
- -Changed wording of some specs to be english rather than engrish :)
-
-commit f68ad63065002d4a3c9a0742770da4a112780aa7
-Author: Mae <mae@unknown>
-Date: Mon Feb 5 20:02:24 2007 +0000
-
- - Remove printf from cpu_raise_primitive_failure so that the screen doesn't get littered
- - Created PrimitiveSpecHelper and a "primitives" spec subdirectory
- - Added rake task spec:primitives
- - Added compare_spec as an example
- - New rba's
-
-commit f997d3791099912001d09a427f24252182ba1d6c
-Author: Hurdlea <hurdlea@unknown>
-Date: Sat Feb 3 08:10:48 2007 +0000
-
- * Added MatchData#values_at
- * Fixed implementation of MatchData#select
- * Updated specs for MatchData#values_at, select
-
-commit 4f8301aeb3a5a296a64b887b0f164ca02be2a71f
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Feb 2 17:00:10 2007 +0000
-
- Added specs for and empty module methods private, protected, public as a first approximation to allow code that uses them to not choke. Added String#match.
-
-commit 15c3678ddcc365891fd92cc9cd33eb22308916e8
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Feb 2 10:43:58 2007 +0000
-
- Committing Adam Ritter's patch to recognize 'for i in ...' expression, and associated spec. Uncommented line in float_spec.
-
-commit 370d7a955bf6e41c4ea7cf0f9217128ae7a72fd4
-Author: Hurdlea <hurdlea@unknown>
-Date: Fri Feb 2 07:06:22 2007 +0000
-
- * Added MatchData#inspect, select, to_a, size, to_s
- * MatchData#[] is now more compliant - behaves more like Array#[]
- * Added Regexp#hash
- * Added Regexp#hash spec
-
-commit b496d50c0ebf7d5c523efe2ef5383dd8043aa3f0
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Fri Feb 2 00:36:37 2007 +0000
-
- Added specs for Dir and modified rubinius_target to allow
- specs to change directories safely.
-
-commit 6ddf4051f3a6be7076e947bf3eccbc5dd9a7803f
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 19:11:14 2007 +0000
-
- Fixed Float#divmod, returning 0 guard on primitive, raising FloatDomainError rather than ZeroDivisionError. Fixed Float#% when other is zero. Spec try helper doesn't yet work with rubinius_target
-
-commit 679f3fbe54960a690f4e41e1403fdc8f50c0f346
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 18:36:44 2007 +0000
-
- Added more zero division behavior specs.
-
-commit b4d739a7cb68d6f82d657b69aee00923e0bfdbb4
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 18:12:02 2007 +0000
-
- oops, damn keystrokes. Previous commit msg should just include Fixnum. This change points out a problem that I'm not sure about: 1.quo(0) => Infinity in irb and run from a file, but in the spec I get zero division error. wth?
-
-commit 4e24fe43a7d6c55a53880a1c347e836f12937ed4
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 18:03:13 2007 +0000
-
- Added more specs around zero division behavior for Float and Fixnum.
-
-commit b8f412ee2bf3701acd211372d28ec596d6858ac8
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 18:01:44 2007 +0000
-
- Added more specs around zero division behavior for Float and Fixnum.
-
-commit 17a17e3008422bab9e91f8464d1ce2823c13ce78
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 17:51:47 2007 +0000
-
- Added try spec helper method for spec'ing things that raise exceptions. Added more Float specs that describe division by 0 behavior.
-
-commit 2c2bfc3663a34fbf4fd70a5787236ec8b9a87024
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 17:22:39 2007 +0000
-
- Added spec for Float#% when other is zero to show current implementation is broken.
-
-commit d1ddd71d5bd45df0c16651ecad2db3c1b75d90f8
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Feb 1 17:06:56 2007 +0000
-
- Reverted mae's breakage to Float. seriously mae: you did NOT run the float specs and you did NOT write new specs for the behavior you were changing so you did NOT understand what you were doing. As a good CS student, you can negate the above to know what you SHOULD do. ;) Please, WRITE and RUN your specs.
-
-commit b2e08a170d1ab222d67d8767fa880a5e21c5bf74
-Author: Mae <mae@unknown>
-Date: Thu Feb 1 10:53:48 2007 +0000
-
- know when to shoot your baby in the crib -- cleanup outdated unused code
-
-commit aac75dd658c96cf930852d86dbc79b66830bace5
-Author: Eero Saynatkari <eero@kittensoft.org>
-Date: Thu Feb 1 09:12:03 2007 +0000
-
- Improved specs for Hash.[].
-
-commit 40f637f2685e969f097fbbb2ffa3f0173e6f9866
-Author: Mae <mae@unknown>
-Date: Thu Feb 1 02:44:14 2007 +0000
-
- Fixed my pure ruby Numeric#floor and Numeric#ceil methods
- - Please smash your c primitive brix BWAHAHA
- - Also implemented eql? for float and now all 32 float specs pass
- - Added some edge cases for ceil/float that were not previously covered in specs
-
-commit 5cc6f6b6068e945c6f5896370ee20567e57122e7
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 31 11:24:23 2007 +0000
-
- Added Float#round. We now have 32 of 32 float specs passing. Please confirm on your platform.
-
-commit 9b902a80a008120a86ae18d4abff04d42efefc8f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 31 06:22:10 2007 +0000
-
- Folded in coerce specs.
-
-commit 09e61132d5b9e9b08d27f2f51db9580808bb370e
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 31 03:22:23 2007 +0000
-
- Created spec/incompatible for specs that show where Rubinius is incompatible with other implementations. Added bignum_spec and fixnum_spec to incompatible dir. Under MRI, Bignum.coerce(Fixnum) => [Bignum, Bignum] whereas Fixnum.coerce(Bignum) => [Float, Float]. Since Bignum should be a seamless extension of Fixnum, this behavior in MRI seems less than consistent. Under Rubinius, mixed Fixnum and Bignum promote to Bignum uniformly, and this makes much more sense. There are other places where Rubinius implementation may deviate from MRI, so spec/incompatible is for describing those behaviors. Updated coerce specs.
-
-commit cb52bb9633d0e323d2f7d6c90879fb7decfea7d7
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 30 10:44:46 2007 +0000
-
- Added Numeric#coerce primitive. Reimplemented a number of primitves and methods on Fixnum, Float, Bignum to use Numeric#coerce rather than implementing knowledge of one another all over the place. Folded in mae's coerce specs. There is currently a (desirable IMHO) incompatibility in Numeric#coerce in that Bignum.coerce(Fixnum) == Fixnum.coerce(Bignum). There are a lot of other methods that need to be reimplemented using Numeric#coerce. Also, bignum_compare needs to be implemented (just returns 0 atm).
-
-commit e1aa382f2d596a73ef20dfde4184af7a721724e9
-Author: Mae <mae@unknown>
-Date: Tue Jan 30 00:26:11 2007 +0000
-
- added specs for coercion of Fixnum, Bignum, and Float
-
-commit bd292d64a511eba51ea1569870bcf0fa365c903d
-Author: Cabo <cabo@unknown>
-Date: Sun Jan 28 21:05:10 2007 +0000
-
- include yesterday's failed cases
-
-commit 7cac7f32e5c80e78aa75dfed7f4822e65d1ab4df
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 28 08:08:12 2007 +0000
-
- committing rue's continuation specs. doomo arigatoo.
-
-commit f542b93031f8982daa13777d2eada81068e96ad5
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 28 07:03:46 2007 +0000
-
- committing rue's class specs. thanks rue!
-
-commit 319b6f194d3c699a75de8da2ba3b53b8a4feffb1
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 28 04:49:01 2007 +0000
-
- Commiting rue's binding specs.
-
-commit d8326b1321cc09c0aa64f441d2a81df6735603fd
-Author: Cabo <cabo@unknown>
-Date: Sat Jan 27 00:02:33 2007 +0000
-
- remove superfluous p from "& should create an array with no
- duplicates" (which now passes)
-
-commit 7d3baf10a79c1500e660fe5566ba8f3107d5a826
-Author: Hurdlea <hurdlea@unknown>
-Date: Thu Jan 25 05:43:50 2007 +0000
-
- * Added MatchData specs
-
-commit 2d9966c9c30e541c18ac77ca646a1af41daf702e
-Author: Hurdlea <hurdlea@unknown>
-Date: Thu Jan 25 05:42:44 2007 +0000
-
- * Added Match2 and correct Match3 in compiler.rb
- * Added alias String#to_str
- * Tweaked a few regexep specs for string return types
- * Fixed MatchData#length so it uses Tuple#fields to get the no. items
-
-commit 0d9f9e21c2a268e0710c963c745f07d494e2ab1f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 24 21:43:17 2007 +0000
-
- Commiting zimbatm's update to exception_spec.
-
-commit 037d8b29872f1c4a81108a0713afd78cbdf9b484
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 20 04:03:20 2007 +0000
-
- a few more tweaks to get string specs to execute with rcompile and shotgun.
-
-commit cfe7a6b4c87ac3ffccaeb7e70b9e6c386054e052
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 20 03:49:01 2007 +0000
-
- added parser dir under spec. added parser/symbol_spec.rb to capture parsing a complex symbol like :' for one or two', which rcompile and shotgun choke on at the moment. removed this from core/string_spec because it crashes shotgun and makes it impossible to run all the specs.
-
-commit d39040ab1563f063192a3835723cfbae7bf147cb
-Author: Cabo <cabo@unknown>
-Date: Fri Jan 19 23:45:52 2007 +0000
-
- lib/kernel.rbc is no longer a required (or wanted) command line argument
-
-commit 4774788e0ae9b24b3ff0b769aede0ba2de3f00b1
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 19 21:05:10 2007 +0000
-
- added correct guard on Array#first to return nil when array is empty. added specs for #first and #last to describe this behavior. Thanks to cabo for finding this.
-
-commit baf1453678c9906c65b2f7c82bdb0e179e22d1b8
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 19 02:49:02 2007 +0000
-
- added some minor changes to structure and wording of language/expression_spec. removed array and defined spec from language directory since they were added to language/literals directory. renamed several spec files to follow naming conventions.
-
-commit 7a24923ab9b79b226b6d8831e834ab509d5d2b76
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 19 01:27:10 2007 +0000
-
- committing zimbatm's patch to language specs. super nice and thank you. please give zimbatm a commit bit!
-
-commit 9cd8c779a88f48604733afbe4357b7101a487669
-Author: Vic <vic@unknown>
-Date: Thu Jan 18 22:20:34 2007 +0000
-
- Added Proc.given, the analog of MethodContext.current
- Proc.given obtains the proc given to the current MethodContext.
- Later will be able to get a Proc from a given Binding.
-
- Original author: Victor Hugo Borja <vic@rubyforge.org>
- Date: 2007-01-18 16:16:06+00:00
-
-commit 50c42413d33951397a46edb55ca910a2e8fb87e6
-Author: Vic <vic@unknown>
-Date: Thu Jan 18 21:34:29 2007 +0000
-
- No output is available for specs if the returning value is a Numeric or Symbol
- When the :example execution on shotgun evaluates to a Numeric or Symbol, no method
- :stdout is added, because these object do not have singleton-classes on MRI.
- If you really need both, stdout and a Numeric/Symbol, your evaluation may lead to
- an array containing that Numeric/Symbol.
-
- Also saved MRI from getting eval errors in cases like the following:
-
- example do
- class A; end
- A.new
- end
-
- This leads to the following being evaled by MRI: [ #<A:0xb7a69c8c> , stdout]
- which causes an error because of #<A:0xb7a69c8c> being invalid ruby syntax.
- This patch fixes this situation by converting #<A:0xb7a69c8c> into "#<A:0xb7a69c8c>"
-
- Original author: Victor Hugo Borja <vic@rubyforge.org>
- Date: 2007-01-18 15:23:55+00:00
-
-commit ec5bea103b4b96ecde54668e47ab9e10ac8ec4ee
-Author: Hurdlea <hurdlea@unknown>
-Date: Thu Jan 18 21:04:22 2007 +0000
-
- * Added bitwsie operators to Fixnum & | ^ << >> ~
- * Split the fixnum specs into coerced and non-coerced tests
- * Added primitives to support fixnum bitwise ops
- * Fixed a bounds tests in Interger#chr
-
-commit 238d7e0611e9198c28a5e0ebe684bc7f1f03bf0f
-Author: Vic <vic@unknown>
-Date: Thu Jan 18 20:11:58 2007 +0000
-
- [rAdded specs for the new STDOUT support] Empty log message
-
- Original author: Victor Hugo Borja <vic@rubyforge.org>
- Date: 2007-01-18 13:44:19+00:00
-
-commit 859b26f38749f160a706ed9dbb8f2a80886e94ef
-Author: Vic <vic@unknown>
-Date: Thu Jan 18 19:37:03 2007 +0000
-
- Allow to specs to test what is written to STDOUT
-
- also added String#unindent on spec_helper to help make output heredocs more readable.
-
- You can access both the evaluation result and the stdout produced, ej:
-
- context "Rubinius target" do
-
- specify "should allow to get the resulting STDOUT" do
- example do
- puts "hola"
- puts "space is significant in this heredoc"
- puts "unindent removes the first blanks found on the first line"
- puts "on each of these lines"
- puts "adios"
- end.stdout.should == <<-OUT.unindent
- hola
- space is significant in this heredoc
- unindent removes the first blanks found on the first line
- on each of these lines
- adios
- OUT
- end
-
- specify "should allow to get the lines written to STDOUT" do
- example do
- puts "hello"
- end.stdout_lines.length == 1
-
- example do
- print "bye"
- end.stdout_lines.first.should == "bye"
- end
-
- specify "should allow to access the evaluation result along with STDOUT" do
- result = example do
- puts "ok"
- Object.new.class
- end
- result.should == Object
- result.stdout_lines.should == ["ok\n"]
- end
-
- end
-
-commit e17069925d139c93acec00161a7111e6c78d54bb
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 18 08:44:33 2007 +0000
-
- converted shotgun-test/test_sexp to spec/shotgun/sexp_spec. thanks to Victor Borja's recent additions to rubinius_target, it was a breeze.
-
-commit 46e9a259bc2212dee1fa7efa8ead468e63970731
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 17 08:02:35 2007 +0000
-
- filled in the rest of the documented String instance methods except #pack.
-
-commit dfd08d6536ea497cf86d06ca503206d54b19479d
-Author: Cabo <cabo@unknown>
-Date: Tue Jan 16 10:24:18 2007 +0000
-
- A bit more array fun (and lots of FIXMEs)
-
-commit b1e50e43d8d79a5dbd82345134ecd4bdffc6d182
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 16 08:46:48 2007 +0000
-
- and yet a few more string specs. these will asymptotically approach done.
-
-commit 4048d3dfa90a6de54ea2ed0aec2ec6adafb50b0c
-Author: Cabo <cabo@unknown>
-Date: Tue Jan 16 07:02:50 2007 +0000
-
- I want to see what 'Shotgun has crashed' means, beautiful backtrace and all
-
-commit 0387baa914cb35c589c7872f7f98cf9f8ee10711
-Author: Cabo <cabo@unknown>
-Date: Tue Jan 16 02:19:45 2007 +0000
-
- Fix Array#slice! bug workarounds
-
-commit c6b110b47667c5d6750492177492434f4c0446f8
-Author: Cabo <cabo@unknown>
-Date: Tue Jan 16 01:33:18 2007 +0000
-
- add shift spec and fix String#strip so it works
-
-commit 19bcc086b7674f12e01f879a6ca83f3289feb770
-Author: Cabo <cabo@unknown>
-Date: Tue Jan 16 00:06:03 2007 +0000
-
- Integer#chr should return a new string (spec)
-
-commit 5aa81499711ad5e57f5dfc03417f23705eb79b44
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 23:48:16 2007 +0000
-
- a few more string specs.
-
-commit 8cd873e183c62b8929305ea54b9a437ca22ddb28
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 22:42:24 2007 +0000
-
- committing Victor's define_method patch.
-
-commit cd04f4c570cd95fb869f025c4dac6e9342e2ba2a
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 22:02:23 2007 +0000
-
- committing Victor Hugo Borja's instance_eval patch.
-
-commit a481142988d585bb8fa54e0186f5c9cf88ada8d9
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 20:13:03 2007 +0000
-
- added a code method to mri_target and jruby_target to parallel the behavior of the code method for rubinius_target. now core/proc_spec.rb is passing with mri target.
-
-commit a4c621e8319349eda766f73ed9ca55f2a9323ac2
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 19:08:22 2007 +0000
-
- checked in nicksieger's patch to spec_helper that enables specs to run on jruby, woohoo!
-
-commit 6b02aac6107b01258f85f9d15a77b498ad15e5b0
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 18:06:23 2007 +0000
-
- checking in cabo's changes to target specs for jruby and rubinius. modified rubinius_target specs that compared paths to use should_match because a hash is used to generate part of the path.
-
-commit 6aa175d3367d76152476888ff1c52479530c56a2
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 15 17:57:25 2007 +0000
-
- committing cabo's changes to remove heredocs from a number of specs. It is still possible to pass code as a source string to the example method. Use this if the block method is causing rubinius to choke on the ruby2ruby generated source. soon, soon, we'll have rspec running (I hope\!).
-
-commit 6679194f8e6afdbbb71f5213508bb81f12fdb2e7
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 14 17:28:06 2007 +0000
-
- incorporated nicksieger's changes to mri_target removing needless requires. added jruby_target.rb and spec to parallel mri_target.rb.
-
-commit f573b9c16efccb92eec98d923831deafc7a3c809
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 14 08:10:24 2007 +0000
-
- converted mri_target to use eval, yield to execute specs. converted some specs to new style. addressed issues with hash specs that implicitly relied on hash ordering, fixed numerous issues that result from loss of floating-point precision by using #inspect where necessary (more of these issues may arise in the specs on different platforms). added spec templates for documented String instance methods (many of which need to be filled in).
-
-commit 917cd03e5bee749d18d8d0c257381bca2362abbd
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 14 00:11:17 2007 +0000
-
- checking in Alan Hurdles patch to allow running specific files, e.g. COMPILER=rcompile rake spec:core:array .
-
-commit 508eaacf9aaf67465a78ac53284ba6f06c3bcb3d
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 21:09:51 2007 +0000
-
- added integer specs. these should be platform independent but other platforms may have some trouble with spec for 'chr' ;)
-
-commit 21463a87bac2121fa61c1c99927cdb039c724d89
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 20:37:37 2007 +0000
-
- implemented the rest of the hash specs, this should cover the documented class, instance methods.
-
-commit 3656a95a1829b0be1a8b0d968e0a9e433ef9c847
-Author: Frederick <frederick@unknown>
-Date: Sat Jan 13 13:14:41 2007 +0000
-
- Implements Fixnum#size
-
-commit ca38e49022f6bdf41b0e98409d3fec3528e59bfd
-Author: Frederick <frederick@unknown>
-Date: Sat Jan 13 12:54:30 2007 +0000
-
- shotgun/string_spec.rb now follow new spec conventions
-
-commit 1b684385fe970f11a526e280d15c3f147a826886
-Author: Frederick <frederick@unknown>
-Date: Sat Jan 13 12:42:38 2007 +0000
-
- language/expression_spec.rb and language/exception_spec.rb now use new spec style
-
-commit f62c2539a1eef27b356e4d809d76c4f9ddecd2a5
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 08:14:12 2007 +0000
-
- new style specs for hash. numerous of these need to be implemented but there should be templates for all the documented class and instance methods.
-
-commit 28083a6e6dc89502d1c76e2a16f0003a589f01e0
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 08:12:37 2007 +0000
-
- one more, bignum.
-
-commit 076aab00b795ff777c5ac11955130f12f69e1377
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 08:07:30 2007 +0000
-
- new style specs for float, fixnum, symbol, string, object, file, module, regexp, range.
-
-commit 0161ab3527e91674eed4eeaad029eee654325155
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 07:39:26 2007 +0000
-
- true, false, nil, enumerable specs are new style.
-
-commit bb11cce41a472606312eb0a62948c4a339f23dd9
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 07:27:05 2007 +0000
-
- converted existing class and comparable specs to new style.
-
-commit 595b83a75044772136b83eaf84402ed73eb79da5
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Jan 13 07:08:14 2007 +0000
-
- ladies and gentlemen, a huge round of applause and gratitude to headius for inspiration and help getting specs in a form that will easily run on MRI, JRuby, and Rubinius. Checking in the modified spec/core/array_spec.rb. The rest to follow. The mri_target is still using the sub-process method, but that should be superfluous now.
-
-commit ae75e76915432757be3c9a7126c2ee8c6656652c
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 12 08:13:29 2007 +0000
-
- added a bunch more specs for array. two still need to be filled out. I think that covers all the documented class and instance methods.
-
-commit 8daf38e0f99eed3e42d654086a98e673d9855bef
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 12 01:14:35 2007 +0000
-
- checking in more of cabo's changes to kernel/core/array.rb and array specs.
-
-commit 0a349583aba629748d5e85de0ede6f38730512f1
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 12 00:57:22 2007 +0000
-
- checking in cabo's changes to array and array spec.
-
-commit 052512fea9b74e532ef6b68612c81061ad84e4f2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 11 05:16:47 2007 +0000
-
- finished Bignum specs for documented instance methods.
-
-commit 7f4786c85b2e0e95abc2728492ed1a7424d01dbe
-Author: Frederick <frederick@unknown>
-Date: Wed Jan 10 23:44:34 2007 +0000
-
- Added File.mtime, File.atime, File.ctime
- Avoid reusing old .rbc is .rb is newer
- Remove useless CHECK_PTR
-
-commit 70458d6446f0858570571a64b5294c0bb4ac358f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 10 17:40:36 2007 +0000
-
- moved exception and expression specs to spec/language. added stub for time_spec in spec/library. updated a string spec that was failing. added specs for all (I think) float and fixnum instance methods. added specs for bignum, but about half need examples.
-
-commit ffe4a7a48dcc116f73b89b9a046d4430ed51975a
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 9 18:07:31 2007 +0000
-
- removed duplicate bk task from Rakefile. removed shotgun-tests/test-array.rb as all tests have corresponding specs in spec/core. added beginning of specs for bignum separated into spec/core for stuff that should be indendent of mri or rubinius, and spec/shotgun for implementation specific.
-
-commit 946d0b42293ea081666e71e13c4b77d5b5dba886
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 7 05:38:33 2007 +0000
-
- checking in Alan Hurdles patches to regexp, string, and spec_string.
-
-commit 5f035040c4b3ce842fff4b39d1ca657c97deb7a4
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 7 03:03:31 2007 +0000
-
- updated mri and rubinius target impl specs. added environment option for running rubinius target using obsolete.rcompile, e.g.: COMPILER=rcompile spec spec/core/symbol_spec -f s. If you don't use the COMPILER env var, rubinius target will use shotgun to compile.
-
-commit 6ea911ae5740508cdbd8feb5cddba5b8bf7fe1c3
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Jan 7 02:32:35 2007 +0000
-
- changed some Hash specs to use instance vars rather than local vars because some versions of Ruby2Ruby output borked sexp for block local vars. E.g. use @h rather than h.
-
-commit 256fe9a8cada7ed512556e1701a5264670c6c28f
-Author: Mae <mae@unknown>
-Date: Sat Jan 6 07:55:32 2007 +0000
-
- made regression spec for buggy behavior of [1,2,3][2..-1]
-
-commit 0ffe8a3e6cd92bc5cd872cc22919885ea80366a0
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 5 20:05:03 2007 +0000
-
- added spec for String#reverse! to Laurent Julliard's spec for String#reverse and his implementation of both methods.
-
-commit 170737d2c77a4b2de862380cb87f7705560cca64
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Jan 5 18:24:32 2007 +0000
-
- * Much better implementation of Hash#key?
- * Added working support for default Hash values and procs
- * Added hash_get_undef for situations where nil and undefined hash values need to be differentiated
-
-commit 332378a8900f09009626cb7c4dbf0c8740a657c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 5 07:31:56 2007 +0000
-
- added specs for aliases of Hash#key?
-
-commit 27c3b2aeaa3208a7e0218f051f623b93e2e635d8
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 5 07:28:29 2007 +0000
-
- added spec for Hash#key?
-
-commit 2e88d941bc1b1ea506396a915e3c3c4e3dfd1601
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Jan 5 06:35:09 2007 +0000
-
- updated and simplified float and fixnum specs.
-
-commit e4a5b6d8529d60e62875004bb60f33c6452ccf98
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Fri Jan 5 06:28:04 2007 +0000
-
- * defined?() now handles: defined?(Kernel.puts) flavors of arguments.
-
-commit 27660379c09e561590cf1bc48a9459e29fc00e9c
-Author: Mae <mae@unknown>
-Date: Fri Jan 5 06:10:11 2007 +0000
-
- Added spec for cvar declaration in class bodies
-
-commit a9b7b9f7db02ba78514eb869c2c52d4e5067f8d2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 4 08:08:59 2007 +0000
-
- added class def source code to specs.
-
-commit cdfa499ee238671c655800a81b51611704383500
-Author: Mae <mae@unknown>
-Date: Thu Jan 4 07:54:20 2007 +0000
-
- fixed typo in spec still 7 failing specs *GLARES AT DEFILER*
-
-commit 03be9ca7da61363f8f0a02ee951bbafaf297c31b
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 4 07:43:58 2007 +0000
-
- added specs for Module#const_defined?.
-
-commit c511d4c7a75001f2597b13f9fc2e910d2dd4d9a2
-Author: Mae <mae@unknown>
-Date: Thu Jan 4 06:54:07 2007 +0000
-
- changed defined spec to be more dumb and just figure out whether its a true/false evaluation
-
-commit 4d9135f9694e4b692faf6a4c7b8dcd59f79f5069
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 4 06:38:57 2007 +0000
-
- added library spec (beginning) for enumerator. trivial update for comparable specs. added specs for enumerable.
-
-commit 3de6e339526b1402f8995a5acc38fde707ec0695
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Jan 4 00:34:50 2007 +0000
-
- added specs for comparable methods.
-
-commit ea25c6b17533c280e640dc97e3fec1207fb4be7b
-Author: Mae <mae@unknown>
-Date: Wed Jan 3 17:47:09 2007 +0000
-
- almost done with defined? spec -- still need 'yield' and 'zsuper' test cases
- from project dir: SPEC_TARGET=mri spec spec/language/defined_spec.rb
- change SPEC_TARGET to rubinius to test on rubinius
-
-commit b795f6c2dc98952e7fa7231cded9156ade962b18
-Author: Mae <mae@unknown>
-Date: Wed Jan 3 17:25:31 2007 +0000
-
- added incomplete specs for defined? behavior -- more work to be done
-
-commit 25e30e4668f1ef814bfb1182e032449263651590
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 3 17:17:03 2007 +0000
-
- small fix to mri_target to generate reasonable cache soure name. added a couple specs.
-
-commit 3b5bc977ea2a4a3ad42ff83bcab2966459c262c0
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 3 08:51:18 2007 +0000
-
- added object_spec for methods provided by Object, even mixed in ones. added a few specs for basic class, module, exceptions.
-
-commit c4f4dd722658b2a09ae273092744b76e65ce05b2
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Jan 3 02:36:58 2007 +0000
-
- renamed flow_control_spec to expression_spec as these are all covered under heading expressions in pickaxe. run expression spec with mri target and then rubinius target to see an interesting rubinius failure. updated an incorrect string splice spec.
-
-commit ef8aa2f74896944134f5a8884ccc723ca9b472c1
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Jan 2 01:40:16 2007 +0000
-
- separated specs that are shotgun specific methods (e.g. String#prefix?) into spec/shotgun/... fixed wrong specs so that all pass under mri/mir configuration.
-
-commit 8661488b40b9fccccf356889834c6a9162c8bebf
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 22:37:41 2007 +0000
-
- very quick n' dirty implementation of example et al to run specs under mri like under rubinius.
-
-commit 0ebfa43e222ca4794243d36f10c2e429e930f527
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 20:47:13 2007 +0000
-
- added methods for TrueClass and FalseClass, updated specs for each.
-
-commit e9bb50ced8bf997535f0bc9c6deeeffb86c40879
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 20:29:37 2007 +0000
-
- added specs for true, false, nil.
-
-commit c30b0e38b88c686c11c6f7442e027d685d405505
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 18:59:59 2007 +0000
-
- added spec templates for true, false, nil, class, module, enumerable, comparable, flow_control, exception. added specs to various others.
-
-commit b26777261970c213506e444b90412543f39b3c59
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 18:58:37 2007 +0000
-
- added that rubinius target example method takes a default argument to pass strings of code to allow for creating classes, since classes can't be defined in a method body and for now example puts the block code into a method using ruby2ruby.
-
-commit 560c5a1331c76bce07289f1e5950b816fe7c9c24
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Jan 1 01:17:44 2007 +0000
-
- added more string specs.
-
-commit 807864c76b701f6f976f3f2935599ba875fcc10e
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 31 23:13:16 2006 +0000
-
- added more core specs (or templates for specs) to cover existing tests in shotgun-tests.
-
-commit 8f83b600b12722d46b9791b2e2c3a399618474a0
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 31 21:23:07 2006 +0000
-
- removed shotgun/primitives_spec as spec/shotgun should be for shotgun-specific code. created spec/core for ruby core classes. spec/library is now for ruby stdlib classes. added more array specs.
-
-commit 58cc3ce5bd8b84a151b1a6e2334845f268ab894a
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 31 08:58:50 2006 +0000
-
- added specs for class methods of Regexp. added alias Regexp.compile for Regexp.new.
-
-commit 0a5a31bc6ef539eeda3de951ab633f5152d58153
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 31 02:01:34 2006 +0000
-
- added specs for symbol methods. added aliases to symbol for to_i, to_int, and id2name.
-
-commit cdfa28e492b8edfa55b950b06ce05ebb04b64643
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 30 17:27:18 2006 +0000
-
- changed example method for rubinius_target to raise exception if compile fails. added specs for range.
-
-commit 5316e652084b8624828d0a9306f580bfc93184dc
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 29 20:37:46 2006 +0000
-
- added spec files in spec/library for basic types (according to pickaxe book). added specs for all the methods in Regexp. there are many failing specs for a variety of reasons, but the goal is to get a good overview of where work needs to be done. more specs to follow.
-
-commit 06cd5ad6da819f2894996e42f4da70321767c9c7
-Author: Mae <mae@unknown>
-Date: Thu Dec 28 07:36:21 2006 +0000
-
- Added Array expressions gleaned from spec/library/array_spec.rb as proof of concept for rapid compatibility testing
- - A thought occurred to me that the scope for this type of testing might be limited severely to simple compatibility testing
- - Its not very human understandable as a spec -- it just unravels incompatibilities given no hint as to why things are the way they are.
- - It lets the ruby rval speak for itself
- - Is this useful for rubinius?!
-
-commit 1c1fc9335aee4acbcd692c555b0ca194c5301013
-Author: Frederick <frederick@unknown>
-Date: Wed Dec 27 22:46:43 2006 +0000
-
- Fix a bug in the allocation of a string. The underlying storage (byte array) did not have the correct size, leading to a write in a non allocated memory area.
- The rationale is that, the storage are should be able to store the string plus a terminal \0. As we're allocating per block of 4 bytes (a word) we need to get the nearest multiple of 4.
- This patch adds a spec to highlight the bug, and a fix to .. well, fix it ;)
-
-commit cdfdc272b71bbfca23b4c17e5572ebd2b966615e
-Author: Mae <mae@unknown>
-Date: Tue Dec 26 17:52:24 2006 +0000
-
- Added my idea of a sanity check against MRI for compatibility purposes
- - try it out!
- - rake spec:compatibility
- - example compatibility expressions go in spec/compatibility/expressions/*
- - all the expression files are line-separated ruby expressions that return something basic and eval-able
-
-commit f9887648c7f239f8c862158b39f44b2410377204
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 22 19:20:58 2006 +0000
-
- added spec file for String methods.
-
-commit 8178e4478977c81940ac4bdcd8bea608be11708b
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 22 17:14:46 2006 +0000
-
- fixed that ruby2ruby was not generating correct ruby source when a local var was used in a block. changed local var to instance var and it works, converted primitives_spec to new block-style.
-
-commit 8a00080a1edb864af7573e8f9761f65fa1202d07
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 22 06:58:28 2006 +0000
-
- changed array_spec to not use local variables in blocks where possible because rubytoruby is not converting them to ruby source correctly. Array#uniq! fails at the moment. re-added that compile checks code-cache first so specs run faster.
-
-commit 4a199c559eebe73cd21d0997126b799f5d4e2be5
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 22 06:00:21 2006 +0000
-
- converted array_spec.rb to block-style specs, but they still depend on strings to be output. rewrote spec_helper based on nicksieger's example code. some specs are failing due to bugs converting to sexp and back to ruby source.
-
-commit 854bbc3617559a2ceac975d79a57ffa825a5cda6
-Author: Brian Ford <brixen@gmail.com>
-Date: Fri Dec 22 03:34:18 2006 +0000
-
- added spec/targets for specs for 'target' part of host/target spec runner configuration. added mri_target and rubinius_target and specs.
-
-commit db81559c9c914413d2064b4202ec8ce43e503af2
-Author: Brian Ford <brixen@gmail.com>
-Date: Thu Dec 21 05:51:55 2006 +0000
-
- added spec:targets task to run specs for target part of host/target spec configuration. added specs for mri_target and rubinius_target.
-
-commit a243a70bd17ec7e9839b69bb18e63d5d943b6095
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 20 19:02:01 2006 +0000
-
- updated primitives_spec to use example method.
-
-commit 9ce077283dd10c21377add499c5bcc4ea87cfe0f
-Author: Brian Ford <brixen@gmail.com>
-Date: Wed Dec 20 17:11:00 2006 +0000
-
- Changed method from rubinius to example for specs. This is in anticipation of having independent 'host' (system running rspec) and 'target' (system executing spec). Created parallel arrayb_spec that illustrates this with a mri/mri configuration. Also added spec_bhelper that is a *very rough* beginning for having mri/rubinius configuration using block-style specs.
-
-commit a8ad71a0da9e1a866521074743ea1dfcceb596cb
-Author: Wilson Bilkovich <wilson@supremetyrant.com>
-Date: Wed Dec 20 15:39:36 2006 +0000
-
- Applying 'array patch' from Jason Perkins (2006-12-20 8:30 EST)
-
-commit 82b3d880131e7080ebc6b4289b3954d89a988c13
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 19 17:30:21 2006 +0000
-
- added more specs to array_spec. most of these are failing, so there seems to be a lot of Array that needs implementing.
-
-commit c24f0e83b4d446afd541ffefbcb313f199b684ee
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 19 08:24:00 2006 +0000
-
- added specs for Array#* and <<, simplified other specs.
-
-commit 62b0737ce69768a8292bd3d9f13401ec8056f6eb
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 19 07:46:39 2006 +0000
-
- fixed messed up spec for &.
-
-commit 7635389b2abf5c492952a49eb8251d6fb34250c7
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 19 07:40:01 2006 +0000
-
- added spec for Array#&, which is currently unimplemented. updated spec_helper.
-
-commit 42b5e9fc47bcf6bcd403d25795c9bcf07bb5c007
-Author: Brian Ford <brixen@gmail.com>
-Date: Tue Dec 19 06:13:15 2006 +0000
-
- added spec tasks :only to run only spec, :language for high level language conformance spcs, :library for ruby stdlib implementation specs, and :shotgun for specs related to shotgun. rake spec will run all specs and tests. removed spec/spec_suite.rb because all specs can be run from rake. minor updates to spec_helper.
-
-commit da4c42890f4b8163b8d49de64bdb76c16b0e5d1f
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 18 17:41:44 2006 +0000
-
- added shotgun dir under spec for things that relate to shotgun implementation of VM, like the prmitives_spec, while reserving spec/library for general ruby implementation of the std lib.
-
-commit 925cbf9f84f78a48189f7030c205942d266a6f66
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 18 09:45:25 2006 +0000
-
- added Fixnum#% primitive implementation. changed array_spec to use Fixnum#%. fixed test_primitive test for Fixnum#%.
-
-commit 06e50e48a92e3fa7d1fc4d6b681872d08e5aeba3
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 18 09:10:37 2006 +0000
-
- Added Fixnum#% primitive test, spec, cpu/primitive, stub.
-
-commit e0fbcf29f46dde89f65d13c1b6d7601a470cf223
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 18 07:54:02 2006 +0000
-
- all ports of test_array test to array_spec are now passing.
-
-commit c2330c2ff65cfa964d954340fb0eb2507972efd5
-Author: Brian Ford <brixen@gmail.com>
-Date: Mon Dec 18 07:39:55 2006 +0000
-
- updated spec_helper to ensure code-cache dir exists. fixed several failing specs in array_spec by correcting expected value.
-
-commit 81cc03c6f7ce499da563543f00d273d3a9c3a184
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 17 06:27:15 2006 +0000
-
- Ported the rest of test_array.rb tests to specs. Several of these specs are not passing but ported them all to illustrate behavior of specs.
-
-commit b4cb073931f403119a5ed9b63a2c915612a9c46f
-Author: Brian Ford <brixen@gmail.com>
-Date: Sun Dec 17 04:42:55 2006 +0000
-
- spec/spec_helper.rb rubinius method is a very naive port of shotgun-tests/helper.rb run_code method. spec/library/array_spec.rb is several ports of the tests in shotgun-tests/test_array.rb, which is testing /kernel/array.rb. In other words, you can now create specs that run under RSpec (which is running under MRI 1.8.x) that exercises the rubinius vm, shotgun, and the stdlib that is being written in ruby. Confused? Read the source, Luke. :)
-
-commit 1b37cd1ee800060fb215a52d2902c3f4b778a656
-Author: Brian Ford <brixen@gmail.com>
-Date: Sat Dec 16 07:55:41 2006 +0000
-
- Added spec dir with spec_suite.rb and spec_helper.rb provided by nullstyle.
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index 7c9363da37..a474e205f0 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -8,17 +8,19 @@ Spec are grouped in 5 separate top-level groups:
* `command_line`: for the ruby executable command-line flags (`-v`, `-e`, etc)
* `language`: for the language keywords and syntax constructs (`if`, `def`, `A::B`, etc)
-* `core`: for the core methods (`Fixnum#+`, `String#upcase`, no need to require anything)
+* `core`: for the core methods (`Integer#+`, `String#upcase`, no need to require anything)
* `library`: for the standard libraries methods (`CSV.new`, `YAML.parse`, need to require the stdlib)
* `optional/capi`: for functions available to the Ruby C-extension API
The exact file for methods is decided by the `#owner` of a method, for instance for `#group_by`:
+
```ruby
> [].method(:group_by)
=> #<Method: Array(Enumerable)#group_by>
> [].method(:group_by).owner
=> Enumerable
```
+
Which should therefore be specified in `core/enumerable/group_by_spec.rb`.
### MkSpec - a tool to generate the spec structure
@@ -53,12 +55,19 @@ which indicates the file was generated but the method unspecified.
Here is a list of frequently-used matchers, which should be enough for most specs.
There are a few extra specific matchers used in the couple specs that need it.
+The general idea is: add `.should` just before the predicate you expect to be truthy, and done!
+This works for most needs and provides a great error when it fails.
+It's immediately clear which method is used and there no need to remember a mapping like in RSpec between e.g. `eq` and `==`.
+See [this blog post](https://eregon.me/blog/2019/10/07/a-new-should-syntax.html) for the motivation behind that syntax.
+
+#### Comparison matchers
+
```ruby
(1 + 2).should == 3 # Calls #==
(1 + 2).should_not == 5
-File.should equal(File) # Calls #equal? (tests identity)
-(1 + 2).should eql(3) # Calls #eql? (Hash equality)
+File.should.equal?(File) # Calls #equal? (tests identity)
+(1 + 2).should.eql?(3) # Calls #eql? (Hash equality)
1.should < 2
2.should <= 2
@@ -66,32 +75,55 @@ File.should equal(File) # Calls #equal? (tests identity)
4.should > 3
"Hello".should =~ /l{2}/ # Calls #=~ (Regexp match)
+```
-[].should be_empty # Calls #empty?
-[1,2,3].should include(2) # Calls #include?
+#### Predicate matchers
+
+```ruby
+[].should.empty?
+[1,2,3].should.include?(2)
+
+"hello".should.start_with?("h")
+"hello".should.end_with?("o")
(0.1 + 0.2).should be_close(0.3, TOLERANCE) # (0.2-0.1).abs < TOLERANCE
-(0.0/0.0).should be_nan # Calls Float#nan?
-(1.0/0.0).should be_positive_infinity
-(-1.0/0.0).should be_negative_infinity
+(0.0/0.0).should.nan?
-3.14.should be_an_instance_of(Float) # Calls #instance_of?
-3.14.should be_kind_of(Numeric) # Calls #is_a?
-Numeric.should be_ancestor_of(Float) # Float.ancestors.include?(Numeric)
+3.14.should.instance_of?(Float) # Calls #instance_of?
+3.14.should.is_a?(Numeric) # Calls #is_a?
+
+3.14.should.respond_to?(:to_i)
+Integer.should.method_defined?(:+, false)
+```
-3.14.should respond_to(:to_i) # Calls #respond_to?
-Fixnum.should have_instance_method(:+)
-Array.should have_method(:new)
-# Also have_constant, have_private_instance_method, have_singleton_method, etc
+#### Exception matchers
+```ruby
-> {
raise "oops"
-}.should raise_error(RuntimeError, /oops/)
+}.should.raise(RuntimeError, /oops/)
+
+-> {
+ raise "oops"
+}.should.raise(RuntimeError) { |e|
+ # Custom checks on the Exception object
+ e.message.should.include?("oops")
+ e.cause.should == nil
+}
+```
+
+##### `should_not.raise`
+
+**Avoid this!** Instead, use an expectation testing what the code in the lambda does.
+If an exception is raised, it will fail the example anyway.
+
+```ruby
+-> { ... }.should_not.raise
+```
-# To avoid! Instead, use an expectation testing what the code in the lambda does.
-# If an exception is raised, it will fail the example anyway.
--> { ... }.should_not raise_error
+#### Warning matcher
+```ruby
-> {
Fixnum
}.should complain(/constant ::Fixnum is deprecated/) # Expect a warning
@@ -102,15 +134,21 @@ Array.should have_method(:new)
Different guards are available as defined by mspec.
Here is a list of the most commonly-used guards:
+#### Version guards
+
```ruby
-ruby_version_is ""..."2.4" do
- # Specs for RUBY_VERSION < 2.4
+ruby_version_is ""..."3.2" do
+ # Specs for RUBY_VERSION < 3.2
end
-ruby_version_is "2.4" do
- # Specs for RUBY_VERSION >= 2.4
+ruby_version_is "3.2" do
+ # Specs for RUBY_VERSION >= 3.2
end
+```
+
+#### Platform guards
+```ruby
platform_is :windows do
# Specs only valid on Windows
end
@@ -125,34 +163,48 @@ end
platform_is_not :linux, :darwin do # Not Linux and not Darwin
end
-platform_is wordsize: 64 do
+platform_is pointer_size: 64 do
# 64-bit platform
end
big_endian do
# Big-endian platform
end
+```
+
+#### Guard for bug
+
+In case there is a bug in MRI and the fix will be backported to previous versions.
+If it is not backported or not likely, use `ruby_version_is` instead.
+First, file a bug at https://bugs.ruby-lang.org/.
+The problem is `ruby_bug` would make non-MRI implementations fail this spec while MRI itself does not pass it, so it should only be used if the bug is/will be fixed and backported.
+Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI (which has the bug) to pass the spec, or behave the same as the latest release of MRI (which has the bug) and fail the spec, both which make no sense.
+
+IOW, `ruby_bug '#NN', ''...'X.Y' do` is equivalent to `guard_not { RUBY_ENGINE == "ruby" && ruby_version_is ''...'X.Y' } do`. So it skips tests on MRI on specified versions (where a bug is present) and runs tests on alternative implementations only.
-# In case there is a bug in MRI but the expected behavior is obvious
-# First file a bug at https://bugs.ruby-lang.org/
-# It is better to use a ruby_version_is guard if there was a release with the fix
-ruby_bug '#13669', ''...'2.5' do
+```ruby
+ruby_bug '#13669', ''...'3.2' do
it "works like this" do
# Specify the expected behavior here, not the bug
end
end
+```
+#### Combining guards
-# Combining guards
-guard -> { platform_is :windows and ruby_version_is ""..."2.3" } do
- # Windows and RUBY_VERSION < 2.3
+```ruby
+guard -> { platform_is :windows and ruby_version_is ""..."3.2" } do
+ # Windows and RUBY_VERSION < 3.2
end
-guard_not -> { platform_is :windows and ruby_version_is ""..."2.3" } do
+guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do
# The opposite
end
+```
+
+#### Custom guard
-# Custom guard
+```ruby
max_uint = (1 << 32) - 1
guard -> { max_uint <= fixnum_max } do
end
@@ -160,6 +212,8 @@ end
Custom guards are better than a simple `if` as they allow [mspec commands](https://github.com/ruby/mspec/issues/30#issuecomment-312487779) to work properly.
+#### Implementation-specific behaviors
+
In general, the usage of guards should be minimized as possible.
There are no guards to define implementation-specific behavior because
@@ -170,67 +224,67 @@ If an implementation does not support some feature, simply tag the related specs
### Shared Specs
-Often throughout Ruby, identical functionality is used by different methods and modules. In order
-to avoid duplication of specs, we have shared specs that are re-used in other specs. The use is a
+Often throughout Ruby, identical functionality is used by different methods and modules. In order
+to avoid duplication of specs, we have shared specs that are re-used in other specs. The use is a
bit tricky however, so let's go over it.
Commonly, if a shared spec is only reused within its own module, the shared spec will live within a
-shared directory inside that module's directory. For example, the `core/hash/shared/key.rb` spec is
+shared directory inside that module's directory. For example, the `core/hash/shared/iteration.rb` spec is
only used by `Hash` specs, and so it lives inside `core/hash/shared/`.
When a shared spec is used across multiple modules or classes, it lives within the `shared/` directory.
-An example of this is the `shared/file/socket.rb` which is used by `core/file/socket_spec.rb`,
+An example of this is the `shared/file/socket.rb` which is used by `core/file/socket_spec.rb`,
`core/filetest/socket_spec.rb`, and `core/file/state/socket_spec.rb` and so it lives in the root `shared/`.
Defining a shared spec involves adding a `shared: true` option to the top-level `describe` block. This
-will signal not to run the specs directly by the runner. Shared specs have access to two instance
+will signal not to run the specs directly by the runner. Shared specs have access to two instance
variables from the implementor spec: `@method` and `@object`, which the implementor spec will pass in.
Here's an example of a snippet of a shared spec and two specs which integrates it:
-``` ruby
-# core/hash/shared/key.rb
-describe :hash_key_p, shared: true do
- it "returns true if the key's matching value was false" do
- { xyz: false }.send(@method, :xyz).should == true
+```ruby
+# core/hash/shared/iteration.rb
+describe :hash_iteration_no_block, shared: true do
+ it "returns an Enumerator if called on a non-empty hash without a block" do
+ { 1 => 2 }.send(@method).should.instance_of?(Enumerator)
end
end
-# core/hash/key_spec.rb
-describe "Hash#key?" do
- it_behaves_like :hash_key_p, :key?
+# core/hash/select_spec.rb
+describe "Hash#select" do
+ it_behaves_like :hash_iteration_no_block, :select
end
-# core/hash/include_spec.rb
-describe "Hash#include?" do
- it_behaves_like :hash_key_p, :include?
+# core/hash/reject_spec.rb
+describe "Hash#reject" do
+ it_behaves_like :hash_iteration_no_block, :reject
end
```
-In the example, the first `describe` defines the shared spec `:hash_key_p`, which defines a spec that
-calls the `@method` method with an expectation. In the implementor spec, we use `it_behaves_like` to
-integrate the shared spec. `it_behaves_like` takes 3 parameters: the key of the shared spec, a method,
-and an object. These last two parameters are accessible via `@method` and `@object` in the shared spec.
+In the example, the first `describe` defines the shared spec `:hash_iteration_no_block`, which defines a spec that
+calls the `@method` method with an expectation. In the implementor spec, we use `it_behaves_like` to
+integrate the shared spec. `it_behaves_like` takes 3 parameters: the key of the shared spec, a method,
+and an object. These last two parameters are accessible via `@method` and `@object` in the shared spec.
Sometimes, shared specs require more context from the implementor class than a simple object. We can address
-this by passing a lambda as the method, which will have the scope of the implementor. Here's an example of
+this by passing a lambda as the method, which will have the scope of the implementor. Here's an example of
how this is used currently:
-``` ruby
+```ruby
describe :kernel_sprintf, shared: true do
it "raises TypeError exception if cannot convert to Integer" do
- -> { @method.call("%b", Object.new) }.should raise_error(TypeError)
+ -> { @method.call("%b", Object.new) }.should.raise(TypeError)
end
end
describe "Kernel#sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
sprintf(format, *args)
}
end
describe "Kernel.sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
Kernel.sprintf(format, *args)
}
end
diff --git a/spec/ruby/README.md b/spec/ruby/README.md
index f2e18d5800..b259a97e21 100644
--- a/spec/ruby/README.md
+++ b/spec/ruby/README.md
@@ -1,10 +1,10 @@
# The Ruby Spec Suite
-[![Build Status](https://travis-ci.org/ruby/spec.svg)](https://travis-ci.org/ruby/spec)
-[![Build Status](https://ci.appveyor.com/api/projects/status/1gs6f399320o44b1?svg=true)](https://ci.appveyor.com/project/eregon/spec-x948i)
-[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec)
+[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg)](https://github.com/ruby/spec/actions)
-The Ruby Spec Suite is a test suite for the behavior of the Ruby programming language.
+The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
+
+### Description and Motivation
It is not a standardized specification like the ISO one, and does not aim to become one.
Instead, it is a practical tool to describe and test the behavior of Ruby with code.
@@ -17,28 +17,54 @@ Every example code has a textual description, which presents several advantages:
The specs are written with syntax similar to RSpec 2.
They are run with MSpec, the purpose-built framework for running the Ruby Spec Suite.
-For more information, see the [MSpec](http://github.com/ruby/mspec) project.
+For more information, see the [MSpec](https://github.com/ruby/mspec) project.
The specs describe the [language syntax](language/), the [core library](core/), the [standard library](library/), the [C API for extensions](optional/capi) and the [command line flags](command_line/).
The language specs are grouped by keyword while the core and standard library specs are grouped by class and method.
ruby/spec is known to be tested in these implementations for every commit:
-* [MRI](http://rubyci.org/) on 30 platforms and 4 versions
+
+* [MRI](https://rubyci.org/) on 30 platforms and 4 versions
* [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x
-* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
+* [TruffleRuby](https://github.com/truffleruby/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec)
+* [Artichoke](https://github.com/artichoke/spec/tree/artichoke-vendor)
+
+ruby/spec describes the behavior of Ruby 3.3 and more recent Ruby versions.
+More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (3.3.x, 3.4.x, etc), and those are tested in CI.
+
+### Synchronization with Ruby Implementations
+
+The specs are synchronized both ways around once a month by @andrykonchin between ruby/spec, MRI, JRuby and TruffleRuby,
+using [this script](https://github.com/ruby/mspec/blob/master/tool/sync/sync-rubyspec.rb).
+Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs.
+Any of these repositories can be used to add or edit specs, use what is most convenient for you.
-The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby.
-Each of these repositories has a full copy of the files to ease editing specs.
+For *testing* the development version of a Ruby implementation, one should always test against that implementation's copy of the specs under `spec/ruby`, as that's what the Ruby implementation tests against in their CI.
+Also, this repository doesn't always contain the latest spec changes from MRI (it's synchronized monthly), and does not contain tags (specs marked as failing on that Ruby implementation).
+Running specs on a Ruby implementation can be done with:
-ruby/spec describes the behavior of Ruby 2.3 and more recent Ruby versions.
-More precisely, every latest stable MRI release [passes](https://rubyci.org/) all specs of ruby/spec
-(2.3.x, 2.4.x, 2.5.x, etc).
+```console
+$ cd ruby_implementation/spec/ruby
+# Add ../ruby_implementation/bin in PATH, or pass -t /path/to/bin/ruby
+$ ../mspec/bin/mspec
+```
+
+### Specs for old Ruby versions
For older specs try these commits:
+
* Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures)
* Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed)
* Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3)
+* Ruby 2.3.8 - [Suite](https://github.com/ruby/spec/commit/dc733114d8ae66a3368ba3a98422c50147a76ba5) using [MSpec](https://github.com/ruby/mspec/commit/4599bc195fb109f2a482a01c32a7d659518369ea)
+* Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2)
+* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041)
+* Ruby 2.6.10 - [Suite](https://github.com/ruby/spec/commit/aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e) using [MSpec](https://github.com/ruby/mspec/commit/5e36c684e9e2b92b1187589bba1df22c640a8661)
+* Ruby 2.7.8 - [Suite](https://github.com/ruby/spec/commit/93787e6035c925b593a9c0c6fb0e7e07a6f1df1f) using [MSpec](https://github.com/ruby/mspec/commit/1d8cf64722d8a7529f7cd205be5f16a89b7a67fd)
+* Ruby 3.0.7 - [Suite](https://github.com/ruby/spec/commit/affef93d9940f615e4836f64b011da211f570913) using [MSpec](https://github.com/ruby/mspec/commit/0aabb3e548eb5ea6cad0125f8f46cee34542b6b7)
+* Ruby 3.1.6 - [Suite](https://github.com/ruby/spec/commit/ec960f2389d1c2265d32397fa8afa6d462014efc) using [MSpec](https://github.com/ruby/mspec/commit/484310dbed35b84c74484fd674602f88c42d063a)
+* Ruby 3.2.9 - [Suite](https://github.com/ruby/spec/commit/97f076242b7fc6e60703e6a6053365065cd6fc30) using [MSpec](https://github.com/ruby/mspec/commit/54704795e21128a930af2021c72c49cb87065134)
### Running the specs
@@ -50,7 +76,7 @@ Then move to it:
$ cd spec
-Clone [MSpec](http://github.com/ruby/mspec):
+Clone [MSpec](https://github.com/ruby/mspec):
$ git clone https://github.com/ruby/mspec.git ../mspec
@@ -63,7 +89,7 @@ This will execute all the specs using the executable named `ruby` on your curren
### Running Specs with a Specific Ruby Implementation
Use the `-t` option to specify the Ruby implementation with which to run the specs.
-The argument may be a full path to the Ruby binary.
+The argument is either a full path to the Ruby binary, or an executable in `$PATH`.
$ ../mspec/bin/mspec -t /path/to/some/bin/ruby
@@ -88,21 +114,54 @@ In similar fashion, the following commands run the respective specs:
$ ../mspec/bin/mspec :library
$ ../mspec/bin/mspec :capi
-### Contributing
+### Sanity Checks When Running Specs
+
+A number of checks for various kind of "leaks" (file descriptors, temporary files,
+threads, subprocesses, `ENV`, `ARGV`, global encodings, top-level constants) can be
+enabled with `CHECK_LEAKS=true`:
+
+ $ CHECK_LEAKS=true ../mspec/bin/mspec
+
+New top-level constants should only be introduced when needed or follow the
+pattern `<ClassBeingTested>Specs` such as `module StringSpecs`.
+Other constants used for testing should be nested under such a module.
+
+Exceptions to these rules are contained in the file `.mspec.constants`.
+MSpec can automatically add new top-level constants in this file with:
+
+ $ CHECK_LEAKS=save mspec ../mspec/bin/mspec file
+
+### Running Specs on S390x CPU Architecture
+
+Run the specs with `DFLTCC=0` if you see failing specs related to the zlib library on s390x CPU architecture. The failures can happen with the zlib library applying the patch madler/zlib#410 to enable the deflate algorithm producing a different compressed byte stream.
+
+ $ DFLTCC=0 ../mspec/bin/mspec
+
+### Contributing and Writing Specs
+
+See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) for documentation about contributing and writing specs (guards, matchers, etc).
+
+### Dependencies
+
+These command-line executables are needed to run the specs.
+
+* `echo`
+* `stat` for `core/file/*time_spec.rb`
+* `find` for `core/file/fixtures/file_types.rb` (package `findutils`, not needed on Windows)
-See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md).
+The file `/etc/services` is required for socket specs (package `netbase` on Debian, not needed on Windows).
### Socket specs from rubysl-socket
-Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket).
+Most specs under `library/socket` were imported from the rubysl-socket project (which is no longer on GitHub).
The 3 copyright holders of rubysl-socket, Yorick Peterse, Chuck Remes and
-Brian Shirai, [agreed to relicense those specs](https://github.com/rubysl/rubysl-socket/issues/15)
-under the MIT license in ruby/spec.
+Brian Shirai, agreed to relicense those specs under the MIT license in ruby/spec.
### History and RubySpec
This project was originally born from [Rubinius](https://github.com/rubinius/rubinius) tests being converted to the spec style.
+The revision history of these specs is available [here](https://github.com/ruby/spec/blob/2b886623/CHANGES.before-2008-05-10).
These specs were later extracted to their own project, RubySpec, with a specific vision and principles.
At the end of 2014, Brian Shirai, the creator of RubySpec, decided to [end RubySpec](http://rubinius.com/2014/12/31/matz-s-ruby-developers-don-t-use-rubyspec/).
-A couple months later, the different repositories were merged and [the project was revived](http://eregon.github.io/rubyspec/2015/07/29/rubyspec-is-reborn.html).
+A couple months later, the different repositories were merged and [the project was revived](https://eregon.github.io/rubyspec/2015/07/29/rubyspec-is-reborn.html).
On 12 January 2016, the name was changed to "The Ruby Spec Suite" for clarity and to let the RubySpec ideology rest in peace.
diff --git a/spec/ruby/appveyor.yml b/spec/ruby/appveyor.yml
deleted file mode 100644
index 88dd753070..0000000000
--- a/spec/ruby/appveyor.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-version: "{build}"
-clone_depth: 5
-init:
- # To avoid duplicated executables in PATH, see https://github.com/ruby/spec/pull/468
- - set PATH=C:\Ruby%ruby_version%\bin;C:\Program Files\7-Zip;C:\Program Files\AppVeyor\BuildAgent;C:\Program Files\Git\cmd;C:\Windows\system32;C:\Program Files;C:\Windows
- # Loads trunk build and updates MSYS2 / MinGW to most recent gcc compiler
- - ps: |
- if ($env:ruby_version -eq '_trunk') {
- $trunk_uri = 'https://ci.appveyor.com/api/projects/MSP-Greg/ruby-loco/artifacts/ruby_trunk.7z'
- (New-Object Net.WebClient).DownloadFile($trunk_uri, 'C:\ruby_trunk.7z')
- 7z.exe x C:\ruby_trunk.7z -oC:\Ruby_trunk
- }
-
-environment:
- matrix:
- - ruby_version: 24-x64
- - ruby_version: 25-x64
- - ruby_version: _trunk # So the folder name is ruby_trunk
-install:
- - git clone https://github.com/ruby/mspec.git ../mspec
-build: off
-test_script:
- - SET CHECK_LEAKS=true
- - ../mspec/bin/mspec -rdevkit -ff
-on_finish:
- - ruby -v
-matrix:
- allow_failures:
- - ruby_version: _trunk
-branches:
- only:
- - master
- - /^try/
diff --git a/spec/ruby/bin/rubocop b/spec/ruby/bin/rubocop
new file mode 100755
index 0000000000..0937c47906
--- /dev/null
+++ b/spec/ruby/bin/rubocop
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'bundler/inline'
+
+gemfile do
+ source 'https://rubygems.org'
+
+ gem 'rubocop', '1.86.2'
+end
+
+exec(Gem.bin_path('rubocop', 'rubocop'), *ARGV)
diff --git a/spec/ruby/command_line/backtrace_limit_spec.rb b/spec/ruby/command_line/backtrace_limit_spec.rb
new file mode 100644
index 0000000000..4d57bc268b
--- /dev/null
+++ b/spec/ruby/command_line/backtrace_limit_spec.rb
@@ -0,0 +1,93 @@
+require_relative '../spec_helper'
+
+describe "The --backtrace-limit command line option" do
+ ruby_version_is ""..."3.4" do
+ it "limits top-level backtraces to a given number of entries" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+top
+/fixtures/backtrace.rb:2:in `a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in `b'
+\tfrom /fixtures/backtrace.rb:10:in `c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "affects Exception#full_message" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+full_message
+/fixtures/backtrace.rb:2:in `a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in `b'
+\tfrom /fixtures/backtrace.rb:10:in `c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "does not affect Exception#backtrace" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+backtrace
+/fixtures/backtrace.rb:2:in `a'
+/fixtures/backtrace.rb:6:in `b'
+/fixtures/backtrace.rb:10:in `c'
+/fixtures/backtrace.rb:14:in `d'
+/fixtures/backtrace.rb:29:in `<main>'
+ MSG
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "limits top-level backtraces to a given number of entries" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+top
+/fixtures/backtrace.rb:2:in 'Object#a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in 'Object#b'
+\tfrom /fixtures/backtrace.rb:10:in 'Object#c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "affects Exception#full_message" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+full_message
+/fixtures/backtrace.rb:2:in 'Object#a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in 'Object#b'
+\tfrom /fixtures/backtrace.rb:10:in 'Object#c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "does not affect Exception#backtrace" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+backtrace
+/fixtures/backtrace.rb:2:in 'Object#a'
+/fixtures/backtrace.rb:6:in 'Object#b'
+/fixtures/backtrace.rb:10:in 'Object#c'
+/fixtures/backtrace.rb:14:in 'Object#d'
+/fixtures/backtrace.rb:29:in '<main>'
+ MSG
+ end
+ end
+end
diff --git a/spec/ruby/command_line/dash_0_spec.rb b/spec/ruby/command_line/dash_0_spec.rb
new file mode 100755
index 0000000000..2ce4f49b5e
--- /dev/null
+++ b/spec/ruby/command_line/dash_0_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../spec_helper'
+
+describe "The -0 command line option" do
+ it "sets $/ and $-0" do
+ ruby_exe("puts $/, $-0", options: "-072").should == ":\n:\n"
+ end
+
+ ruby_version_is "4.0" do
+ it "sets $/ and $-0 as a frozen string" do
+ ruby_exe("puts $/.frozen?, $-0.frozen?", options: "-072").should == "true\ntrue\n"
+ end
+ end
+end
diff --git a/spec/ruby/command_line/dash_a_spec.rb b/spec/ruby/command_line/dash_a_spec.rb
index 9ea135dc76..43d923ce16 100644
--- a/spec/ruby/command_line/dash_a_spec.rb
+++ b/spec/ruby/command_line/dash_a_spec.rb
@@ -6,13 +6,13 @@ describe "The -a command line option" do
end
it "runs the code in loop conditional on Kernel.gets()" do
- ruby_exe("puts $F.last", options: "-n -a", escape: true,
+ ruby_exe("puts $F.last", options: "-n -a",
args: " < #{@names}").should ==
"jones\nfield\ngrey\n"
end
it "sets $-a" do
- ruby_exe("puts $-a", options: "-n -a", escape: true,
+ ruby_exe("puts $-a", options: "-n -a",
args: " < #{@names}").should ==
"true\ntrue\ntrue\n"
end
diff --git a/spec/ruby/command_line/dash_e_spec.rb b/spec/ruby/command_line/dash_e_spec.rb
index 70ecdd5dce..24ed34376d 100644
--- a/spec/ruby/command_line/dash_e_spec.rb
+++ b/spec/ruby/command_line/dash_e_spec.rb
@@ -23,9 +23,9 @@ describe "The -e command line option" do
#needs to test return => LocalJumpError
- describe "with -n and a Fixnum range" do
+ describe "with -n and an Integer range" do
before :each do
- @script = "-W0 -ne 'print if %s' #{fixture(__FILE__, "conditional_range.txt")}"
+ @script = "-ne 'print if %s' #{fixture(__FILE__, "conditional_range.txt")}"
end
it "mimics an awk conditional by comparing an inclusive-end range with $." do
diff --git a/spec/ruby/command_line/dash_encoding_spec.rb b/spec/ruby/command_line/dash_encoding_spec.rb
index 36ce55af5f..5803d328c1 100644
--- a/spec/ruby/command_line/dash_encoding_spec.rb
+++ b/spec/ruby/command_line/dash_encoding_spec.rb
@@ -25,6 +25,12 @@ describe "The --encoding command line option" do
end
it "does not accept a third encoding" do
- ruby_exe(@test_string, options: "--disable-gems --encoding big5:#{@enc2}:utf-32le", args: "2>&1").should =~ /extra argument for --encoding: utf-32le/
+ options = {
+ options: "--disable-gems --encoding big5:#{@enc2}:utf-32le",
+ args: "2>&1",
+ exit_status: 1
+ }
+
+ ruby_exe(@test_string, options).should =~ /extra argument for --encoding: utf-32le/
end
end
diff --git a/spec/ruby/command_line/dash_l_spec.rb b/spec/ruby/command_line/dash_l_spec.rb
new file mode 100644
index 0000000000..44a98445f3
--- /dev/null
+++ b/spec/ruby/command_line/dash_l_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../spec_helper'
+
+describe "The -l command line option" do
+ before :each do
+ @names = fixture __FILE__, "full_names.txt"
+ end
+
+ it "chomps lines with default separator" do
+ ruby_exe('puts $_.end_with?("\n")', options: "-n -l",
+ args: " < #{@names}").should ==
+ "false\nfalse\nfalse\n"
+ end
+
+ it "chomps last line based on $/" do
+ ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l",
+ args: " < #{@names}").should ==
+ "alice j\nbob field\njames grey\n"
+ end
+
+ it "sets $\\ to the value of $/" do
+ ruby_exe("puts $\\ == $/", options: "-W0 -n -l",
+ args: " < #{@names}").should ==
+ "true\ntrue\ntrue\n"
+ end
+
+ it "sets $-l" do
+ ruby_exe("puts $-l", options: "-n -l",
+ args: " < #{@names}").should ==
+ "true\ntrue\ntrue\n"
+ end
+end
diff --git a/spec/ruby/command_line/dash_n_spec.rb b/spec/ruby/command_line/dash_n_spec.rb
index 9d331d6065..1dd9379259 100644
--- a/spec/ruby/command_line/dash_n_spec.rb
+++ b/spec/ruby/command_line/dash_n_spec.rb
@@ -6,19 +6,19 @@ describe "The -n command line option" do
end
it "runs the code in loop conditional on Kernel.gets()" do
- ruby_exe("puts $_", options: "-n", escape: true,
+ ruby_exe("puts $_", options: "-n",
args: " < #{@names}").should ==
"alice\nbob\njames\n"
end
it "only evaluates BEGIN blocks once" do
- ruby_exe("BEGIN { puts \"hi\" }; puts $_", options: "-n", escape: true,
+ ruby_exe("BEGIN { puts \"hi\" }; puts $_", options: "-n",
args: " < #{@names}").should ==
"hi\nalice\nbob\njames\n"
end
it "only evaluates END blocks once" do
- ruby_exe("puts $_; END {puts \"bye\"}", options: "-n", escape: true,
+ ruby_exe("puts $_; END {puts \"bye\"}", options: "-n",
args: " < #{@names}").should ==
"alice\nbob\njames\nbye\n"
end
@@ -29,7 +29,7 @@ describe "The -n command line option" do
$total += 1
END { puts $total }
script
- ruby_exe(script, options: "-n", escape: true,
+ ruby_exe(script, options: "-n",
args: " < #{@names}").should ==
"3\n"
end
diff --git a/spec/ruby/command_line/dash_p_spec.rb b/spec/ruby/command_line/dash_p_spec.rb
index 39827c3868..967e3796de 100644
--- a/spec/ruby/command_line/dash_p_spec.rb
+++ b/spec/ruby/command_line/dash_p_spec.rb
@@ -6,13 +6,13 @@ describe "The -p command line option" do
end
it "runs the code in loop conditional on Kernel.gets() and prints $_" do
- ruby_exe("$_ = $_.upcase", options: "-p", escape: true,
+ ruby_exe("$_ = $_.upcase", options: "-p",
args: " < #{@names}").should ==
"ALICE\nBOB\nJAMES\n"
end
it "sets $-p" do
- ruby_exe("$_ = $-p", options: "-p", escape: true,
+ ruby_exe("$_ = $-p", options: "-p",
args: " < #{@names}").should ==
"truetruetrue"
end
diff --git a/spec/ruby/command_line/dash_r_spec.rb b/spec/ruby/command_line/dash_r_spec.rb
index b29895bd26..0de9ba2e24 100644
--- a/spec/ruby/command_line/dash_r_spec.rb
+++ b/spec/ruby/command_line/dash_r_spec.rb
@@ -7,7 +7,22 @@ describe "The -r command line option" do
end
it "requires the specified file" do
- result = ruby_exe(@script, options: "-r #{@test_file}")
- result.should include(@test_file + ".rb")
+ out = ruby_exe(@script, options: "-r #{@test_file}")
+ out.should.include?("REQUIRED")
+ out.should.include?(@test_file + ".rb")
+ end
+
+ it "requires the file before parsing the main script" do
+ out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), options: "-r #{@test_file}", args: "2>&1", exit_status: 1)
+ $?.should_not.success?
+ out.should.include?("REQUIRED")
+ out.should.include?("SyntaxError")
+ end
+
+ it "does not require the file if the main script file does not exist" do
+ out = `#{ruby_exe.to_a.join(' ')} -r #{@test_file} #{fixture(__FILE__, "does_not_exist.rb")} 2>&1`
+ $?.should_not.success?
+ out.should_not.include?("REQUIRED")
+ out.should.include?("No such file or directory")
end
end
diff --git a/spec/ruby/command_line/dash_upper_c_spec.rb b/spec/ruby/command_line/dash_upper_c_spec.rb
index 761beaadab..ece1b32105 100644
--- a/spec/ruby/command_line/dash_upper_c_spec.rb
+++ b/spec/ruby/command_line/dash_upper_c_spec.rb
@@ -1,23 +1,6 @@
require_relative '../spec_helper'
+require_relative 'shared/change_directory'
-describe 'The -C command line option' do
- before :all do
- @script = fixture(__FILE__, 'dash_upper_c_script.rb')
- @tempdir = File.dirname(@script)
- end
-
- it 'changes the PWD when using a file' do
- output = ruby_exe(@script, options: "-C #{@tempdir}")
- output.should == @tempdir
- end
-
- it 'does not need a space after -C for the argument' do
- output = ruby_exe(@script, options: "-C#{@tempdir}")
- output.should == @tempdir
- end
-
- it 'changes the PWD when using -e' do
- output = ruby_exe(nil, options: "-C #{@tempdir} -e 'print Dir.pwd'")
- output.should == @tempdir
- end
+describe "The -C command line option" do
+ it_behaves_like :command_line_change_directory, "-C"
end
diff --git a/spec/ruby/command_line/dash_upper_e_spec.rb b/spec/ruby/command_line/dash_upper_e_spec.rb
index b3c6ce262b..5a83962583 100644
--- a/spec/ruby/command_line/dash_upper_e_spec.rb
+++ b/spec/ruby/command_line/dash_upper_e_spec.rb
@@ -31,6 +31,7 @@ describe "ruby -E" do
it "raises a RuntimeError if used with -U" do
ruby_exe("p 1",
options: '-Eascii:ascii -U',
- args: '2>&1').should =~ /RuntimeError/
+ args: '2>&1',
+ exit_status: 1).should =~ /RuntimeError/
end
end
diff --git a/spec/ruby/command_line/dash_upper_f_spec.rb b/spec/ruby/command_line/dash_upper_f_spec.rb
index 967acc2ece..5c10a7140d 100644
--- a/spec/ruby/command_line/dash_upper_f_spec.rb
+++ b/spec/ruby/command_line/dash_upper_f_spec.rb
@@ -6,7 +6,7 @@ describe "the -F command line option" do
end
it "specifies the field separator pattern for -a" do
- ruby_exe("puts $F[0]", options: "-naF:", escape: true,
+ ruby_exe("puts $F[0]", options: "-naF:",
args: " < #{@passwd}").should ==
"nobody\nroot\ndaemon\n"
end
diff --git a/spec/ruby/command_line/dash_upper_i_spec.rb b/spec/ruby/command_line/dash_upper_i_spec.rb
index 4cafb724e3..4005a27d23 100644
--- a/spec/ruby/command_line/dash_upper_i_spec.rb
+++ b/spec/ruby/command_line/dash_upper_i_spec.rb
@@ -6,7 +6,7 @@ describe "The -I command line option" do
end
it "adds the path to the load path ($:)" do
- ruby_exe(@script, options: "-I fixtures").should include("fixtures")
+ ruby_exe(@script, options: "-I fixtures").should.include?("fixtures")
end
it "adds the path at the front of $LOAD_PATH" do
@@ -18,16 +18,16 @@ describe "The -I command line option" do
idx.should < 2
idx.should < lines.size-1
else
- lines[0].should include("fixtures")
+ lines[0].should.include?("fixtures")
end
end
it "adds the path expanded from CWD to $LOAD_PATH" do
- ruby_exe(@script, options: "-I fixtures").lines.should include "#{Dir.pwd}/fixtures\n"
+ ruby_exe(@script, options: "-I fixtures").lines.should.include? "#{Dir.pwd}/fixtures\n"
end
it "expands a path from CWD even if it does not exist" do
- ruby_exe(@script, options: "-I not_exist/not_exist").lines.should include "#{Dir.pwd}/not_exist/not_exist\n"
+ ruby_exe(@script, options: "-I not_exist/not_exist").lines.should.include? "#{Dir.pwd}/not_exist/not_exist\n"
end
end
@@ -45,7 +45,7 @@ platform_is_not :windows do
end
it "does not expand symlinks" do
- ruby_exe(@script, options: "-I #{@symlink}").lines.should include "#{@symlink}\n"
+ ruby_exe(@script, options: "-I #{@symlink}").lines.should.include? "#{@symlink}\n"
end
end
end
diff --git a/spec/ruby/command_line/dash_upper_k_spec.rb b/spec/ruby/command_line/dash_upper_k_spec.rb
index ef1248b19c..7e71532295 100644
--- a/spec/ruby/command_line/dash_upper_k_spec.rb
+++ b/spec/ruby/command_line/dash_upper_k_spec.rb
@@ -6,24 +6,24 @@ describe 'The -K command line option' do
end
describe 'sets __ENCODING__ and Encoding.default_external' do
- it "to Encoding::ASCII_8BIT with -Ka" do
+ it "to Encoding::BINARY with -Ka" do
ruby_exe(@test_string, options: '-Ka').should ==
- [Encoding::ASCII_8BIT.name, Encoding::ASCII_8BIT.name, nil].inspect
+ [Encoding::BINARY.name, Encoding::BINARY.name, nil].inspect
end
- it "to Encoding::ASCII_8BIT with -KA" do
+ it "to Encoding::BINARY with -KA" do
ruby_exe(@test_string, options: '-KA').should ==
- [Encoding::ASCII_8BIT.name, Encoding::ASCII_8BIT.name, nil].inspect
+ [Encoding::BINARY.name, Encoding::BINARY.name, nil].inspect
end
- it "to Encoding::ASCII_8BIT with -Kn" do
+ it "to Encoding::BINARY with -Kn" do
ruby_exe(@test_string, options: '-Kn').should ==
- [Encoding::ASCII_8BIT.name, Encoding::ASCII_8BIT.name, nil].inspect
+ [Encoding::BINARY.name, Encoding::BINARY.name, nil].inspect
end
- it "to Encoding::ASCII_8BIT with -KN" do
+ it "to Encoding::BINARY with -KN" do
ruby_exe(@test_string, options: '-KN').should ==
- [Encoding::ASCII_8BIT.name, Encoding::ASCII_8BIT.name, nil].inspect
+ [Encoding::BINARY.name, Encoding::BINARY.name, nil].inspect
end
it "to Encoding::EUC_JP with -Ke" do
@@ -58,8 +58,8 @@ describe 'The -K command line option' do
end
it "ignores unknown codes" do
- locale = Encoding.find('locale')
+ external = Encoding.find('external')
ruby_exe(@test_string, options: '-KZ').should ==
- [Encoding::UTF_8.name, locale.name, nil].inspect
+ [Encoding::UTF_8.name, external.name, nil].inspect
end
end
diff --git a/spec/ruby/command_line/dash_upper_s_spec.rb b/spec/ruby/command_line/dash_upper_s_spec.rb
index 3a28fa2ad2..71c6016659 100644
--- a/spec/ruby/command_line/dash_upper_s_spec.rb
+++ b/spec/ruby/command_line/dash_upper_s_spec.rb
@@ -2,7 +2,8 @@ require_relative '../spec_helper'
describe 'The -S command line option' do
before :each do
- @path = [ENV['PATH'], fixture(__FILE__, "bin")].join(':')
+ @bin = fixture(__FILE__, "bin")
+ @path = [ENV['PATH'], @bin].join(File::PATH_SEPARATOR)
end
platform_is_not :windows do
@@ -10,20 +11,57 @@ describe 'The -S command line option' do
# and MRI shows warning when including world writable path in ENV['PATH'].
# This is why we are using /success$/ matching in the following cases.
+ it "runs launcher found in RUBYPATH, but only code after the first /\#!.*ruby.*/-ish line in target file" do
+ result = ruby_exe(nil, options: '-S hybrid_launcher.sh', env: { 'RUBYPATH' => @bin }, args: '2>&1')
+ result.should =~ /success$/
+ end
+
it "runs launcher found in PATH, but only code after the first /\#!.*ruby.*/-ish line in target file" do
result = ruby_exe(nil, options: '-S hybrid_launcher.sh', env: { 'PATH' => @path }, args: '2>&1')
result.should =~ /success$/
end
+ it "runs launcher found in RUBYPATH" do
+ result = ruby_exe(nil, options: '-S launcher.rb', env: { 'RUBYPATH' => @bin }, args: '2>&1')
+ result.should =~ /success$/
+ end
+
it "runs launcher found in PATH" do
result = ruby_exe(nil, options: '-S launcher.rb', env: { 'PATH' => @path }, args: '2>&1')
result.should =~ /success$/
end
+ it "runs launcher found in RUBYPATH and sets the exit status to 1 if it fails" do
+ result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'RUBYPATH' => @bin }, args: '2>&1', exit_status: 1)
+ result.should =~ /\bdie\b/
+ $?.exitstatus.should == 1
+ end
+
it "runs launcher found in PATH and sets the exit status to 1 if it fails" do
- result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'PATH' => @path }, args: '2>&1')
+ result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'PATH' => @path }, args: '2>&1', exit_status: 1)
result.should =~ /\bdie\b/
$?.exitstatus.should == 1
end
+
+ ruby_version_is "4.1" do
+ describe "if the script name contains separator" do
+ before(:each) do
+ @bin = File.dirname(@bin)
+ @path = [ENV['PATH'], @bin].join(File::PATH_SEPARATOR)
+ end
+
+ it "does not search launcher in RUBYPATH" do
+ result = ruby_exe(nil, options: '-S bin/launcher.rb', env: { 'RUBYPATH' => @bin }, args: '2>&1', exit_status: 1)
+ result.should =~ /LoadError/
+ $?.should_not.success?
+ end
+
+ it "does not search launcher in PATH" do
+ result = ruby_exe(nil, options: '-S bin/launcher.rb', env: { 'PATH' => @path }, args: '2>&1', exit_status: 1)
+ result.should =~ /LoadError/
+ $?.should_not.success?
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/command_line/dash_upper_u_spec.rb b/spec/ruby/command_line/dash_upper_u_spec.rb
index 2546b5b9f4..2c210eb603 100644
--- a/spec/ruby/command_line/dash_upper_u_spec.rb
+++ b/spec/ruby/command_line/dash_upper_u_spec.rb
@@ -2,42 +2,51 @@ require_relative '../spec_helper'
describe "ruby -U" do
it "sets Encoding.default_internal to UTF-8" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U').should == 'UTF-8'
+ end
+
+ it "sets Encoding.default_internal to UTF-8 when RUBYOPT is empty or only spaces" do
+ ruby_exe('p Encoding.default_internal',
+ options: '-U', env: { 'RUBYOPT' => '' }).should == "#<Encoding:UTF-8>\n"
+ ruby_exe('p Encoding.default_internal',
+ options: '-U', env: { 'RUBYOPT' => ' ' }).should == "#<Encoding:UTF-8>\n"
end
it "does nothing different if specified multiple times" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U -U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U -U').should == 'UTF-8'
end
it "is overruled by Encoding.default_internal=" do
- ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the default external encoding" do
- ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the source encoding" do
- ruby_exe("print __ENCODING__.name",
- options: '-U -KE').should == 'EUC-JP'
- ruby_exe("print __ENCODING__.name",
- options: '-KE -U').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-U -KE').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-KE -U').should == 'EUC-JP'
end
# I assume IO redirection will break on Windows...
it "raises a RuntimeError if used with -Eext:int" do
ruby_exe("p 1",
options: '-U -Eascii:ascii',
- args: '2>&1').should =~ /RuntimeError/
+ args: '2>&1',
+ exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError if used with -E:int" do
ruby_exe("p 1",
options: '-U -E:ascii',
- args: '2>&1').should =~ /RuntimeError/
+ args: '2>&1',
+ exit_status: 1).should =~ /RuntimeError/
end
end
diff --git a/spec/ruby/command_line/dash_upper_w_spec.rb b/spec/ruby/command_line/dash_upper_w_spec.rb
index 31bb976ad2..4019510d42 100644
--- a/spec/ruby/command_line/dash_upper_w_spec.rb
+++ b/spec/ruby/command_line/dash_upper_w_spec.rb
@@ -18,3 +18,27 @@ end
describe "The -W command line option with 2" do
it_behaves_like :command_line_verbose, "-W2"
end
+
+describe "The -W command line option with :deprecated" do
+ it "enables deprecation warnings" do
+ ruby_exe('p Warning[:deprecated]', options: '-W:deprecated').should == "true\n"
+ end
+end
+
+describe "The -W command line option with :no-deprecated" do
+ it "suppresses deprecation warnings" do
+ ruby_exe('p Warning[:deprecated]', options: '-w -W:no-deprecated').should == "false\n"
+ end
+end
+
+describe "The -W command line option with :experimental" do
+ it "enables experimental warnings" do
+ ruby_exe('p Warning[:experimental]', options: '-W:experimental').should == "true\n"
+ end
+end
+
+describe "The -W command line option with :no-experimental" do
+ it "suppresses experimental warnings" do
+ ruby_exe('p Warning[:experimental]', options: '-w -W:no-experimental').should == "false\n"
+ end
+end
diff --git a/spec/ruby/command_line/dash_upper_x_spec.rb b/spec/ruby/command_line/dash_upper_x_spec.rb
new file mode 100644
index 0000000000..8ef9aae4b1
--- /dev/null
+++ b/spec/ruby/command_line/dash_upper_x_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../spec_helper'
+require_relative 'shared/change_directory'
+
+describe "The -X command line option" do
+ it_behaves_like :command_line_change_directory, "-X"
+end
diff --git a/spec/ruby/command_line/dash_v_spec.rb b/spec/ruby/command_line/dash_v_spec.rb
index 04d684fdad..6a4f7d3a15 100644
--- a/spec/ruby/command_line/dash_v_spec.rb
+++ b/spec/ruby/command_line/dash_v_spec.rb
@@ -6,7 +6,10 @@ describe "The -v command line option" do
describe "when used alone" do
it "prints version and ends" do
- ruby_exe(nil, args: '-v').should include(RUBY_DESCRIPTION)
- end
+ ruby_exe(nil, args: '-v').gsub("+PRISM ", "").should.include?(RUBY_DESCRIPTION.gsub("+PRISM ", ""))
+ end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) ||
+ (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?) ||
+ (ENV['RUBY_GC_LIBRARY'] && ENV['RUBY_GC_LIBRARY'].length > 0) ||
+ (ENV['RUBY_MN_THREADS'] == '1')
end
end
diff --git a/spec/ruby/command_line/dash_w_spec.rb b/spec/ruby/command_line/dash_w_spec.rb
index 1d93e0347b..f310dca3ed 100644
--- a/spec/ruby/command_line/dash_w_spec.rb
+++ b/spec/ruby/command_line/dash_w_spec.rb
@@ -3,4 +3,8 @@ require_relative 'shared/verbose'
describe "The -w command line option" do
it_behaves_like :command_line_verbose, "-w"
+
+ it "enables both deprecated and experimental warnings" do
+ ruby_exe('p Warning[:deprecated]; p Warning[:experimental]', options: '-w').should == "true\ntrue\n"
+ end
end
diff --git a/spec/ruby/command_line/dash_x_spec.rb b/spec/ruby/command_line/dash_x_spec.rb
index ad6be23063..38f97a5ab1 100644
--- a/spec/ruby/command_line/dash_x_spec.rb
+++ b/spec/ruby/command_line/dash_x_spec.rb
@@ -9,8 +9,8 @@ describe "The -x command line option" do
it "fails when /\#!.*ruby.*/-ish line in target file is not found" do
bad_embedded_ruby = fixture __FILE__, "bin/bad_embedded_ruby.txt"
- result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1')
- result.should include "no Ruby script found in input"
+ result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1', exit_status: 1)
+ result.should.include? "no Ruby script found in input"
end
it "behaves as -x was set when non-ruby shebang is encountered on first line" do
@@ -18,6 +18,4 @@ describe "The -x command line option" do
result = ruby_exe(embedded_ruby)
result.should == "success\n"
end
-
- it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/command_line/error_message_spec.rb b/spec/ruby/command_line/error_message_spec.rb
index 5fee3ead44..157cb8969c 100644
--- a/spec/ruby/command_line/error_message_spec.rb
+++ b/spec/ruby/command_line/error_message_spec.rb
@@ -2,10 +2,15 @@ require_relative '../spec_helper'
describe "The error message caused by an exception" do
it "is not printed to stdout" do
- out = ruby_exe("this_does_not_exist", args: "2> #{File::NULL}")
- out.chomp.empty?.should == true
+ out = ruby_exe("this_does_not_exist", args: "2> #{File::NULL}", exit_status: 1)
+ out.chomp.should.empty?
- out = ruby_exe("end #syntax error", args: "2> #{File::NULL}")
- out.chomp.empty?.should == true
+ out = ruby_exe("end #syntax error", args: "2> #{File::NULL}", exit_status: 1)
+ out.chomp.should.empty?
+ end
+
+ it "is not modified with extra escaping of control characters and backslashes" do
+ out = ruby_exe('raise "\e[31mRed\e[0m error\\\\message"', args: "2>&1", exit_status: 1)
+ out.chomp.should.include?("\e[31mRed\e[0m error\\message")
end
end
diff --git a/spec/ruby/command_line/feature_spec.rb b/spec/ruby/command_line/feature_spec.rb
new file mode 100644
index 0000000000..0a3252b88d
--- /dev/null
+++ b/spec/ruby/command_line/feature_spec.rb
@@ -0,0 +1,71 @@
+require_relative '../spec_helper'
+
+describe "The --enable and --disable flags" do
+ before :all do
+ # Since some specs disable reading RUBYOPT, we instead pass its contents as :options for those specs
+ rubyopt = [ENV["RUBYOPT"]]
+ rubyopt << ENV["#{RUBY_ENGINE.upcase}OPT"] unless RUBY_ENGINE == 'ruby'
+ @rubyopt = RUBY_ENGINE == "ruby" ? "" : rubyopt.compact.join(" ")
+ end
+
+ it "can be used with gems" do
+ ruby_exe("p defined?(Gem)", options: "--enable=gems").chomp.should == "\"constant\""
+ ruby_exe("p defined?(Gem)", options: "--disable=gems").chomp.should == "nil"
+ ruby_exe("p defined?(Gem)", options: "--enable-gems").chomp.should == "\"constant\""
+ ruby_exe("p defined?(Gem)", options: "--disable-gems").chomp.should == "nil"
+ end
+
+ it "can be used with gem" do
+ ruby_exe("p defined?(Gem)", options: "--enable=gem").chomp.should == "\"constant\""
+ ruby_exe("p defined?(Gem)", options: "--disable=gem").chomp.should == "nil"
+ ruby_exe("p defined?(Gem)", options: "--enable-gem").chomp.should == "\"constant\""
+ ruby_exe("p defined?(Gem)", options: "--disable-gem").chomp.should == "nil"
+ end
+
+ it "can be used with did_you_mean" do
+ ruby_exe("p defined?(DidYouMean)", options: "--enable=did_you_mean").chomp.should == "\"constant\""
+ ruby_exe("p defined?(DidYouMean)", options: "--disable=did_you_mean").chomp.should == "nil"
+ ruby_exe("p defined?(DidYouMean)", options: "--enable-did_you_mean").chomp.should == "\"constant\""
+ ruby_exe("p defined?(DidYouMean)", options: "--disable-did_you_mean").chomp.should == "nil"
+ end
+
+ it "can be used with rubyopt" do
+ ruby_exe("p $VERBOSE", options: "--enable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true"
+ ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false"
+ ruby_exe("p $VERBOSE", options: "--enable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true"
+ ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false"
+ end
+
+ it "can be used with frozen-string-literal" do
+ ruby_exe("p 'foo'.frozen?", options: "--enable=frozen-string-literal").chomp.should == "true"
+ ruby_exe("p 'foo'.frozen?", options: "--disable=frozen-string-literal").chomp.should == "false"
+ ruby_exe("p 'foo'.frozen?", options: "--enable-frozen-string-literal").chomp.should == "true"
+ ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false"
+ end
+
+ # frequently hangs for >60s on GitHub Actions macos-latest
+ # MinGW's YJIT support seems broken
+ platform_is_not :darwin, :mingw do
+ it "can be used with all for enable" do
+ e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
+ env = {'RUBYOPT' => '-w'}
+ # Use a single variant here because it can be quite slow as it might enable jit, etc
+ ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
+ end unless defined?(RubyVM::YJIT) && defined?(RubyVM::ZJIT) && RubyVM::ZJIT.enabled? # You're not supposed to enable YJIT with --enable-all when ZJIT options are passed.
+ end
+
+ it "can be used with all for disable" do
+ e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
+ env = {'RUBYOPT' => '-w'}
+ ruby_exe(e, options: "#{@rubyopt} --disable=all", env: env).chomp.should == "[nil, nil, false, false]"
+ ruby_exe(e, options: "#{@rubyopt} --disable-all", env: env).chomp.should == "[nil, nil, false, false]"
+ end
+
+ it "prints a warning for unknown features" do
+ ruby_exe("p 14", options: "--enable=ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --enable')
+ ruby_exe("p 14", options: "--disable=ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --disable')
+ ruby_exe("p 14", options: "--enable-ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --enable')
+ ruby_exe("p 14", options: "--disable-ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --disable')
+ end
+
+end
diff --git a/spec/ruby/command_line/fixtures/backtrace.rb b/spec/ruby/command_line/fixtures/backtrace.rb
new file mode 100644
index 0000000000..99acae95c8
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/backtrace.rb
@@ -0,0 +1,35 @@
+def a
+ raise 'oops'
+end
+
+def b
+ a
+end
+
+def c
+ b
+end
+
+def d
+ c
+end
+
+arg = ARGV.first
+$stderr.puts arg
+
+case arg
+when 'full_message'
+ begin
+ d
+ rescue => exc
+ puts exc.full_message
+ end
+when 'backtrace'
+ begin
+ d
+ rescue => exc
+ puts exc.backtrace
+ end
+else
+ d
+end
diff --git a/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt b/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
index a2b7ad085f..61b946977a 100644
--- a/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
+++ b/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
@@ -1,3 +1,3 @@
-@@@This line is not value Ruby
+@@@This line is not valid Ruby
#!rub_y
puts 'success'
diff --git a/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt b/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
index c556bf0b71..0ec0f358db 100644
--- a/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
+++ b/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
@@ -1,3 +1,3 @@
-@@@This line is not value Ruby
+@@@This line is not valid Ruby
#!ruby
-puts 'success' \ No newline at end of file
+puts 'success'
diff --git a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
index 0eede2a99f..fd3249f0e5 100644
--- a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
+++ b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
-exec somehow this file
+echo 'error' && exit 1
#!ruby
puts 'success'
diff --git a/spec/ruby/command_line/fixtures/dash_upper_c_script.rb b/spec/ruby/command_line/fixtures/change_directory_script.rb
index abe244705f..abe244705f 100644
--- a/spec/ruby/command_line/fixtures/dash_upper_c_script.rb
+++ b/spec/ruby/command_line/fixtures/change_directory_script.rb
diff --git a/spec/ruby/command_line/fixtures/debug_info.rb b/spec/ruby/command_line/fixtures/debug_info.rb
index ee607910c0..f02b041920 100644
--- a/spec/ruby/command_line/fixtures/debug_info.rb
+++ b/spec/ruby/command_line/fixtures/debug_info.rb
@@ -1,4 +1,3 @@
-# frozen_string_literal: true
a = 'string'
b = a
c = b
diff --git a/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb b/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
index fa348d59e7..df4b952c46 100644
--- a/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
+++ b/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
Binary files differ
diff --git a/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb b/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
index 074092c9d9..f5547a5bae 100644
--- a/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
+++ b/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
@@ -1 +1 @@
-p "abc".object_id == "abc".object_id
+p "abc".equal?("abc")
diff --git a/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb
new file mode 100644
index 0000000000..fb84b546c0
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb
new file mode 100644
index 0000000000..381a742001
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/fixtures/string_literal_raw.rb b/spec/ruby/command_line/fixtures/string_literal_raw.rb
new file mode 100644
index 0000000000..56b1841296
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_raw.rb
@@ -0,0 +1,3 @@
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/fixtures/test_file.rb b/spec/ruby/command_line/fixtures/test_file.rb
index 961e3c0b0c..30a832299e 100644
--- a/spec/ruby/command_line/fixtures/test_file.rb
+++ b/spec/ruby/command_line/fixtures/test_file.rb
@@ -1 +1 @@
-"test file"
+puts "REQUIRED"
diff --git a/spec/ruby/command_line/frozen_strings_spec.rb b/spec/ruby/command_line/frozen_strings_spec.rb
index b2631a4c76..32ff7d0371 100644
--- a/spec/ruby/command_line/frozen_strings_spec.rb
+++ b/spec/ruby/command_line/frozen_strings_spec.rb
@@ -19,10 +19,76 @@ describe "The --enable-frozen-string-literal flag causes string literals to" do
end
end
+describe "The --disable-frozen-string-literal flag causes string literals to" do
+
+ it "produce a different object each time" do
+ ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb"), options: "--disable-frozen-string-literal").chomp.should == "false"
+ end
+
+end
+
+describe "With neither --enable-frozen-string-literal nor --disable-frozen-string-literal flag set" do
+ before do
+ # disable --enable-frozen-string-literal and --disable-frozen-string-literal passed in $RUBYOPT
+ @rubyopt = ENV["RUBYOPT"]
+ ENV["RUBYOPT"] = ""
+ end
+
+ after do
+ ENV["RUBYOPT"] = @rubyopt
+ end
+
+ it "produce a different object each time" do
+ ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb")).chomp.should == "false"
+ end
+
+ context "if file has no frozen_string_literal comment" do
+ it "produce different mutable strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:false interned:false"
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "complain about modification of produced mutable strings" do
+ -> { eval(<<~RUBY) }.should complain(/warning: literal string will be frozen in the future \(run with --debug-frozen-string-literal for more information\)/)
+ "test" << "!"
+ RUBY
+ end
+
+ it "does not complain about modification if Warning[:deprecated] is false" do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ -> { eval(<<~RUBY) }.should_not complain
+ "test" << "!"
+ RUBY
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ end
+ end
+
+ it "if file has frozen_string_literal:true comment produce same frozen strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_frozen_comment.rb")).chomp.should == "frozen:true interned:true"
+ end
+
+ it "if file has frozen_string_literal:false comment produce different mutable strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_mutable_comment.rb")).chomp.should == "frozen:false interned:false"
+ end
+end
+
describe "The --debug flag produces" do
it "debugging info on attempted frozen string modification" do
- error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1")
- error_str.should include("can't modify frozen String, created at ")
- error_str.should include("command_line/fixtures/debug_info.rb:2")
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--enable-frozen-string-literal --debug', args: "2>&1")
+ error_str.should.include?("can't modify frozen String")
+ error_str.should.include?("created at")
+ error_str.should.include?("command_line/fixtures/debug_info.rb:1")
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "debugging info on mutating chilled string" do
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '-w --debug', args: "2>&1")
+ error_str.should.include?("literal string will be frozen in the future")
+ error_str.should.include?("the string was created here")
+ error_str.should.include?("command_line/fixtures/debug_info.rb:1")
+ end
end
end
diff --git a/spec/ruby/command_line/rubylib_spec.rb b/spec/ruby/command_line/rubylib_spec.rb
index 20e9c2cf95..1bedd146e3 100644
--- a/spec/ruby/command_line/rubylib_spec.rb
+++ b/spec/ruby/command_line/rubylib_spec.rb
@@ -14,15 +14,15 @@ describe "The RUBYLIB environment variable" do
dir = tmp("rubylib/incl")
ENV["RUBYLIB"] = @pre + dir
paths = ruby_exe("puts $LOAD_PATH").lines.map(&:chomp)
- paths.should include(dir)
+ paths.should.include?(dir)
end
it "adds a File::PATH_SEPARATOR-separated list of directories to $LOAD_PATH" do
dir1, dir2 = tmp("rubylib/incl1"), tmp("rubylib/incl2")
ENV["RUBYLIB"] = @pre + "#{dir1}#{File::PATH_SEPARATOR}#{dir2}"
paths = ruby_exe("puts $LOAD_PATH").lines.map(&:chomp)
- paths.should include(dir1)
- paths.should include(dir2)
+ paths.should.include?(dir1)
+ paths.should.include?(dir2)
paths.index(dir1).should < paths.index(dir2)
end
@@ -30,6 +30,7 @@ describe "The RUBYLIB environment variable" do
dir = tmp("rubylib/incl_front")
ENV["RUBYLIB"] = @pre + dir
paths = ruby_exe("puts $LOAD_PATH").lines.map(&:chomp)
+ paths.shift if paths.first.end_with?('/gem-rehash')
if PlatformGuard.implementation? :ruby
# In a MRI checkout, $PWD and some extra -I entries end up as
# the first entries in $LOAD_PATH. So just assert that it's not last.
@@ -45,8 +46,8 @@ describe "The RUBYLIB environment variable" do
rubylib_dir = tmp("rubylib_include")
ENV["RUBYLIB"] = @pre + rubylib_dir
paths = ruby_exe("puts $LOAD_PATH", options: "-I #{dash_i_dir}").lines.map(&:chomp)
- paths.should include(dash_i_dir)
- paths.should include(rubylib_dir)
+ paths.should.include?(dash_i_dir)
+ paths.should.include?(rubylib_dir)
paths.index(dash_i_dir).should < paths.index(rubylib_dir)
end
@@ -55,14 +56,14 @@ describe "The RUBYLIB environment variable" do
rubylib_dir = tmp("rubylib_include")
ENV["RUBYLIB"] = @pre + rubylib_dir
paths = ruby_exe("puts $LOAD_PATH", env: { "RUBYOPT" => "-I#{rubyopt_dir}" }).lines.map(&:chomp)
- paths.should include(rubyopt_dir)
- paths.should include(rubylib_dir)
+ paths.should.include?(rubyopt_dir)
+ paths.should.include?(rubylib_dir)
paths.index(rubyopt_dir).should < paths.index(rubylib_dir)
end
it "keeps spaces in the value" do
ENV["RUBYLIB"] = @pre + " rubylib/incl "
out = ruby_exe("puts $LOAD_PATH")
- out.should include(" rubylib/incl ")
+ out.should.include?(" rubylib/incl ")
end
end
diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb
index 2db42f77ef..eb297cd6fe 100644
--- a/spec/ruby/command_line/rubyopt_spec.rb
+++ b/spec/ruby/command_line/rubyopt_spec.rb
@@ -11,52 +11,70 @@ describe "Processing RUBYOPT" do
it "adds the -I path to $LOAD_PATH" do
ENV["RUBYOPT"] = "-Ioptrubyspecincl"
- result = ruby_exe("puts $LOAD_PATH.grep(/byspecin/)", escape: true)
+ result = ruby_exe("puts $LOAD_PATH.grep(/byspecin/)")
result.chomp[-15..-1].should == "optrubyspecincl"
end
it "sets $DEBUG to true for '-d'" do
ENV["RUBYOPT"] = '-d'
command = %[puts "value of $DEBUG is \#{$DEBUG}"]
- result = ruby_exe(command, escape: true, args: "2>&1")
+ result = ruby_exe(command, args: "2>&1")
result.should =~ /value of \$DEBUG is true/
end
- guard -> { not CROSS_COMPILING } do
+ guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
end
it "sets $VERBOSE to true for '-w'" do
ENV["RUBYOPT"] = '-w'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
end
it "sets $VERBOSE to true for '-W'" do
ENV["RUBYOPT"] = '-W'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
end
it "sets $VERBOSE to nil for '-W0'" do
ENV["RUBYOPT"] = '-W0'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "nil"
+ ruby_exe("p $VERBOSE").chomp.should == "nil"
end
it "sets $VERBOSE to false for '-W1'" do
ENV["RUBYOPT"] = '-W1'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "false"
+ ruby_exe("p $VERBOSE").chomp.should == "false"
end
it "sets $VERBOSE to true for '-W2'" do
ENV["RUBYOPT"] = '-W2'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
+ end
+
+ it "suppresses deprecation warnings for '-W:no-deprecated'" do
+ ENV["RUBYOPT"] = '-W:no-deprecated'
+ result = ruby_exe('$; = ""', args: '2>&1')
+ result.should == ""
+ end
+
+ it "suppresses experimental warnings for '-W:no-experimental'" do
+ ENV["RUBYOPT"] = '-W:no-experimental'
+ result = ruby_exe('case 0; in a; end', args: '2>&1')
+ result.should == ""
+ end
+
+ it "suppresses deprecation and experimental warnings for '-W:no-deprecated -W:no-experimental'" do
+ ENV["RUBYOPT"] = '-W:no-deprecated -W:no-experimental'
+ result = ruby_exe('case ($; = ""); in a; end', args: '2>&1')
+ result.should == ""
end
it "requires the file for '-r'" do
@@ -67,101 +85,101 @@ describe "Processing RUBYOPT" do
it "raises a RuntimeError for '-a'" do
ENV["RUBYOPT"] = '-a'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-p'" do
ENV["RUBYOPT"] = '-p'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-n'" do
ENV["RUBYOPT"] = '-n'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-y'" do
ENV["RUBYOPT"] = '-y'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-c'" do
ENV["RUBYOPT"] = '-c'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-s'" do
ENV["RUBYOPT"] = '-s'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-h'" do
ENV["RUBYOPT"] = '-h'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '--help'" do
ENV["RUBYOPT"] = '--help'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-l'" do
ENV["RUBYOPT"] = '-l'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-S'" do
ENV["RUBYOPT"] = '-S irb'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-e'" do
ENV["RUBYOPT"] = '-e0'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-i'" do
ENV["RUBYOPT"] = '-i.bak'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-x'" do
ENV["RUBYOPT"] = '-x'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-C'" do
ENV["RUBYOPT"] = '-C'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-X'" do
ENV["RUBYOPT"] = '-X.'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-F'" do
ENV["RUBYOPT"] = '-F'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '-0'" do
ENV["RUBYOPT"] = '-0'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '--copyright'" do
ENV["RUBYOPT"] = '--copyright'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '--version'" do
ENV["RUBYOPT"] = '--version'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
it "raises a RuntimeError for '--yydebug'" do
ENV["RUBYOPT"] = '--yydebug'
- ruby_exe("", args: '2>&1').should =~ /RuntimeError/
+ ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
end
end
diff --git a/spec/ruby/command_line/shared/change_directory.rb b/spec/ruby/command_line/shared/change_directory.rb
new file mode 100644
index 0000000000..9cb6e90ac6
--- /dev/null
+++ b/spec/ruby/command_line/shared/change_directory.rb
@@ -0,0 +1,21 @@
+describe :command_line_change_directory, shared: true do
+ before :all do
+ @script = fixture(__FILE__, 'change_directory_script.rb')
+ @tempdir = File.dirname(@script)
+ end
+
+ it 'changes the PWD when using a file' do
+ output = ruby_exe(@script, options: "#{@method} #{@tempdir}")
+ output.should == @tempdir
+ end
+
+ it 'does not need a space after -C for the argument' do
+ output = ruby_exe(@script, options: "#{@method}#{@tempdir}")
+ output.should == @tempdir
+ end
+
+ it 'changes the PWD when using -e' do
+ output = ruby_exe(nil, options: "#{@method} #{@tempdir} -e 'print Dir.pwd'")
+ output.should == @tempdir
+ end
+end
diff --git a/spec/ruby/command_line/shared/verbose.rb b/spec/ruby/command_line/shared/verbose.rb
index 457fe3006a..c5c44c269e 100644
--- a/spec/ruby/command_line/shared/verbose.rb
+++ b/spec/ruby/command_line/shared/verbose.rb
@@ -4,6 +4,6 @@ describe :command_line_verbose, shared: true do
end
it "sets $VERBOSE to true" do
- ruby_exe(@script, options: @method).chomp.split.last.should == "true"
+ ruby_exe(@script, options: @method).chomp.b.split.last.should == "true"
end
end
diff --git a/spec/ruby/command_line/syntax_error_spec.rb b/spec/ruby/command_line/syntax_error_spec.rb
index f61cfe928d..88864c048e 100644
--- a/spec/ruby/command_line/syntax_error_spec.rb
+++ b/spec/ruby/command_line/syntax_error_spec.rb
@@ -2,12 +2,12 @@ require_relative '../spec_helper'
describe "The interpreter" do
it "prints an error when given a file with invalid syntax" do
- out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), args: "2>&1")
- out.should include "syntax error"
+ out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), args: "2>&1", exit_status: 1)
+ out.should.include?("SyntaxError")
end
it "prints an error when given code via -e with invalid syntax" do
- out = ruby_exe(nil, args: "-e 'a{' 2>&1")
- out.should include "syntax error"
+ out = ruby_exe(nil, args: "-e 'a{' 2>&1", exit_status: 1)
+ out.should.include?("SyntaxError")
end
end
diff --git a/spec/ruby/core/argf/argf_spec.rb b/spec/ruby/core/argf/argf_spec.rb
index af67170b98..f9468539bb 100644
--- a/spec/ruby/core/argf/argf_spec.rb
+++ b/spec/ruby/core/argf/argf_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "ARGF" do
it "is extended by the Enumerable module" do
- ARGF.should be_kind_of(Enumerable)
+ ARGF.should.is_a?(Enumerable)
end
it "is an instance of ARGF.class" do
- ARGF.should be_an_instance_of(ARGF.class)
+ ARGF.should.instance_of?(ARGF.class)
end
end
diff --git a/spec/ruby/core/argf/argv_spec.rb b/spec/ruby/core/argf/argv_spec.rb
index eab03c450f..77dfe78c21 100644
--- a/spec/ruby/core/argf/argv_spec.rb
+++ b/spec/ruby/core/argf/argv_spec.rb
@@ -7,7 +7,7 @@ describe "ARGF.argv" do
end
it "returns ARGV for the initial ARGF" do
- ARGF.argv.should equal ARGV
+ ARGF.argv.should.equal? ARGV
end
it "returns the remaining arguments to treat" do
diff --git a/spec/ruby/core/argf/binmode_spec.rb b/spec/ruby/core/argf/binmode_spec.rb
index 061145a0c7..5288e3199d 100644
--- a/spec/ruby/core/argf/binmode_spec.rb
+++ b/spec/ruby/core/argf/binmode_spec.rb
@@ -9,7 +9,7 @@ describe "ARGF.binmode" do
it "returns self" do
argf [@bin_file] do
- @argf.binmode.should equal @argf
+ @argf.binmode.should.equal? @argf
end
end
@@ -22,7 +22,7 @@ describe "ARGF.binmode" do
end
end
- it "puts alls subsequent stream reading through ARGF into binmode" do
+ it "puts all subsequent streams reading through ARGF into binmode" do
argf [@bin_file, @bin_file] do
@argf.binmode
@argf.gets.should == "test\r\n"
@@ -31,13 +31,13 @@ describe "ARGF.binmode" do
end
end
- it "sets the file's encoding to ASCII-8BIT" do
+ it "sets the file's encoding to BINARY" do
argf [@bin_file, @file1] do
@argf.binmode
- @argf.binmode?.should == true
- @argf.gets.encoding.should == Encoding::ASCII_8BIT
+ @argf.should.binmode?
+ @argf.gets.encoding.should == Encoding::BINARY
@argf.skip
- @argf.read.encoding.should == Encoding::ASCII_8BIT
+ @argf.read.encoding.should == Encoding::BINARY
end
end
end
diff --git a/spec/ruby/core/argf/bytes_spec.rb b/spec/ruby/core/argf/bytes_spec.rb
deleted file mode 100644
index 71d07fabcb..0000000000
--- a/spec/ruby/core/argf/bytes_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_byte'
-
-describe "ARGF.bytes" do
- it_behaves_like :argf_each_byte, :bytes
-end
diff --git a/spec/ruby/core/argf/chars_spec.rb b/spec/ruby/core/argf/chars_spec.rb
deleted file mode 100644
index ee79ea763b..0000000000
--- a/spec/ruby/core/argf/chars_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_char'
-
-describe "ARGF.chars" do
- it_behaves_like :argf_each_char, :chars
-end
diff --git a/spec/ruby/core/argf/close_spec.rb b/spec/ruby/core/argf/close_spec.rb
index 56faf30664..8ca7d71dc2 100644
--- a/spec/ruby/core/argf/close_spec.rb
+++ b/spec/ruby/core/argf/close_spec.rb
@@ -10,20 +10,20 @@ describe "ARGF.close" do
argf [@file1_name, @file2_name] do
io = @argf.to_io
@argf.close
- io.closed?.should be_true
+ io.closed?.should == true
end
end
it "returns self" do
argf [@file1_name, @file2_name] do
- @argf.close.should equal(@argf)
+ @argf.close.should.equal?(@argf)
end
end
it "doesn't raise an IOError if called on a closed stream" do
argf [@file1_name] do
- lambda { @argf.close }.should_not raise_error
- lambda { @argf.close }.should_not raise_error
+ -> { @argf.close }.should_not.raise
+ -> { @argf.close }.should_not.raise
end
end
end
diff --git a/spec/ruby/core/argf/closed_spec.rb b/spec/ruby/core/argf/closed_spec.rb
index e2dd6134e5..769381e8c3 100644
--- a/spec/ruby/core/argf/closed_spec.rb
+++ b/spec/ruby/core/argf/closed_spec.rb
@@ -11,7 +11,7 @@ describe "ARGF.closed?" do
stream = @argf.to_io
stream.close
- @argf.closed?.should be_true
+ @argf.closed?.should == true
stream.reopen(@argf.filename, 'r')
end
end
diff --git a/spec/ruby/core/argf/codepoints_spec.rb b/spec/ruby/core/argf/codepoints_spec.rb
deleted file mode 100644
index 7aa8a761fe..0000000000
--- a/spec/ruby/core/argf/codepoints_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_codepoint'
-
-describe "ARGF.codepoints" do
- it_behaves_like :argf_each_codepoint, :codepoints
-end
diff --git a/spec/ruby/core/argf/each_byte_spec.rb b/spec/ruby/core/argf/each_byte_spec.rb
index c5cce9f250..d9e4e7fe5b 100644
--- a/spec/ruby/core/argf/each_byte_spec.rb
+++ b/spec/ruby/core/argf/each_byte_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_byte'
describe "ARGF.each_byte" do
- it_behaves_like :argf_each_byte, :each_byte
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @bytes = []
+ File.read(@file1_name).each_byte { |b| @bytes << b }
+ File.read(@file2_name).each_byte { |b| @bytes << b }
+ end
+
+ it "yields each byte of all streams to the passed block" do
+ argf [@file1_name, @file2_name] do
+ bytes = []
+ @argf.each_byte { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_byte {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_byte
+ enum.should.instance_of?(Enumerator)
+
+ bytes = []
+ enum.each { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_byte
+ enum.should.instance_of?(Enumerator)
+
+ bytes = []
+ enum.each { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_byte.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_char_spec.rb b/spec/ruby/core/argf/each_char_spec.rb
index 724e5e6e3e..62d19b6574 100644
--- a/spec/ruby/core/argf/each_char_spec.rb
+++ b/spec/ruby/core/argf/each_char_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_char'
describe "ARGF.each_char" do
- it_behaves_like :argf_each_char, :each_char
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @chars = []
+ File.read(@file1_name).each_char { |c| @chars << c }
+ File.read(@file2_name).each_char { |c| @chars << c }
+ end
+
+ it "yields each char of all streams to the passed block" do
+ argf [@file1_name, @file2_name] do
+ chars = []
+ @argf.each_char { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_char {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_char
+ enum.should.instance_of?(Enumerator)
+
+ chars = []
+ enum.each { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_char
+ enum.should.instance_of?(Enumerator)
+
+ chars = []
+ enum.each { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_char.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_codepoint_spec.rb b/spec/ruby/core/argf/each_codepoint_spec.rb
index 0bf8bf9764..ad55785cba 100644
--- a/spec/ruby/core/argf/each_codepoint_spec.rb
+++ b/spec/ruby/core/argf/each_codepoint_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_codepoint'
describe "ARGF.each_codepoint" do
- it_behaves_like :argf_each_codepoint, :each_codepoint
+ before :each do
+ file1_name = fixture __FILE__, "file1.txt"
+ file2_name = fixture __FILE__, "file2.txt"
+ @filenames = [file1_name, file2_name]
+
+ @codepoints = File.read(file1_name).codepoints
+ @codepoints.concat File.read(file2_name).codepoints
+ end
+
+ it "is a public method" do
+ argf @filenames do
+ @argf.public_methods(false).should.include?(:each_codepoint)
+ end
+ end
+
+ it "does not require arguments" do
+ argf @filenames do
+ @argf.method(:each_codepoint).arity.should == 0
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf @filenames do
+ @argf.each_codepoint {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf @filenames do
+ @argf.each_codepoint.should.instance_of?(Enumerator)
+ end
+ end
+
+ it "yields each codepoint of all streams" do
+ argf @filenames do
+ @argf.each_codepoint.to_a.should == @codepoints
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf @filenames do
+ @argf.each_codepoint.should.instance_of?(Enumerator)
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf @filenames do
+ @argf.each_codepoint.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_line_spec.rb b/spec/ruby/core/argf/each_line_spec.rb
index 52a7e5c411..fc4d6433b8 100644
--- a/spec/ruby/core/argf/each_line_spec.rb
+++ b/spec/ruby/core/argf/each_line_spec.rb
@@ -1,6 +1,64 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_line'
describe "ARGF.each_line" do
- it_behaves_like :argf_each_line, :each_line
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @lines = File.readlines @file1_name
+ @lines += File.readlines @file2_name
+ end
+
+ it "is a public method" do
+ argf [@file1_name, @file2_name] do
+ @argf.public_methods(false).should.include?(:each_line)
+ end
+ end
+
+ it "requires multiple arguments" do
+ argf [@file1_name, @file2_name] do
+ @argf.method(:each_line).arity.should < 0
+ end
+ end
+
+ it "reads each line of files" do
+ argf [@file1_name, @file2_name] do
+ lines = []
+ @argf.each_line { |b| lines << b }
+ lines.should == @lines
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line {}.should.equal?(@argf)
+ end
+ end
+
+ describe "with a separator" do
+ it "yields each separated section of all streams" do
+ argf [@file1_name, @file2_name] do
+ @argf.send(:each_line, '.').to_a.should ==
+ (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.'))
+ end
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line.should.instance_of?(Enumerator)
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_spec.rb b/spec/ruby/core/argf/each_spec.rb
index 5742ba43bd..25f60b31d2 100644
--- a/spec/ruby/core/argf/each_spec.rb
+++ b/spec/ruby/core/argf/each_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_line'
describe "ARGF.each" do
- it_behaves_like :argf_each_line, :each
+ it "is an alias of ARGF.each_line" do
+ ARGF.method(:each).should == ARGF.method(:each_line)
+ end
end
diff --git a/spec/ruby/core/argf/eof_spec.rb b/spec/ruby/core/argf/eof_spec.rb
index 518f6e566e..940d104d69 100644
--- a/spec/ruby/core/argf/eof_spec.rb
+++ b/spec/ruby/core/argf/eof_spec.rb
@@ -1,10 +1,32 @@
require_relative '../../spec_helper'
-require_relative 'shared/eof'
describe "ARGF.eof" do
- it_behaves_like :argf_eof, :eof
+ it "is an alias of ARGF.eof?" do
+ ARGF.method(:eof).should == ARGF.method(:eof?)
+ end
end
describe "ARGF.eof?" do
- it_behaves_like :argf_eof, :eof?
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns true when reaching the end of a file" do
+ argf [@file1, @file2] do
+ result = []
+ while @argf.gets
+ result << @argf.eof?
+ end
+ result.should == [false, true, false, true]
+ end
+ end
+
+ it "raises IOError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.eof? }.should.raise(IOError)
+ end
+ end
end
diff --git a/spec/ruby/core/argf/filename_spec.rb b/spec/ruby/core/argf/filename_spec.rb
index 7c0446269d..f4b6e922c6 100644
--- a/spec/ruby/core/argf/filename_spec.rb
+++ b/spec/ruby/core/argf/filename_spec.rb
@@ -1,6 +1,30 @@
require_relative '../../spec_helper'
-require_relative 'shared/filename'
describe "ARGF.filename" do
- it_behaves_like :argf_filename, :filename
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns the current file name on each file" do
+ argf [@file1, @file2] do
+ result = []
+ # returns first current file even when not yet open
+ result << @argf.filename
+ result << @argf.filename while @argf.gets
+ # returns last current file even when closed
+ result << @argf.filename
+
+ result.map! { |f| File.expand_path(f) }
+ result.should == [@file1, @file1, @file1, @file2, @file2, @file2]
+ end
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "sets the $FILENAME global variable with the current file name on each file" do
+ script = fixture __FILE__, "filename.rb"
+ out = ruby_exe(script, args: [@file1, @file2])
+ out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n"
+ end
end
diff --git a/spec/ruby/core/argf/fileno_spec.rb b/spec/ruby/core/argf/fileno_spec.rb
index 29d50c3582..99245f043c 100644
--- a/spec/ruby/core/argf/fileno_spec.rb
+++ b/spec/ruby/core/argf/fileno_spec.rb
@@ -1,6 +1,26 @@
require_relative '../../spec_helper'
-require_relative 'shared/fileno'
describe "ARGF.fileno" do
- it_behaves_like :argf_fileno, :fileno
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns the current file number on each file" do
+ argf [@file1, @file2] do
+ result = []
+ # returns first current file even when not yet open
+ result << @argf.fileno while @argf.gets
+ # returns last current file even when closed
+ result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer]
+ end
+ end
+
+ it "raises an ArgumentError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.fileno }.should.raise(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/argf/gets_spec.rb b/spec/ruby/core/argf/gets_spec.rb
index 5863147ec8..cc7673b190 100644
--- a/spec/ruby/core/argf/gets_spec.rb
+++ b/spec/ruby/core/argf/gets_spec.rb
@@ -26,25 +26,23 @@ describe "ARGF.gets" do
end
end
- with_feature :encoding do
- before :each do
- @external = Encoding.default_external
- @internal = Encoding.default_internal
+ before :each do
+ @external = Encoding.default_external
+ @internal = Encoding.default_internal
- Encoding.default_external = Encoding::UTF_8
- Encoding.default_internal = nil
- end
+ Encoding.default_external = Encoding::UTF_8
+ Encoding.default_internal = nil
+ end
- after :each do
- Encoding.default_external = @external
- Encoding.default_internal = @internal
- end
+ after :each do
+ Encoding.default_external = @external
+ Encoding.default_internal = @internal
+ end
- it "reads the contents of the file with default encoding" do
- Encoding.default_external = Encoding::US_ASCII
- argf [@file1_name, @file2_name] do
- @argf.gets.encoding.should == Encoding::US_ASCII
- end
+ it "reads the contents of the file with default encoding" do
+ Encoding.default_external = Encoding::US_ASCII
+ argf [@file1_name, @file2_name] do
+ @argf.gets.encoding.should == Encoding::US_ASCII
end
end
diff --git a/spec/ruby/core/argf/inspect_spec.rb b/spec/ruby/core/argf/inspect_spec.rb
new file mode 100644
index 0000000000..df0e3ba8dc
--- /dev/null
+++ b/spec/ruby/core/argf/inspect_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+
+describe "ARGF.inspect" do
+ it "is an alias of ARGF.to_s" do
+ ARGF.method(:inspect).should == ARGF.method(:to_s)
+ end
+end
diff --git a/spec/ruby/core/argf/lines_spec.rb b/spec/ruby/core/argf/lines_spec.rb
deleted file mode 100644
index 6ca6ff1256..0000000000
--- a/spec/ruby/core/argf/lines_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_line'
-
-describe "ARGF.lines" do
- it_behaves_like :argf_each_line, :lines
-end
diff --git a/spec/ruby/core/argf/path_spec.rb b/spec/ruby/core/argf/path_spec.rb
index 7120f7d0e3..2f7b91999f 100644
--- a/spec/ruby/core/argf/path_spec.rb
+++ b/spec/ruby/core/argf/path_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/filename'
describe "ARGF.path" do
- it_behaves_like :argf_filename, :path
+ it "is an alias of ARGF.filename" do
+ ARGF.method(:path).should == ARGF.method(:filename)
+ end
end
diff --git a/spec/ruby/core/argf/pos_spec.rb b/spec/ruby/core/argf/pos_spec.rb
index fb3f25b945..1ff16e4f17 100644
--- a/spec/ruby/core/argf/pos_spec.rb
+++ b/spec/ruby/core/argf/pos_spec.rb
@@ -1,8 +1,35 @@
require_relative '../../spec_helper'
-require_relative 'shared/pos'
describe "ARGF.pos" do
- it_behaves_like :argf_pos, :pos
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ it "gives the correct position for each read operation" do
+ argf [@file1, @file2] do
+ size1 = File.size(@file1)
+ size2 = File.size(@file2)
+
+ @argf.read(2)
+ @argf.pos.should == 2
+ @argf.read(size1-2)
+ @argf.pos.should == size1
+ @argf.read(6)
+ @argf.pos.should == 6
+ @argf.rewind
+ @argf.pos.should == 0
+ @argf.read(size2)
+ @argf.pos.should == size2
+ end
+ end
+
+ it "raises an ArgumentError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.pos }.should.raise(ArgumentError)
+ end
+ end
end
describe "ARGF.pos=" do
diff --git a/spec/ruby/core/argf/read_nonblock_spec.rb b/spec/ruby/core/argf/read_nonblock_spec.rb
index 466264119f..5c6bd52d80 100644
--- a/spec/ruby/core/argf/read_nonblock_spec.rb
+++ b/spec/ruby/core/argf/read_nonblock_spec.rb
@@ -64,9 +64,9 @@ platform_is_not :windows do
it 'raises IO::EAGAINWaitReadable when empty' do
argf ['-'] do
- lambda {
+ -> {
@argf.read_nonblock(4)
- }.should raise_error(IO::EAGAINWaitReadable)
+ }.should.raise(IO::EAGAINWaitReadable)
end
end
diff --git a/spec/ruby/core/argf/read_spec.rb b/spec/ruby/core/argf/read_spec.rb
index b889605572..bbeef95456 100644
--- a/spec/ruby/core/argf/read_spec.rb
+++ b/spec/ruby/core/argf/read_spec.rb
@@ -62,26 +62,24 @@ describe "ARGF.read" do
end
end
- with_feature :encoding do
- before :each do
- @external = Encoding.default_external
- @internal = Encoding.default_internal
+ before :each do
+ @external = Encoding.default_external
+ @internal = Encoding.default_internal
- Encoding.default_external = Encoding::UTF_8
- Encoding.default_internal = nil
- end
+ Encoding.default_external = Encoding::UTF_8
+ Encoding.default_internal = nil
+ end
- after :each do
- Encoding.default_external = @external
- Encoding.default_internal = @internal
- end
+ after :each do
+ Encoding.default_external = @external
+ Encoding.default_internal = @internal
+ end
- it "reads the contents of the file with default encoding" do
- Encoding.default_external = Encoding::US_ASCII
- argf [@file1_name, @file2_name] do
- @argf.read.encoding.should == Encoding::US_ASCII
- end
+ it "reads the contents of the file with default encoding" do
+ Encoding.default_external = Encoding::US_ASCII
+ argf [@file1_name, @file2_name] do
+ @argf.read.encoding.should == Encoding::US_ASCII
end
end
end
diff --git a/spec/ruby/core/argf/readchar_spec.rb b/spec/ruby/core/argf/readchar_spec.rb
index bd3bfd28ae..63632721ec 100644
--- a/spec/ruby/core/argf/readchar_spec.rb
+++ b/spec/ruby/core/argf/readchar_spec.rb
@@ -13,7 +13,7 @@ describe "ARGF.readchar" do
it "raises EOFError when end of stream reached" do
argf [@file1, @file2] do
- lambda { while @argf.readchar; end }.should raise_error(EOFError)
+ -> { while @argf.readchar; end }.should.raise(EOFError)
end
end
end
diff --git a/spec/ruby/core/argf/readline_spec.rb b/spec/ruby/core/argf/readline_spec.rb
index e196274068..8c23549b1b 100644
--- a/spec/ruby/core/argf/readline_spec.rb
+++ b/spec/ruby/core/argf/readline_spec.rb
@@ -17,7 +17,7 @@ describe "ARGF.readline" do
it "raises an EOFError when reaching end of files" do
argf [@file1, @file2] do
- lambda { while @argf.readline; end }.should raise_error(EOFError)
+ -> { while @argf.readline; end }.should.raise(EOFError)
end
end
end
diff --git a/spec/ruby/core/argf/readlines_spec.rb b/spec/ruby/core/argf/readlines_spec.rb
index 30be936dab..156bb6a33f 100644
--- a/spec/ruby/core/argf/readlines_spec.rb
+++ b/spec/ruby/core/argf/readlines_spec.rb
@@ -1,6 +1,24 @@
require_relative '../../spec_helper'
-require_relative 'shared/readlines'
describe "ARGF.readlines" do
- it_behaves_like :argf_readlines, :readlines
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+
+ @lines = File.readlines(@file1)
+ @lines += File.readlines(@file2)
+ end
+
+ it "reads all lines of all files" do
+ argf [@file1, @file2] do
+ @argf.readlines.should == @lines
+ end
+ end
+
+ it "returns an empty Array when end of stream reached" do
+ argf [@file1, @file2] do
+ @argf.read
+ @argf.readlines.should == []
+ end
+ end
end
diff --git a/spec/ruby/core/argf/readpartial_spec.rb b/spec/ruby/core/argf/readpartial_spec.rb
index 4e697683dc..9f04e72cc2 100644
--- a/spec/ruby/core/argf/readpartial_spec.rb
+++ b/spec/ruby/core/argf/readpartial_spec.rb
@@ -16,7 +16,7 @@ describe "ARGF.readpartial" do
it "raises an ArgumentError if called without a maximum read length" do
argf [@file1_name] do
- lambda { @argf.readpartial }.should raise_error(ArgumentError)
+ -> { @argf.readpartial }.should.raise(ArgumentError)
end
end
@@ -29,7 +29,7 @@ describe "ARGF.readpartial" do
it "clears output buffer even if EOFError is raised because @argf is at end" do
begin
- output = "to be cleared"
+ output = +"to be cleared"
argf [@file1_name] do
@argf.read
@@ -59,8 +59,8 @@ describe "ARGF.readpartial" do
@argf.readpartial(@file1.size)
@argf.readpartial(1)
@argf.readpartial(@file2.size)
- lambda { @argf.readpartial(1) }.should raise_error(EOFError)
- lambda { @argf.readpartial(1) }.should raise_error(EOFError)
+ -> { @argf.readpartial(1) }.should.raise(EOFError)
+ -> { @argf.readpartial(1) }.should.raise(EOFError)
end
end
@@ -69,7 +69,7 @@ describe "ARGF.readpartial" do
print ARGF.readpartial(#{@stdin.size})
ARGF.readpartial(1) rescue print $!.class
STR
- stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true)
+ stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}")
stdin.should == @stdin + "EOFError"
end
end
diff --git a/spec/ruby/core/argf/rewind_spec.rb b/spec/ruby/core/argf/rewind_spec.rb
index fcb2e81a3e..9255f790fe 100644
--- a/spec/ruby/core/argf/rewind_spec.rb
+++ b/spec/ruby/core/argf/rewind_spec.rb
@@ -33,7 +33,7 @@ describe "ARGF.rewind" do
it "raises an ArgumentError when end of stream reached" do
argf [@file1_name, @file2_name] do
@argf.read
- lambda { @argf.rewind }.should raise_error(ArgumentError)
+ -> { @argf.rewind }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/argf/seek_spec.rb b/spec/ruby/core/argf/seek_spec.rb
index c983c0cb5a..c1ea1ea438 100644
--- a/spec/ruby/core/argf/seek_spec.rb
+++ b/spec/ruby/core/argf/seek_spec.rb
@@ -57,7 +57,7 @@ describe "ARGF.seek" do
it "takes at least one argument (offset)" do
argf [@file1_name] do
- lambda { @argf.seek }.should raise_error(ArgumentError)
+ -> { @argf.seek }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/argf/shared/each_byte.rb b/spec/ruby/core/argf/shared/each_byte.rb
deleted file mode 100644
index 6b1dc1dae2..0000000000
--- a/spec/ruby/core/argf/shared/each_byte.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_byte, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @bytes = []
- File.read(@file1_name).each_byte { |b| @bytes << b }
- File.read(@file2_name).each_byte { |b| @bytes << b }
- end
-
- it "yields each byte of all streams to the passed block" do
- argf [@file1_name, @file2_name] do
- bytes = []
- @argf.send(@method) { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- bytes = []
- enum.each { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- bytes = []
- enum.each { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_char.rb b/spec/ruby/core/argf/shared/each_char.rb
deleted file mode 100644
index 9e333ecc5b..0000000000
--- a/spec/ruby/core/argf/shared/each_char.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_char, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @chars = []
- File.read(@file1_name).each_char { |c| @chars << c }
- File.read(@file2_name).each_char { |c| @chars << c }
- end
-
- it "yields each char of all streams to the passed block" do
- argf [@file1_name, @file2_name] do
- chars = []
- @argf.send(@method) { |c| chars << c }
- chars.should == @chars
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- chars = []
- enum.each { |c| chars << c }
- chars.should == @chars
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- chars = []
- enum.each { |c| chars << c }
- chars.should == @chars
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_codepoint.rb b/spec/ruby/core/argf/shared/each_codepoint.rb
deleted file mode 100644
index e2a2dfff46..0000000000
--- a/spec/ruby/core/argf/shared/each_codepoint.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_codepoint, shared: true do
- before :each do
- file1_name = fixture __FILE__, "file1.txt"
- file2_name = fixture __FILE__, "file2.txt"
- @filenames = [file1_name, file2_name]
-
- @codepoints = File.read(file1_name).codepoints
- @codepoints.concat File.read(file2_name).codepoints
- end
-
- it "is a public method" do
- argf @filenames do
- @argf.public_methods(false).should include(@method)
- end
- end
-
- it "does not require arguments" do
- argf @filenames do
- @argf.method(@method).arity.should == 0
- end
- end
-
- it "returns self when passed a block" do
- argf @filenames do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf @filenames do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- it "yields each codepoint of all streams" do
- argf @filenames do
- @argf.send(@method).to_a.should == @codepoints
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf @filenames do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf @filenames do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_line.rb b/spec/ruby/core/argf/shared/each_line.rb
deleted file mode 100644
index c0ef77dc54..0000000000
--- a/spec/ruby/core/argf/shared/each_line.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-describe :argf_each_line, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @lines = File.readlines @file1_name
- @lines += File.readlines @file2_name
- end
-
- it "is a public method" do
- argf [@file1_name, @file2_name] do
- @argf.public_methods(false).should include(@method)
- end
- end
-
- it "requires multiple arguments" do
- argf [@file1_name, @file2_name] do
- @argf.method(@method).arity.should < 0
- end
- end
-
- it "reads each line of files" do
- argf [@file1_name, @file2_name] do
- lines = []
- @argf.send(@method) { |b| lines << b }
- lines.should == @lines
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- describe "with a separator" do
- it "yields each separated section of all streams" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method, '.').to_a.should ==
- (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.'))
- end
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/eof.rb b/spec/ruby/core/argf/shared/eof.rb
deleted file mode 100644
index bba18ede50..0000000000
--- a/spec/ruby/core/argf/shared/eof.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-describe :argf_eof, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns true when reaching the end of a file" do
- argf [@file1, @file2] do
- result = []
- while @argf.gets
- result << @argf.send(@method)
- end
- result.should == [false, true, false, true]
- end
- end
-
- it "raises IOError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- lambda { @argf.send(@method) }.should raise_error(IOError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/filename.rb b/spec/ruby/core/argf/shared/filename.rb
deleted file mode 100644
index f47c673dc0..0000000000
--- a/spec/ruby/core/argf/shared/filename.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-describe :argf_filename, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns the current file name on each file" do
- argf [@file1, @file2] do
- result = []
- # returns first current file even when not yet open
- result << @argf.send(@method)
- result << @argf.send(@method) while @argf.gets
- # returns last current file even when closed
- result << @argf.send(@method)
-
- result.map! { |f| File.expand_path(f) }
- result.should == [@file1, @file1, @file1, @file2, @file2, @file2]
- end
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "sets the $FILENAME global variable with the current file name on each file" do
- script = fixture __FILE__, "filename.rb"
- out = ruby_exe(script, args: [@file1, @file2])
- out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n"
- end
-end
diff --git a/spec/ruby/core/argf/shared/fileno.rb b/spec/ruby/core/argf/shared/fileno.rb
deleted file mode 100644
index 891e250ad9..0000000000
--- a/spec/ruby/core/argf/shared/fileno.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-describe :argf_fileno, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns the current file number on each file" do
- argf [@file1, @file2] do
- result = []
- # returns first current file even when not yet open
- result << @argf.send(@method) while @argf.gets
- # returns last current file even when closed
- result.map { |d| d.class }.should == [Fixnum, Fixnum, Fixnum, Fixnum]
- end
- end
-
- it "raises an ArgumentError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- lambda { @argf.send(@method) }.should raise_error(ArgumentError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/getc.rb b/spec/ruby/core/argf/shared/getc.rb
index 8be39c60b6..d63372d9d7 100644
--- a/spec/ruby/core/argf/shared/getc.rb
+++ b/spec/ruby/core/argf/shared/getc.rb
@@ -9,7 +9,7 @@ describe :argf_getc, shared: true do
it "reads each char of files" do
argf [@file1, @file2] do
- chars = ""
+ chars = +""
@chars.size.times { chars << @argf.send(@method) }
chars.should == @chars
end
diff --git a/spec/ruby/core/argf/shared/pos.rb b/spec/ruby/core/argf/shared/pos.rb
deleted file mode 100644
index f7184f3d7c..0000000000
--- a/spec/ruby/core/argf/shared/pos.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-describe :argf_pos, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- it "gives the correct position for each read operation" do
- argf [@file1, @file2] do
- size1 = File.size(@file1)
- size2 = File.size(@file2)
-
- @argf.read(2)
- @argf.send(@method).should == 2
- @argf.read(size1-2)
- @argf.send(@method).should == size1
- @argf.read(6)
- @argf.send(@method).should == 6
- @argf.rewind
- @argf.send(@method).should == 0
- @argf.read(size2)
- @argf.send(@method).should == size2
- end
- end
-
- it "raises an ArgumentError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- lambda { @argf.send(@method) }.should raise_error(ArgumentError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/read.rb b/spec/ruby/core/argf/shared/read.rb
index fe903983c0..e76d022139 100644
--- a/spec/ruby/core/argf/shared/read.rb
+++ b/spec/ruby/core/argf/shared/read.rb
@@ -15,7 +15,7 @@ describe :argf_read, shared: true do
it "treats second argument as an output buffer" do
argf [@file1_name] do
- buffer = ""
+ buffer = +""
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
@@ -23,7 +23,7 @@ describe :argf_read, shared: true do
it "clears output buffer before appending to it" do
argf [@file1_name] do
- buffer = "to be cleared"
+ buffer = +"to be cleared"
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
diff --git a/spec/ruby/core/argf/shared/readlines.rb b/spec/ruby/core/argf/shared/readlines.rb
deleted file mode 100644
index 505fa94acb..0000000000
--- a/spec/ruby/core/argf/shared/readlines.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-describe :argf_readlines, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
-
- @lines = File.readlines(@file1)
- @lines += File.readlines(@file2)
- end
-
- it "reads all lines of all files" do
- argf [@file1, @file2] do
- @argf.send(@method).should == @lines
- end
- end
-
- it "returns an empty Array when end of stream reached" do
- argf [@file1, @file2] do
- @argf.read
- @argf.send(@method).should == []
- end
- end
-end
diff --git a/spec/ruby/core/argf/skip_spec.rb b/spec/ruby/core/argf/skip_spec.rb
index 89b7146e3a..bb1c0ae110 100644
--- a/spec/ruby/core/argf/skip_spec.rb
+++ b/spec/ruby/core/argf/skip_spec.rb
@@ -37,6 +37,6 @@ describe "ARGF.skip" do
# which as a side-effect calls argf.file which will initialize
# internals of ARGF enough for this to work.
it "has no effect when nothing has been processed yet" do
- lambda { ARGF.class.new(@file1_name).skip }.should_not raise_error
+ -> { ARGF.class.new(@file1_name).skip }.should_not.raise
end
end
diff --git a/spec/ruby/core/argf/tell_spec.rb b/spec/ruby/core/argf/tell_spec.rb
index 16d9f29920..bb28df74a2 100644
--- a/spec/ruby/core/argf/tell_spec.rb
+++ b/spec/ruby/core/argf/tell_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/pos'
describe "ARGF.tell" do
- it_behaves_like :argf_pos, :tell
+ it "is an alias of ARGF.pos" do
+ ARGF.method(:tell).should == ARGF.method(:pos)
+ end
end
diff --git a/spec/ruby/core/argf/to_a_spec.rb b/spec/ruby/core/argf/to_a_spec.rb
index b17a93db33..d95dc732ec 100644
--- a/spec/ruby/core/argf/to_a_spec.rb
+++ b/spec/ruby/core/argf/to_a_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/readlines'
describe "ARGF.to_a" do
- it_behaves_like :argf_readlines, :to_a
+ it "is an alias of ARGF.readlines" do
+ ARGF.method(:to_a).should == ARGF.method(:readlines)
+ end
end
diff --git a/spec/ruby/core/argf/to_i_spec.rb b/spec/ruby/core/argf/to_i_spec.rb
index 2183de6cd4..e8df378f4e 100644
--- a/spec/ruby/core/argf/to_i_spec.rb
+++ b/spec/ruby/core/argf/to_i_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/fileno'
describe "ARGF.to_i" do
- it_behaves_like :argf_fileno, :to_i
+ it "is an alias of ARGF.fileno" do
+ ARGF.method(:to_i).should == ARGF.method(:fileno)
+ end
end
diff --git a/spec/ruby/core/argf/to_io_spec.rb b/spec/ruby/core/argf/to_io_spec.rb
index 062383d291..ab5de58bcf 100644
--- a/spec/ruby/core/argf/to_io_spec.rb
+++ b/spec/ruby/core/argf/to_io_spec.rb
@@ -15,7 +15,7 @@ describe "ARGF.to_io" do
result << @argf.to_io
end
- result.each { |io| io.should be_kind_of(IO) }
+ result.each { |io| io.should.is_a?(IO) }
result[0].should == result[1]
result[2].should == result[3]
end
diff --git a/spec/ruby/core/array/all_spec.rb b/spec/ruby/core/array/all_spec.rb
new file mode 100644
index 0000000000..680e8c26fa
--- /dev/null
+++ b/spec/ruby/core/array/all_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#all?" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :all?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].all?(/bar/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/allocate_spec.rb b/spec/ruby/core/array/allocate_spec.rb
index a1800e7e16..c9eceef590 100644
--- a/spec/ruby/core/array/allocate_spec.rb
+++ b/spec/ruby/core/array/allocate_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Array.allocate" do
it "returns an instance of Array" do
ary = Array.allocate
- ary.should be_an_instance_of(Array)
+ ary.should.instance_of?(Array)
end
it "returns a fully-formed instance of Array" do
@@ -14,6 +14,6 @@ describe "Array.allocate" do
end
it "does not accept any arguments" do
- lambda { Array.allocate(1) }.should raise_error(ArgumentError)
+ -> { Array.allocate(1) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/any_spec.rb b/spec/ruby/core/array/any_spec.rb
index 2fa5353e99..b51ce62f0f 100644
--- a/spec/ruby/core/array/any_spec.rb
+++ b/spec/ruby/core/array/any_spec.rb
@@ -1,24 +1,28 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#any?" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
it "is false if the array is empty" do
empty_array = []
- empty_array.any?.should == false
+ empty_array.should_not.any?
end
it "is false if the array is not empty, but all the members of the array are falsy" do
falsy_array = [false, nil, false]
- falsy_array.any?.should == false
+ falsy_array.should_not.any?
end
it "is true if the array has any truthy members" do
not_empty_array = ['anything', nil]
- not_empty_array.any?.should == true
+ not_empty_array.should.any?
end
end
describe 'with a block given' do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :any?
+
it 'is false if the array is empty' do
empty_array = []
empty_array.any? {|v| 1 == 1 }.should == false
@@ -34,4 +38,12 @@ describe "Array#any?" do
array_with_members.any? {|v| v == 42 }.should == false
end
end
+
+ describe 'when given a pattern argument' do
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].any?(/bar/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+ end
end
diff --git a/spec/ruby/core/array/append_spec.rb b/spec/ruby/core/array/append_spec.rb
index 08ea814d89..5480d9f65e 100644
--- a/spec/ruby/core/array/append_spec.rb
+++ b/spec/ruby/core/array/append_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/push'
describe "Array#<<" do
it "pushes the object onto the end of the array" do
@@ -10,8 +9,8 @@ describe "Array#<<" do
it "returns self to allow chaining" do
a = []
b = a
- (a << 1).should equal(b)
- (a << 2 << 3).should equal(b)
+ (a << 1).should.equal?(b)
+ (a << 2 << 3).should.equal?(b)
end
it "correctly resizes the Array" do
@@ -30,13 +29,13 @@ describe "Array#<<" do
a.should == [:foo]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array << 5 }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array << 5 }.should.raise(FrozenError)
end
end
-ruby_version_is "2.5" do
- describe "Array#append" do
- it_behaves_like :array_push, :append
+describe "Array#append" do
+ it "is an alias of Array#push" do
+ Array.instance_method(:append).should == Array.instance_method(:push)
end
end
diff --git a/spec/ruby/core/array/assoc_spec.rb b/spec/ruby/core/array/assoc_spec.rb
index f8479d763c..a5026cf5d4 100644
--- a/spec/ruby/core/array/assoc_spec.rb
+++ b/spec/ruby/core/array/assoc_spec.rb
@@ -6,18 +6,18 @@ describe "Array#assoc" do
s1 = ["colors", "red", "blue", "green"]
s2 = [:letters, "a", "b", "c"]
s3 = [4]
- s4 = ["colors", "cyan", "yellow", "magenda"]
+ s4 = ["colors", "cyan", "yellow", "magenta"]
s5 = [:letters, "a", "i", "u"]
s_nil = [nil, nil]
a = [s1, s2, s3, s4, s5, s_nil]
- a.assoc(s1.first).should equal(s1)
- a.assoc(s2.first).should equal(s2)
- a.assoc(s3.first).should equal(s3)
- a.assoc(s4.first).should equal(s1)
- a.assoc(s5.first).should equal(s2)
- a.assoc(s_nil.first).should equal(s_nil)
- a.assoc(4).should equal(s3)
- a.assoc("key not in array").should be_nil
+ a.assoc(s1.first).should.equal?(s1)
+ a.assoc(s2.first).should.equal?(s2)
+ a.assoc(s3.first).should.equal?(s3)
+ a.assoc(s4.first).should.equal?(s1)
+ a.assoc(s5.first).should.equal?(s2)
+ a.assoc(s_nil.first).should.equal?(s_nil)
+ a.assoc(4).should.equal?(s3)
+ a.assoc("key not in array").should == nil
end
it "calls == on first element of each array" do
@@ -25,16 +25,28 @@ describe "Array#assoc" do
key2 = mock('key2')
items = [['not it', 1], [ArraySpecs::AssocKey.new, 2], ['na', 3]]
- items.assoc(key1).should equal(items[1])
- items.assoc(key2).should be_nil
+ items.assoc(key1).should.equal?(items[1])
+ items.assoc(key2).should == nil
end
it "ignores any non-Array elements" do
- [1, 2, 3].assoc(2).should be_nil
+ [1, 2, 3].assoc(2).should == nil
s1 = [4]
s2 = [5, 4, 3]
a = ["foo", [], s1, s2, nil, []]
- a.assoc(s1.first).should equal(s1)
- a.assoc(s2.first).should equal(s2)
+ a.assoc(s1.first).should.equal?(s1)
+ a.assoc(s2.first).should.equal?(s2)
+ end
+
+ it "calls to_ary on non-array elements" do
+ s1 = [1, 2]
+ s2 = ArraySpecs::ArrayConvertible.new(2, 3)
+ a = [s1, s2]
+
+ s1.should_not_receive(:to_ary)
+ a.assoc(s1.first).should.equal?(s1)
+
+ a.assoc(2).should == [2, 3]
+ s2.called.should.equal?(:to_ary)
end
end
diff --git a/spec/ruby/core/array/at_spec.rb b/spec/ruby/core/array/at_spec.rb
index d237c9508a..3c7c99fdff 100644
--- a/spec/ruby/core/array/at_spec.rb
+++ b/spec/ruby/core/array/at_spec.rb
@@ -47,10 +47,10 @@ describe "Array#at" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- lambda { [].at("cat") }.should raise_error(TypeError)
+ -> { [].at("cat") }.should.raise(TypeError)
end
it "raises an ArgumentError when 2 or more arguments are passed" do
- lambda { [:a, :b].at(0,1) }.should raise_error(ArgumentError)
+ -> { [:a, :b].at(0,1) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/bsearch_index_spec.rb b/spec/ruby/core/array/bsearch_index_spec.rb
index a075d06ed3..e1d5eb66bb 100644
--- a/spec/ruby/core/array/bsearch_index_spec.rb
+++ b/spec/ruby/core/array/bsearch_index_spec.rb
@@ -8,11 +8,11 @@ describe "Array#bsearch_index" do
end
it "returns an Enumerator" do
- @enum.should be_an_instance_of(Enumerator)
+ @enum.should.instance_of?(Enumerator)
end
it "returns an Enumerator with unknown size" do
- @enum.size.should be_nil
+ @enum.size.should == nil
end
it "returns index of element when block condition is satisfied" do
@@ -21,11 +21,11 @@ describe "Array#bsearch_index" do
end
it "raises a TypeError when block returns a String" do
- lambda { [1, 2, 3].bsearch_index { "not ok" } }.should raise_error(TypeError)
+ -> { [1, 2, 3].bsearch_index { "not ok" } }.should.raise(TypeError)
end
it "returns nil when block is empty" do
- [1, 2, 3].bsearch_index {}.should be_nil
+ [1, 2, 3].bsearch_index {}.should == nil
end
context "minimum mode" do
@@ -40,8 +40,8 @@ describe "Array#bsearch_index" do
end
it "returns nil when block condition is never satisfied" do
- @array.bsearch_index { false }.should be_nil
- @array.bsearch_index { |x| x >= 100 }.should be_nil
+ @array.bsearch_index { false }.should == nil
+ @array.bsearch_index { |x| x >= 100 }.should == nil
end
end
@@ -51,34 +51,30 @@ describe "Array#bsearch_index" do
end
it "returns the index of any matched elements where element is between 4 <= x < 8" do
- [1, 2].should include(@array.bsearch_index { |x| 1 - x / 4 })
+ [1, 2].should.include?(@array.bsearch_index { |x| 1 - x / 4 })
end
it "returns the index of any matched elements where element is between 8 <= x < 10" do
- @array.bsearch_index { |x| 4 - x / 2 }.should be_nil
+ @array.bsearch_index { |x| 4 - x / 2 }.should == nil
end
it "returns nil when block never returns 0" do
- @array.bsearch_index { |x| 1 }.should be_nil
- @array.bsearch_index { |x| -1 }.should be_nil
- end
-
- it "returns the middle element when block always returns zero" do
- @array.bsearch_index { |x| 0 }.should == 2
+ @array.bsearch_index { |x| 1 }.should == nil
+ @array.bsearch_index { |x| -1 }.should == nil
end
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
- [1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
+ [1, 2].should.include?(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
end
it "returns nil when block never returns 0" do
- @array.bsearch_index { |x| 1 * (2**100) }.should be_nil
- @array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
+ @array.bsearch_index { |x| 1 * (2**100) }.should == nil
+ @array.bsearch_index { |x| (-1) * (2**100) }.should == nil
end
- it "handles values from Bignum#coerce" do
- [1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
+ it "handles values from Integer#coerce" do
+ [1, 2].should.include?(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
end
end
diff --git a/spec/ruby/core/array/bsearch_spec.rb b/spec/ruby/core/array/bsearch_spec.rb
index 57b95fb934..12aec60654 100644
--- a/spec/ruby/core/array/bsearch_spec.rb
+++ b/spec/ruby/core/array/bsearch_spec.rb
@@ -3,26 +3,26 @@ require_relative '../enumerable/shared/enumeratorized'
describe "Array#bsearch" do
it "returns an Enumerator when not passed a block" do
- [1].bsearch.should be_an_instance_of(Enumerator)
+ [1].bsearch.should.instance_of?(Enumerator)
end
it_behaves_like :enumeratorized_with_unknown_size, :bsearch, [1,2,3]
it "raises a TypeError if the block returns an Object" do
- lambda { [1].bsearch { Object.new } }.should raise_error(TypeError)
+ -> { [1].bsearch { Object.new } }.should.raise(TypeError)
end
it "raises a TypeError if the block returns a String" do
- lambda { [1].bsearch { "1" } }.should raise_error(TypeError)
+ -> { [1].bsearch { "1" } }.should.raise(TypeError)
end
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
- [0, 1, 2, 3].bsearch { |x| x > 3 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x > 3 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- [0, 1, 2, 3].bsearch { |x| nil }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| nil }.should == nil
end
it "returns element at zero if the block returns true for every element" do
@@ -38,21 +38,21 @@ describe "Array#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- [0, 1, 2, 3].bsearch { |x| x <=> 5 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x <=> 5 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- [0, 1, 2, 3].bsearch { |x| x <=> -1 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x <=> -1 }.should == nil
end
it "returns nil if the block never returns zero" do
- [0, 1, 3, 4].bsearch { |x| x <=> 2 }.should be_nil
+ [0, 1, 3, 4].bsearch { |x| x <=> 2 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- [0, 1, 3, 4].bsearch { |x| Float::INFINITY }.should be_nil
- [0, 1, 3, 4].bsearch { |x| -Float::INFINITY }.should be_nil
+ [0, 1, 3, 4].bsearch { |x| Float::INFINITY }.should == nil
+ [0, 1, 3, 4].bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -62,17 +62,17 @@ describe "Array#bsearch" do
it "returns an element at an index for which block returns 0" do
result = [0, 1, 2, 3, 4].bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2].should include(result)
+ [1, 2].should.include?(result)
end
end
context "with a block that calls break" do
it "returns nil if break is called without a value" do
- ['a', 'b', 'c'].bsearch { |v| break }.should be_nil
+ ['a', 'b', 'c'].bsearch { |v| break }.should == nil
end
it "returns nil if break is called with a nil value" do
- ['a', 'b', 'c'].bsearch { |v| break nil }.should be_nil
+ ['a', 'b', 'c'].bsearch { |v| break nil }.should == nil
end
it "returns object if break is called with an object" do
diff --git a/spec/ruby/core/array/clear_spec.rb b/spec/ruby/core/array/clear_spec.rb
index 8cba1f9e27..15778f864f 100644
--- a/spec/ruby/core/array/clear_spec.rb
+++ b/spec/ruby/core/array/clear_spec.rb
@@ -4,45 +4,29 @@ require_relative 'fixtures/classes'
describe "Array#clear" do
it "removes all elements" do
a = [1, 2, 3, 4]
- a.clear.should equal(a)
+ a.clear.should.equal?(a)
a.should == []
end
it "returns self" do
a = [1]
- a.should equal a.clear
+ a.should.equal? a.clear
end
it "leaves the Array empty" do
a = [1]
a.clear
- a.empty?.should == true
+ a.should.empty?
a.size.should == 0
end
- it "keeps tainted status" do
- a = [1]
- a.taint
- a.tainted?.should be_true
- a.clear
- a.tainted?.should be_true
- end
-
it "does not accept any arguments" do
- lambda { [1].clear(true) }.should raise_error(ArgumentError)
- end
-
- it "keeps untrusted status" do
- a = [1]
- a.untrust
- a.untrusted?.should be_true
- a.clear
- a.untrusted?.should be_true
+ -> { [1].clear(true) }.should.raise(ArgumentError)
end
- it "raises a #{frozen_error_class} on a frozen array" do
+ it "raises a FrozenError on a frozen array" do
a = [1]
a.freeze
- lambda { a.clear }.should raise_error(frozen_error_class)
+ -> { a.clear }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/clone_spec.rb b/spec/ruby/core/array/clone_spec.rb
index 803e746e02..7ce9d40a81 100644
--- a/spec/ruby/core/array/clone_spec.rb
+++ b/spec/ruby/core/array/clone_spec.rb
@@ -12,8 +12,8 @@ describe "Array#clone" do
aa = a.clone
bb = b.clone
- aa.frozen?.should == true
- bb.frozen?.should == false
+ aa.should.frozen?
+ bb.should_not.frozen?
end
it "copies singleton methods" do
@@ -23,9 +23,9 @@ describe "Array#clone" do
aa = a.clone
bb = b.clone
- a.respond_to?(:a_singleton_method).should be_true
- b.respond_to?(:a_singleton_method).should be_false
- aa.respond_to?(:a_singleton_method).should be_true
- bb.respond_to?(:a_singleton_method).should be_false
+ a.respond_to?(:a_singleton_method).should == true
+ b.respond_to?(:a_singleton_method).should == false
+ aa.respond_to?(:a_singleton_method).should == true
+ bb.respond_to?(:a_singleton_method).should == false
end
end
diff --git a/spec/ruby/core/array/collect_spec.rb b/spec/ruby/core/array/collect_spec.rb
index 0ad4c283b1..43a539f805 100644
--- a/spec/ruby/core/array/collect_spec.rb
+++ b/spec/ruby/core/array/collect_spec.rb
@@ -1,11 +1,143 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/collect'
+require_relative '../enumerable/shared/enumeratorized'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#collect" do
- it_behaves_like :array_collect, :collect
+ it "returns a copy of array with each element replaced by the value returned by block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect { |i| i + '!' }
+ b.should == ["a!", "b!", "c!", "d!"]
+ b.should_not.equal? a
+ end
+
+ it "does not return subclass instance" do
+ ArraySpecs::MyArray[1, 2, 3].collect { |x| x + 1 }.should.instance_of?(Array)
+ end
+
+ it "does not change self" do
+ a = ['a', 'b', 'c', 'd']
+ a.collect { |i| i + '!' }
+ a.should == ['a', 'b', 'c', 'd']
+ end
+
+ it "returns the evaluated value of block if it broke in the block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect {|i|
+ if i == 'c'
+ break 0
+ else
+ i + '!'
+ end
+ }
+ b.should == 0
+ end
+
+ it "returns an Enumerator when no block given" do
+ a = [1, 2, 3]
+ a.collect.should.instance_of?(Enumerator)
+ end
+
+ it "raises an ArgumentError when no block and with arguments" do
+ a = [1, 2, 3]
+ -> {
+ a.collect(:foo)
+ }.should.raise(ArgumentError)
+ end
+
+ before :each do
+ @object = [1, 2, 3, 4]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :collect
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect
end
describe "Array#collect!" do
- it_behaves_like :array_collect_b, :collect!
+ it "replaces each element with the value returned by block" do
+ a = [7, 9, 3, 5]
+ a.collect! { |i| i - 1 }.should.equal?(a)
+ a.should == [6, 8, 2, 4]
+ end
+
+ it "returns self" do
+ a = [1, 2, 3, 4, 5]
+ b = a.collect! {|i| i+1 }
+ a.should.equal? b
+ end
+
+ it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect! {|i|
+ if i == 'c'
+ break 0
+ else
+ i + '!'
+ end
+ }
+ b.should == 0
+ a.should == ['a!', 'b!', 'c', 'd']
+ end
+
+ it "returns an Enumerator when no block given, and the enumerator can modify the original array" do
+ a = [1, 2, 3]
+ enum = a.collect!
+ enum.should.instance_of?(Enumerator)
+ enum.each{|i| "#{i}!" }
+ a.should == ["1!", "2!", "3!"]
+ end
+
+ describe "when frozen" do
+ it "raises a FrozenError" do
+ -> { ArraySpecs.frozen_array.collect! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when empty" do
+ -> { ArraySpecs.empty_frozen_array.collect! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when calling #each on the returned Enumerator" do
+ enumerator = ArraySpecs.frozen_array.collect!
+ -> { enumerator.each {|x| x } }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when calling #each on the returned Enumerator when empty" do
+ enumerator = ArraySpecs.empty_frozen_array.collect!
+ -> { enumerator.each {|x| x } }.should.raise(FrozenError)
+ end
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.collect! { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.collect! do |e|
+ case e
+ when 1 then -1
+ when 2 then -2
+ when 3 then raise StandardError, 'Oops'
+ else 0
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [-1, -2, 3, 4]
+ end
+
+ before :each do
+ @object = [1, 2, 3, 4]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :collect!
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect!
end
diff --git a/spec/ruby/core/array/combination_spec.rb b/spec/ruby/core/array/combination_spec.rb
index 94a8e19341..ac570687ca 100644
--- a/spec/ruby/core/array/combination_spec.rb
+++ b/spec/ruby/core/array/combination_spec.rb
@@ -6,11 +6,11 @@ describe "Array#combination" do
end
it "returns an enumerator when no block is provided" do
- @array.combination(2).should be_an_instance_of(Enumerator)
+ @array.combination(2).should.instance_of?(Enumerator)
end
it "returns self when a block is given" do
- @array.combination(2){}.should equal(@array)
+ @array.combination(2){}.should.equal?(@array)
end
it "yields nothing for out of bounds length and return self" do
@@ -30,7 +30,7 @@ describe "Array#combination" do
it "yields a copy of self if the argument is the size of the receiver" do
r = @array.combination(4).to_a
r.should == [@array]
- r[0].should_not equal(@array)
+ r[0].should_not.equal?(@array)
end
it "yields [] when length is 0" do
@@ -58,7 +58,7 @@ describe "Array#combination" do
@array.combination(-1).size.should == 0
[].combination(-2).size.should == 0
end
- it "returns the binomial coeficient between the array size the number of combinations" do
+ it "returns the binomial coefficient between the array size the number of combinations" do
@array.combination(5).size.should == 0
@array.combination(4).size.should == 1
@array.combination(3).size.should == 4
diff --git a/spec/ruby/core/array/compact_spec.rb b/spec/ruby/core/array/compact_spec.rb
index 4818217be1..dbcd16da35 100644
--- a/spec/ruby/core/array/compact_spec.rb
+++ b/spec/ruby/core/array/compact_spec.rb
@@ -15,63 +15,37 @@ describe "Array#compact" do
it "does not return self" do
a = [1, 2, 3]
- a.compact.should_not equal(a)
+ a.compact.should_not.equal?(a)
end
it "does not return subclass instance for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3, nil].compact.should be_an_instance_of(Array)
- end
-
- it "does not keep tainted status even if all elements are removed" do
- a = [nil, nil]
- a.taint
- a.compact.tainted?.should be_false
- end
-
- it "does not keep untrusted status even if all elements are removed" do
- a = [nil, nil]
- a.untrust
- a.compact.untrusted?.should be_false
+ ArraySpecs::MyArray[1, 2, 3, nil].compact.should.instance_of?(Array)
end
end
describe "Array#compact!" do
it "removes all nil elements" do
a = ['a', nil, 'b', false, 'c']
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
a = [nil, 'a', 'b', false, 'c']
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
a = ['a', 'b', false, 'c', nil]
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
end
it "returns self if some nil elements are removed" do
a = ['a', nil, 'b', false, 'c']
- a.compact!.should equal a
+ a.compact!.should.equal? a
end
it "returns nil if there are no nil elements to remove" do
[1, 2, false, 3].compact!.should == nil
end
- it "keeps tainted status even if all elements are removed" do
- a = [nil, nil]
- a.taint
- a.compact!
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status even if all elements are removed" do
- a = [nil, nil]
- a.untrust
- a.compact!
- a.untrusted?.should be_true
- end
-
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.compact! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.compact! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/comparison_spec.rb b/spec/ruby/core/array/comparison_spec.rb
index 5d1c3265f1..14e8931e5a 100644
--- a/spec/ruby/core/array/comparison_spec.rb
+++ b/spec/ruby/core/array/comparison_spec.rb
@@ -92,6 +92,6 @@ describe "Array#<=>" do
end
it "returns nil when the argument is not array-like" do
- ([] <=> false).should be_nil
+ ([] <=> false).should == nil
end
end
diff --git a/spec/ruby/core/array/concat_spec.rb b/spec/ruby/core/array/concat_spec.rb
index 985c5d884a..1e8d20c36c 100644
--- a/spec/ruby/core/array/concat_spec.rb
+++ b/spec/ruby/core/array/concat_spec.rb
@@ -4,12 +4,12 @@ require_relative 'fixtures/classes'
describe "Array#concat" do
it "returns the array itself" do
ary = [1,2,3]
- ary.concat([4,5,6]).equal?(ary).should be_true
+ ary.concat([4,5,6]).equal?(ary).should == true
end
it "appends the elements in the other array" do
ary = [1, 2, 3]
- ary.concat([9, 10, 11]).should equal(ary)
+ ary.concat([9, 10, 11]).should.equal?(ary)
ary.should == [1, 2, 3, 9, 10, 11]
ary.concat([])
ary.should == [1, 2, 3, 9, 10, 11]
@@ -32,69 +32,13 @@ describe "Array#concat" do
[].concat(obj).should == [5, 6, 7]
end
- it "raises a #{frozen_error_class} when Array is frozen and modification occurs" do
- lambda { ArraySpecs.frozen_array.concat [1] }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when Array is frozen and modification occurs" do
+ -> { ArraySpecs.frozen_array.concat [1] }.should.raise(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} when Array is frozen and no modification occurs" do
- lambda { ArraySpecs.frozen_array.concat([]) }.should raise_error(frozen_error_class)
- end
-
- it "keeps tainted status" do
- ary = [1, 2]
- ary.taint
- ary.concat([3])
- ary.tainted?.should be_true
- ary.concat([])
- ary.tainted?.should be_true
- end
-
- it "is not infected by the other" do
- ary = [1,2]
- other = [3]; other.taint
- ary.tainted?.should be_false
- ary.concat(other)
- ary.tainted?.should be_false
- end
-
- it "keeps the tainted status of elements" do
- ary = [ Object.new, Object.new, Object.new ]
- ary.each {|x| x.taint }
-
- ary.concat([ Object.new ])
- ary[0].tainted?.should be_true
- ary[1].tainted?.should be_true
- ary[2].tainted?.should be_true
- ary[3].tainted?.should be_false
- end
-
- it "keeps untrusted status" do
- ary = [1, 2]
- ary.untrust
- ary.concat([3])
- ary.untrusted?.should be_true
- ary.concat([])
- ary.untrusted?.should be_true
- end
-
- it "is not infected untrustedness by the other" do
- ary = [1,2]
- other = [3]; other.untrust
- ary.untrusted?.should be_false
- ary.concat(other)
- ary.untrusted?.should be_false
- end
-
- it "keeps the untrusted status of elements" do
- ary = [ Object.new, Object.new, Object.new ]
- ary.each {|x| x.untrust }
-
- ary.concat([ Object.new ])
- ary[0].untrusted?.should be_true
- ary[1].untrusted?.should be_true
- ary[2].untrusted?.should be_true
- ary[3].untrusted?.should be_false
+ it "raises a FrozenError when Array is frozen and no modification occurs" do
+ -> { ArraySpecs.frozen_array.concat([]) }.should.raise(FrozenError)
end
it "appends elements to an Array with enough capacity that has been shifted" do
@@ -110,23 +54,21 @@ describe "Array#concat" do
ary.concat([5, 6]).should == [4, 5, 6]
end
- ruby_version_is "2.4" do
- it "takes multiple arguments" do
- ary = [1, 2]
- ary.concat [3, 4]
- ary.should == [1, 2, 3, 4]
- end
+ it "takes multiple arguments" do
+ ary = [1, 2]
+ ary.concat [3, 4]
+ ary.should == [1, 2, 3, 4]
+ end
- it "concatenates the initial value when given arguments contain 2 self" do
- ary = [1, 2]
- ary.concat ary, ary
- ary.should == [1, 2, 1, 2, 1, 2]
- end
+ it "concatenates the initial value when given arguments contain 2 self" do
+ ary = [1, 2]
+ ary.concat ary, ary
+ ary.should == [1, 2, 1, 2, 1, 2]
+ end
- it "returns self when given no arguments" do
- ary = [1, 2]
- ary.concat.should equal(ary)
- ary.should == [1, 2]
- end
+ it "returns self when given no arguments" do
+ ary = [1, 2]
+ ary.concat.should.equal?(ary)
+ ary.should == [1, 2]
end
end
diff --git a/spec/ruby/core/array/constructor_spec.rb b/spec/ruby/core/array/constructor_spec.rb
index 6f36074c45..c4398c535d 100644
--- a/spec/ruby/core/array/constructor_spec.rb
+++ b/spec/ruby/core/array/constructor_spec.rb
@@ -7,7 +7,7 @@ describe "Array.[]" do
Array.[](5, true, nil, 'a', "Ruby", obj).should == [5, true, nil, "a", "Ruby", obj]
a = ArraySpecs::MyArray.[](5, true, nil, 'a', "Ruby", obj)
- a.should be_an_instance_of(ArraySpecs::MyArray)
+ a.should.instance_of?(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end
@@ -18,7 +18,7 @@ describe "Array[]" do
Array[5, true, nil, 'a', "Ruby", obj].should == Array.[](5, true, nil, "a", "Ruby", obj)
a = ArraySpecs::MyArray[5, true, nil, 'a', "Ruby", obj]
- a.should be_an_instance_of(ArraySpecs::MyArray)
+ a.should.instance_of?(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end
diff --git a/spec/ruby/core/array/count_spec.rb b/spec/ruby/core/array/count_spec.rb
index eaf275aeb7..e778233c16 100644
--- a/spec/ruby/core/array/count_spec.rb
+++ b/spec/ruby/core/array/count_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#count" do
it "returns the number of elements" do
@@ -12,4 +13,14 @@ describe "Array#count" do
it "returns the number of element for which the block evaluates to true" do
[:a, :b, :c].count { |s| s != :b }.should == 2
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ [:a, :b, :b, :c].count(:b) { |e| e.size > 10 }.should == 2
+ }.should complain(/given block not used/)
+ end
+
+ context "when a block argument given" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :count
+ end
end
diff --git a/spec/ruby/core/array/cycle_spec.rb b/spec/ruby/core/array/cycle_spec.rb
index 018005abb4..29284257e9 100644
--- a/spec/ruby/core/array/cycle_spec.rb
+++ b/spec/ruby/core/array/cycle_spec.rb
@@ -6,21 +6,21 @@ describe "Array#cycle" do
ScratchPad.record []
@array = [1, 2, 3]
- @prc = lambda { |x| ScratchPad << x }
+ @prc = -> x { ScratchPad << x }
end
it "does not yield and returns nil when the array is empty and passed value is an integer" do
- [].cycle(6, &@prc).should be_nil
+ [].cycle(6, &@prc).should == nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when the array is empty and passed value is nil" do
- [].cycle(nil, &@prc).should be_nil
+ [].cycle(nil, &@prc).should == nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when passed 0" do
- @array.cycle(0, &@prc).should be_nil
+ @array.cycle(0, &@prc).should == nil
ScratchPad.recorded.should == []
end
@@ -46,15 +46,15 @@ describe "Array#cycle" do
end
it "does not rescue StopIteration when not passed a count" do
- lambda do
+ -> do
@array.cycle { raise StopIteration }
- end.should raise_error(StopIteration)
+ end.should.raise(StopIteration)
end
it "does not rescue StopIteration when passed a count" do
- lambda do
+ -> do
@array.cycle(3) { raise StopIteration }
- end.should raise_error(StopIteration)
+ end.should.raise(StopIteration)
end
it "iterates the array Integer(count) times when passed a Float count" do
@@ -74,23 +74,23 @@ describe "Array#cycle" do
count = mock("cycle count 2")
count.should_receive(:to_int).and_return("2")
- lambda { @array.cycle(count, &@prc) }.should raise_error(TypeError)
+ -> { @array.cycle(count, &@prc) }.should.raise(TypeError)
end
it "raises a TypeError if passed a String" do
- lambda { @array.cycle("4") { } }.should raise_error(TypeError)
+ -> { @array.cycle("4") { } }.should.raise(TypeError)
end
it "raises a TypeError if passed an Object" do
- lambda { @array.cycle(mock("cycle count")) { } }.should raise_error(TypeError)
+ -> { @array.cycle(mock("cycle count")) { } }.should.raise(TypeError)
end
it "raises a TypeError if passed true" do
- lambda { @array.cycle(true) { } }.should raise_error(TypeError)
+ -> { @array.cycle(true) { } }.should.raise(TypeError)
end
it "raises a TypeError if passed false" do
- lambda { @array.cycle(false) { } }.should raise_error(TypeError)
+ -> { @array.cycle(false) { } }.should.raise(TypeError)
end
before :all do
diff --git a/spec/ruby/core/array/deconstruct_spec.rb b/spec/ruby/core/array/deconstruct_spec.rb
new file mode 100644
index 0000000000..11bb8e72c4
--- /dev/null
+++ b/spec/ruby/core/array/deconstruct_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+
+describe "Array#deconstruct" do
+ it "returns self" do
+ array = [1]
+
+ array.deconstruct.should.equal? array
+ end
+end
diff --git a/spec/ruby/core/array/delete_at_spec.rb b/spec/ruby/core/array/delete_at_spec.rb
index 021554c76a..1e298b6730 100644
--- a/spec/ruby/core/array/delete_at_spec.rb
+++ b/spec/ruby/core/array/delete_at_spec.rb
@@ -35,27 +35,7 @@ describe "Array#delete_at" do
a.delete_at(-2).should == 1
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { [1,2,3].freeze.delete_at(0) }.should raise_error(frozen_error_class)
- end
-
- it "keeps tainted status" do
- ary = [1, 2]
- ary.taint
- ary.tainted?.should be_true
- ary.delete_at(0)
- ary.tainted?.should be_true
- ary.delete_at(0) # now empty
- ary.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- ary = [1, 2]
- ary.untrust
- ary.untrusted?.should be_true
- ary.delete_at(0)
- ary.untrusted?.should be_true
- ary.delete_at(0) # now empty
- ary.untrusted?.should be_true
+ it "raises a FrozenError on a frozen array" do
+ -> { [1,2,3].freeze.delete_at(0) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/delete_if_spec.rb b/spec/ruby/core/array/delete_if_spec.rb
index 12a7d1662d..701a612395 100644
--- a/spec/ruby/core/array/delete_if_spec.rb
+++ b/spec/ruby/core/array/delete_if_spec.rb
@@ -2,6 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative 'shared/delete_if'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#delete_if" do
@@ -16,7 +17,7 @@ describe "Array#delete_if" do
end
it "returns self" do
- @a.delete_if{ true }.equal?(@a).should be_true
+ @a.delete_if{ true }.equal?(@a).should == true
end
it_behaves_like :enumeratorize, :delete_if
@@ -24,43 +25,58 @@ describe "Array#delete_if" do
it "returns self when called on an Array emptied with #shift" do
array = [1]
array.shift
- array.delete_if { |x| true }.should equal(array)
+ array.delete_if { |x| true }.should.equal?(array)
end
it "returns an Enumerator if no block given, and the enumerator can modify the original array" do
enum = @a.delete_if
- enum.should be_an_instance_of(Enumerator)
- @a.should_not be_empty
+ enum.should.instance_of?(Enumerator)
+ @a.should_not.empty?
enum.each { true }
- @a.should be_empty
+ @a.should.empty?
end
it "returns an Enumerator if no block given, and the array is frozen" do
- @a.freeze.delete_if.should be_an_instance_of(Enumerator)
+ @a.freeze.delete_if.should.instance_of?(Enumerator)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.delete_if {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.delete_if {} }.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.delete_if {} }.should.raise(FrozenError)
end
- it "keeps tainted status" do
- @a.taint
- @a.tainted?.should be_true
- @a.delete_if{ true }
- @a.tainted?.should be_true
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.delete_if { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
end
- it "keeps untrusted status" do
- @a.untrust
- @a.untrusted?.should be_true
- @a.delete_if{ true }
- @a.untrusted?.should be_true
+ it "only removes elements for which the block returns true, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.delete_if do |e|
+ case e
+ when 2 then true
+ when 3 then raise StandardError, 'Oops'
+ else false
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 3, 4]
end
it_behaves_like :enumeratorized_with_origin_size, :delete_if, [1,2,3]
it_behaves_like :delete_if, :delete_if
+
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :delete_if
end
diff --git a/spec/ruby/core/array/delete_spec.rb b/spec/ruby/core/array/delete_spec.rb
index 62476f489b..0d80b2839d 100644
--- a/spec/ruby/core/array/delete_spec.rb
+++ b/spec/ruby/core/array/delete_spec.rb
@@ -40,27 +40,7 @@ describe "Array#delete" do
[1, 2, 3].freeze.delete(0).should == nil
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { [1, 2, 3].freeze.delete(1) }.should raise_error(frozen_error_class)
- end
-
- it "keeps tainted status" do
- a = [1, 2]
- a.taint
- a.tainted?.should be_true
- a.delete(2)
- a.tainted?.should be_true
- a.delete(1) # now empty
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- a = [1, 2]
- a.untrust
- a.untrusted?.should be_true
- a.delete(2)
- a.untrusted?.should be_true
- a.delete(1) # now empty
- a.untrusted?.should be_true
+ it "raises a FrozenError on a frozen array" do
+ -> { [1, 2, 3].freeze.delete(1) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/difference_spec.rb b/spec/ruby/core/array/difference_spec.rb
new file mode 100644
index 0000000000..63e32feca0
--- /dev/null
+++ b/spec/ruby/core/array/difference_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/difference'
+
+describe "Array#difference" do
+ it_behaves_like :array_binary_difference, :difference
+
+ it "returns a copy when called without any parameter" do
+ x = [1, 2, 3, 2]
+ x.difference.should == x
+ x.difference.should_not.equal? x
+ end
+
+ it "does not return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].difference.should.instance_of?(Array)
+ end
+
+ it "accepts multiple arguments" do
+ x = [1, 2, 3, 1]
+ x.difference([], [0, 1], [3, 4], [3]).should == [2]
+ end
+end
diff --git a/spec/ruby/core/array/dig_spec.rb b/spec/ruby/core/array/dig_spec.rb
index 1ace4893ee..4166ff9f1f 100644
--- a/spec/ruby/core/array/dig_spec.rb
+++ b/spec/ruby/core/array/dig_spec.rb
@@ -4,7 +4,7 @@ describe "Array#dig" do
it "returns #at with one arg" do
['a'].dig(0).should == 'a'
- ['a'].dig(1).should be_nil
+ ['a'].dig(1).should == nil
end
it "recurses array elements" do
@@ -20,22 +20,22 @@ describe "Array#dig" do
end
it "raises a TypeError for a non-numeric index" do
- lambda {
+ -> {
['a'].dig(:first)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]
- lambda {
+ -> {
a.dig(0, 1)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
- lambda {
+ -> {
[10].dig()
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "returns nil if any intermediate step is nil" do
diff --git a/spec/ruby/core/array/drop_spec.rb b/spec/ruby/core/array/drop_spec.rb
index 1bd2e6cc25..c0e1c9edce 100644
--- a/spec/ruby/core/array/drop_spec.rb
+++ b/spec/ruby/core/array/drop_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "Array#drop" do
it "removes the specified number of elements from the start of the array" do
@@ -6,7 +7,7 @@ describe "Array#drop" do
end
it "raises an ArgumentError if the number of elements specified is negative" do
- lambda { [1, 2].drop(-3) }.should raise_error(ArgumentError)
+ -> { [1, 2].drop(-3) }.should.raise(ArgumentError)
end
it "returns an empty Array if all elements are dropped" do
@@ -30,4 +31,26 @@ describe "Array#drop" do
ary.shift
ary.drop(1).should == [2]
end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(2)
+
+ [1, 2, 3].drop(obj).should == [3]
+ end
+
+ it "raises a TypeError when the passed argument can't be coerced to Integer" do
+ -> { [1, 2].drop("cat") }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the passed argument isn't an integer and #to_int returns non-Integer" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return("cat")
+
+ -> { [1, 2].drop(obj) }.should.raise(TypeError)
+ end
+
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should.instance_of?(Array)
+ end
end
diff --git a/spec/ruby/core/array/drop_while_spec.rb b/spec/ruby/core/array/drop_while_spec.rb
index cfb6b1e267..4fead3ff06 100644
--- a/spec/ruby/core/array/drop_while_spec.rb
+++ b/spec/ruby/core/array/drop_while_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#drop_while" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :drop_while
+
it "removes elements from the start of the array while the block evaluates to true" do
[1, 2, 3, 4].drop_while { |n| n < 4 }.should == [4]
end
@@ -12,4 +17,8 @@ describe "Array#drop_while" do
it "removes elements from the start of the array until the block returns false" do
[1, 2, 3, false, 5].drop_while { |n| n }.should == [false, 5]
end
+
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should.instance_of?(Array)
+ end
end
diff --git a/spec/ruby/core/array/dup_spec.rb b/spec/ruby/core/array/dup_spec.rb
index 17f467d5fc..f14aeca3b5 100644
--- a/spec/ruby/core/array/dup_spec.rb
+++ b/spec/ruby/core/array/dup_spec.rb
@@ -12,8 +12,8 @@ describe "Array#dup" do
aa = a.dup
bb = b.dup
- aa.frozen?.should be_false
- bb.frozen?.should be_false
+ aa.frozen?.should == false
+ bb.frozen?.should == false
end
it "does not copy singleton methods" do
@@ -23,9 +23,9 @@ describe "Array#dup" do
aa = a.dup
bb = b.dup
- a.respond_to?(:a_singleton_method).should be_true
- b.respond_to?(:a_singleton_method).should be_false
- aa.respond_to?(:a_singleton_method).should be_false
- bb.respond_to?(:a_singleton_method).should be_false
+ a.respond_to?(:a_singleton_method).should == true
+ b.respond_to?(:a_singleton_method).should == false
+ aa.respond_to?(:a_singleton_method).should == false
+ bb.respond_to?(:a_singleton_method).should == false
end
end
diff --git a/spec/ruby/core/array/each_index_spec.rb b/spec/ruby/core/array/each_index_spec.rb
index 51af5842c4..b238a89d8a 100644
--- a/spec/ruby/core/array/each_index_spec.rb
+++ b/spec/ruby/core/array/each_index_spec.rb
@@ -5,7 +5,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#each_index" do
before :each do
@@ -20,7 +20,7 @@ describe "Array#each_index" do
it "returns self" do
a = [:a, :b, :c]
- a.each_index { |i| }.should equal(a)
+ a.each_index { |i| }.should.equal?(a)
end
it "is not confused by removing elements from the front" do
@@ -40,3 +40,19 @@ describe "Array#each_index" do
it_behaves_like :enumeratorize, :each_index
it_behaves_like :enumeratorized_with_origin_size, :each_index, [1,2,3]
end
+
+describe "Array#each_index" do
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.each_index do |index|
+ ScratchPad << index
+ array << i if i < 100
+ i += 1
+ end
+
+ ScratchPad.recorded.should == (0..102).to_a # element indices
+ end
+end
diff --git a/spec/ruby/core/array/each_spec.rb b/spec/ruby/core/array/each_spec.rb
index ad8a5ad3d5..73a4c36b17 100644
--- a/spec/ruby/core/array/each_spec.rb
+++ b/spec/ruby/core/array/each_spec.rb
@@ -1,20 +1,50 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
-# Modifying a collection while the contents are being iterated
-# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
+# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
+# CRuby simply reads the array storage and checks the size for every iteration;
+# like `i = 0; while i < size; yield self[i]; i += 1; end`
describe "Array#each" do
it "yields each element to the block" do
a = []
x = [1, 2, 3]
- x.each { |item| a << item }.should equal(x)
+ x.each { |item| a << item }.should.equal?(x)
a.should == [1, 2, 3]
end
+ it "yields each element to the block even if the array is changed during iteration" do
+ a = [1, 2, 3, 4, 5]
+ iterated = []
+ a.each { |x| iterated << x; a << x+5 if x.even? }
+ iterated.should == [1, 2, 3, 4, 5, 7, 9]
+ end
+
+ it "yields only elements that are still in the array" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.pop if x.even? }
+ iterated.should == [0, 1, 2]
+ end
+
+ it "yields elements based on an internal index" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.shift if x.even? }
+ iterated.should == [0, 2, 4]
+ end
+
+ it "yields the same element multiple times if inserting while iterating" do
+ a = [1, 2]
+ iterated = []
+ a.each { |x| iterated << x; a.unshift(0) if a.size == 2 }
+ iterated.should == [1, 1, 2]
+ end
+
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []
@@ -27,6 +57,26 @@ describe "Array#each" do
b.should == [2, nil, 4]
end
+ it "yields elements added to the end of the array by the block" do
+ a = [2]
+ iterated = []
+ a.each { |x| iterated << x; x.times { a << 0 } }
+
+ iterated.should == [2, 0, 0]
+ end
+
+ it "does not yield elements deleted from the end of the array" do
+ a = [2, 3, 1]
+ iterated = []
+ a.each { |x| iterated << x; a.delete_at(2) if x == 3 }
+
+ iterated.should == [2, 3]
+ end
+
it_behaves_like :enumeratorize, :each
it_behaves_like :enumeratorized_with_origin_size, :each, [1,2,3]
end
+
+describe "Array#each" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :each
+end
diff --git a/spec/ruby/core/array/element_reference_spec.rb b/spec/ruby/core/array/element_reference_spec.rb
index 31e5578a09..d5f4b54961 100644
--- a/spec/ruby/core/array/element_reference_spec.rb
+++ b/spec/ruby/core/array/element_reference_spec.rb
@@ -1,9 +1,862 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/slice'
describe "Array#[]" do
- it_behaves_like :array_slice, :[]
+ it "returns the element at index with [index]" do
+ [ "a", "b", "c", "d", "e" ][1].should == "b"
+
+ a = [1, 2, 3, 4]
+
+ a[0].should == 1
+ a[1].should == 2
+ a[2].should == 3
+ a[3].should == 4
+ a[4].should == nil
+ a[10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the element at index from the end of the array with [-index]" do
+ [ "a", "b", "c", "d", "e" ][-2].should == "d"
+
+ a = [1, 2, 3, 4]
+
+ a[-1].should == 4
+ a[-2].should == 3
+ a[-3].should == 2
+ a[-4].should == 1
+ a[-5].should == nil
+ a[-10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns count elements starting from index with [index, count]" do
+ [ "a", "b", "c", "d", "e" ][2, 3].should == ["c", "d", "e"]
+
+ a = [1, 2, 3, 4]
+
+ a[0, 0].should == []
+ a[0, 1].should == [1]
+ a[0, 2].should == [1, 2]
+ a[0, 4].should == [1, 2, 3, 4]
+ a[0, 6].should == [1, 2, 3, 4]
+ a[0, -1].should == nil
+ a[0, -2].should == nil
+ a[0, -4].should == nil
+
+ a[2, 0].should == []
+ a[2, 1].should == [3]
+ a[2, 2].should == [3, 4]
+ a[2, 4].should == [3, 4]
+ a[2, -1].should == nil
+
+ a[4, 0].should == []
+ a[4, 2].should == []
+ a[4, -1].should == nil
+
+ a[5, 0].should == nil
+ a[5, 2].should == nil
+ a[5, -1].should == nil
+
+ a[6, 0].should == nil
+ a[6, 2].should == nil
+ a[6, -1].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns count elements starting at index from the end of array with [-index, count]" do
+ [ "a", "b", "c", "d", "e" ][-2, 2].should == ["d", "e"]
+
+ a = [1, 2, 3, 4]
+
+ a[-1, 0].should == []
+ a[-1, 1].should == [4]
+ a[-1, 2].should == [4]
+ a[-1, -1].should == nil
+
+ a[-2, 0].should == []
+ a[-2, 1].should == [3]
+ a[-2, 2].should == [3, 4]
+ a[-2, 4].should == [3, 4]
+ a[-2, -1].should == nil
+
+ a[-4, 0].should == []
+ a[-4, 1].should == [1]
+ a[-4, 2].should == [1, 2]
+ a[-4, 4].should == [1, 2, 3, 4]
+ a[-4, 6].should == [1, 2, 3, 4]
+ a[-4, -1].should == nil
+
+ a[-5, 0].should == nil
+ a[-5, 1].should == nil
+ a[-5, 10].should == nil
+ a[-5, -1].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the first count elements with [0, count]" do
+ [ "a", "b", "c", "d", "e" ][0, 3].should == ["a", "b", "c"]
+ end
+
+ it "returns the subarray which is independent to self with [index,count]" do
+ a = [1, 2, 3]
+ sub = a[1, 2]
+ sub.replace([:a, :b])
+ a.should == [1, 2, 3]
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.stub!(:to_int).and_return(2)
+
+ a = [1, 2, 3, 4]
+ a[obj].should == 3
+ a[obj, 1].should == [3]
+ a[obj, obj].should == [3, 4]
+ a[0, obj].should == [1, 2]
+ end
+
+ it "raises TypeError if to_int returns non-integer" do
+ from = mock('from')
+ to = mock('to')
+
+ # So we can construct a range out of them...
+ def from.<=>(o) 0 end
+ def to.<=>(o) 0 end
+
+ a = [1, 2, 3, 4, 5]
+
+ def from.to_int() 'cat' end
+ def to.to_int() -2 end
+
+ -> { a[from..to] }.should.raise(TypeError)
+
+ def from.to_int() 1 end
+ def to.to_int() 'cat' end
+
+ -> { a[from..to] }.should.raise(TypeError)
+ end
+
+ it "returns the elements specified by Range indexes with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][1..3].should == ["b", "c", "d"]
+ [ "a", "b", "c", "d", "e" ][4..-1].should == ['e']
+ [ "a", "b", "c", "d", "e" ][3..3].should == ['d']
+ [ "a", "b", "c", "d", "e" ][3..-2].should == ['d']
+ ['a'][0..-1].should == ['a']
+
+ a = [1, 2, 3, 4]
+
+ a[0..-10].should == []
+ a[0..0].should == [1]
+ a[0..1].should == [1, 2]
+ a[0..2].should == [1, 2, 3]
+ a[0..3].should == [1, 2, 3, 4]
+ a[0..4].should == [1, 2, 3, 4]
+ a[0..10].should == [1, 2, 3, 4]
+
+ a[2..-10].should == []
+ a[2..0].should == []
+ a[2..2].should == [3]
+ a[2..3].should == [3, 4]
+ a[2..4].should == [3, 4]
+
+ a[3..0].should == []
+ a[3..3].should == [4]
+ a[3..4].should == [4]
+
+ a[4..0].should == []
+ a[4..4].should == []
+ a[4..5].should == []
+
+ a[5..0].should == nil
+ a[5..5].should == nil
+ a[5..6].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns elements specified by Range indexes except the element at index n with [m...n]" do
+ [ "a", "b", "c", "d", "e" ][1...3].should == ["b", "c"]
+
+ a = [1, 2, 3, 4]
+
+ a[0...-10].should == []
+ a[0...0].should == []
+ a[0...1].should == [1]
+ a[0...2].should == [1, 2]
+ a[0...3].should == [1, 2, 3]
+ a[0...4].should == [1, 2, 3, 4]
+ a[0...10].should == [1, 2, 3, 4]
+
+ a[2...-10].should == []
+ a[2...0].should == []
+ a[2...2].should == []
+ a[2...3].should == [3]
+ a[2...4].should == [3, 4]
+
+ a[3...0].should == []
+ a[3...3].should == []
+ a[3...4].should == [4]
+
+ a[4...0].should == []
+ a[4...4].should == []
+ a[4...5].should == []
+
+ a[5...0].should == nil
+ a[5...5].should == nil
+ a[5...6].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns elements that exist if range start is in the array but range end is not with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][4..7].should == ["e"]
+ end
+
+ it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do
+ a = [1, 2, 3, 4]
+
+ a[-1..-1].should == [4]
+ a[-1...-1].should == []
+ a[-1..3].should == [4]
+ a[-1...3].should == []
+ a[-1..4].should == [4]
+ a[-1...4].should == [4]
+ a[-1..10].should == [4]
+ a[-1...10].should == [4]
+ a[-1..0].should == []
+ a[-1..-4].should == []
+ a[-1...-4].should == []
+ a[-1..-6].should == []
+ a[-1...-6].should == []
+
+ a[-2..-2].should == [3]
+ a[-2...-2].should == []
+ a[-2..-1].should == [3, 4]
+ a[-2...-1].should == [3]
+ a[-2..10].should == [3, 4]
+ a[-2...10].should == [3, 4]
+
+ a[-4..-4].should == [1]
+ a[-4..-2].should == [1, 2, 3]
+ a[-4...-2].should == [1, 2]
+ a[-4..-1].should == [1, 2, 3, 4]
+ a[-4...-1].should == [1, 2, 3]
+ a[-4..3].should == [1, 2, 3, 4]
+ a[-4...3].should == [1, 2, 3]
+ a[-4..4].should == [1, 2, 3, 4]
+ a[-4...4].should == [1, 2, 3, 4]
+ a[-4...4].should == [1, 2, 3, 4]
+ a[-4..0].should == [1]
+ a[-4...0].should == []
+ a[-4..1].should == [1, 2]
+ a[-4...1].should == [1]
+
+ a[-5..-5].should == nil
+ a[-5...-5].should == nil
+ a[-5..-4].should == nil
+ a[-5..-1].should == nil
+ a[-5..10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the subarray which is independent to self with [m..n]" do
+ a = [1, 2, 3]
+ sub = a[1..2]
+ sub.replace([:a, :b])
+ a.should == [1, 2, 3]
+ end
+
+ it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do
+ from = mock('from')
+ to = mock('to')
+
+ # So we can construct a range out of them...
+ def from.<=>(o) 0 end
+ def to.<=>(o) 0 end
+
+ def from.to_int() 1 end
+ def to.to_int() -2 end
+
+ a = [1, 2, 3, 4]
+
+ a[from..to].should == [2, 3]
+ a[from...to].should == [2]
+ a[1..0].should == []
+ a[1...0].should == []
+
+ -> { a["a" .. "b"] }.should.raise(TypeError)
+ -> { a["a" ... "b"] }.should.raise(TypeError)
+ -> { a[from .. "b"] }.should.raise(TypeError)
+ -> { a[from ... "b"] }.should.raise(TypeError)
+ end
+
+ it "returns the same elements as [m..n] and [m...n] with Range subclasses" do
+ a = [1, 2, 3, 4]
+ range_incl = ArraySpecs::MyRange.new(1, 2)
+ range_excl = ArraySpecs::MyRange.new(-3, -1, true)
+
+ a[range_incl].should == [2, 3]
+ a[range_excl].should == [2, 3]
+ end
+
+ it "returns nil for a requested index not in the array with [index]" do
+ [ "a", "b", "c", "d", "e" ][5].should == nil
+ end
+
+ it "returns [] if the index is valid but length is zero with [index, length]" do
+ [ "a", "b", "c", "d", "e" ][0, 0].should == []
+ [ "a", "b", "c", "d", "e" ][2, 0].should == []
+ end
+
+ it "returns nil if length is zero but index is invalid with [index, length]" do
+ [ "a", "b", "c", "d", "e" ][100, 0].should == nil
+ [ "a", "b", "c", "d", "e" ][-50, 0].should == nil
+ end
+
+ # This is by design. It is in the official documentation.
+ it "returns [] if index == array.size with [index, length]" do
+ %w|a b c d e|[5, 2].should == []
+ end
+
+ it "returns nil if index > array.size with [index, length]" do
+ %w|a b c d e|[6, 2].should == nil
+ end
+
+ it "returns nil if length is negative with [index, length]" do
+ %w|a b c d e|[3, -1].should == nil
+ %w|a b c d e|[2, -2].should == nil
+ %w|a b c d e|[1, -100].should == nil
+ end
+
+ it "returns nil if no requested index is in the array with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][6..10].should == nil
+ end
+
+ it "returns nil if range start is not in the array with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][-10..2].should == nil
+ [ "a", "b", "c", "d", "e" ][10..12].should == nil
+ end
+
+ it "returns an empty array when m == n with [m...n]" do
+ [1, 2, 3, 4, 5][1...1].should == []
+ end
+
+ it "returns an empty array with [0...0]" do
+ [1, 2, 3, 4, 5][0...0].should == []
+ end
+
+ it "returns a subarray where m, n negatives and m < n with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][-3..-2].should == ["c", "d"]
+ end
+
+ it "returns an array containing the first element with [0..0]" do
+ [1, 2, 3, 4, 5][0..0].should == [1]
+ end
+
+ it "returns the entire array with [0..-1]" do
+ [1, 2, 3, 4, 5][0..-1].should == [1, 2, 3, 4, 5]
+ end
+
+ it "returns all but the last element with [0...-1]" do
+ [1, 2, 3, 4, 5][0...-1].should == [1, 2, 3, 4]
+ end
+
+ it "returns [3] for [2..-1] out of [1, 2, 3]" do
+ [1,2,3][2..-1].should == [3]
+ end
+
+ it "returns an empty array when m > n and m, n are positive with [m..n]" do
+ [1, 2, 3, 4, 5][3..2].should == []
+ end
+
+ it "returns an empty array when m > n and m, n are negative with [m..n]" do
+ [1, 2, 3, 4, 5][-2..-3].should == []
+ end
+
+ it "does not expand array when the indices are outside of the array bounds" do
+ a = [1, 2]
+ a[4].should == nil
+ a.should == [1, 2]
+ a[4, 0].should == nil
+ a.should == [1, 2]
+ a[6, 1].should == nil
+ a.should == [1, 2]
+ a[8...8].should == nil
+ a.should == [1, 2]
+ a[10..10].should == nil
+ a.should == [1, 2]
+ end
+
+ describe "with a subclass of Array" do
+ before :each do
+ ScratchPad.clear
+
+ @array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
+ end
+
+ it "returns a Array instance with [n, m]" do
+ @array[0, 2].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n, m]" do
+ @array[-3, 2].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n..m]" do
+ @array[1..3].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n...m]" do
+ @array[1...3].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n..-m]" do
+ @array[-3..-1].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n...-m]" do
+ @array[-3...-1].should.instance_of?(Array)
+ end
+
+ it "returns an empty array when m == n with [m...n]" do
+ @array[1...1].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array with [0...0]" do
+ @array[0...0].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array when m > n and m, n are positive with [m..n]" do
+ @array[3..2].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array when m > n and m, n are negative with [m..n]" do
+ @array[-2..-3].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns [] if index == array.size with [index, length]" do
+ @array[5, 2].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns [] if the index is valid but length is zero with [index, length]" do
+ @array[0, 0].should == []
+ @array[2, 0].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "does not call #initialize on the subclass instance" do
+ @array[0, 3].should == [1, 2, 3]
+ ScratchPad.recorded.should == nil
+ end
+ end
+
+ it "raises a RangeError when the start index is out of range of Fixnum" do
+ array = [1, 2, 3, 4, 5, 6]
+ obj = mock('large value')
+ obj.should_receive(:to_int).and_return(bignum_value)
+ -> { array[obj] }.should.raise(RangeError)
+
+ obj = 8e19
+ -> { array[obj] }.should.raise(RangeError)
+
+ # boundary value when longs are 64 bits
+ -> { array[2.0**63] }.should.raise(RangeError)
+
+ # just under the boundary value when longs are 64 bits
+ array[max_long.to_f.prev_float].should == nil
+ end
+
+ it "raises a RangeError when the length is out of range of Fixnum" do
+ array = [1, 2, 3, 4, 5, 6]
+ obj = mock('large value')
+ obj.should_receive(:to_int).and_return(bignum_value)
+ -> { array[1, obj] }.should.raise(RangeError)
+
+ obj = 8e19
+ -> { array[1, obj] }.should.raise(RangeError)
+ end
+
+ it "raises a type error if a range is passed with a length" do
+ ->{ [1, 2, 3][1..2, 1] }.should.raise(TypeError)
+ end
+
+ it "raises a RangeError if passed a range with a bound that is too large" do
+ array = [1, 2, 3, 4, 5, 6]
+ -> { array[bignum_value..(bignum_value + 1)] }.should.raise(RangeError)
+ -> { array[0..bignum_value] }.should.raise(RangeError)
+ end
+
+ it "can accept endless ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[eval("(2..)")].should == [2, 3, 4, 5]
+ a[eval("(2...)")].should == [2, 3, 4, 5]
+ a[eval("(-2..)")].should == [4, 5]
+ a[eval("(-2...)")].should == [4, 5]
+ a[eval("(9..)")].should == nil
+ a[eval("(9...)")].should == nil
+ a[eval("(-9..)")].should == nil
+ a[eval("(-9...)")].should == nil
+ end
+
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ before :each do
+ @array = [0, 1, 2, 3, 4, 5]
+ end
+
+ it "has endless range and positive steps" do
+ @array[eval("(0..).step(1)")].should == [0, 1, 2, 3, 4, 5]
+ @array[eval("(0..).step(2)")].should == [0, 2, 4]
+ @array[eval("(0..).step(10)")].should == [0]
+
+ @array[eval("(2..).step(1)")].should == [2, 3, 4, 5]
+ @array[eval("(2..).step(2)")].should == [2, 4]
+ @array[eval("(2..).step(10)")].should == [2]
+
+ @array[eval("(-3..).step(1)")].should == [3, 4, 5]
+ @array[eval("(-3..).step(2)")].should == [3, 5]
+ @array[eval("(-3..).step(10)")].should == [3]
+ end
+
+ it "has beginless range and positive steps" do
+ # end with zero index
+ @array[(..0).step(1)].should == [0]
+ @array[(...0).step(1)].should == []
+
+ @array[(..0).step(2)].should == [0]
+ @array[(...0).step(2)].should == []
+
+ @array[(..0).step(10)].should == [0]
+ @array[(...0).step(10)].should == []
+
+ # end with positive index
+ @array[(..3).step(1)].should == [0, 1, 2, 3]
+ @array[(...3).step(1)].should == [0, 1, 2]
+
+ @array[(..3).step(2)].should == [0, 2]
+ @array[(...3).step(2)].should == [0, 2]
+
+ @array[(..3).step(10)].should == [0]
+ @array[(...3).step(10)].should == [0]
+
+ # end with negative index
+ @array[(..-2).step(1)].should == [0, 1, 2, 3, 4,]
+ @array[(...-2).step(1)].should == [0, 1, 2, 3]
+
+ @array[(..-2).step(2)].should == [0, 2, 4]
+ @array[(...-2).step(2)].should == [0, 2]
+
+ @array[(..-2).step(10)].should == [0]
+ @array[(...-2).step(10)].should == [0]
+ end
+
+ it "has endless range and negative steps" do
+ @array[eval("(0..).step(-1)")].should == [0]
+ @array[eval("(0..).step(-2)")].should == [0]
+ @array[eval("(0..).step(-10)")].should == [0]
+
+ @array[eval("(2..).step(-1)")].should == [2, 1, 0]
+ @array[eval("(2..).step(-2)")].should == [2, 0]
+
+ @array[eval("(-3..).step(-1)")].should == [3, 2, 1, 0]
+ @array[eval("(-3..).step(-2)")].should == [3, 1]
+ end
+
+ it "has closed range and positive steps" do
+ # start and end with 0
+ @array[eval("(0..0).step(1)")].should == [0]
+ @array[eval("(0...0).step(1)")].should == []
+
+ @array[eval("(0..0).step(2)")].should == [0]
+ @array[eval("(0...0).step(2)")].should == []
+
+ @array[eval("(0..0).step(10)")].should == [0]
+ @array[eval("(0...0).step(10)")].should == []
+
+ # start and end with positive index
+ @array[eval("(1..3).step(1)")].should == [1, 2, 3]
+ @array[eval("(1...3).step(1)")].should == [1, 2]
+
+ @array[eval("(1..3).step(2)")].should == [1, 3]
+ @array[eval("(1...3).step(2)")].should == [1]
+
+ @array[eval("(1..3).step(10)")].should == [1]
+ @array[eval("(1...3).step(10)")].should == [1]
+
+ # start with positive index, end with negative index
+ @array[eval("(1..-2).step(1)")].should == [1, 2, 3, 4]
+ @array[eval("(1...-2).step(1)")].should == [1, 2, 3]
+
+ @array[eval("(1..-2).step(2)")].should == [1, 3]
+ @array[eval("(1...-2).step(2)")].should == [1, 3]
+
+ @array[eval("(1..-2).step(10)")].should == [1]
+ @array[eval("(1...-2).step(10)")].should == [1]
+
+ # start with negative index, end with positive index
+ @array[eval("(-4..4).step(1)")].should == [2, 3, 4]
+ @array[eval("(-4...4).step(1)")].should == [2, 3]
+
+ @array[eval("(-4..4).step(2)")].should == [2, 4]
+ @array[eval("(-4...4).step(2)")].should == [2]
+
+ @array[eval("(-4..4).step(10)")].should == [2]
+ @array[eval("(-4...4).step(10)")].should == [2]
+
+ # start with negative index, end with negative index
+ @array[eval("(-4..-2).step(1)")].should == [2, 3, 4]
+ @array[eval("(-4...-2).step(1)")].should == [2, 3]
+
+ @array[eval("(-4..-2).step(2)")].should == [2, 4]
+ @array[eval("(-4...-2).step(2)")].should == [2]
+
+ @array[eval("(-4..-2).step(10)")].should == [2]
+ @array[eval("(-4...-2).step(10)")].should == [2]
+ end
+
+ it "has closed range and negative steps" do
+ # start and end with 0
+ @array[eval("(0..0).step(-1)")].should == [0]
+ @array[eval("(0...0).step(-1)")].should == []
+
+ @array[eval("(0..0).step(-2)")].should == [0]
+ @array[eval("(0...0).step(-2)")].should == []
+
+ @array[eval("(0..0).step(-10)")].should == [0]
+ @array[eval("(0...0).step(-10)")].should == []
+
+ # start and end with positive index
+ @array[eval("(1..3).step(-1)")].should == []
+ @array[eval("(1...3).step(-1)")].should == []
+
+ @array[eval("(1..3).step(-2)")].should == []
+ @array[eval("(1...3).step(-2)")].should == []
+
+ @array[eval("(1..3).step(-10)")].should == []
+ @array[eval("(1...3).step(-10)")].should == []
+
+ # start with positive index, end with negative index
+ @array[eval("(1..-2).step(-1)")].should == []
+ @array[eval("(1...-2).step(-1)")].should == []
+
+ @array[eval("(1..-2).step(-2)")].should == []
+ @array[eval("(1...-2).step(-2)")].should == []
+
+ @array[eval("(1..-2).step(-10)")].should == []
+ @array[eval("(1...-2).step(-10)")].should == []
+
+ # start with negative index, end with positive index
+ @array[eval("(-4..4).step(-1)")].should == []
+ @array[eval("(-4...4).step(-1)")].should == []
+
+ @array[eval("(-4..4).step(-2)")].should == []
+ @array[eval("(-4...4).step(-2)")].should == []
+
+ @array[eval("(-4..4).step(-10)")].should == []
+ @array[eval("(-4...4).step(-10)")].should == []
+
+ # start with negative index, end with negative index
+ @array[eval("(-4..-2).step(-1)")].should == []
+ @array[eval("(-4...-2).step(-1)")].should == []
+
+ @array[eval("(-4..-2).step(-2)")].should == []
+ @array[eval("(-4...-2).step(-2)")].should == []
+
+ @array[eval("(-4..-2).step(-10)")].should == []
+ @array[eval("(-4...-2).step(-10)")].should == []
+ end
+
+ it "has inverted closed range and positive steps" do
+ # start and end with positive index
+ @array[eval("(3..1).step(1)")].should == []
+ @array[eval("(3...1).step(1)")].should == []
+
+ @array[eval("(3..1).step(2)")].should == []
+ @array[eval("(3...1).step(2)")].should == []
+
+ @array[eval("(3..1).step(10)")].should == []
+ @array[eval("(3...1).step(10)")].should == []
+
+ # start with negative index, end with positive index
+ @array[eval("(-2..1).step(1)")].should == []
+ @array[eval("(-2...1).step(1)")].should == []
+
+ @array[eval("(-2..1).step(2)")].should == []
+ @array[eval("(-2...1).step(2)")].should == []
+
+ @array[eval("(-2..1).step(10)")].should == []
+ @array[eval("(-2...1).step(10)")].should == []
+
+ # start with positive index, end with negative index
+ @array[eval("(4..-4).step(1)")].should == []
+ @array[eval("(4...-4).step(1)")].should == []
+
+ @array[eval("(4..-4).step(2)")].should == []
+ @array[eval("(4...-4).step(2)")].should == []
+
+ @array[eval("(4..-4).step(10)")].should == []
+ @array[eval("(4...-4).step(10)")].should == []
+
+ # start with negative index, end with negative index
+ @array[eval("(-2..-4).step(1)")].should == []
+ @array[eval("(-2...-4).step(1)")].should == []
+
+ @array[eval("(-2..-4).step(2)")].should == []
+ @array[eval("(-2...-4).step(2)")].should == []
+
+ @array[eval("(-2..-4).step(10)")].should == []
+ @array[eval("(-2...-4).step(10)")].should == []
+ end
+
+ it "has range with bounds outside of array" do
+ # end is equal to array's length
+ @array[(0..6).step(1)].should == [0, 1, 2, 3, 4, 5]
+ -> { @array[(0..6).step(2)] }.should.raise(RangeError)
+
+ # end is greater than length with positive steps
+ @array[(1..6).step(2)].should == [1, 3, 5]
+ @array[(2..7).step(2)].should == [2, 4]
+ -> { @array[(2..8).step(2)] }.should.raise(RangeError)
+
+ # begin is greater than length with negative steps
+ @array[(6..1).step(-2)].should == [5, 3, 1]
+ @array[(7..2).step(-2)].should == [5, 3]
+ -> { @array[(8..2).step(-2)] }.should.raise(RangeError)
+ end
+
+ it "has endless range with start outside of array's bounds" do
+ @array[eval("(6..).step(1)")].should == []
+ @array[eval("(7..).step(1)")].should == nil
+
+ @array[eval("(6..).step(2)")].should == []
+ -> { @array[eval("(7..).step(2)")] }.should.raise(RangeError)
+ end
+ end
+
+ it "can accept beginless ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[(..3)].should == [0, 1, 2, 3]
+ a[(...3)].should == [0, 1, 2]
+ a[(..-3)].should == [0, 1, 2, 3]
+ a[(...-3)].should == [0, 1, 2]
+ a[(..0)].should == [0]
+ a[(...0)].should == []
+ a[(..9)].should == [0, 1, 2, 3, 4, 5]
+ a[(...9)].should == [0, 1, 2, 3, 4, 5]
+ a[(..-9)].should == []
+ a[(...-9)].should == []
+ end
+
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ it "with infinite/inverted ranges and negative steps" do
+ array = [0, 1, 2, 3, 4, 5]
+ array[(2..).step(-1)].should == [2, 1, 0]
+ array[(2..).step(-2)].should == [2, 0]
+ array[(2..).step(-3)].should == [2]
+ array[(2..).step(-4)].should == [2]
+
+ array[(-3..).step(-1)].should == [3, 2, 1, 0]
+ array[(-3..).step(-2)].should == [3, 1]
+ array[(-3..).step(-3)].should == [3, 0]
+ array[(-3..).step(-4)].should == [3]
+ array[(-3..).step(-5)].should == [3]
+
+ array[(..0).step(-1)].should == [5, 4, 3, 2, 1, 0]
+ array[(..0).step(-2)].should == [5, 3, 1]
+ array[(..0).step(-3)].should == [5, 2]
+ array[(..0).step(-4)].should == [5, 1]
+ array[(..0).step(-5)].should == [5, 0]
+ array[(..0).step(-6)].should == [5]
+ array[(..0).step(-7)].should == [5]
+
+ array[(...0).step(-1)].should == [5, 4, 3, 2, 1]
+ array[(...0).step(-2)].should == [5, 3, 1]
+ array[(...0).step(-3)].should == [5, 2]
+ array[(...0).step(-4)].should == [5, 1]
+ array[(...0).step(-5)].should == [5]
+ array[(...0).step(-6)].should == [5]
+
+ array[(...1).step(-1)].should == [5, 4, 3, 2]
+ array[(...1).step(-2)].should == [5, 3]
+ array[(...1).step(-3)].should == [5, 2]
+ array[(...1).step(-4)].should == [5]
+ array[(...1).step(-5)].should == [5]
+
+ array[(..-5).step(-1)].should == [5, 4, 3, 2, 1]
+ array[(..-5).step(-2)].should == [5, 3, 1]
+ array[(..-5).step(-3)].should == [5, 2]
+ array[(..-5).step(-4)].should == [5, 1]
+ array[(..-5).step(-5)].should == [5]
+ array[(..-5).step(-6)].should == [5]
+
+ array[(...-5).step(-1)].should == [5, 4, 3, 2]
+ array[(...-5).step(-2)].should == [5, 3]
+ array[(...-5).step(-3)].should == [5, 2]
+ array[(...-5).step(-4)].should == [5]
+ array[(...-5).step(-5)].should == [5]
+
+ array[(4..1).step(-1)].should == [4, 3, 2, 1]
+ array[(4..1).step(-2)].should == [4, 2]
+ array[(4..1).step(-3)].should == [4, 1]
+ array[(4..1).step(-4)].should == [4]
+ array[(4..1).step(-5)].should == [4]
+
+ array[(4...1).step(-1)].should == [4, 3, 2]
+ array[(4...1).step(-2)].should == [4, 2]
+ array[(4...1).step(-3)].should == [4]
+ array[(4...1).step(-4)].should == [4]
+
+ array[(-2..1).step(-1)].should == [4, 3, 2, 1]
+ array[(-2..1).step(-2)].should == [4, 2]
+ array[(-2..1).step(-3)].should == [4, 1]
+ array[(-2..1).step(-4)].should == [4]
+ array[(-2..1).step(-5)].should == [4]
+
+ array[(-2...1).step(-1)].should == [4, 3, 2]
+ array[(-2...1).step(-2)].should == [4, 2]
+ array[(-2...1).step(-3)].should == [4]
+ array[(-2...1).step(-4)].should == [4]
+
+ array[(4..-5).step(-1)].should == [4, 3, 2, 1]
+ array[(4..-5).step(-2)].should == [4, 2]
+ array[(4..-5).step(-3)].should == [4, 1]
+ array[(4..-5).step(-4)].should == [4]
+ array[(4..-5).step(-5)].should == [4]
+
+ array[(4...-5).step(-1)].should == [4, 3, 2]
+ array[(4...-5).step(-2)].should == [4, 2]
+ array[(4...-5).step(-3)].should == [4]
+ array[(4...-5).step(-4)].should == [4]
+
+ array[(-2..-5).step(-1)].should == [4, 3, 2, 1]
+ array[(-2..-5).step(-2)].should == [4, 2]
+ array[(-2..-5).step(-3)].should == [4, 1]
+ array[(-2..-5).step(-4)].should == [4]
+ array[(-2..-5).step(-5)].should == [4]
+
+ array[(-2...-5).step(-1)].should == [4, 3, 2]
+ array[(-2...-5).step(-2)].should == [4, 2]
+ array[(-2...-5).step(-3)].should == [4]
+ array[(-2...-5).step(-4)].should == [4]
+ end
+ end
+
+ it "can accept nil...nil ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[eval("(nil...nil)")].should == a
+ a[(...nil)].should == a
+ a[eval("(nil..)")].should == a
+ end
end
describe "Array.[]" do
@@ -39,12 +892,12 @@ describe "Array.[]" do
end
it "returns an instance of the subclass" do
- ArraySpecs::MyArray[1, 2, 3].should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray[1, 2, 3].should.instance_of?(ArraySpecs::MyArray)
end
it "does not call #initialize on the subclass instance" do
ArraySpecs::MyArray[1, 2, 3].should == [1, 2, 3]
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
end
diff --git a/spec/ruby/core/array/element_set_spec.rb b/spec/ruby/core/array/element_set_spec.rb
index 9992e4d32b..671e4338de 100644
--- a/spec/ruby/core/array/element_set_spec.rb
+++ b/spec/ruby/core/array/element_set_spec.rb
@@ -36,6 +36,7 @@ describe "Array#[]=" do
a[3, 2] = ['a', 'b', 'c', 'd']
a.should == [2, 2, 3, "a", "b", "c", "d", 6]
end
+
it "replaces the section defined by [start,length] with the given values" do
a = [1, 2, 3, 4, 5, 6]
a[3, 2] = 'a', 'b', 'c', 'd'
@@ -94,8 +95,8 @@ describe "Array#[]=" do
it "checks frozen before attempting to coerce arguments" do
a = [1,2,3,4].freeze
- lambda {a[:foo] = 1}.should raise_error(frozen_error_class)
- lambda {a[:foo, :bar] = 1}.should raise_error(frozen_error_class)
+ -> {a[:foo] = 1}.should.raise(FrozenError)
+ -> {a[:foo, :bar] = 1}.should.raise(FrozenError)
end
it "sets elements in the range arguments when passed ranges" do
@@ -169,6 +170,7 @@ describe "Array#[]=" do
ary[1...1] = []
ary.should == [1, 2, 3]
end
+
it "does nothing if the section defined by range has negative width and the rhs is an empty array" do
ary = [1, 2, 3, 4, 5]
ary[1...0] = []
@@ -195,25 +197,25 @@ describe "Array#[]=" do
a[to .. from] = ["x"]
a.should == [1, "a", "b", "x", "c", 4]
- lambda { a["a" .. "b"] = [] }.should raise_error(TypeError)
- lambda { a[from .. "b"] = [] }.should raise_error(TypeError)
+ -> { a["a" .. "b"] = [] }.should.raise(TypeError)
+ -> { a[from .. "b"] = [] }.should.raise(TypeError)
end
it "raises an IndexError when passed indexes out of bounds" do
a = [1, 2, 3, 4]
- lambda { a[-5] = "" }.should raise_error(IndexError)
- lambda { a[-5, -1] = "" }.should raise_error(IndexError)
- lambda { a[-5, 0] = "" }.should raise_error(IndexError)
- lambda { a[-5, 1] = "" }.should raise_error(IndexError)
- lambda { a[-5, 2] = "" }.should raise_error(IndexError)
- lambda { a[-5, 10] = "" }.should raise_error(IndexError)
-
- lambda { a[-5..-5] = "" }.should raise_error(RangeError)
- lambda { a[-5...-5] = "" }.should raise_error(RangeError)
- lambda { a[-5..-4] = "" }.should raise_error(RangeError)
- lambda { a[-5...-4] = "" }.should raise_error(RangeError)
- lambda { a[-5..10] = "" }.should raise_error(RangeError)
- lambda { a[-5...10] = "" }.should raise_error(RangeError)
+ -> { a[-5] = "" }.should.raise(IndexError)
+ -> { a[-5, -1] = "" }.should.raise(IndexError)
+ -> { a[-5, 0] = "" }.should.raise(IndexError)
+ -> { a[-5, 1] = "" }.should.raise(IndexError)
+ -> { a[-5, 2] = "" }.should.raise(IndexError)
+ -> { a[-5, 10] = "" }.should.raise(IndexError)
+
+ -> { a[-5..-5] = "" }.should.raise(RangeError)
+ -> { a[-5...-5] = "" }.should.raise(RangeError)
+ -> { a[-5..-4] = "" }.should.raise(RangeError)
+ -> { a[-5...-4] = "" }.should.raise(RangeError)
+ -> { a[-5..10] = "" }.should.raise(RangeError)
+ -> { a[-5...10] = "" }.should.raise(RangeError)
# ok
a[0..-9] = [1]
@@ -236,8 +238,8 @@ describe "Array#[]=" do
ary.should == [5, 6, 7]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array[0, 0] = [] }.should.raise(FrozenError)
end
end
@@ -284,6 +286,12 @@ describe "Array#[]= with [index, count]" do
(a[2, 3] = [4, 5]).should == [4, 5]
end
+ it "accepts a frozen String literal as RHS" do
+ a = ['a', 'b', 'c']
+ a[0, 2] = 'd'.freeze
+ a.should == ['d', 'c']
+ end
+
it "just sets the section defined by [start,length] to nil even if the rhs is nil" do
a = ['a', 'b', 'c', 'd', 'e']
a[1, 3] = nil
@@ -323,6 +331,10 @@ describe "Array#[]= with [index, count]" do
b = [1, 2, 3, 4, 5]
b[10, 0] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1]
+
+ c = [1, 2, 3, 4, 5]
+ c[10, 0] = []
+ c.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil]
end
it "inserts other section in place defined by idx" do
@@ -337,12 +349,12 @@ describe "Array#[]= with [index, count]" do
it "raises an IndexError when passed start and negative length" do
a = [1, 2, 3, 4]
- lambda { a[-2, -1] = "" }.should raise_error(IndexError)
- lambda { a[0, -1] = "" }.should raise_error(IndexError)
- lambda { a[2, -1] = "" }.should raise_error(IndexError)
- lambda { a[4, -1] = "" }.should raise_error(IndexError)
- lambda { a[10, -1] = "" }.should raise_error(IndexError)
- lambda { [1, 2, 3, 4, 5][2, -1] = [7, 8] }.should raise_error(IndexError)
+ -> { a[-2, -1] = "" }.should.raise(IndexError)
+ -> { a[0, -1] = "" }.should.raise(IndexError)
+ -> { a[2, -1] = "" }.should.raise(IndexError)
+ -> { a[4, -1] = "" }.should.raise(IndexError)
+ -> { a[10, -1] = "" }.should.raise(IndexError)
+ -> { [1, 2, 3, 4, 5][2, -1] = [7, 8] }.should.raise(IndexError)
end
end
@@ -396,6 +408,14 @@ describe "Array#[]= with [m..n]" do
a.should == [1, 2, 3, 8, 4, 5]
end
+ it "inserts at the end if m > the array size" do
+ a = [1, 2, 3]
+ a[3..3] = [4]
+ a.should == [1, 2, 3, 4]
+ a[5..7] = [6]
+ a.should == [1, 2, 3, 4, nil, 6]
+ end
+
describe "Range subclasses" do
before :each do
@range_incl = ArraySpecs::MyRange.new(1, 2)
@@ -425,6 +445,87 @@ describe "Array#[]= with [m..n]" do
end
end
+describe "Array#[]= with [m..]" do
+ it "just sets the section defined by range to nil even if the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(2..)")] = nil
+ a.should == [1, 2, nil]
+ end
+
+ it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(-3..)")] = nil
+ a.should == [1, 2, nil]
+ end
+
+ it "replaces the section defined by range" do
+ a = [6, 5, 4, 3, 2, 1]
+ a[eval("(3...)")] = 9
+ a.should == [6, 5, 4, 9]
+ a[eval("(2..)")] = [7, 7, 7]
+ a.should == [6, 5, 7, 7, 7]
+ end
+
+ it "replaces the section if m and n < 0" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(-3..)")] = [7, 8, 9]
+ a.should == [1, 2, 7, 8, 9]
+ end
+
+ it "inserts at the end if m > the array size" do
+ a = [1, 2, 3]
+ a[eval("(3..)")] = [4]
+ a.should == [1, 2, 3, 4]
+ a[eval("(5..)")] = [6]
+ a.should == [1, 2, 3, 4, nil, 6]
+ end
+end
+
+describe "Array#[]= with [..n] and [...n]" do
+ it "just sets the section defined by range to nil even if the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[(..2)] = nil
+ a.should == [nil, 4, 5]
+ a[(...2)] = nil
+ a.should == [nil, 5]
+ end
+
+ it "just sets the section defined by range to nil if n < 0 and the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[(..-3)] = nil
+ a.should == [nil, 4, 5]
+ a[(...-1)] = [nil, 5]
+ end
+
+ it "replaces the section defined by range" do
+ a = [6, 5, 4, 3, 2, 1]
+ a[(...3)] = 9
+ a.should == [9, 3, 2, 1]
+ a[(..2)] = [7, 7, 7, 7, 7]
+ a.should == [7, 7, 7, 7, 7, 1]
+ end
+
+ it "replaces the section if n < 0" do
+ a = [1, 2, 3, 4, 5]
+ a[(..-2)] = [7, 8, 9]
+ a.should == [7, 8, 9, 5]
+ end
+
+ it "replaces everything if n > the array size" do
+ a = [1, 2, 3]
+ a[(...7)] = [4]
+ a.should == [4]
+ end
+
+ it "inserts at the beginning if n < negative the array size" do
+ a = [1, 2, 3]
+ a[(..-7)] = [4]
+ a.should == [4, 1, 2, 3]
+ a[(...-10)] = [6]
+ a.should == [6, 4, 1, 2, 3]
+ end
+end
+
describe "Array#[] after a shift" do
it "works for insertion" do
a = [1,2]
diff --git a/spec/ruby/core/array/empty_spec.rb b/spec/ruby/core/array/empty_spec.rb
index b5f3e8ed48..f70b1b6ebe 100644
--- a/spec/ruby/core/array/empty_spec.rb
+++ b/spec/ruby/core/array/empty_spec.rb
@@ -3,8 +3,8 @@ require_relative 'fixtures/classes'
describe "Array#empty?" do
it "returns true if the array has no elements" do
- [].empty?.should == true
- [1].empty?.should == false
- [1, 2].empty?.should == false
+ [].should.empty?
+ [1].should_not.empty?
+ [1, 2].should_not.empty?
end
end
diff --git a/spec/ruby/core/array/eql_spec.rb b/spec/ruby/core/array/eql_spec.rb
index 8565b94c60..9a7447c2e8 100644
--- a/spec/ruby/core/array/eql_spec.rb
+++ b/spec/ruby/core/array/eql_spec.rb
@@ -6,7 +6,7 @@ describe "Array#eql?" do
it_behaves_like :array_eql, :eql?
it "returns false if any corresponding elements are not #eql?" do
- [1, 2, 3, 4].should_not eql([1, 2, 3, 4.0])
+ [1, 2, 3, 4].should_not.eql?([1, 2, 3, 4.0])
end
it "returns false if other is not a kind of Array" do
@@ -14,6 +14,6 @@ describe "Array#eql?" do
obj.should_not_receive(:to_ary)
obj.should_not_receive(:eql?)
- [1, 2, 3].should_not eql(obj)
+ [1, 2, 3].should_not.eql?(obj)
end
end
diff --git a/spec/ruby/core/array/equal_value_spec.rb b/spec/ruby/core/array/equal_value_spec.rb
index 39117c3d7c..4f7c0ce5e3 100644
--- a/spec/ruby/core/array/equal_value_spec.rb
+++ b/spec/ruby/core/array/equal_value_spec.rb
@@ -10,17 +10,17 @@ describe "Array#==" do
obj.should_receive(:respond_to?).at_least(1).with(:to_ary).and_return(true)
obj.should_receive(:==).with([1]).at_least(1).and_return(true)
- ([1] == obj).should be_true
- ([[1]] == [obj]).should be_true
- ([[[1], 3], 2] == [[obj, 3], 2]).should be_true
+ ([1] == obj).should == true
+ ([[1]] == [obj]).should == true
+ ([[[1], 3], 2] == [[obj, 3], 2]).should == true
# recursive arrays
arr1 = [[1]]
arr1 << arr1
arr2 = [obj]
arr2 << arr2
- (arr1 == arr2).should be_true
- (arr2 == arr1).should be_true
+ (arr1 == arr2).should == true
+ (arr2 == arr1).should == true
end
it "returns false if any corresponding elements are not #==" do
@@ -44,8 +44,8 @@ describe "Array#==" do
[obj].should == [5]
end
- # As per bug #1720
- it "returns false for [NaN] == [NaN]" do
- [nan_value].should_not == [nan_value]
+ # See https://bugs.ruby-lang.org/issues/1720
+ it "returns true for [NaN] == [NaN] because Array#== first checks with #equal? and NaN.equal?(NaN) is true" do
+ [Float::NAN].should == [Float::NAN]
end
end
diff --git a/spec/ruby/core/array/fetch_spec.rb b/spec/ruby/core/array/fetch_spec.rb
index ccca463935..ee94cfcbb2 100644
--- a/spec/ruby/core/array/fetch_spec.rb
+++ b/spec/ruby/core/array/fetch_spec.rb
@@ -12,9 +12,9 @@ describe "Array#fetch" do
end
it "raises an IndexError if there is no element at index" do
- lambda { [1, 2, 3].fetch(3) }.should raise_error(IndexError)
- lambda { [1, 2, 3].fetch(-4) }.should raise_error(IndexError)
- lambda { [].fetch(0) }.should raise_error(IndexError)
+ -> { [1, 2, 3].fetch(3) }.should.raise(IndexError, "index 3 outside of array bounds: -3...3")
+ -> { [1, 2, 3].fetch(-4) }.should.raise(IndexError, "index -4 outside of array bounds: -3...3")
+ -> { [].fetch(0) }.should.raise(IndexError, "index 0 outside of array bounds: 0...0")
end
it "returns default if there is no element at index if passed a default value" do
@@ -33,11 +33,11 @@ describe "Array#fetch" do
o = mock('5')
def o.to_int(); 5; end
- [1, 2, 3].fetch(o) { |i| i }.should equal(o)
+ [1, 2, 3].fetch(o) { |i| i }.should.equal?(o)
end
it "gives precedence to the default block over the default argument" do
- lambda {
+ -> {
@result = [1, 2, 3].fetch(9, :foo) { |i| i * i }
}.should complain(/block supersedes default value argument/)
@result.should == 81
@@ -50,6 +50,6 @@ describe "Array#fetch" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- lambda { [].fetch("cat") }.should raise_error(TypeError)
+ -> { [].fetch("cat") }.should.raise(TypeError, "no implicit conversion of String into Integer")
end
end
diff --git a/spec/ruby/core/array/fetch_values_spec.rb b/spec/ruby/core/array/fetch_values_spec.rb
new file mode 100644
index 0000000000..237d6ad7f7
--- /dev/null
+++ b/spec/ruby/core/array/fetch_values_spec.rb
@@ -0,0 +1,55 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Array#fetch_values" do
+ before :each do
+ @array = [:a, :b, :c]
+ end
+
+ ruby_version_is "3.4" do
+ describe "with matched indexes" do
+ it "returns the values for indexes" do
+ @array.fetch_values(0).should == [:a]
+ @array.fetch_values(0, 2).should == [:a, :c]
+ @array.fetch_values(-1).should == [:c]
+ end
+
+ it "returns the values for indexes ordered in the order of the requested indexes" do
+ @array.fetch_values(2, 0).should == [:c, :a]
+ end
+ end
+
+ describe "with unmatched indexes" do
+ it "raises a index error if no block is provided" do
+ -> { @array.fetch_values(0, 1, 44) }.should.raise(IndexError, "index 44 outside of array bounds: -3...3")
+ end
+
+ it "returns the default value from block" do
+ @array.fetch_values(44) { |index| "`#{index}' is not found" }.should == ["`44' is not found"]
+ @array.fetch_values(0, 44) { |index| "`#{index}' is not found" }.should == [:a, "`44' is not found"]
+ end
+ end
+
+ describe "without keys" do
+ it "returns an empty Array" do
+ @array.fetch_values.should == []
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+ @array.fetch_values(obj).should == [:c]
+ end
+
+ it "does not support a Range object as argument" do
+ -> {
+ @array.fetch_values(1..2)
+ }.should.raise(TypeError, "no implicit conversion of Range into Integer")
+ end
+
+ it "raises a TypeError when the passed argument can't be coerced to Integer" do
+ -> { [].fetch_values("cat") }.should.raise(TypeError, "no implicit conversion of String into Integer")
+ end
+ end
+end
diff --git a/spec/ruby/core/array/fill_spec.rb b/spec/ruby/core/array/fill_spec.rb
index f953613c26..e4d51bd998 100644
--- a/spec/ruby/core/array/fill_spec.rb
+++ b/spec/ruby/core/array/fill_spec.rb
@@ -3,14 +3,14 @@ require_relative 'fixtures/classes'
describe "Array#fill" do
before :all do
- @never_passed = lambda do |i|
+ @never_passed = -> i do
raise ExpectationNotMetError, "the control path should not pass here"
end
end
it "returns self" do
ary = [1, 2, 3]
- ary.fill(:a).should equal(ary)
+ ary.fill(:a).should.equal?(ary)
end
it "is destructive" do
@@ -21,14 +21,14 @@ describe "Array#fill" do
it "does not replicate the filler" do
ary = [1, 2, 3, 4]
- str = "x"
+ str = +"x"
ary.fill(str).should == [str, str, str, str]
str << "y"
ary.should == [str, str, str, str]
- ary[0].should equal(str)
- ary[1].should equal(str)
- ary[2].should equal(str)
- ary[3].should equal(str)
+ ary[0].should.equal?(str)
+ ary[1].should.equal?(str)
+ ary[2].should.equal?(str)
+ ary[3].should.equal?(str)
end
it "replaces all elements in the array with the filler if not given a index nor a length" do
@@ -43,34 +43,72 @@ describe "Array#fill" do
[nil, nil, nil, nil].fill { |i| i * 2 }.should == [0, 2, 4, 6]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.fill('x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.fill('x') }.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.fill('x') }.should.raise(FrozenError)
end
it "raises an ArgumentError if 4 or more arguments are passed when no block given" do
- lambda { [].fill('a') }.should_not raise_error(ArgumentError)
-
- lambda { [].fill('a', 1) }.should_not raise_error(ArgumentError)
-
- lambda { [].fill('a', 1, 2) }.should_not raise_error(ArgumentError)
- lambda { [].fill('a', 1, 2, true) }.should raise_error(ArgumentError)
+ [].fill('a').should == []
+ [].fill('a', 1).should == []
+ [].fill('a', 1, 2).should == [nil, 'a', 'a']
+ -> { [].fill('a', 1, 2, true) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if no argument passed and no block given" do
- lambda { [].fill }.should raise_error(ArgumentError)
+ -> { [].fill }.should.raise(ArgumentError)
end
it "raises an ArgumentError if 3 or more arguments are passed when a block given" do
- lambda { [].fill() {|i|} }.should_not raise_error(ArgumentError)
+ [].fill() {|i|}.should == []
+ [].fill(1) {|i|}.should == []
+ [].fill(1, 2) {|i|}.should == [nil, nil, nil]
+ -> { [].fill(1, 2, true) {|i|} }.should.raise(ArgumentError)
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.fill { raise StandardError, 'Oops' }
+ rescue
+ end
- lambda { [].fill(1) {|i|} }.should_not raise_error(ArgumentError)
+ a.should == [1, 2, 3]
+ end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.fill do |i|
+ case i
+ when 0 then -1
+ when 1 then -2
+ when 2 then raise StandardError, 'Oops'
+ else 0
+ end
+ end
+ rescue StandardError
+ end
- lambda { [].fill(1, 2) {|i|} }.should_not raise_error(ArgumentError)
- lambda { [].fill(1, 2, true) {|i|} }.should raise_error(ArgumentError)
+ a.should == [-1, -2, 3, 4]
+ end
+
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.fill do |index|
+ ScratchPad << index
+ array << i if i < 100
+ i++
+ index
+ end
+
+ ScratchPad.recorded.should == [0, 1, 2]
end
end
@@ -169,25 +207,25 @@ describe "Array#fill with (filler, index, length)" do
[1, 2, 3, 4, 5].fill(-2, -2, &@never_passed).should == [1, 2, 3, 4, 5]
end
- # See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17481
+ # See: https://blade.ruby-lang.org/ruby-core/17481
it "does not raise an exception if the given length is negative and its absolute value does not exceed the index" do
- lambda { [1, 2, 3, 4].fill('a', 3, -1)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill('a', 3, -2)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill('a', 3, -3)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill('a', 3, -1).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -2).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -3).should == [1, 2, 3, 4]
- lambda { [1, 2, 3, 4].fill(3, -1, &@never_passed)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill(3, -2, &@never_passed)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill(3, -3, &@never_passed)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill(3, -1, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -2, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -3, &@never_passed).should == [1, 2, 3, 4]
end
it "does not raise an exception even if the given length is negative and its absolute value exceeds the index" do
- lambda { [1, 2, 3, 4].fill('a', 3, -4)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill('a', 3, -5)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill('a', 3, -10000)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill('a', 3, -4).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -5).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -10000).should == [1, 2, 3, 4]
- lambda { [1, 2, 3, 4].fill(3, -4, &@never_passed)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill(3, -5, &@never_passed)}.should_not raise_error(ArgumentError)
- lambda { [1, 2, 3, 4].fill(3, -10000, &@never_passed)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill(3, -4, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -5, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -10000, &@never_passed).should == [1, 2, 3, 4]
end
it "tries to convert the second and third arguments to Integers using #to_int" do
@@ -199,17 +237,24 @@ describe "Array#fill with (filler, index, length)" do
end
it "raises a TypeError if the index is not numeric" do
- lambda { [].fill 'a', true }.should raise_error(TypeError)
+ -> { [].fill 'a', true }.should.raise(TypeError)
obj = mock('nonnumeric')
- lambda { [].fill('a', obj) }.should raise_error(TypeError)
+ -> { [].fill('a', obj) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the length is not numeric" do
+ -> { [1, 2, 3].fill("x", 1, "foo") }.should.raise(TypeError, /no implicit conversion of String into Integer/)
+ -> { [1, 2, 3].fill("x", 1, :"foo") }.should.raise(TypeError, /no implicit conversion of Symbol into Integer/)
+ -> { [1, 2, 3].fill("x", 1, Object.new) }.should.raise(TypeError, /no implicit conversion of Object into Integer/)
end
not_supported_on :opal do
it "raises an ArgumentError or RangeError for too-large sizes" do
+ error_types = [RangeError, ArgumentError]
arr = [1, 2, 3]
- lambda { arr.fill(10, 1, fixnum_max) }.should raise_error(ArgumentError)
- lambda { arr.fill(10, 1, bignum_value) }.should raise_error(RangeError)
+ -> { arr.fill(10, 1, fixnum_max) }.should.raise { |err| error_types.should.include?(err.class) }
+ -> { arr.fill(10, 1, bignum_value) }.should.raise(RangeError)
end
end
end
@@ -239,7 +284,7 @@ describe "Array#fill with (filler, range)" do
end
it "raises a TypeError with range and length argument" do
- lambda { [].fill('x', 0 .. 2, 5) }.should raise_error(TypeError)
+ -> { [].fill('x', 0 .. 2, 5) }.should.raise(TypeError)
end
it "replaces elements between the (-m)th to the last and the (n+1)th from the first if given an range m..n where m < 0 and n >= 0" do
@@ -291,13 +336,13 @@ describe "Array#fill with (filler, range)" do
end
it "raises an exception if some of the given range lies before the first of the array" do
- lambda { [1, 2, 3].fill('x', -5..-3) }.should raise_error(RangeError)
- lambda { [1, 2, 3].fill('x', -5...-3) }.should raise_error(RangeError)
- lambda { [1, 2, 3].fill('x', -5..-4) }.should raise_error(RangeError)
+ -> { [1, 2, 3].fill('x', -5..-3) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill('x', -5...-3) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill('x', -5..-4) }.should.raise(RangeError)
- lambda { [1, 2, 3].fill(-5..-3, &@never_passed) }.should raise_error(RangeError)
- lambda { [1, 2, 3].fill(-5...-3, &@never_passed) }.should raise_error(RangeError)
- lambda { [1, 2, 3].fill(-5..-4, &@never_passed) }.should raise_error(RangeError)
+ -> { [1, 2, 3].fill(-5..-3, &@never_passed) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill(-5...-3, &@never_passed) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill(-5..-4, &@never_passed) }.should.raise(RangeError)
end
it "tries to convert the start and end of the passed range to Integers using #to_int" do
@@ -312,6 +357,18 @@ describe "Array#fill with (filler, range)" do
it "raises a TypeError if the start or end of the passed range is not numeric" do
obj = mock('nonnumeric')
def obj.<=>(rhs); rhs == self ? 0 : nil end
- lambda { [].fill('a', obj..obj) }.should raise_error(TypeError)
+ -> { [].fill('a', obj..obj) }.should.raise(TypeError)
+ end
+
+ it "works with endless ranges" do
+ [1, 2, 3, 4].fill('x', eval("(1..)")).should == [1, 'x', 'x', 'x']
+ [1, 2, 3, 4].fill('x', eval("(3...)")).should == [1, 2, 3, 'x']
+ [1, 2, 3, 4].fill(eval("(1..)")) { |x| x + 2 }.should == [1, 3, 4, 5]
+ [1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5]
+ end
+
+ it "works with beginless ranges" do
+ [1, 2, 3, 4].fill('x', (..2)).should == ["x", "x", "x", 4]
+ [1, 2, 3, 4].fill((...2)) { |x| x + 2 }.should == [2, 3, 3, 4]
end
end
diff --git a/spec/ruby/core/array/filter_spec.rb b/spec/ruby/core/array/filter_spec.rb
index ee4f71ca28..6ebda61069 100644
--- a/spec/ruby/core/array/filter_spec.rb
+++ b/spec/ruby/core/array/filter_spec.rb
@@ -1,16 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
-ruby_version_is "2.6" do
- describe "Array#filter" do
- it_behaves_like :array_select, :filter
+describe "Array#filter" do
+ it "is an alias of Array#select" do
+ Array.instance_method(:filter).should == Array.instance_method(:select)
end
+end
- describe "Array#filter!" do
- it "returns nil if no changes were made in the array" do
- [1, 2, 3].filter! { true }.should be_nil
- end
-
- it_behaves_like :keep_if, :filter!
+describe "Array#filter!" do
+ it "is an alias of Array#select!" do
+ Array.instance_method(:filter!).should == Array.instance_method(:select!)
end
end
diff --git a/spec/ruby/core/array/find_index_spec.rb b/spec/ruby/core/array/find_index_spec.rb
index 759472024a..17ff6c04a7 100644
--- a/spec/ruby/core/array/find_index_spec.rb
+++ b/spec/ruby/core/array/find_index_spec.rb
@@ -1,6 +1,42 @@
require_relative '../../spec_helper'
-require_relative 'shared/index'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#find_index" do
- it_behaves_like :array_index, :find_index
+ it "returns the index of the first element == to object" do
+ x = mock('3')
+ def x.==(obj) 3 == obj; end
+
+ [2, x, 3, 1, 3, 1].find_index(3).should == 1
+ [2, 3.0, 3, x, 1, 3, 1].find_index(x).should == 1
+ end
+
+ it "returns 0 if first element == to object" do
+ [2, 1, 3, 2, 5].find_index(2).should == 0
+ end
+
+ it "returns size-1 if only last element == to object" do
+ [2, 1, 3, 1, 5].find_index(5).should == 4
+ end
+
+ it "returns nil if no element == to object" do
+ [2, 1, 1, 1, 1].find_index(3).should == nil
+ end
+
+ it "accepts a block instead of an argument" do
+ [4, 2, 1, 5, 1, 3].find_index {|x| x < 2}.should == 2
+ end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ [4, 2, 1, 5, 1, 3].find_index(5) {|x| x < 2}.should == 3
+ }.should complain(/given block not used/)
+ end
+
+ describe "given no argument and no block" do
+ it "produces an Enumerator" do
+ [].find_index.should.instance_of?(Enumerator)
+ end
+ end
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :find_index
end
diff --git a/spec/ruby/core/array/first_spec.rb b/spec/ruby/core/array/first_spec.rb
index 5a0a25aeef..2c343ac8f6 100644
--- a/spec/ruby/core/array/first_spec.rb
+++ b/spec/ruby/core/array/first_spec.rb
@@ -30,11 +30,11 @@ describe "Array#first" do
end
it "raises an ArgumentError when count is negative" do
- lambda { [1, 2].first(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].first(-1) }.should.raise(ArgumentError)
end
it "raises a RangeError when count is a Bignum" do
- lambda { [].first(bignum_value) }.should raise_error(RangeError)
+ -> { [].first(bignum_value) }.should.raise(RangeError)
end
it "returns the entire array when count > length" do
@@ -53,10 +53,10 @@ describe "Array#first" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.first.should equal(empty)
+ empty.first.should.equal?(empty)
ary = ArraySpecs.head_recursive_array
- ary.first.should equal(ary)
+ ary.first.should.equal?(ary)
end
it "tries to convert the passed argument to an Integer using #to_int" do
@@ -66,19 +66,19 @@ describe "Array#first" do
end
it "raises a TypeError if the passed argument is not numeric" do
- lambda { [1,2].first(nil) }.should raise_error(TypeError)
- lambda { [1,2].first("a") }.should raise_error(TypeError)
+ -> { [1,2].first(nil) }.should.raise(TypeError)
+ -> { [1,2].first("a") }.should.raise(TypeError)
obj = mock("nonnumeric")
- lambda { [1,2].first(obj) }.should raise_error(TypeError)
+ -> { [1,2].first(obj) }.should.raise(TypeError)
end
it "does not return subclass instance when passed count on Array subclasses" do
- ArraySpecs::MyArray[].first(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[].first(2).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(1).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[].first(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[].first(2).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(1).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(2).should.instance_of?(Array)
end
it "is not destructive" do
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index 7ca9067328..05283c0f74 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -40,6 +40,62 @@ module ArraySpecs
a
end
+ # Chi squared critical values for tests with n degrees of freedom at 99% confidence.
+ # Values obtained from NIST Engineering Statistic Handbook at
+ # https://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
+
+ CHI_SQUARED_CRITICAL_VALUES = [
+ 0,
+ 6.635, 9.210, 11.345, 13.277, 15.086, 16.812, 18.475, 20.090, 21.666, 23.209,
+ 24.725, 26.217, 27.688, 29.141, 30.578, 32.000, 33.409, 34.805, 36.191, 37.566,
+ 38.932, 40.289, 41.638, 42.980, 44.314, 45.642, 46.963, 48.278, 49.588, 50.892,
+ 52.191, 53.486, 54.776, 56.061, 57.342, 58.619, 59.893, 61.162, 62.428, 63.691,
+ 64.950, 66.206, 67.459, 68.710, 69.957, 71.201, 72.443, 73.683, 74.919, 76.154,
+ 77.386, 78.616, 79.843, 81.069, 82.292, 83.513, 84.733, 85.950, 87.166, 88.379,
+ 89.591, 90.802, 92.010, 93.217, 94.422, 95.626, 96.828, 98.028, 99.228, 100.425,
+ 101.621, 102.816, 104.010, 105.202, 106.393, 107.583, 108.771, 109.958, 111.144, 112.329,
+ 113.512, 114.695, 115.876, 117.057, 118.236, 119.414, 120.591, 121.767, 122.942, 124.116,
+ 125.289, 126.462, 127.633, 128.803, 129.973, 131.141, 132.309, 133.476, 134.642, 135.807,
+ ]
+
+ def self.measure_sample_fairness(size, samples, iters)
+ ary = Array.new(size) { |x| x }
+ expected = iters.fdiv size
+ (samples).times do |i|
+ chi_results = []
+ 3.times do
+ counts = Array.new(size, 0)
+ iters.times do
+ x = ary.sample(samples)[i]
+ counts[x] += 1
+ end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
+ chi_results << chi_squared
+ break if chi_squared <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+
+ chi_results.min.should <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+ end
+
+ def self.measure_sample_fairness_large_sample_size(size, samples, iters)
+ ary = Array.new(size) { |x| x }
+ counts = Array.new(size, 0)
+ expected = (iters * samples).fdiv size
+ iters.times do
+ ary.sample(samples).each do |sample|
+ counts[sample] += 1
+ end
+ end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
+
+ # Chi squared critical values for tests with 4 degrees of freedom
+ # Values obtained from NIST Engineering Statistic Handbook at
+ # https://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
+
+ chi_squared.should <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+
class MyArray < Array
# The #initialize method has a different signature than Array to help
# catch places in the specs that do not assert the #initialize is not
@@ -81,7 +137,7 @@ module ArraySpecs
end
end
- class ArrayConvertable
+ class ArrayConvertible
attr_accessor :called
def initialize(*values, &block)
@values = values;
@@ -98,6 +154,16 @@ module ArraySpecs
end
end
+ class ArrayMethodMissing
+ def initialize(*values, &block)
+ @values = values;
+ end
+
+ def method_missing(name, *args)
+ @values
+ end
+ end
+
class SortSame
def <=>(other); 0; end
def ==(other); true; end
@@ -126,7 +192,7 @@ module ArraySpecs
attr_accessor :order
end
- class ComparableWithFixnum
+ class ComparableWithInteger
include Comparable
def initialize(num)
@num = num
@@ -144,373 +210,377 @@ module ArraySpecs
end
def self.universal_pack_object
- obj = mock("string float int")
+ obj = mock("string float int".freeze)
obj.stub!(:to_int).and_return(1)
obj.stub!(:to_str).and_return("1")
obj.stub!(:to_f).and_return(1.0)
obj
end
- LargeArray = ["test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_add_table",
- "assert_difference",
- "assert_operator",
- "instance_variables",
- "class",
- "instance_variable_get",
- "__class__",
- "expects",
- "assert_no_difference",
- "name",
- "assert_blank",
- "assert_not_same",
- "is_a?",
- "test_add_table_with_decimals",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "assert_present",
- "assert_no_match",
- "__instance_of__",
- "assert_deprecated",
- "assert",
- "assert_throws",
- "kind_of?",
- "try",
- "__instance_variable_get__",
- "object_id",
- "timeout",
- "instance_variable_set",
- "assert_nothing_thrown",
- "__instance_variable_set__",
- "copy_object",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "assert_not_deprecated",
- "assert_in_delta",
- "id",
- "copy_metaclass",
- "test_create_table_without_a_block",
- "dup",
- "assert_not_nil",
- "send",
- "__instance_variables__",
- "to_sql",
- "mock",
- "assert_send",
- "instance_variable_defined?",
- "clone",
- "require",
- "test_migrator",
- "__instance_variable_defined_eh__",
- "frozen?",
- "test_add_column_not_null_with_default",
- "freeze",
- "test_migrator_one_up",
- "test_migrator_one_down",
- "singleton_methods",
- "method_exists?",
- "create_fixtures",
- "test_migrator_one_up_one_down",
- "test_native_decimal_insert_manual_vs_automatic",
- "instance_exec",
- "__is_a__",
- "test_migrator_double_up",
- "stub",
- "private_methods",
- "stubs",
- "test_migrator_double_down",
- "fixture_path",
- "private_singleton_methods",
- "stub_everything",
- "test_migrator_one_up_with_exception_and_rollback",
- "sequence",
- "protected_methods",
- "enum_for",
- "test_finds_migrations",
- "run_before_mocha",
- "states",
- "protected_singleton_methods",
- "to_json",
- "instance_values",
- "==",
- "mocha_setup",
- "public_methods",
- "test_finds_pending_migrations",
- "mocha_verify",
- "assert_kind_of",
- "===",
- "=~",
- "test_relative_migrations",
- "mocha_teardown",
- "gem",
- "mocha",
- "test_only_loads_pending_migrations",
- "test_add_column_with_precision_and_scale",
- "require_or_load",
- "eql?",
- "require_dependency",
- "test_native_types",
- "test_target_version_zero_should_run_only_once",
- "extend",
- "to_matcher",
- "unloadable",
- "require_association",
- "hash",
- "__id__",
- "load_dependency",
- "equals",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_verbosity",
- "kind_of",
- "to_yaml",
- "to_bool",
- "test_migrator_verbosity_off",
- "taint",
- "test_migrator_going_down_due_to_version_target",
- "tainted?",
- "mocha_inspect",
- "test_migrator_rollback",
- "vim",
- "untaint",
- "taguri=",
- "test_migrator_forward",
- "test_schema_migrations_table_name",
- "test_proper_table_name",
- "all_of",
- "test_add_drop_table_with_prefix_and_suffix",
- "_setup_callbacks",
- "setup",
- "Not",
- "test_create_table_with_binary_column",
- "assert_not_equal",
- "enable_warnings",
- "acts_like?",
- "Rational",
- "_removed_setup_callbacks",
- "Table",
- "bind",
- "any_of",
- "__method__",
- "test_migrator_with_duplicates",
- "_teardown_callbacks",
- "method",
- "test_migrator_with_duplicate_names",
- "_removed_teardown_callbacks",
- "any_parameters",
- "test_migrator_with_missing_version_numbers",
- "test_add_remove_single_field_using_string_arguments",
- "test_create_table_with_custom_sequence_name",
- "test_add_remove_single_field_using_symbol_arguments",
- "_one_time_conditions_valid_14?",
- "_one_time_conditions_valid_16?",
- "run_callbacks",
- "anything",
- "silence_warnings",
- "instance_variable_names",
- "_fixture_path",
- "copy_instance_variables_from",
- "fixture_path?",
- "has_entry",
- "__marshal__",
- "_fixture_table_names",
- "__kind_of__",
- "fixture_table_names?",
- "test_add_rename",
- "assert_equal",
- "_fixture_class_names",
- "fixture_class_names?",
- "has_entries",
- "_use_transactional_fixtures",
- "people",
- "test_rename_column_using_symbol_arguments",
- "use_transactional_fixtures?",
- "instance_eval",
- "blank?",
- "with_warnings",
- "__nil__",
- "load",
- "metaclass",
- "_use_instantiated_fixtures",
- "has_key",
- "class_eval",
- "present?",
- "test_rename_column",
- "teardown",
- "use_instantiated_fixtures?",
- "method_name",
- "silence_stderr",
- "presence",
- "test_rename_column_preserves_default_value_not_null",
- "silence_stream",
- "_pre_loaded_fixtures",
- "__metaclass__",
- "__fixnum__",
- "pre_loaded_fixtures?",
- "has_value",
- "suppress",
- "to_yaml_properties",
- "test_rename_nonexistent_column",
- "test_add_index",
- "includes",
- "find_correlate_in",
- "equality_predicate_sql",
- "assert_nothing_raised",
- "let",
- "not_predicate_sql",
- "test_rename_column_with_sql_reserved_word",
- "singleton_class",
- "test_rename_column_with_an_index",
- "display",
- "taguri",
- "to_yaml_style",
- "test_remove_column_with_index",
- "size",
- "current_adapter?",
- "test_remove_column_with_multi_column_index",
- "respond_to?",
- "test_change_type_of_not_null_column",
- "is_a",
- "to_a",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "require_library_or_gem",
- "setup_fixtures",
- "equal?",
- "teardown_fixtures",
- "nil?",
- "fixture_table_names",
- "fixture_class_names",
- "test_create_table_without_id",
- "use_transactional_fixtures",
- "test_add_column_with_primary_key_attribute",
- "repair_validations",
- "use_instantiated_fixtures",
- "instance_of?",
- "test_create_table_adds_id",
- "test_rename_table",
- "pre_loaded_fixtures",
- "to_enum",
- "test_create_table_with_not_null_column",
- "instance_of",
- "test_change_column_nullability",
- "optionally",
- "test_rename_table_with_an_index",
- "run",
- "test_change_column",
- "default_test",
- "assert_raise",
- "test_create_table_with_defaults",
- "assert_nil",
- "flunk",
- "regexp_matches",
- "duplicable?",
- "reset_mocha",
- "stubba_method",
- "filter_backtrace",
- "test_create_table_with_limits",
- "responds_with",
- "stubba_object",
- "test_change_column_with_nil_default",
- "assert_block",
- "__show__",
- "assert_date_from_db",
- "__respond_to_eh__",
- "run_in_transaction?",
- "inspect",
- "assert_sql",
- "test_change_column_with_new_default",
- "yaml_equivalent",
- "build_message",
- "to_s",
- "test_change_column_default",
- "assert_queries",
- "pending",
- "as_json",
- "assert_no_queries",
- "test_change_column_quotes_column_names",
- "assert_match",
- "test_keeping_default_and_notnull_constaint_on_change",
- "methods",
- "connection_allow_concurrency_setup",
- "connection_allow_concurrency_teardown",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "__send__",
- "make_connection",
- "assert_raises",
- "tap",
- "with_kcode",
- "assert_instance_of",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "assert_respond_to",
- "test_change_column_default_to_null",
- "assert_same",
- "__extend__"]
-
- LargeTestArraySorted = ["test_add_column_not_null_with_default",
- "test_add_column_with_precision_and_scale",
- "test_add_column_with_primary_key_attribute",
- "test_add_drop_table_with_prefix_and_suffix",
- "test_add_index",
- "test_add_remove_single_field_using_string_arguments",
- "test_add_remove_single_field_using_symbol_arguments",
- "test_add_rename",
- "test_add_table",
- "test_add_table_with_decimals",
- "test_change_column",
- "test_change_column_default",
- "test_change_column_default_to_null",
- "test_change_column_nullability",
- "test_change_column_quotes_column_names",
- "test_change_column_with_new_default",
- "test_change_column_with_nil_default",
- "test_change_type_of_not_null_column",
- "test_create_table_adds_id",
- "test_create_table_with_binary_column",
- "test_create_table_with_custom_sequence_name",
- "test_create_table_with_defaults",
- "test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_create_table_with_limits",
- "test_create_table_with_not_null_column",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "test_create_table_without_a_block",
- "test_create_table_without_id",
- "test_finds_migrations",
- "test_finds_pending_migrations",
- "test_keeping_default_and_notnull_constaint_on_change",
- "test_migrator",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_double_down",
- "test_migrator_double_up",
- "test_migrator_forward",
- "test_migrator_going_down_due_to_version_target",
- "test_migrator_one_down",
- "test_migrator_one_up",
- "test_migrator_one_up_one_down",
- "test_migrator_one_up_with_exception_and_rollback",
- "test_migrator_rollback",
- "test_migrator_verbosity",
- "test_migrator_verbosity_off",
- "test_migrator_with_duplicate_names",
- "test_migrator_with_duplicates",
- "test_migrator_with_missing_version_numbers",
- "test_native_decimal_insert_manual_vs_automatic",
- "test_native_types",
- "test_only_loads_pending_migrations",
- "test_proper_table_name",
- "test_relative_migrations",
- "test_remove_column_with_index",
- "test_remove_column_with_multi_column_index",
- "test_rename_column",
- "test_rename_column_preserves_default_value_not_null",
- "test_rename_column_using_symbol_arguments",
- "test_rename_column_with_an_index",
- "test_rename_column_with_sql_reserved_word",
- "test_rename_nonexistent_column",
- "test_rename_table",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "test_rename_table_with_an_index",
- "test_schema_migrations_table_name",
- "test_target_version_zero_should_run_only_once"]
+ LargeArray = [
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_add_table",
+ "assert_difference",
+ "assert_operator",
+ "instance_variables",
+ "class",
+ "instance_variable_get",
+ "__class__",
+ "expects",
+ "assert_no_difference",
+ "name",
+ "assert_blank",
+ "assert_not_same",
+ "is_a?",
+ "test_add_table_with_decimals",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "assert_present",
+ "assert_no_match",
+ "__instance_of__",
+ "assert_deprecated",
+ "assert",
+ "assert_throws",
+ "kind_of?",
+ "try",
+ "__instance_variable_get__",
+ "object_id",
+ "timeout",
+ "instance_variable_set",
+ "assert_nothing_thrown",
+ "__instance_variable_set__",
+ "copy_object",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "assert_not_deprecated",
+ "assert_in_delta",
+ "id",
+ "copy_metaclass",
+ "test_create_table_without_a_block",
+ "dup",
+ "assert_not_nil",
+ "send",
+ "__instance_variables__",
+ "to_sql",
+ "mock",
+ "assert_send",
+ "instance_variable_defined?",
+ "clone",
+ "require",
+ "test_migrator",
+ "__instance_variable_defined_eh__",
+ "frozen?",
+ "test_add_column_not_null_with_default",
+ "freeze",
+ "test_migrator_one_up",
+ "test_migrator_one_down",
+ "singleton_methods",
+ "method_exists?",
+ "create_fixtures",
+ "test_migrator_one_up_one_down",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "instance_exec",
+ "__is_a__",
+ "test_migrator_double_up",
+ "stub",
+ "private_methods",
+ "stubs",
+ "test_migrator_double_down",
+ "fixture_path",
+ "private_singleton_methods",
+ "stub_everything",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "sequence",
+ "protected_methods",
+ "enum_for",
+ "test_finds_migrations",
+ "run_before_mocha",
+ "states",
+ "protected_singleton_methods",
+ "to_json",
+ "instance_values",
+ "==",
+ "mocha_setup",
+ "public_methods",
+ "test_finds_pending_migrations",
+ "mocha_verify",
+ "assert_kind_of",
+ "===",
+ "=~",
+ "test_relative_migrations",
+ "mocha_teardown",
+ "gem",
+ "mocha",
+ "test_only_loads_pending_migrations",
+ "test_add_column_with_precision_and_scale",
+ "require_or_load",
+ "eql?",
+ "require_dependency",
+ "test_native_types",
+ "test_target_version_zero_should_run_only_once",
+ "extend",
+ "to_matcher",
+ "unloadable",
+ "require_association",
+ "hash",
+ "__id__",
+ "load_dependency",
+ "equals",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_verbosity",
+ "kind_of",
+ "to_yaml",
+ "to_bool",
+ "test_migrator_verbosity_off",
+ "taint",
+ "test_migrator_going_down_due_to_version_target",
+ "tainted?",
+ "mocha_inspect",
+ "test_migrator_rollback",
+ "vim",
+ "untaint",
+ "taguri=",
+ "test_migrator_forward",
+ "test_schema_migrations_table_name",
+ "test_proper_table_name",
+ "all_of",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "_setup_callbacks",
+ "setup",
+ "Not",
+ "test_create_table_with_binary_column",
+ "assert_not_equal",
+ "enable_warnings",
+ "acts_like?",
+ "Rational",
+ "_removed_setup_callbacks",
+ "Table",
+ "bind",
+ "any_of",
+ "__method__",
+ "test_migrator_with_duplicates",
+ "_teardown_callbacks",
+ "method",
+ "test_migrator_with_duplicate_names",
+ "_removed_teardown_callbacks",
+ "any_parameters",
+ "test_migrator_with_missing_version_numbers",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_create_table_with_custom_sequence_name",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "_one_time_conditions_valid_14?",
+ "_one_time_conditions_valid_16?",
+ "run_callbacks",
+ "anything",
+ "silence_warnings",
+ "instance_variable_names",
+ "_fixture_path",
+ "copy_instance_variables_from",
+ "fixture_path?",
+ "has_entry",
+ "__marshal__",
+ "_fixture_table_names",
+ "__kind_of__",
+ "fixture_table_names?",
+ "test_add_rename",
+ "assert_equal",
+ "_fixture_class_names",
+ "fixture_class_names?",
+ "has_entries",
+ "_use_transactional_fixtures",
+ "people",
+ "test_rename_column_using_symbol_arguments",
+ "use_transactional_fixtures?",
+ "instance_eval",
+ "blank?",
+ "with_warnings",
+ "__nil__",
+ "load",
+ "metaclass",
+ "_use_instantiated_fixtures",
+ "has_key",
+ "class_eval",
+ "present?",
+ "test_rename_column",
+ "teardown",
+ "use_instantiated_fixtures?",
+ "method_name",
+ "silence_stderr",
+ "presence",
+ "test_rename_column_preserves_default_value_not_null",
+ "silence_stream",
+ "_pre_loaded_fixtures",
+ "__metaclass__",
+ "__fixnum__",
+ "pre_loaded_fixtures?",
+ "has_value",
+ "suppress",
+ "to_yaml_properties",
+ "test_rename_nonexistent_column",
+ "test_add_index",
+ "includes",
+ "find_correlate_in",
+ "equality_predicate_sql",
+ "assert_nothing_raised",
+ "let",
+ "not_predicate_sql",
+ "test_rename_column_with_sql_reserved_word",
+ "singleton_class",
+ "test_rename_column_with_an_index",
+ "display",
+ "taguri",
+ "to_yaml_style",
+ "test_remove_column_with_index",
+ "size",
+ "current_adapter?",
+ "test_remove_column_with_multi_column_index",
+ "respond_to?",
+ "test_change_type_of_not_null_column",
+ "is_a",
+ "to_a",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "require_library_or_gem",
+ "setup_fixtures",
+ "equal?",
+ "teardown_fixtures",
+ "nil?",
+ "fixture_table_names",
+ "fixture_class_names",
+ "test_create_table_without_id",
+ "use_transactional_fixtures",
+ "test_add_column_with_primary_key_attribute",
+ "repair_validations",
+ "use_instantiated_fixtures",
+ "instance_of?",
+ "test_create_table_adds_id",
+ "test_rename_table",
+ "pre_loaded_fixtures",
+ "to_enum",
+ "test_create_table_with_not_null_column",
+ "instance_of",
+ "test_change_column_nullability",
+ "optionally",
+ "test_rename_table_with_an_index",
+ "run",
+ "test_change_column",
+ "default_test",
+ "assert_raise",
+ "test_create_table_with_defaults",
+ "assert_nil",
+ "flunk",
+ "regexp_matches",
+ "duplicable?",
+ "reset_mocha",
+ "stubba_method",
+ "filter_backtrace",
+ "test_create_table_with_limits",
+ "responds_with",
+ "stubba_object",
+ "test_change_column_with_nil_default",
+ "assert_block",
+ "__show__",
+ "assert_date_from_db",
+ "__respond_to_eh__",
+ "run_in_transaction?",
+ "inspect",
+ "assert_sql",
+ "test_change_column_with_new_default",
+ "yaml_equivalent",
+ "build_message",
+ "to_s",
+ "test_change_column_default",
+ "assert_queries",
+ "pending",
+ "as_json",
+ "assert_no_queries",
+ "test_change_column_quotes_column_names",
+ "assert_match",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "methods",
+ "connection_allow_concurrency_setup",
+ "connection_allow_concurrency_teardown",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "__send__",
+ "make_connection",
+ "assert_raises",
+ "tap",
+ "with_kcode",
+ "assert_instance_of",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "assert_respond_to",
+ "test_change_column_default_to_null",
+ "assert_same",
+ "__extend__",
+ ]
+
+ LargeTestArraySorted = [
+ "test_add_column_not_null_with_default",
+ "test_add_column_with_precision_and_scale",
+ "test_add_column_with_primary_key_attribute",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "test_add_index",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "test_add_rename",
+ "test_add_table",
+ "test_add_table_with_decimals",
+ "test_change_column",
+ "test_change_column_default",
+ "test_change_column_default_to_null",
+ "test_change_column_nullability",
+ "test_change_column_quotes_column_names",
+ "test_change_column_with_new_default",
+ "test_change_column_with_nil_default",
+ "test_change_type_of_not_null_column",
+ "test_create_table_adds_id",
+ "test_create_table_with_binary_column",
+ "test_create_table_with_custom_sequence_name",
+ "test_create_table_with_defaults",
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_create_table_with_limits",
+ "test_create_table_with_not_null_column",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "test_create_table_without_a_block",
+ "test_create_table_without_id",
+ "test_finds_migrations",
+ "test_finds_pending_migrations",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "test_migrator",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_double_down",
+ "test_migrator_double_up",
+ "test_migrator_forward",
+ "test_migrator_going_down_due_to_version_target",
+ "test_migrator_one_down",
+ "test_migrator_one_up",
+ "test_migrator_one_up_one_down",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "test_migrator_rollback",
+ "test_migrator_verbosity",
+ "test_migrator_verbosity_off",
+ "test_migrator_with_duplicate_names",
+ "test_migrator_with_duplicates",
+ "test_migrator_with_missing_version_numbers",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "test_native_types",
+ "test_only_loads_pending_migrations",
+ "test_proper_table_name",
+ "test_relative_migrations",
+ "test_remove_column_with_index",
+ "test_remove_column_with_multi_column_index",
+ "test_rename_column",
+ "test_rename_column_preserves_default_value_not_null",
+ "test_rename_column_using_symbol_arguments",
+ "test_rename_column_with_an_index",
+ "test_rename_column_with_sql_reserved_word",
+ "test_rename_nonexistent_column",
+ "test_rename_table",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "test_rename_table_with_an_index",
+ "test_schema_migrations_table_name",
+ "test_target_version_zero_should_run_only_once",
+ ]
class PrivateToAry
private
diff --git a/spec/ruby/core/array/fixtures/encoded_strings.rb b/spec/ruby/core/array/fixtures/encoded_strings.rb
index e31e247afe..b5888d86ae 100644
--- a/spec/ruby/core/array/fixtures/encoded_strings.rb
+++ b/spec/ruby/core/array/fixtures/encoded_strings.rb
@@ -2,14 +2,14 @@
module ArraySpecs
def self.array_with_usascii_and_7bit_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'bar'
]
end
def self.array_with_usascii_and_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'báz'
]
end
@@ -17,7 +17,7 @@ module ArraySpecs
def self.array_with_7bit_utf8_and_usascii_strings
[
'bar',
- 'foo'.force_encoding('US-ASCII')
+ 'foo'.dup.force_encoding('US-ASCII')
]
end
@@ -25,45 +25,45 @@ module ArraySpecs
[
'báz',
'bar',
- 'foo'.force_encoding('US-ASCII')
+ 'foo'.dup.force_encoding('US-ASCII')
]
end
def self.array_with_usascii_and_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'bar',
'báz'
]
end
- def self.array_with_utf8_and_7bit_ascii8bit_strings
+ def self.array_with_utf8_and_7bit_binary_strings
[
'bar',
'báz',
- 'foo'.force_encoding('ASCII-8BIT')
+ 'foo'.dup.force_encoding('BINARY')
]
end
- def self.array_with_utf8_and_ascii8bit_strings
+ def self.array_with_utf8_and_binary_strings
[
'bar',
'báz',
- [255].pack('C').force_encoding('ASCII-8BIT')
+ [255].pack('C').force_encoding('BINARY')
]
end
- def self.array_with_usascii_and_7bit_ascii8bit_strings
+ def self.array_with_usascii_and_7bit_binary_strings
[
- 'bar'.force_encoding('US-ASCII'),
- 'foo'.force_encoding('ASCII-8BIT')
+ 'bar'.dup.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('BINARY')
]
end
- def self.array_with_usascii_and_ascii8bit_strings
+ def self.array_with_usascii_and_binary_strings
[
- 'bar'.force_encoding('US-ASCII'),
- [255].pack('C').force_encoding('ASCII-8BIT')
+ 'bar'.dup.force_encoding('US-ASCII'),
+ [255].pack('C').force_encoding('BINARY')
]
end
end
diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb
index 1b7361552a..272406b8f9 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -13,7 +13,7 @@ describe "Array#flatten" do
it "returns dup when the level of recursion is 0" do
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(0).should == a
- a.flatten(0).should_not equal(a)
+ a.flatten(0).should_not.equal?(a)
end
it "ignores negative levels" do
@@ -30,7 +30,7 @@ describe "Array#flatten" do
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
- lambda { [ 1, 2, [3, [4, 5] ] ].flatten(obj) }.should raise_error(TypeError)
+ -> { [ 1, 2, [3, [4, 5] ] ].flatten(obj) }.should.raise(TypeError)
end
it "does not call flatten on elements" do
@@ -46,13 +46,13 @@ describe "Array#flatten" do
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
- lambda { x.flatten }.should raise_error(ArgumentError)
+ -> { x.flatten }.should.raise(ArgumentError)
x = []
y = []
x << y
y << x
- lambda { x.flatten }.should raise_error(ArgumentError)
+ -> { x.flatten }.should.raise(ArgumentError)
end
it "flattens any element which responds to #to_ary, using the return value of said method" do
@@ -75,12 +75,12 @@ describe "Array#flatten" do
[[obj]].flatten(1)
end
- it "returns subclass instance for Array subclasses" do
- ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4]
- [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
+ it "returns Array instance for Array subclasses" do
+ ArraySpecs::MyArray[].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, [2], 3].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4]
+ [ArraySpecs::MyArray[1, 2, 3]].flatten.should.instance_of?(Array)
end
it "is not destructive" do
@@ -106,23 +106,13 @@ describe "Array#flatten" do
it "raises a TypeError if #to_ary does not return an Array" do
@obj.should_receive(:to_ary).and_return(1)
- lambda { [@obj].flatten }.should raise_error(TypeError)
+ -> { [@obj].flatten }.should.raise(TypeError)
end
- ruby_version_is ""..."2.5" do
- it "calls respond_to_missing?(:to_ary, false) to try coercing" do
- def @obj.respond_to_missing?(*args) ScratchPad << args; false end
- [@obj].flatten.should == [@obj]
- ScratchPad.recorded.should == [[:to_ary, false]]
- end
- end
-
- ruby_version_is "2.5" do
- it "calls respond_to_missing?(:to_ary, true) to try coercing" do
- def @obj.respond_to_missing?(*args) ScratchPad << args; false end
- [@obj].flatten.should == [@obj]
- ScratchPad.recorded.should == [[:to_ary, true]]
- end
+ it "calls respond_to_missing?(:to_ary, true) to try coercing" do
+ def @obj.respond_to_missing?(*args) ScratchPad << args; false end
+ [@obj].flatten.should == [@obj]
+ ScratchPad.recorded.should == [[:to_ary, true]]
end
it "does not call #to_ary if not defined when #respond_to_missing? returns false" do
@@ -135,7 +125,7 @@ describe "Array#flatten" do
it "calls #to_ary if not defined when #respond_to_missing? returns true" do
def @obj.respond_to_missing?(name, priv) ScratchPad << name; true end
- lambda { [@obj].flatten }.should raise_error(NoMethodError)
+ -> { [@obj].flatten }.should.raise(NoMethodError)
ScratchPad.recorded.should == [:to_ary]
end
@@ -145,14 +135,6 @@ describe "Array#flatten" do
end
end
- it "returns a tainted array if self is tainted" do
- [].taint.flatten.tainted?.should be_true
- end
-
- it "returns an untrusted array if self is untrusted" do
- [].untrust.flatten.untrusted?.should be_true
- end
-
it "performs respond_to? and method_missing-aware checks when coercing elements to array" do
bo = BasicObject.new
[bo].flatten.should == [bo]
@@ -186,7 +168,7 @@ describe "Array#flatten!" do
it "returns self if made some modifications" do
a = [[[1, [2, 3]],[2, 3, [4, [4, [5, 5]], [1, 2, 3]]], [4]], []]
- a.flatten!.should equal(a)
+ a.flatten!.should.equal?(a)
end
it "returns nil if no modifications took place" do
@@ -226,7 +208,7 @@ describe "Array#flatten!" do
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
- lambda { [ 1, 2, [3, [4, 5] ] ].flatten!(obj) }.should raise_error(TypeError)
+ -> { [ 1, 2, [3, [4, 5] ] ].flatten!(obj) }.should.raise(TypeError)
end
it "does not call flatten! on elements" do
@@ -242,13 +224,13 @@ describe "Array#flatten!" do
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
- lambda { x.flatten! }.should raise_error(ArgumentError)
+ -> { x.flatten! }.should.raise(ArgumentError)
x = []
y = []
x << y
y << x
- lambda { x.flatten! }.should raise_error(ArgumentError)
+ -> { x.flatten! }.should.raise(ArgumentError)
end
it "flattens any elements which responds to #to_ary, using the return value of said method" do
@@ -266,19 +248,19 @@ describe "Array#flatten!" do
ary = [ArraySpecs::MyArray[1, 2, 3]]
ary.flatten!
- ary.should be_an_instance_of(Array)
+ ary.should.instance_of?(Array)
ary.should == [1, 2, 3]
end
- it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do
+ it "raises a FrozenError on frozen arrays when the array is modified" do
nested_ary = [1, 2, []]
nested_ary.freeze
- lambda { nested_ary.flatten! }.should raise_error(frozen_error_class)
+ -> { nested_ary.flatten! }.should.raise(FrozenError)
end
# see [ruby-core:23663]
- it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do
- lambda { ArraySpecs.frozen_array.flatten! }.should raise_error(frozen_error_class)
- lambda { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.flatten! }.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.flatten! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/frozen_spec.rb b/spec/ruby/core/array/frozen_spec.rb
index bb4b2b4067..3ba54be46b 100644
--- a/spec/ruby/core/array/frozen_spec.rb
+++ b/spec/ruby/core/array/frozen_spec.rb
@@ -4,13 +4,13 @@ require_relative 'fixtures/classes'
describe "Array#frozen?" do
it "returns true if array is frozen" do
a = [1, 2, 3]
- a.frozen?.should == false
+ a.should_not.frozen?
a.freeze
- a.frozen?.should == true
+ a.should.frozen?
end
it "returns false for an array being sorted by #sort" do
a = [1, 2, 3]
- a.sort { |x,y| a.frozen?.should == false; x <=> y }
+ a.sort { |x,y| a.should_not.frozen?; x <=> y }
end
end
diff --git a/spec/ruby/core/array/hash_spec.rb b/spec/ruby/core/array/hash_spec.rb
index 638acff12b..3b7b6d5bed 100644
--- a/spec/ruby/core/array/hash_spec.rb
+++ b/spec/ruby/core/array/hash_spec.rb
@@ -7,16 +7,16 @@ describe "Array#hash" do
[[], [1, 2, 3]].each do |ary|
ary.hash.should == ary.dup.hash
- ary.hash.should be_an_instance_of(Fixnum)
+ ary.hash.should.instance_of?(Integer)
end
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- lambda { empty.hash }.should_not raise_error
+ -> { empty.hash }.should_not.raise
array = ArraySpecs.recursive_array
- lambda { array.hash }.should_not raise_error
+ -> { array.hash }.should_not.raise
end
it "returns the same hash for equal recursive arrays" do
@@ -74,7 +74,7 @@ describe "Array#hash" do
a.fill 'a', 0..3
b = %w|a a a a|
a.hash.should == b.hash
- a.should eql(b)
+ a.should.eql?(b)
end
it "produces different hashes for nested arrays with different values and empty terminator" do
diff --git a/spec/ruby/core/array/index_spec.rb b/spec/ruby/core/array/index_spec.rb
index 3acb7d0ef3..b66cb6eb53 100644
--- a/spec/ruby/core/array/index_spec.rb
+++ b/spec/ruby/core/array/index_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/index'
describe "Array#index" do
- it_behaves_like :array_index, :index
+ it "is an alias of Array#find_index" do
+ Array.instance_method(:index).should == Array.instance_method(:find_index)
+ end
end
diff --git a/spec/ruby/core/array/initialize_spec.rb b/spec/ruby/core/array/initialize_spec.rb
index 350538a222..19ee37825e 100644
--- a/spec/ruby/core/array/initialize_spec.rb
+++ b/spec/ruby/core/array/initialize_spec.rb
@@ -7,7 +7,7 @@ describe "Array#initialize" do
end
it "is private" do
- Array.should have_private_instance_method("initialize")
+ Array.private_instance_methods(false).should.include?(:initialize)
end
it "is called on subclasses" do
@@ -19,26 +19,26 @@ describe "Array#initialize" do
it "preserves the object's identity even when changing its value" do
a = [1, 2, 3]
- a.send(:initialize).should equal(a)
+ a.send(:initialize).should.equal?(a)
a.should_not == [1, 2, 3]
end
it "raises an ArgumentError if passed 3 or more arguments" do
- lambda do
+ -> do
[1, 2].send :initialize, 1, 'x', true
- end.should raise_error(ArgumentError)
- lambda do
+ end.should.raise(ArgumentError)
+ -> do
[1, 2].send(:initialize, 1, 'x', true) {}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
- it "raises a #{frozen_error_class} on frozen arrays" do
- lambda do
+ it "raises a FrozenError on frozen arrays" do
+ -> do
ArraySpecs.frozen_array.send :initialize
- end.should raise_error(frozen_error_class)
- lambda do
+ end.should.raise(FrozenError)
+ -> do
ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
- end.should raise_error(frozen_error_class)
+ end.should.raise(FrozenError)
end
it "calls #to_ary to convert the value to an array, even if it's private" do
@@ -49,11 +49,13 @@ end
describe "Array#initialize with no arguments" do
it "makes the array empty" do
- [1, 2, 3].send(:initialize).should be_empty
+ [1, 2, 3].send(:initialize).should.empty?
end
it "does not use the given block" do
- lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ -> {
+ -> { [1, 2, 3].send(:initialize) { raise } }.should_not.raise
+ }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true)
end
end
@@ -64,7 +66,7 @@ describe "Array#initialize with (array)" do
end
it "does not use the given block" do
- lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ ->{ [1, 2, 3].send(:initialize) { raise } }.should_not.raise
end
it "calls #to_ary to convert the value to an array" do
@@ -81,7 +83,7 @@ describe "Array#initialize with (array)" do
end
it "raises a TypeError if an Array type argument and a default object" do
- lambda { [].send(:initialize, [1, 2], 1) }.should raise_error(TypeError)
+ -> { [].send(:initialize, [1, 2], 1) }.should.raise(TypeError)
end
end
@@ -90,8 +92,8 @@ describe "Array#initialize with (size, object=nil)" do
a = []
obj = [3]
a.send(:initialize, 2, obj).should == [obj, obj]
- a[0].should equal(obj)
- a[1].should equal(obj)
+ a[0].should.equal?(obj)
+ a[1].should.equal?(obj)
b = []
b.send(:initialize, 3, 14).should == [14, 14, 14]
@@ -103,12 +105,12 @@ describe "Array#initialize with (size, object=nil)" do
end
it "raises an ArgumentError if size is negative" do
- lambda { [].send(:initialize, -1, :a) }.should raise_error(ArgumentError)
- lambda { [].send(:initialize, -1) }.should raise_error(ArgumentError)
+ -> { [].send(:initialize, -1, :a) }.should.raise(ArgumentError)
+ -> { [].send(:initialize, -1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
- lambda { [].send(:initialize, fixnum_max+1) }.should raise_error(ArgumentError)
+ -> { [].send(:initialize, fixnum_max+1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
@@ -126,7 +128,7 @@ describe "Array#initialize with (size, object=nil)" do
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
- lambda{ [].send(:initialize, obj, :a) }.should raise_error(TypeError)
+ ->{ [].send(:initialize, obj, :a) }.should.raise(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
@@ -134,7 +136,7 @@ describe "Array#initialize with (size, object=nil)" do
end
it "uses the block value instead of using the default value" do
- lambda {
+ -> {
@result = [].send(:initialize, 3, :obj) { |i| i.to_s }
}.should complain(/block supersedes default value argument/)
@result.should == ['0', '1', '2']
diff --git a/spec/ruby/core/array/insert_spec.rb b/spec/ruby/core/array/insert_spec.rb
index b65a14a6b7..38e132fd25 100644
--- a/spec/ruby/core/array/insert_spec.rb
+++ b/spec/ruby/core/array/insert_spec.rb
@@ -4,8 +4,8 @@ require_relative 'fixtures/classes'
describe "Array#insert" do
it "returns self" do
ary = []
- ary.insert(0).should equal(ary)
- ary.insert(0, :a).should equal(ary)
+ ary.insert(0).should.equal?(ary)
+ ary.insert(0, :a).should.equal?(ary)
end
it "inserts objects before the element at index for non-negative index" do
@@ -46,8 +46,8 @@ describe "Array#insert" do
end
it "raises an IndexError if the negative index is out of bounds" do
- lambda { [].insert(-2, 1) }.should raise_error(IndexError)
- lambda { [1].insert(-3, 2) }.should raise_error(IndexError)
+ -> { [].insert(-2, 1) }.should.raise(IndexError)
+ -> { [1].insert(-3, 2) }.should.raise(IndexError)
end
it "does nothing of no object is passed" do
@@ -64,15 +64,15 @@ describe "Array#insert" do
end
it "raises an ArgumentError if no argument passed" do
- lambda { [].insert() }.should raise_error(ArgumentError)
+ -> { [].insert() }.should.raise(ArgumentError)
end
- it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do
- lambda { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array is modified" do
+ -> { ArraySpecs.frozen_array.insert(0, 'x') }.should.raise(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do
- lambda { ArraySpecs.frozen_array.insert(0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.insert(0) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/inspect_spec.rb b/spec/ruby/core/array/inspect_spec.rb
index 0832224f5a..e5dca82889 100644
--- a/spec/ruby/core/array/inspect_spec.rb
+++ b/spec/ruby/core/array/inspect_spec.rb
@@ -1,7 +1,108 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/inspect'
describe "Array#inspect" do
- it_behaves_like :array_inspect, :inspect
+ it "returns a string" do
+ [1, 2, 3].inspect.should.instance_of?(String)
+ end
+
+ it "returns '[]' for an empty Array" do
+ [].inspect.should == "[]"
+ end
+
+ it "calls inspect on its elements and joins the results with commas" do
+ items = Array.new(3) do |i|
+ obj = mock(i.to_s)
+ obj.should_receive(:inspect).and_return(i.to_s)
+ obj
+ end
+ items.inspect.should == "[0, 1, 2]"
+ end
+
+ it "does not call #to_s on a String returned from #inspect" do
+ str = +"abc"
+ str.should_not_receive(:to_s)
+
+ [str].inspect.should == '["abc"]'
+ end
+
+ it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
+ obj = mock("Array#inspect/to_s calls #to_s")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return("abc")
+
+ [obj].inspect.should == "[abc]"
+ end
+
+ it "does not call #to_str on the object returned from #inspect when it is not a String" do
+ obj = mock("Array#inspect/to_s does not call #to_str")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_not_receive(:to_str)
+
+ [obj].inspect.should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
+ end
+
+ it "does not call #to_str on the object returned from #to_s when it is not a String" do
+ obj = mock("Array#inspect/to_s does not call #to_str on #to_s result")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return(obj)
+ obj.should_not_receive(:to_str)
+
+ [obj].inspect.should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
+ end
+
+ it "does not swallow exceptions raised by #to_s" do
+ obj = mock("Array#inspect/to_s does not swallow #to_s exceptions")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_raise(Exception)
+
+ -> { [obj].inspect }.should.raise(Exception)
+ end
+
+ it "represents a recursive element with '[...]'" do
+ ArraySpecs.recursive_array.inspect.should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]"
+ ArraySpecs.head_recursive_array.inspect.should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]"
+ ArraySpecs.empty_recursive_array.inspect.should == "[[...]]"
+ end
+
+ describe "with encoding" do
+ before :each do
+ @default_external_encoding = Encoding.default_external
+ end
+
+ after :each do
+ Encoding.default_external = @default_external_encoding
+ end
+
+ it "returns a US-ASCII string for an empty Array" do
+ [].inspect.encoding.should == Encoding::US_ASCII
+ end
+
+ it "use the default external encoding if it is ascii compatible" do
+ Encoding.default_external = Encoding.find('UTF-8')
+
+ utf8 = "utf8".encode("UTF-8")
+ jp = "jp".encode("EUC-JP")
+ array = [jp, utf8]
+
+ array.inspect.encoding.name.should == "UTF-8"
+ end
+
+ it "use US-ASCII encoding if the default external encoding is not ascii compatible" do
+ Encoding.default_external = Encoding.find('UTF-32')
+
+ utf8 = "utf8".encode("UTF-8")
+ jp = "jp".encode("EUC-JP")
+ array = [jp, utf8]
+
+ array.inspect.encoding.name.should == "US-ASCII"
+ end
+
+ it "does not raise if inspected result is not default external encoding" do
+ utf_16be = mock(+"utf_16be")
+ utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE))
+
+ [utf_16be].inspect.should == '["utf_16be \u3042"]'
+ end
+ end
end
diff --git a/spec/ruby/core/array/intersect_spec.rb b/spec/ruby/core/array/intersect_spec.rb
new file mode 100644
index 0000000000..456aa26c6e
--- /dev/null
+++ b/spec/ruby/core/array/intersect_spec.rb
@@ -0,0 +1,64 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe 'Array#intersect?' do
+ describe 'when at least one element in two Arrays is the same' do
+ it 'returns true' do
+ [1, 2].intersect?([2, 3, 4]).should == true
+ [2, 3, 4].intersect?([1, 2]).should == true
+ end
+ end
+
+ describe 'when there are no elements in common between two Arrays' do
+ it 'returns false' do
+ [0, 1, 2].intersect?([3, 4]).should == false
+ [3, 4].intersect?([0, 1, 2]).should == false
+ [3, 4].intersect?([]).should == false
+ [].intersect?([0, 1, 2]).should == false
+ end
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+
+ [1, 2].intersect?(obj).should == true
+ end
+
+ it "determines equivalence between elements in the sense of eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
+
+ [obj1].intersect?([obj2]).should == true
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(false)
+ obj2.stub!(:eql?).and_return(false)
+
+ [obj1].intersect?([obj2]).should == false
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6].intersect?(ArraySpecs::ToAryArray[1, 2, 5, 6]).should == true
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].intersect?([x]).should == true
+ end
+
+ it "has semantic of !(a & b).empty?" do
+ [].intersect?([]).should == false
+ [nil].intersect?([nil]).should == true
+ end
+end
diff --git a/spec/ruby/core/array/intersection_spec.rb b/spec/ruby/core/array/intersection_spec.rb
index 7bf2ec4dbe..e01a68d389 100644
--- a/spec/ruby/core/array/intersection_spec.rb
+++ b/spec/ruby/core/array/intersection_spec.rb
@@ -1,87 +1,19 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/intersection'
describe "Array#&" do
- it "creates an array with elements common to both arrays (intersection)" do
- ([] & []).should == []
- ([1, 2] & []).should == []
- ([] & [1, 2]).should == []
- ([ 1, 3, 5 ] & [ 1, 2, 3 ]).should == [1, 3]
- end
-
- it "creates an array with no duplicates" do
- ([ 1, 1, 3, 5 ] & [ 1, 2, 3 ]).uniq!.should == nil
- end
-
- it "creates an array with elements in order they are first encountered" do
- ([ 1, 2, 3, 2, 5 ] & [ 5, 2, 3, 4 ]).should == [2, 3, 5]
- end
-
- it "does not modify the original Array" do
- a = [1, 1, 3, 5]
- (a & [1, 2, 3]).should == [1, 3]
- a.should == [1, 1, 3, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty & empty).should == empty
-
- (ArraySpecs.recursive_array & []).should == []
- ([] & ArraySpecs.recursive_array).should == []
-
- (ArraySpecs.recursive_array & ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array]
- end
-
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('[1,2,3]')
- obj.should_receive(:to_ary).and_return([1, 2, 3])
- ([1, 2] & obj).should == ([1, 2])
- end
-
- it "determines equivalence between elements in the sense of eql?" do
- not_supported_on :opal do
- ([5.0, 4.0] & [5, 4]).should == []
- end
-
- str = "x"
- ([str] & [str.dup]).should == [str]
-
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(true)
- obj2.stub!(:eql?).and_return(true)
-
- ([obj1] & [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj1]
-
- obj1 = mock('3')
- obj2 = mock('4')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(false)
+ it_behaves_like :array_intersection, :&
+end
- ([obj1] & [obj2]).should == []
- ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj2]
- end
+describe "Array#intersection" do
+ it_behaves_like :array_intersection, :intersection
- it "does return subclass instances for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] & []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- ([] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ it "accepts multiple arguments" do
+ [1, 2, 3, 4].intersection([1, 2, 3], [2, 3, 4]).should == [2, 3]
end
- it "does not call to_ary on array subclasses" do
- ([5, 6] & ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6]
- end
-
- it "properly handles an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
-
- ([x] & [x]).should == [x]
+ it "preserves elements order from original array" do
+ [1, 2, 3, 4].intersection([3, 2, 1]).should == [1, 2, 3]
end
end
diff --git a/spec/ruby/core/array/join_spec.rb b/spec/ruby/core/array/join_spec.rb
index 16f0dcee7a..3b4946a99f 100644
--- a/spec/ruby/core/array/join_spec.rb
+++ b/spec/ruby/core/array/join_spec.rb
@@ -4,7 +4,6 @@ require_relative 'shared/join'
describe "Array#join" do
it_behaves_like :array_join_with_string_separator, :join
- it_behaves_like :array_join_with_default_separator, :join
it "does not separate elements when the passed separator is nil" do
[1, 2, 3].join(nil).should == '123'
@@ -24,11 +23,108 @@ describe "Array#join" do
it "raises a TypeError if the separator cannot be coerced to a String by calling #to_str" do
obj = mock("not a string")
- lambda { [1, 2].join(obj) }.should raise_error(TypeError)
+ -> { [1, 2].join(obj) }.should.raise(TypeError)
end
it "raises a TypeError if passed false as the separator" do
- lambda { [1, 2].join(false) }.should raise_error(TypeError)
+ -> { [1, 2].join(false) }.should.raise(TypeError)
+ end
+end
+
+describe "Array#join with default separator" do
+ before :each do
+ @separator = $,
+ end
+
+ after :each do
+ $, = @separator
+ end
+
+ it "returns an empty string if the Array is empty" do
+ [].join.should == ''
+ end
+
+ it "returns a US-ASCII string for an empty Array" do
+ [].join.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a string formed by concatenating each String element separated by $," do
+ suppress_warning {
+ $, = " | "
+ ["1", "2", "3"].join.should == "1 | 2 | 3"
+ }
+ end
+
+ it "attempts coercion via #to_str first" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return("foo")
+ [obj].join.should == "foo"
+ end
+
+ it "attempts coercion via #to_ary second" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"])
+ [obj].join.should == "foo"
+ end
+
+ it "attempts coercion via #to_s third" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_ary).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_s).any_number_of_times.and_return("foo")
+ [obj].join.should == "foo"
+ end
+
+ it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do
+ obj = mock('o')
+ class << obj; undef :to_s; end
+ -> { [1, obj].join }.should.raise(NoMethodError)
+ end
+
+ it "raises an ArgumentError when the Array is recursive" do
+ -> { ArraySpecs.recursive_array.join }.should.raise(ArgumentError)
+ -> { ArraySpecs.head_recursive_array.join }.should.raise(ArgumentError)
+ -> { ArraySpecs.empty_recursive_array.join }.should.raise(ArgumentError)
+ end
+
+ it "uses the first encoding when other strings are compatible" do
+ ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings
+ ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings
+ ary3 = ArraySpecs.array_with_utf8_and_7bit_binary_strings
+ ary4 = ArraySpecs.array_with_usascii_and_7bit_binary_strings
+
+ ary1.join.encoding.should == Encoding::UTF_8
+ ary2.join.encoding.should == Encoding::US_ASCII
+ ary3.join.encoding.should == Encoding::UTF_8
+ ary4.join.encoding.should == Encoding::US_ASCII
+ end
+
+ it "uses the widest common encoding when other strings are incompatible" do
+ ary1 = ArraySpecs.array_with_utf8_and_usascii_strings
+ ary2 = ArraySpecs.array_with_usascii_and_utf8_strings
+
+ ary1.join.encoding.should == Encoding::UTF_8
+ ary2.join.encoding.should == Encoding::UTF_8
+ end
+
+ it "fails for arrays with incompatibly-encoded strings" do
+ ary_utf8_bad_binary = ArraySpecs.array_with_utf8_and_binary_strings
+
+ -> { ary_utf8_bad_binary.join }.should.raise(EncodingError)
+ end
+
+ context "when $, is not nil" do
+ before do
+ suppress_warning do
+ $, = '*'
+ end
+ end
+
+ it "warns" do
+ -> { [].join }.should complain(/warning: \$, is set to non-nil value/)
+ -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/)
+ end
end
end
@@ -38,11 +134,13 @@ describe "Array#join with $," do
end
after :each do
- $, = @before_separator
+ suppress_warning {$, = @before_separator}
end
it "separates elements with default separator when the passed separator is nil" do
- $, = "_"
- [1, 2, 3].join(nil).should == '1_2_3'
+ suppress_warning {
+ $, = "_"
+ [1, 2, 3].join(nil).should == '1_2_3'
+ }
end
end
diff --git a/spec/ruby/core/array/keep_if_spec.rb b/spec/ruby/core/array/keep_if_spec.rb
index bf2bdeaf91..62a65a04e8 100644
--- a/spec/ruby/core/array/keep_if_spec.rb
+++ b/spec/ruby/core/array/keep_if_spec.rb
@@ -1,9 +1,10 @@
+require_relative '../../spec_helper'
require_relative 'shared/keep_if'
describe "Array#keep_if" do
it "returns the same array if no changes were made" do
array = [1, 2, 3]
- array.keep_if { true }.should equal(array)
+ array.keep_if { true }.should.equal?(array)
end
it_behaves_like :keep_if, :keep_if
diff --git a/spec/ruby/core/array/last_spec.rb b/spec/ruby/core/array/last_spec.rb
index 871f4a2352..ed417bcd2a 100644
--- a/spec/ruby/core/array/last_spec.rb
+++ b/spec/ruby/core/array/last_spec.rb
@@ -28,7 +28,7 @@ describe "Array#last" do
end
it "raises an ArgumentError when count is negative" do
- lambda { [1, 2].last(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].last(-1) }.should.raise(ArgumentError)
end
it "returns the entire array when count > length" do
@@ -47,32 +47,32 @@ describe "Array#last" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.last.should equal(empty)
+ empty.last.should.equal?(empty)
array = ArraySpecs.recursive_array
- array.last.should equal(array)
+ array.last.should.equal?(array)
end
- it "tries to convert the passed argument to an Integer usinig #to_int" do
+ it "tries to convert the passed argument to an Integer using #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
[1, 2, 3, 4, 5].last(obj).should == [4, 5]
end
it "raises a TypeError if the passed argument is not numeric" do
- lambda { [1,2].last(nil) }.should raise_error(TypeError)
- lambda { [1,2].last("a") }.should raise_error(TypeError)
+ -> { [1,2].last(nil) }.should.raise(TypeError)
+ -> { [1,2].last("a") }.should.raise(TypeError)
obj = mock("nonnumeric")
- lambda { [1,2].last(obj) }.should raise_error(TypeError)
+ -> { [1,2].last(obj) }.should.raise(TypeError)
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[].last(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[].last(2).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(1).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[].last(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[].last(2).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(1).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(2).should.instance_of?(Array)
end
it "is not destructive" do
diff --git a/spec/ruby/core/array/length_spec.rb b/spec/ruby/core/array/length_spec.rb
index a90c001300..74b2eb3a08 100644
--- a/spec/ruby/core/array/length_spec.rb
+++ b/spec/ruby/core/array/length_spec.rb
@@ -1,7 +1,14 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Array#length" do
- it_behaves_like :array_length, :length
+ it "returns the number of elements" do
+ [].length.should == 0
+ [1, 2, 3].length.should == 3
+ end
+
+ it "properly handles recursive arrays" do
+ ArraySpecs.empty_recursive_array.length.should == 1
+ ArraySpecs.recursive_array.length.should == 8
+ end
end
diff --git a/spec/ruby/core/array/map_spec.rb b/spec/ruby/core/array/map_spec.rb
index 0c7f3afa8c..f5e88c8624 100644
--- a/spec/ruby/core/array/map_spec.rb
+++ b/spec/ruby/core/array/map_spec.rb
@@ -1,11 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/collect'
describe "Array#map" do
- it_behaves_like :array_collect, :map
+ it "is an alias of Array#collect" do
+ Array.instance_method(:map).should == Array.instance_method(:collect)
+ end
end
describe "Array#map!" do
- it_behaves_like :array_collect_b, :map!
+ it "is an alias of Array#collect!" do
+ Array.instance_method(:map!).should == Array.instance_method(:collect!)
+ end
end
diff --git a/spec/ruby/core/array/max_spec.rb b/spec/ruby/core/array/max_spec.rb
index 5d0423d1e4..868275a748 100644
--- a/spec/ruby/core/array/max_spec.rb
+++ b/spec/ruby/core/array/max_spec.rb
@@ -1,10 +1,8 @@
require_relative '../../spec_helper'
describe "Array#max" do
- ruby_version_is "2.4" do
- it "is defined on Array" do
- [1].method(:max).owner.should equal Array
- end
+ it "is defined on Array" do
+ [1].method(:max).owner.should.equal? Array
end
it "returns nil with no values" do
@@ -70,18 +68,18 @@ describe "Array#max" do
end
it "raises a NoMethodError for elements without #<=>" do
- lambda do
+ -> do
[BasicObject.new, BasicObject.new].max
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
- lambda do
+ -> do
[11,"22"].max
- end.should raise_error(ArgumentError)
- lambda do
+ end.should.raise(ArgumentError)
+ -> do
[11,12,22,33].max{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "returns the maximum element (with block)" do
diff --git a/spec/ruby/core/array/min_spec.rb b/spec/ruby/core/array/min_spec.rb
index 903fa69bb8..5913e08cf8 100644
--- a/spec/ruby/core/array/min_spec.rb
+++ b/spec/ruby/core/array/min_spec.rb
@@ -1,10 +1,8 @@
require_relative '../../spec_helper'
describe "Array#min" do
- ruby_version_is "2.4" do
- it "is defined on Array" do
- [1].method(:max).owner.should equal Array
- end
+ it "is defined on Array" do
+ [1].method(:max).owner.should.equal? Array
end
it "returns nil with no values" do
@@ -66,22 +64,22 @@ describe "Array#min" do
end
it "returns nil for an empty Enumerable" do
- [].min.should be_nil
+ [].min.should == nil
end
it "raises a NoMethodError for elements without #<=>" do
- lambda do
+ -> do
[BasicObject.new, BasicObject.new].min
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
- lambda do
+ -> do
[11,"22"].min
- end.should raise_error(ArgumentError)
- lambda do
+ end.should.raise(ArgumentError)
+ -> do
[11,12,22,33].min{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "returns the minimum when using a block rule" do
diff --git a/spec/ruby/core/array/minmax_spec.rb b/spec/ruby/core/array/minmax_spec.rb
new file mode 100644
index 0000000000..e11fe63347
--- /dev/null
+++ b/spec/ruby/core/array/minmax_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/enumerable/minmax'
+
+describe "Array#minmax" do
+ before :each do
+ @enum = [6, 4, 5, 10, 8]
+ @empty_enum = []
+ @incomparable_enum = [BasicObject.new, BasicObject.new]
+ @incompatible_enum = [11, "22"]
+ @strs = ["333", "2", "60", "55555", "1010", "111"]
+ end
+
+ it_behaves_like :enumerable_minmax, :minmax
+end
diff --git a/spec/ruby/core/array/minus_spec.rb b/spec/ruby/core/array/minus_spec.rb
index 8cb6bb323c..cb1bf56d76 100644
--- a/spec/ruby/core/array/minus_spec.rb
+++ b/spec/ruby/core/array/minus_spec.rb
@@ -1,87 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/difference'
describe "Array#-" do
- it "creates an array minus any items from other array" do
- ([] - [ 1, 2, 4 ]).should == []
- ([1, 2, 4] - []).should == [1, 2, 4]
- ([ 1, 2, 3, 4, 5 ] - [ 1, 2, 4 ]).should == [3, 5]
- end
-
- it "removes multiple items on the lhs equal to one on the rhs" do
- ([1, 1, 2, 2, 3, 3, 4, 5] - [1, 2, 4]).should == [3, 3, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty - empty).should == []
-
- ([] - ArraySpecs.recursive_array).should == []
-
- array = ArraySpecs.recursive_array
- (array - array).should == []
- end
-
- it "tries to convert the passed arguments to Arrays using #to_ary" do
- obj = mock('[2,3,3,4]')
- obj.should_receive(:to_ary).and_return([2, 3, 3, 4])
- ([1, 1, 2, 2, 3, 4] - obj).should == [1, 1]
- end
-
- it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
- obj = mock('not an array')
- lambda { [1, 2, 3] - obj }.should raise_error(TypeError)
- end
-
- it "does not return subclass instance for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] - []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- ([1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- end
-
- it "does not call to_ary on array subclasses" do
- ([5, 6, 7] - ArraySpecs::ToAryArray[7]).should == [5, 6]
- end
-
- it "removes an item identified as equivalent via #hash and #eql?" do
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(true)
-
- ([obj1] - [obj2]).should == []
- ([obj1, obj1, obj2, obj2] - [obj2]).should == []
- end
-
- it "doesn't remove an item with the same hash but not #eql?" do
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(false)
-
- ([obj1] - [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] - [obj2]).should == [obj1, obj1]
- end
-
- it "removes an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
-
- ([x] - [x]).should == []
- end
-
- it "is not destructive" do
- a = [1, 2, 3]
- a - []
- a.should == [1, 2, 3]
- a - [1]
- a.should == [1, 2, 3]
- a - [1,2,3]
- a.should == [1, 2, 3]
- a - [:a, :b, :c]
- a.should == [1, 2, 3]
- end
+ it_behaves_like :array_binary_difference, :-
end
diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb
index f9ba20258a..1ac14e1b09 100644
--- a/spec/ruby/core/array/multiply_spec.rb
+++ b/spec/ruby/core/array/multiply_spec.rb
@@ -17,7 +17,7 @@ describe "Array#*" do
it "raises a TypeError if the argument can neither be converted to a string nor an integer" do
obj = mock('not a string or integer')
- lambda{ [1,2] * obj }.should raise_error(TypeError)
+ ->{ [1,2] * obj }.should.raise(TypeError)
end
it "converts the passed argument to a String rather than an Integer" do
@@ -28,15 +28,15 @@ describe "Array#*" do
end
it "raises a TypeError is the passed argument is nil" do
- lambda{ [1,2] * nil }.should raise_error(TypeError)
+ ->{ [1,2] * nil }.should.raise(TypeError)
end
it "raises an ArgumentError when passed 2 or more arguments" do
- lambda{ [1,2].send(:*, 1, 2) }.should raise_error(ArgumentError)
+ ->{ [1,2].send(:*, 1, 2) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed no arguments" do
- lambda{ [1,2].send(:*) }.should raise_error(ArgumentError)
+ ->{ [1,2].send(:*) }.should.raise(ArgumentError)
end
end
@@ -50,7 +50,7 @@ describe "Array#* with an integer" do
it "does not return self even if the passed integer is 1" do
ary = [1, 2, 3]
- (ary * 1).should_not equal(ary)
+ (ary * 1).should_not.equal?(ary)
end
it "properly handles recursive arrays" do
@@ -65,8 +65,8 @@ describe "Array#* with an integer" do
end
it "raises an ArgumentError when passed a negative integer" do
- lambda { [ 1, 2, 3 ] * -1 }.should raise_error(ArgumentError)
- lambda { [] * -1 }.should raise_error(ArgumentError)
+ -> { [ 1, 2, 3 ] * -1 }.should.raise(ArgumentError)
+ -> { [] * -1 }.should.raise(ArgumentError)
end
describe "with a subclass of Array" do
@@ -76,55 +76,17 @@ describe "Array#* with an integer" do
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
- it "returns a subclass instance" do
- (@array * 0).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 1).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 2).should be_an_instance_of(ArraySpecs::MyArray)
+ it "returns an Array instance" do
+ (@array * 0).should.instance_of?(Array)
+ (@array * 1).should.instance_of?(Array)
+ (@array * 2).should.instance_of?(Array)
end
it "does not call #initialize on the subclass instance" do
(@array * 2).should == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
-
- it "copies the taint status of the original array even if the passed count is 0" do
- ary = [1, 2, 3]
- ary.taint
- (ary * 0).tainted?.should == true
- end
-
- it "copies the taint status of the original array even if the array is empty" do
- ary = []
- ary.taint
- (ary * 3).tainted?.should == true
- end
-
- it "copies the taint status of the original array if the passed count is not 0" do
- ary = [1, 2, 3]
- ary.taint
- (ary * 1).tainted?.should == true
- (ary * 2).tainted?.should == true
- end
-
- it "copies the untrusted status of the original array even if the passed count is 0" do
- ary = [1, 2, 3]
- ary.untrust
- (ary * 0).untrusted?.should == true
- end
-
- it "copies the untrusted status of the original array even if the array is empty" do
- ary = []
- ary.untrust
- (ary * 3).untrusted?.should == true
- end
-
- it "copies the untrusted status of the original array if the passed count is not 0" do
- ary = [1, 2, 3]
- ary.untrust
- (ary * 1).untrusted?.should == true
- (ary * 2).untrusted?.should == true
- end
end
describe "Array#* with a string" do
diff --git a/spec/ruby/core/array/new_spec.rb b/spec/ruby/core/array/new_spec.rb
index d5e4b5722f..b2f23e2f6b 100644
--- a/spec/ruby/core/array/new_spec.rb
+++ b/spec/ruby/core/array/new_spec.rb
@@ -3,30 +3,32 @@ require_relative 'fixtures/classes'
describe "Array.new" do
it "returns an instance of Array" do
- Array.new.should be_an_instance_of(Array)
+ Array.new.should.instance_of?(Array)
end
it "returns an instance of a subclass" do
- ArraySpecs::MyArray.new(1, 2).should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray.new(1, 2).should.instance_of?(ArraySpecs::MyArray)
end
it "raises an ArgumentError if passed 3 or more arguments" do
- lambda do
+ -> do
[1, 2].send :initialize, 1, 'x', true
- end.should raise_error(ArgumentError)
- lambda do
+ end.should.raise(ArgumentError)
+ -> do
[1, 2].send(:initialize, 1, 'x', true) {}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
describe "Array.new with no arguments" do
it "returns an empty array" do
- Array.new.should be_empty
+ Array.new.should.empty?
end
it "does not use the given block" do
- lambda{ Array.new { raise } }.should_not raise_error
+ -> {
+ -> { Array.new { raise } }.should_not.raise
+ }.should complain(/warning: given block not used/, verbose: true)
end
end
@@ -37,7 +39,7 @@ describe "Array.new with (array)" do
end
it "does not use the given block" do
- lambda{ Array.new([1, 2]) { raise } }.should_not raise_error
+ ->{ Array.new([1, 2]) { raise } }.should_not.raise
end
it "calls #to_ary to convert the value to an array" do
@@ -54,7 +56,7 @@ describe "Array.new with (array)" do
end
it "raises a TypeError if an Array type argument and a default object" do
- lambda { Array.new([1, 2], 1) }.should raise_error(TypeError)
+ -> { Array.new([1, 2], 1) }.should.raise(TypeError)
end
end
@@ -63,8 +65,8 @@ describe "Array.new with (size, object=nil)" do
obj = [3]
a = Array.new(2, obj)
a.should == [obj, obj]
- a[0].should equal(obj)
- a[1].should equal(obj)
+ a[0].should.equal?(obj)
+ a[1].should.equal?(obj)
Array.new(3, 14).should == [14, 14, 14]
end
@@ -74,12 +76,12 @@ describe "Array.new with (size, object=nil)" do
end
it "raises an ArgumentError if size is negative" do
- lambda { Array.new(-1, :a) }.should raise_error(ArgumentError)
- lambda { Array.new(-1) }.should raise_error(ArgumentError)
+ -> { Array.new(-1, :a) }.should.raise(ArgumentError)
+ -> { Array.new(-1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
- lambda { Array.new(fixnum_max+1) }.should raise_error(ArgumentError)
+ -> { Array.new(fixnum_max+1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
@@ -97,7 +99,7 @@ describe "Array.new with (size, object=nil)" do
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
- lambda{ Array.new(obj, :a) }.should raise_error(TypeError)
+ ->{ Array.new(obj, :a) }.should.raise(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
@@ -105,7 +107,7 @@ describe "Array.new with (size, object=nil)" do
end
it "uses the block value instead of using the default value" do
- lambda {
+ -> {
@result = Array.new(3, :obj) { |i| i.to_s }
}.should complain(/block supersedes default value argument/)
@result.should == ['0', '1', '2']
diff --git a/spec/ruby/core/array/none_spec.rb b/spec/ruby/core/array/none_spec.rb
new file mode 100644
index 0000000000..31cd8c46d6
--- /dev/null
+++ b/spec/ruby/core/array/none_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#none?" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :none?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].none?(/baz/) { true }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/one_spec.rb b/spec/ruby/core/array/one_spec.rb
new file mode 100644
index 0000000000..0c61907881
--- /dev/null
+++ b/spec/ruby/core/array/one_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#one?" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :one?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].one?(/foo/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb
index 1cee3858ff..03bfd8214c 100644
--- a/spec/ruby/core/array/pack/a_spec.rb
+++ b/spec/ruby/core/array/pack/a_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -12,11 +12,22 @@ describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_string, 'A'
it_behaves_like :array_pack_taint, 'A'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack A string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("A*").should == "``abcdef"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('A') }.should.raise(TypeError)
+ -> { [0].pack('a') }.should.raise(TypeError)
+ end
+
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
end
- it "padds the output with spaces when the count exceeds the size of the String" do
+ it "pads the output with spaces when the count exceeds the size of the String" do
["abc"].pack("A6").should == "abc "
end
@@ -44,7 +55,7 @@ describe "Array#pack with format 'a'" do
["abc"].pack("a*").should == "abc"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("a6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/pack/at_spec.rb b/spec/ruby/core/array/pack/at_spec.rb
index 00763c70f1..bb9801440a 100644
--- a/spec/ruby/core/array/pack/at_spec.rb
+++ b/spec/ruby/core/array/pack/at_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb
index 8a75825e3e..f7576846ef 100644
--- a/spec/ruby/core/array/pack/b_spec.rb
+++ b/spec/ruby/core/array/pack/b_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -13,11 +13,16 @@ describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_taint, 'B'
it "calls #to_str to convert an Object to a String" do
- obj = mock("pack H string")
+ obj = mock("pack B string")
obj.should_receive(:to_str).and_return("``abcdef")
[obj].pack("B*").should == "\x2a"
end
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('B') }.should.raise(TypeError)
+ -> { [0].pack('b') }.should.raise(TypeError)
+ end
+
it "encodes one bit for each character starting with the most significant bit" do
[ [["0"], "\x00"],
[["1"], "\x80"]
@@ -47,8 +52,8 @@ describe "Array#pack with format 'B'" do
].should be_computed_by(:pack, "B*")
end
- it "returns an ASCII-8BIT string" do
- ["1"].pack("B").encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ ["1"].pack("B").encoding.should == Encoding::BINARY
end
it "encodes the string as a sequence of bytes" do
@@ -98,8 +103,8 @@ describe "Array#pack with format 'b'" do
].should be_computed_by(:pack, "b*")
end
- it "returns an ASCII-8BIT string" do
- ["1"].pack("b").encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ ["1"].pack("b").encoding.should == Encoding::BINARY
end
it "encodes the string as a sequence of bytes" do
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
index f2dc3e1930..d104c80186 100644
--- a/spec/ruby/core/array/pack/buffer_spec.rb
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -1,52 +1,60 @@
-# encoding: ascii-8bit
+# encoding: binary
require_relative '../../../spec_helper'
-ruby_version_is '2.4' do
- describe "Array#pack with :buffer option" do
- it "returns specified buffer" do
- n = [ 65, 66, 67 ]
- buffer = " "*3
- result = n.pack("ccc", buffer: buffer) #=> "ABC"
- result.should equal(buffer)
- end
+describe "Array#pack with :buffer option" do
+ it "returns specified buffer" do
+ n = [ 65, 66, 67 ]
+ buffer = " "*3
+ result = n.pack("ccc", buffer: buffer) #=> "ABC"
+ result.should.equal?(buffer)
+ end
+
+ it "adds result at the end of buffer content" do
+ n = [ 65, 66, 67 ] # result without buffer is "ABC"
+
+ buffer = +""
+ n.pack("ccc", buffer: buffer).should == "ABC"
+
+ buffer = +"123"
+ n.pack("ccc", buffer: buffer).should == "123ABC"
+
+ buffer = +"12345"
+ n.pack("ccc", buffer: buffer).should == "12345ABC"
+ end
- it "adds result at the end of buffer content" do
- n = [ 65, 66, 67 ] # result without buffer is "ABC"
+ it "raises TypeError exception if buffer is not String" do
+ -> { [65].pack("ccc", buffer: []) }.should.raise(
+ TypeError, "buffer must be String, not Array")
+ end
- buffer = ""
- n.pack("ccc", buffer: buffer).should == "ABC"
+ it "raise FrozenError if buffer is frozen" do
+ -> { [65].pack("c", buffer: "frozen-string".freeze) }.should.raise(FrozenError)
+ end
- buffer = "123"
- n.pack("ccc", buffer: buffer).should == "123ABC"
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ [65, 66, 67].pack("ccc", buffer: buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
- buffer = "12345"
- n.pack("ccc", buffer: buffer).should == "12345ABC"
+ context "offset (@) is specified" do
+ it 'keeps buffer content if it is longer than offset' do
+ n = [ 65, 66, 67 ]
+ buffer = +"123456"
+ n.pack("@3ccc", buffer: buffer).should == "123ABC"
end
- it "raises TypeError exception if buffer is not String" do
- lambda { [65].pack("ccc", buffer: []) }.should raise_error(
- TypeError, "buffer must be String, not Array")
+ it "fills the gap with \\0 if buffer content is shorter than offset" do
+ n = [ 65, 66, 67 ]
+ buffer = +"123"
+ n.pack("@6ccc", buffer: buffer).should == "123\0\0\0ABC"
end
- context "offset (@) is specified" do
- it 'keeps buffer content if it is longer than offset' do
- n = [ 65, 66, 67 ]
- buffer = "123456"
- n.pack("@3ccc", buffer: buffer).should == "123ABC"
- end
-
- it "fills the gap with \\0 if buffer content is shorter than offset" do
- n = [ 65, 66, 67 ]
- buffer = "123"
- n.pack("@6ccc", buffer: buffer).should == "123\0\0\0ABC"
- end
-
- it 'does not keep buffer content if it is longer than offset + result' do
- n = [ 65, 66, 67 ]
- buffer = "1234567890"
- n.pack("@3ccc", buffer: buffer).should == "123ABC"
- end
+ it 'does not keep buffer content if it is longer than offset + result' do
+ n = [ 65, 66, 67 ]
+ buffer = +"1234567890"
+ n.pack("@3ccc", buffer: buffer).should == "123ABC"
end
end
end
diff --git a/spec/ruby/core/array/pack/c_spec.rb b/spec/ruby/core/array/pack/c_spec.rb
index 225f0970fd..de06207a23 100644
--- a/spec/ruby/core/array/pack/c_spec.rb
+++ b/spec/ruby/core/array/pack/c_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
@@ -45,8 +45,10 @@ describe :array_pack_8bit, shared: true do
[1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/comment_spec.rb b/spec/ruby/core/array/pack/comment_spec.rb
index 07daa2d6fb..daf1cff06a 100644
--- a/spec/ruby/core/array/pack/comment_spec.rb
+++ b/spec/ruby/core/array/pack/comment_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb
index 51bf551ba3..1492d02b1f 100644
--- a/spec/ruby/core/array/pack/h_spec.rb
+++ b/spec/ruby/core/array/pack/h_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -18,6 +18,11 @@ describe "Array#pack with format 'H'" do
[obj].pack("H").should == "\xa0"
end
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('H') }.should.raise(TypeError)
+ -> { [0].pack('h') }.should.raise(TypeError)
+ end
+
it "encodes the first character as the most significant nibble when passed no count modifier" do
["ab"].pack("H").should == "\xa0"
end
@@ -97,8 +102,8 @@ describe "Array#pack with format 'H'" do
].should be_computed_by(:pack, "H")
end
- it "returns an ASCII-8BIT string" do
- ["41"].pack("H").encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ ["41"].pack("H").encoding.should == Encoding::BINARY
end
end
@@ -194,7 +199,7 @@ describe "Array#pack with format 'h'" do
].should be_computed_by(:pack, "h")
end
- it "returns an ASCII-8BIT string" do
- ["41"].pack("h").encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ ["41"].pack("h").encoding.should == Encoding::BINARY
end
end
diff --git a/spec/ruby/core/array/pack/l_spec.rb b/spec/ruby/core/array/pack/l_spec.rb
index 0a5552b984..f6dfb1da83 100644
--- a/spec/ruby/core/array/pack/l_spec.rb
+++ b/spec/ruby/core/array/pack/l_spec.rb
@@ -29,7 +29,7 @@ describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
@@ -51,7 +51,7 @@ describe "Array#pack with format 'L'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
@@ -83,7 +83,7 @@ describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
@@ -105,7 +105,7 @@ describe "Array#pack with format 'l'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
@@ -137,7 +137,7 @@ little_endian do
it_behaves_like :array_pack_32bit_le, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
@@ -155,7 +155,7 @@ little_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
@@ -183,7 +183,7 @@ big_endian do
it_behaves_like :array_pack_32bit_be, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
@@ -201,7 +201,7 @@ big_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index 24acf2cef2..fb670d120e 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -80,8 +80,16 @@ describe "Array#pack with format 'M'" do
].should be_computed_by(:pack, "M")
end
- it "encodes a tab followed by a newline with an encoded newline" do
+ it "encodes a tab at the end of a line with an encoded newline" do
+ ["\t"].pack("M").should == "\t=\n"
["\t\n"].pack("M").should == "\t=\n\n"
+ ["abc\t\nxyz"].pack("M").should == "abc\t=\n\nxyz=\n"
+ end
+
+ it "encodes a space at the end of a line with an encoded newline" do
+ [" "].pack("M").should == " =\n"
+ [" \n"].pack("M").should == " =\n\n"
+ ["abc \nxyz"].pack("M").should == "abc =\n\nxyz=\n"
end
it "encodes 127..255 in hex format" do
@@ -147,7 +155,7 @@ describe "Array#pack with format 'M'" do
it "encodes a recursive array" do
empty = ArraySpecs.empty_recursive_array
- empty.pack('M').should be_an_instance_of(String)
+ empty.pack('M').should.instance_of?(String)
array = ArraySpecs.recursive_array
array.pack('M').should == "1=\n"
@@ -164,7 +172,7 @@ describe "Array#pack with format 'M'" do
obj = mock("pack M non-string")
obj.should_receive(:to_s).and_return(2)
- [obj].pack("M").should be_an_instance_of(String)
+ [obj].pack("M").should.instance_of?(String)
end
it "encodes a Symbol as a String" do
@@ -285,16 +293,16 @@ describe "Array#pack with format 'm'" do
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
- lambda { [obj].pack("m") }.should raise_error(TypeError)
+ -> { [obj].pack("m") }.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
- lambda { [nil].pack("m") }.should raise_error(TypeError)
+ -> { [nil].pack("m") }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer" do
- lambda { [0].pack("m") }.should raise_error(TypeError)
- lambda { [bignum_value].pack("m") }.should raise_error(TypeError)
+ -> { [0].pack("m") }.should.raise(TypeError)
+ -> { [bignum_value].pack("m") }.should.raise(TypeError)
end
it "does not emit a newline if passed zero as the count modifier" do
diff --git a/spec/ruby/core/array/pack/p_spec.rb b/spec/ruby/core/array/pack/p_spec.rb
index 857d403313..b023bf9110 100644
--- a/spec/ruby/core/array/pack/p_spec.rb
+++ b/spec/ruby/core/array/pack/p_spec.rb
@@ -15,16 +15,6 @@ describe "Array#pack with format 'P'" do
["hello"].pack("P").unpack("P5").should == ["hello"]
end
- it "taints the input string" do
- input_string = "hello"
- [input_string].pack("P")
- input_string.tainted?.should be_true
- end
-
- it "does not taint the output string in normal cases" do
- ["hello"].pack("P").tainted?.should be_false
- end
-
it "with nil gives a null pointer" do
[nil].pack("P").unpack("J").should == [0]
end
@@ -42,16 +32,6 @@ describe "Array#pack with format 'p'" do
["hello"].pack("p").unpack("p").should == ["hello"]
end
- it "taints the input string" do
- input_string = "hello"
- [input_string].pack("p")
- input_string.tainted?.should be_true
- end
-
- it "does not taint the output string in normal cases" do
- ["hello"].pack("p").tainted?.should be_false
- end
-
it "with nil gives a null pointer" do
[nil].pack("p").unpack("J").should == [0]
end
diff --git a/spec/ruby/core/array/pack/percent_spec.rb b/spec/ruby/core/array/pack/percent_spec.rb
index 3c0e7eca0f..29b119732a 100644
--- a/spec/ruby/core/array/pack/percent_spec.rb
+++ b/spec/ruby/core/array/pack/percent_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../../spec_helper'
describe "Array#pack with format '%'" do
it "raises an Argument Error" do
- lambda { [1].pack("%") }.should raise_error(ArgumentError)
+ -> { [1].pack("%") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/r_spec.rb b/spec/ruby/core/array/pack/r_spec.rb
new file mode 100644
index 0000000000..cefe1388d2
--- /dev/null
+++ b/spec/ruby/core/array/pack/r_spec.rb
@@ -0,0 +1,89 @@
+# encoding: binary
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+require_relative 'shared/basic'
+require_relative 'shared/numeric_basic'
+require_relative 'shared/integer'
+
+ruby_version_is "4.1" do
+ describe "Array#pack with format 'R'" do
+ it_behaves_like :array_pack_basic, 'R'
+ it_behaves_like :array_pack_basic_non_float, 'R'
+ it_behaves_like :array_pack_arguments, 'R'
+ it_behaves_like :array_pack_numeric_basic, 'R'
+ it_behaves_like :array_pack_integer, 'R'
+
+ it "encodes a ULEB128 integer" do
+ [ [[0], "\x00"],
+ [[1], "\x01"],
+ [[127], "\x7f"],
+ [[128], "\x80\x01"],
+ [[0x3fff], "\xff\x7f"],
+ [[0x4000], "\x80\x80\x01"],
+ [[0xffffffff], "\xff\xff\xff\xff\x0f"],
+ [[0x100000000], "\x80\x80\x80\x80\x10"],
+ [[0xffff_ffff_ffff_ffff], "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01"],
+ [[0xffff_ffff_ffff_ffff_ffff_ffff], "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1f"],
+ ].should be_computed_by(:pack, "R")
+ end
+
+ it "encodes multiple values with '*' modifier" do
+ [1, 2].pack("R*").should == "\x01\x02"
+ [127, 128].pack("R*").should == "\x7f\x80\x01"
+ end
+
+ it "raises an ArgumentError when passed a negative value" do
+ -> { [-1].pack("R") }.should.raise(ArgumentError)
+ -> { [-100].pack("R") }.should.raise(ArgumentError)
+ end
+
+ it "round-trips values through pack and unpack" do
+ values = [0, 1, 127, 128, 0x3fff, 0x4000, 0xffffffff, 0x100000000]
+ values.pack("R*").unpack("R*").should == values
+ end
+ end
+
+ describe "Array#pack with format 'r'" do
+ it_behaves_like :array_pack_basic, 'r'
+ it_behaves_like :array_pack_basic_non_float, 'r'
+ it_behaves_like :array_pack_arguments, 'r'
+ it_behaves_like :array_pack_numeric_basic, 'r'
+ it_behaves_like :array_pack_integer, 'r'
+
+ it "encodes a SLEB128 integer" do
+ [ [[0], "\x00"],
+ [[1], "\x01"],
+ [[-1], "\x7f"],
+ [[-2], "\x7e"],
+ [[127], "\xff\x00"],
+ [[128], "\x80\x01"],
+ [[-127], "\x81\x7f"],
+ [[-128], "\x80\x7f"],
+ ].should be_computed_by(:pack, "r")
+ end
+
+ it "encodes larger positive numbers" do
+ [0x3fff].pack("r").should == "\xff\xff\x00"
+ [0x4000].pack("r").should == "\x80\x80\x01"
+ end
+
+ it "encodes larger negative numbers" do
+ [-0x3fff].pack("r").should == "\x81\x80\x7f"
+ [-0x4000].pack("r").should == "\x80\x80\x7f"
+ end
+
+ it "encodes very large numbers" do
+ [0xffff_ffff_ffff_ffff_ffff_ffff].pack("r").should == "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1F"
+ [-0xffff_ffff_ffff_ffff_ffff_ffff].pack("r").should == "\x81\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x60"
+ end
+
+ it "encodes multiple values with '*' modifier" do
+ [0, 1, -1].pack("r*").should == "\x00\x01\x7f"
+ end
+
+ it "round-trips values through pack and unpack" do
+ values = [0, 1, -1, 127, -127, 128, -128, 0x3fff, -0x3fff, 0x4000, -0x4000]
+ values.pack("r*").unpack("r*").should == values
+ end
+ end
+end
diff --git a/spec/ruby/core/array/pack/shared/basic.rb b/spec/ruby/core/array/pack/shared/basic.rb
index 39ab15308d..2894369c71 100644
--- a/spec/ruby/core/array/pack/shared/basic.rb
+++ b/spec/ruby/core/array/pack/shared/basic.rb
@@ -1,6 +1,6 @@
describe :array_pack_arguments, shared: true do
it "raises an ArgumentError if there are fewer elements than the format requires" do
- lambda { [].pack(pack_format(1)) }.should raise_error(ArgumentError)
+ -> { [].pack(pack_format(1)) }.should.raise(ArgumentError)
end
end
@@ -10,11 +10,11 @@ describe :array_pack_basic, shared: true do
end
it "raises a TypeError when passed nil" do
- lambda { [@obj].pack(nil) }.should raise_error(TypeError)
+ -> { [@obj].pack(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed an Integer" do
- lambda { [@obj].pack(1) }.should raise_error(TypeError)
+ -> { [@obj].pack(1) }.should.raise(TypeError)
end
end
@@ -24,42 +24,50 @@ describe :array_pack_basic_non_float, shared: true do
end
it "ignores whitespace in the format string" do
- [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
+ [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should.instance_of?(String)
+ end
+
+ it "ignores comments in the format string" do
+ # 2 additional directives ('a') are required for the X directive
+ [@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should.instance_of?(String)
+ end
+
+ it "raise ArgumentError when a directive is unknown" do
+ # additional directive ('a') is required for the X directive
+ -> { [@obj, @obj].pack("a K" + pack_format) }.should.raise(ArgumentError, /unknown pack directive 'K'/)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should.raise(ArgumentError, /unknown pack directive '0'/)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should.raise(ArgumentError, /unknown pack directive ':'/)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
- [@obj, @obj].pack(d).should be_an_instance_of(String)
- end
-
- it "taints the output string if the format string is tainted" do
- [@obj, @obj].pack("x"+pack_format.taint).tainted?.should be_true
+ [@obj, @obj].pack(d).should.instance_of?(String)
end
end
describe :array_pack_basic_float, shared: true do
it "ignores whitespace in the format string" do
- [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
+ [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should.instance_of?(String)
+ end
+
+ it "ignores comments in the format string" do
+ [9.3, 4.7].pack(pack_format + "# some comment \n" + pack_format).should.instance_of?(String)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
- [1.2, 4.7].pack(d).should be_an_instance_of(String)
- end
-
- it "taints the output string if the format string is tainted" do
- [3.2, 2.8].pack("x"+pack_format.taint).tainted?.should be_true
+ [1.2, 4.7].pack(d).should.instance_of?(String)
end
end
describe :array_pack_no_platform, shared: true do
it "raises ArgumentError when the format modifier is '_'" do
- lambda{ [1].pack(pack_format("_")) }.should raise_error(ArgumentError)
+ ->{ [1].pack(pack_format("_")) }.should.raise(ArgumentError)
end
it "raises ArgumentError when the format modifier is '!'" do
- lambda{ [1].pack(pack_format("!")) }.should raise_error(ArgumentError)
+ ->{ [1].pack(pack_format("!")) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/encodings.rb b/spec/ruby/core/array/pack/shared/encodings.rb
index 3724a5d859..0b5a5cc8a0 100644
--- a/spec/ruby/core/array/pack/shared/encodings.rb
+++ b/spec/ruby/core/array/pack/shared/encodings.rb
@@ -5,12 +5,12 @@ describe :array_pack_hex, shared: true do
it "raises a TypeError if the object does not respond to #to_str" do
obj = mock("pack hex non-string")
- lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack hex non-string")
obj.should_receive(:to_str).and_return(1)
- lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb
index 082de27acd..c1efcd7677 100644
--- a/spec/ruby/core/array/pack/shared/float.rb
+++ b/spec/ruby/core/array/pack/shared/float.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
describe :array_pack_float_le, shared: true do
it "encodes a positive Float" do
@@ -14,7 +14,7 @@ describe :array_pack_float_le, shared: true do
end
it "raises a TypeError if passed a String representation of a floating point number" do
- lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -25,8 +25,10 @@ describe :array_pack_float_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -41,16 +43,9 @@ describe :array_pack_float_le, shared: true do
[-infinity_value].pack(pack_format).should == "\x00\x00\x80\xff"
end
- platform_is "86" do # x86 / x86_64
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x00\x00\xc0\xff"
- end
- end
-
- platform_is "powerpc64" do
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x00\x00\xc0\x7f"
- end
+ it "encodes NaN" do
+ nans = ["\x00\x00\xc0\xff", "\x00\x00\xc0\x7f", "\xFF\xFF\xFF\x7F"]
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -60,6 +55,14 @@ describe :array_pack_float_le, shared: true do
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\x00\x00\x80\xff"
end
+
+ it "encodes a bignum as a float" do
+ [2 ** 65].pack(pack_format).should == [(2 ** 65).to_f].pack(pack_format)
+ end
+
+ it "encodes a rational as a float" do
+ [Rational(3, 4)].pack(pack_format).should == [Rational(3, 4).to_f].pack(pack_format)
+ end
end
describe :array_pack_float_be, shared: true do
@@ -73,10 +76,15 @@ describe :array_pack_float_be, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "A\x00\x00\x00"
+ [bignum_value].pack(pack_format).should == "_\x80\x00\x00"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "A\x00\x00\x00"
end
it "raises a TypeError if passed a String representation of a floating point number" do
- lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -87,8 +95,10 @@ describe :array_pack_float_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -103,16 +113,9 @@ describe :array_pack_float_be, shared: true do
[-infinity_value].pack(pack_format).should == "\xff\x80\x00\x00"
end
- platform_is "86" do # x86 / x86_64
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\xff\xc0\x00\x00"
- end
- end
-
- platform_is "powerpc64" do
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x7f\xc0\x00\x00"
- end
+ it "encodes NaN" do
+ nans = ["\xff\xc0\x00\x00", "\x7f\xc0\x00\x00", "\x7F\xFF\xFF\xFF"]
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -135,10 +138,15 @@ describe :array_pack_double_le, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@"
+ [bignum_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xF0C"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00 @"
end
it "raises a TypeError if passed a String representation of a floating point number" do
- lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -149,8 +157,10 @@ describe :array_pack_double_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -165,16 +175,13 @@ describe :array_pack_double_le, shared: true do
[-infinity_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf0\xff"
end
- platform_is "86" do # x86 / x86_64
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\xff"
- end
- end
-
- platform_is "powerpc64" do
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\x7f"
- end
+ it "encodes NaN" do
+ nans = [
+ "\x00\x00\x00\x00\x00\x00\xf8\xff",
+ "\x00\x00\x00\x00\x00\x00\xf8\x7f",
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"
+ ]
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -200,7 +207,7 @@ describe :array_pack_double_be, shared: true do
end
it "raises a TypeError if passed a String representation of a floating point number" do
- lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -211,8 +218,10 @@ describe :array_pack_double_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -227,16 +236,13 @@ describe :array_pack_double_be, shared: true do
[-infinity_value].pack(pack_format).should == "\xff\xf0\x00\x00\x00\x00\x00\x00"
end
- platform_is "86" do # x86 / x86_64
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\xff\xf8\x00\x00\x00\x00\x00\x00"
- end
- end
-
- platform_is "powerpc64" do
- it "encodes NaN" do
- [nan_value].pack(pack_format).should == "\x7f\xf8\x00\x00\x00\x00\x00\x00"
- end
+ it "encodes NaN" do
+ nans = [
+ "\xff\xf8\x00\x00\x00\x00\x00\x00",
+ "\x7f\xf8\x00\x00\x00\x00\x00\x00",
+ "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ ]
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
diff --git a/spec/ruby/core/array/pack/shared/integer.rb b/spec/ruby/core/array/pack/shared/integer.rb
index 0df03bbfd1..1cdd386cc1 100644
--- a/spec/ruby/core/array/pack/shared/integer.rb
+++ b/spec/ruby/core/array/pack/shared/integer.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
describe :array_pack_16bit_le, shared: true do
it "encodes the least significant 16 bits of a positive number" do
@@ -41,9 +41,10 @@ describe :array_pack_16bit_le, shared: true do
str.should == "\x78\x65\xcd\xab\x21\x43"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\xcd\xab"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -93,9 +94,10 @@ describe :array_pack_16bit_be, shared: true do
str.should == "\x65\x78\xab\xcd\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x65\x78\xab\xcd"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -145,9 +147,10 @@ describe :array_pack_32bit_le, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -197,9 +200,10 @@ describe :array_pack_32bit_be, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -225,7 +229,7 @@ describe :array_pack_32bit_le_platform, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x21\x43\x65\x78"],
[[-0xff_7865_4321], "\xdf\xbc\x9a\x87"]
@@ -251,7 +255,7 @@ describe :array_pack_32bit_be_platform, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x78\x65\x43\x21"],
[[-0xff_7865_4321], "\x87\x9a\xbc\xdf"]
@@ -309,9 +313,10 @@ describe :array_pack_64bit_le, shared: true do
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -369,9 +374,10 @@ describe :array_pack_64bit_be, shared: true do
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/shared/numeric_basic.rb b/spec/ruby/core/array/pack/shared/numeric_basic.rb
index 9224d6080e..6594914933 100644
--- a/spec/ruby/core/array/pack/shared/numeric_basic.rb
+++ b/spec/ruby/core/array/pack/shared/numeric_basic.rb
@@ -4,41 +4,47 @@ describe :array_pack_numeric_basic, shared: true do
end
it "raises a TypeError when passed nil" do
- lambda { [nil].pack(pack_format) }.should raise_error(TypeError)
+ -> { [nil].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed true" do
- lambda { [true].pack(pack_format) }.should raise_error(TypeError)
+ -> { [true].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed false" do
- lambda { [false].pack(pack_format) }.should raise_error(TypeError)
+ -> { [false].pack(pack_format) }.should.raise(TypeError)
end
- it "returns an ASCII-8BIT string" do
- [0xFF].pack(pack_format).encoding.should == Encoding::ASCII_8BIT
- [0xE3, 0x81, 0x82].pack(pack_format(3)).encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ [0xFF].pack(pack_format).encoding.should == Encoding::BINARY
+ [0xE3, 0x81, 0x82].pack(pack_format(3)).encoding.should == Encoding::BINARY
end
end
describe :array_pack_integer, shared: true do
it "raises a TypeError when the object does not respond to #to_int" do
obj = mock('not an integer')
- lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- lambda { ["5"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["5"].pack(pack_format) }.should.raise(TypeError)
end
end
describe :array_pack_float, shared: true do
it "raises a TypeError if a String does not represent a floating point number" do
- lambda { ["a"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["a"].pack(pack_format) }.should.raise(TypeError)
end
- it "raises a TypeError when the object does not respond to #to_f" do
- obj = mock('not an float')
- lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
+ it "raises a TypeError when the object is not Numeric" do
+ obj = Object.new
+ -> { [obj].pack(pack_format) }.should.raise(TypeError, /can't convert Object into Float/)
+ end
+
+ it "raises a TypeError when the Numeric object does not respond to #to_f" do
+ klass = Class.new(Numeric)
+ obj = klass.new
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb
index 256c1c08e8..b02257059f 100644
--- a/spec/ruby/core/array/pack/shared/string.rb
+++ b/spec/ruby/core/array/pack/shared/string.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_string, shared: true do
it "adds count bytes of a String to the output" do
["abc"].pack(pack_format(2)).should == "ab"
@@ -17,11 +17,11 @@ describe :array_pack_string, shared: true do
end
it "raises an ArgumentError when the Array is empty" do
- lambda { [].pack(pack_format) }.should raise_error(ArgumentError)
+ -> { [].pack(pack_format) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the Array has too few elements" do
- lambda { ["a"].pack(pack_format(nil, 2)) }.should raise_error(ArgumentError)
+ -> { ["a"].pack(pack_format(nil, 2)) }.should.raise(ArgumentError)
end
it "calls #to_str to convert the element to a String" do
@@ -33,16 +33,16 @@ describe :array_pack_string, shared: true do
it "raises a TypeError when the object does not respond to #to_str" do
obj = mock("not a string")
- lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "returns a string in encoding of common to the concatenated results" do
f = pack_format("*")
- [ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::ASCII_8BIT],
- [["abcde\xd1", "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT],
- [["a".force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT],
+ [ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::BINARY],
+ [["abcde\xd1", "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::BINARY],
+ [["a".dup.force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::BINARY],
# under discussion [ruby-dev:37294]
- [["\u{3042 3044 3046 3048}", 1].pack(f+"N"), Encoding::ASCII_8BIT]
+ [["\u{3042 3044 3046 3048}", 1].pack(f+"N"), Encoding::BINARY]
].should be_computed_by(:encoding)
end
end
diff --git a/spec/ruby/core/array/pack/shared/taint.rb b/spec/ruby/core/array/pack/shared/taint.rb
index 88f349cb24..2c2b011c34 100644
--- a/spec/ruby/core/array/pack/shared/taint.rb
+++ b/spec/ruby/core/array/pack/shared/taint.rb
@@ -1,33 +1,2 @@
describe :array_pack_taint, shared: true do
- it "returns a tainted string when a pack argument is tainted" do
- ["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
- end
-
- it "does not return a tainted string when the array is tainted" do
- ["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
- end
-
- it "returns a tainted string when the format is tainted" do
- ["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
- end
-
- it "returns a tainted string when an empty format is tainted" do
- ["abcd", 0x20].pack("".taint).tainted?.should be_true
- end
-
- it "returns a untrusted string when the format is untrusted" do
- ["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when the empty format is untrusted" do
- ["abcd", 0x20].pack("".untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when a pack argument is untrusted" do
- ["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
- end
-
- it "returns a trusted string when the array is untrusted" do
- ["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
- end
end
diff --git a/spec/ruby/core/array/pack/shared/unicode.rb b/spec/ruby/core/array/pack/shared/unicode.rb
index e16110c491..58ba8a8b23 100644
--- a/spec/ruby/core/array/pack/shared/unicode.rb
+++ b/spec/ruby/core/array/pack/shared/unicode.rb
@@ -26,7 +26,7 @@ describe :array_pack_unicode, shared: true do
it "constructs strings with valid encodings" do
str = [0x85].pack("U*")
str.should == "\xc2\x85"
- str.valid_encoding?.should be_true
+ str.valid_encoding?.should == true
end
it "encodes values larger than UTF-8 max codepoints" do
@@ -64,11 +64,13 @@ describe :array_pack_unicode, shared: true do
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return("5")
- lambda { [obj].pack("U") }.should raise_error(TypeError)
+ -> { [obj].pack("U") }.should.raise(TypeError)
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("U\x00U").should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("U\x00U")
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -76,11 +78,11 @@ describe :array_pack_unicode, shared: true do
end
it "raises a RangeError if passed a negative number" do
- lambda { [-1].pack("U") }.should raise_error(RangeError)
+ -> { [-1].pack("U") }.should.raise(RangeError)
end
it "raises a RangeError if passed a number larger than an unsigned 32-bit integer" do
- lambda { [2**32].pack("U") }.should raise_error(RangeError)
+ -> { [2**32].pack("U") }.should.raise(RangeError)
end
it "sets the output string to UTF-8 encoding" do
diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb
index d708518c16..c6a0d77eb2 100644
--- a/spec/ruby/core/array/pack/u_spec.rb
+++ b/spec/ruby/core/array/pack/u_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -18,6 +18,16 @@ describe "Array#pack with format 'u'" do
it_behaves_like :array_pack_arguments, 'u'
it_behaves_like :array_pack_taint, 'u'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack u string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("u*").should == "(8&!A8F-D968`\n"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('u') }.should.raise(TypeError)
+ end
+
it "encodes an empty string as an empty string" do
[""].pack("u").should == ""
end
@@ -112,16 +122,16 @@ describe "Array#pack with format 'u'" do
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
- lambda { [obj].pack("u") }.should raise_error(TypeError)
+ -> { [obj].pack("u") }.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
- lambda { [nil].pack("u") }.should raise_error(TypeError)
+ -> { [nil].pack("u") }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer" do
- lambda { [0].pack("u") }.should raise_error(TypeError)
- lambda { [bignum_value].pack("u") }.should raise_error(TypeError)
+ -> { [0].pack("u") }.should.raise(TypeError)
+ -> { [bignum_value].pack("u") }.should.raise(TypeError)
end
it "sets the output string to US-ASCII encoding" do
diff --git a/spec/ruby/core/array/pack/w_spec.rb b/spec/ruby/core/array/pack/w_spec.rb
index 76be1f925f..263e2a2288 100644
--- a/spec/ruby/core/array/pack/w_spec.rb
+++ b/spec/ruby/core/array/pack/w_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -24,8 +24,10 @@ describe "Array#pack with format 'w'" do
[obj].pack("w").should == "\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("w\x00w").should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("w\x00w")
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -33,10 +35,10 @@ describe "Array#pack with format 'w'" do
end
it "raises an ArgumentError when passed a negative value" do
- lambda { [-1].pack("w") }.should raise_error(ArgumentError)
+ -> { [-1].pack("w") }.should.raise(ArgumentError)
end
- it "returns an ASCII-8BIT string" do
- [1].pack('w').encoding.should == Encoding::ASCII_8BIT
+ it "returns a binary string" do
+ [1].pack('w').encoding.should == Encoding::BINARY
end
end
diff --git a/spec/ruby/core/array/pack/x_spec.rb b/spec/ruby/core/array/pack/x_spec.rb
index 45fe34d08d..7ff587a01e 100644
--- a/spec/ruby/core/array/pack/x_spec.rb
+++ b/spec/ruby/core/array/pack/x_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -30,6 +30,7 @@ describe "Array#pack with format 'x'" do
it "does not add a NULL byte when passed the '*' modifier" do
[].pack("x*").should == ""
+ [1, 2].pack("Cx*C").should == "\x01\x02"
end
end
@@ -55,10 +56,10 @@ describe "Array#pack with format 'X'" do
end
it "raises an ArgumentError if the output string is empty" do
- lambda { [1, 2, 3].pack("XC") }.should raise_error(ArgumentError)
+ -> { [1, 2, 3].pack("XC") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the count modifier is greater than the bytes in the string" do
- lambda { [1, 2, 3].pack("C2X3") }.should raise_error(ArgumentError)
+ -> { [1, 2, 3].pack("C2X3") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb
index d0600f0c26..5cd084c825 100644
--- a/spec/ruby/core/array/pack/z_spec.rb
+++ b/spec/ruby/core/array/pack/z_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -12,11 +12,21 @@ describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_string, 'Z'
it_behaves_like :array_pack_taint, 'Z'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack Z string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("Z*").should == "``abcdef\x00"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('Z') }.should.raise(TypeError)
+ end
+
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("Z6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/partition_spec.rb b/spec/ruby/core/array/partition_spec.rb
index be36fffcab..bd3f3a6b6f 100644
--- a/spec/ruby/core/array/partition_spec.rb
+++ b/spec/ruby/core/array/partition_spec.rb
@@ -36,8 +36,8 @@ describe "Array#partition" do
it "does not return subclass instances on Array subclasses" do
result = ArraySpecs::MyArray[1, 2, 3].partition { |x| x % 2 == 0 }
- result.should be_an_instance_of(Array)
- result[0].should be_an_instance_of(Array)
- result[1].should be_an_instance_of(Array)
+ result.should.instance_of?(Array)
+ result[0].should.instance_of?(Array)
+ result[1].should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/permutation_spec.rb b/spec/ruby/core/array/permutation_spec.rb
index f15bd76639..b5df84b52b 100644
--- a/spec/ruby/core/array/permutation_spec.rb
+++ b/spec/ruby/core/array/permutation_spec.rb
@@ -11,7 +11,7 @@ describe "Array#permutation" do
it "returns an Enumerator of all permutations when called without a block or arguments" do
enum = @numbers.permutation
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
].sort
@@ -19,13 +19,13 @@ describe "Array#permutation" do
it "returns an Enumerator of permutations of given length when called with an argument but no block" do
enum = @numbers.permutation(1)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == [[1],[2],[3]]
end
it "yields all permutations to the block then returns self when called with block but no arguments" do
array = @numbers.permutation {|n| @yielded << n}
- array.should be_an_instance_of(Array)
+ array.should.instance_of?(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
@@ -34,7 +34,7 @@ describe "Array#permutation" do
it "yields all permutations of given length to the block then returns self when called with block and argument" do
array = @numbers.permutation(2) {|n| @yielded << n}
- array.should be_an_instance_of(Array)
+ array.should.instance_of?(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]].sort
end
@@ -78,7 +78,7 @@ describe "Array#permutation" do
[3, 1], [3, 2], [3, [4, 5]],
[[4, 5], 1], [[4, 5], 2], [[4, 5], 3]
]
- expected.each {|e| got.include?(e).should be_true}
+ expected.each {|e| got.include?(e).should == true}
got.size.should == expected.size
end
diff --git a/spec/ruby/core/array/plus_spec.rb b/spec/ruby/core/array/plus_spec.rb
index 7692163980..7ead927fc0 100644
--- a/spec/ruby/core/array/plus_spec.rb
+++ b/spec/ruby/core/array/plus_spec.rb
@@ -14,10 +14,23 @@ describe "Array#+" do
(ary + ary).should == [1, 2, 3, 1, 2, 3]
end
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('["x", "y"]')
- obj.should_receive(:to_ary).and_return(["x", "y"])
- ([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
+ describe "converts the passed argument to an Array using #to_ary" do
+ it "successfully concatenates the resulting array from the #to_ary call" do
+ obj = mock('["x", "y"]')
+ obj.should_receive(:to_ary).and_return(["x", "y"])
+ ([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
+ end
+
+ it "raises a TypeError if the given argument can't be converted to an array" do
+ -> { [1, 2, 3] + nil }.should.raise(TypeError)
+ -> { [1, 2, 3] + "abc" }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
+ obj = mock("hello")
+ obj.should_receive(:to_ary).and_raise(NoMethodError)
+ -> { [1, 2, 3] + obj }.should.raise(NoMethodError)
+ end
end
it "properly handles recursive arrays" do
@@ -32,26 +45,12 @@ describe "Array#+" do
end
it "does return subclass instances with Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] + []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- ([1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
+ (ArraySpecs::MyArray[1, 2, 3] + []).should.instance_of?(Array)
+ (ArraySpecs::MyArray[1, 2, 3] + ArraySpecs::MyArray[]).should.instance_of?(Array)
+ ([1, 2, 3] + ArraySpecs::MyArray[]).should.instance_of?(Array)
end
it "does not call to_ary on array subclasses" do
([5, 6] + ArraySpecs::ToAryArray[1, 2]).should == [5, 6, 1, 2]
end
-
- it "does not get infected even if an original array is tainted" do
- ([1, 2] + [3, 4]).tainted?.should be_false
- ([1, 2].taint + [3, 4]).tainted?.should be_false
- ([1, 2] + [3, 4].taint).tainted?.should be_false
- ([1, 2].taint + [3, 4].taint).tainted?.should be_false
- end
-
- it "does not infected even if an original array is untrusted" do
- ([1, 2] + [3, 4]).untrusted?.should be_false
- ([1, 2].untrust + [3, 4]).untrusted?.should be_false
- ([1, 2] + [3, 4].untrust).untrusted?.should be_false
- ([1, 2].untrust + [3, 4].untrust).untrusted?.should be_false
- end
end
diff --git a/spec/ruby/core/array/pop_spec.rb b/spec/ruby/core/array/pop_spec.rb
index 335a0f2b60..069083331c 100644
--- a/spec/ruby/core/array/pop_spec.rb
+++ b/spec/ruby/core/array/pop_spec.rb
@@ -30,28 +30,12 @@ describe "Array#pop" do
array.pop.should == [1, 'two', 3.0, array, array, array, array]
end
- it "keeps taint status" do
- a = [1, 2].taint
- a.pop
- a.tainted?.should be_true
- a.pop
- a.tainted?.should be_true
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.pop }.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.pop }.should raise_error(frozen_error_class)
- end
-
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.pop }.should raise_error(frozen_error_class)
- end
-
- it "keeps untrusted status" do
- a = [1, 2].untrust
- a.pop
- a.untrusted?.should be_true
- a.pop
- a.untrusted?.should be_true
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.pop }.should.raise(FrozenError)
end
describe "passed a number n as an argument" do
@@ -87,7 +71,7 @@ describe "Array#pop" do
popped2.should == []
a.should == []
- popped1.should_not equal(popped2)
+ popped1.should_not.equal?(popped2)
end
it "returns whole elements if n exceeds size of the array" do
@@ -98,14 +82,14 @@ describe "Array#pop" do
it "does not return self even when it returns whole elements" do
a = [1, 2, 3, 4, 5]
- a.pop(5).should_not equal(a)
+ a.pop(5).should_not.equal?(a)
a = [1, 2, 3, 4, 5]
- a.pop(6).should_not equal(a)
+ a.pop(6).should_not.equal?(a)
end
it "raises an ArgumentError if n is negative" do
- lambda{ [1, 2, 3].pop(-1) }.should raise_error(ArgumentError)
+ ->{ [1, 2, 3].pop(-1) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -120,49 +104,21 @@ describe "Array#pop" do
end
it "raises a TypeError when the passed n cannot be coerced to Integer" do
- lambda{ [1, 2].pop("cat") }.should raise_error(TypeError)
- lambda{ [1, 2].pop(nil) }.should raise_error(TypeError)
+ ->{ [1, 2].pop("cat") }.should.raise(TypeError)
+ ->{ [1, 2].pop(nil) }.should.raise(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
- lambda{ [1, 2].pop(1, 2) }.should raise_error(ArgumentError)
+ ->{ [1, 2].pop(1, 2) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].pop(2).should be_an_instance_of(Array)
- end
-
- it "returns an untainted array even if the array is tainted" do
- ary = [1, 2].taint
- ary.pop(2).tainted?.should be_false
- ary.pop(0).tainted?.should be_false
- end
-
- it "keeps taint status" do
- a = [1, 2].taint
- a.pop(2)
- a.tainted?.should be_true
- a.pop(2)
- a.tainted?.should be_true
- end
-
- it "returns a trusted array even if the array is untrusted" do
- ary = [1, 2].untrust
- ary.pop(2).untrusted?.should be_false
- ary.pop(0).untrusted?.should be_false
- end
-
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.pop(2) }.should raise_error(frozen_error_class)
- lambda { ArraySpecs.frozen_array.pop(0) }.should raise_error(frozen_error_class)
+ ArraySpecs::MyArray[1, 2, 3].pop(2).should.instance_of?(Array)
end
- it "keeps untrusted status" do
- a = [1, 2].untrust
- a.pop(2)
- a.untrusted?.should be_true
- a.pop(2)
- a.untrusted?.should be_true
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.pop(2) }.should.raise(FrozenError)
+ -> { ArraySpecs.frozen_array.pop(0) }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/array/prepend_spec.rb b/spec/ruby/core/array/prepend_spec.rb
index 22230ec300..2d0ce31c71 100644
--- a/spec/ruby/core/array/prepend_spec.rb
+++ b/spec/ruby/core/array/prepend_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/unshift'
-ruby_version_is "2.5" do
- describe "Array#prepend" do
- it_behaves_like :array_unshift, :prepend
+describe "Array#prepend" do
+ it "is an alias of Array#unshift" do
+ Array.instance_method(:prepend).should == Array.instance_method(:unshift)
end
end
diff --git a/spec/ruby/core/array/product_spec.rb b/spec/ruby/core/array/product_spec.rb
index 9207a9b014..837f0eaf34 100644
--- a/spec/ruby/core/array/product_spec.rb
+++ b/spec/ruby/core/array/product_spec.rb
@@ -3,12 +3,17 @@ require_relative 'fixtures/classes'
describe "Array#product" do
it "returns converted arguments using :to_ary" do
- lambda{ [1].product(2..3) }.should raise_error(TypeError)
- ar = ArraySpecs::ArrayConvertable.new(2,3)
+ ->{ [1].product(2..3) }.should.raise(TypeError)
+ ar = ArraySpecs::ArrayConvertible.new(2,3)
[1].product(ar).should == [[1,2],[1,3]]
ar.called.should == :to_ary
end
+ it "returns converted arguments using :method_missing" do
+ ar = ArraySpecs::ArrayMethodMissing.new(2,3)
+ [1].product(ar).should == [[1,2],[1,3]]
+ end
+
it "returns the expected result" do
[1,2].product([3,4,5],[6,8]).should == [[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8],
[2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]]
@@ -24,9 +29,9 @@ describe "Array#product" do
it "does not attempt to produce an unreasonable number of products" do
a = (0..100).to_a
- lambda do
+ -> do
a.product(a, a, a, a, a, a, a, a, a, a)
- end.should raise_error(RangeError)
+ end.should.raise(RangeError)
end
describe "when given a block" do
@@ -38,7 +43,7 @@ describe "Array#product" do
acc = []
[1,2].product([3,4,5],[],[6,8]){|array| acc << array}
- acc.should be_empty
+ acc.should.empty?
end
it "returns self" do
@@ -49,20 +54,20 @@ describe "Array#product" do
it "will ignore unreasonable numbers of products and yield anyway" do
a = (0..100).to_a
- lambda do
+ -> do
a.product(a, a, a, a, a, a, a, a, a, a)
- end.should raise_error(RangeError)
+ end.should.raise(RangeError)
end
end
describe "when given an empty block" do
it "returns self" do
arr = [1,2]
- arr.product([3,4,5],[6,8]){}.should equal(arr)
+ arr.product([3,4,5],[6,8]){}.should.equal?(arr)
arr = []
- arr.product([3,4,5],[6,8]){}.should equal(arr)
+ arr.product([3,4,5],[6,8]){}.should.equal?(arr)
arr = [1,2]
- arr.product([]){}.should equal(arr)
+ arr.product([]){}.should.equal?(arr)
end
end
end
diff --git a/spec/ruby/core/array/push_spec.rb b/spec/ruby/core/array/push_spec.rb
index 607cbc7b4d..6255a84371 100644
--- a/spec/ruby/core/array/push_spec.rb
+++ b/spec/ruby/core/array/push_spec.rb
@@ -1,7 +1,36 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/push'
describe "Array#push" do
- it_behaves_like :array_push, :push
+ it "appends the arguments to the array" do
+ a = [ "a", "b", "c" ]
+ a.push("d", "e", "f").should.equal?(a)
+ a.push.should == ["a", "b", "c", "d", "e", "f"]
+ a.push(5)
+ a.should == ["a", "b", "c", "d", "e", "f", 5]
+
+ a = [0, 1]
+ a.push(2)
+ a.should == [0, 1, 2]
+ end
+
+ it "isn't confused by previous shift" do
+ a = [ "a", "b", "c" ]
+ a.shift
+ a.push("foo")
+ a.should == ["b", "c", "foo"]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.push(:last).should == [empty, :last]
+
+ array = ArraySpecs.recursive_array
+ array.push(:last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
+ end
+
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.push(1) }.should.raise(FrozenError)
+ -> { ArraySpecs.frozen_array.push }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/array/rassoc_spec.rb b/spec/ruby/core/array/rassoc_spec.rb
index decdaae098..95e4ed1892 100644
--- a/spec/ruby/core/array/rassoc_spec.rb
+++ b/spec/ruby/core/array/rassoc_spec.rb
@@ -12,11 +12,11 @@ describe "Array#rassoc" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.rassoc([]).should be_nil
+ empty.rassoc([]).should == nil
[[empty, empty]].rassoc(empty).should == [empty, empty]
array = ArraySpecs.recursive_array
- array.rassoc(array).should be_nil
+ array.rassoc(array).should == nil
[[empty, array]].rassoc(array).should == [empty, array]
end
@@ -28,11 +28,23 @@ describe "Array#rassoc" do
[[1, :foobar], [2, o], [3, mock('foo')]].rassoc(key).should == [2, o]
end
- it "does not check the last element in each contained but speficically the second" do
+ it "does not check the last element in each contained but specifically the second" do
key = 'foobar'
o = mock('foobar')
def o.==(other); other == 'foobar'; end
[[1, :foobar, o], [2, o, 1], [3, mock('foo')]].rassoc(key).should == [2, o, 1]
end
+
+ it "calls to_ary on non-array elements" do
+ s1 = [1, 2]
+ s2 = ArraySpecs::ArrayConvertible.new(2, 3)
+ a = [s1, s2]
+
+ s1.should_not_receive(:to_ary)
+ a.rassoc(2).should.equal?(s1)
+
+ a.rassoc(3).should == [2, 3]
+ s2.called.should.equal?(:to_ary)
+ end
end
diff --git a/spec/ruby/core/array/reject_spec.rb b/spec/ruby/core/array/reject_spec.rb
index 8bce7ad3bf..8d237b3a75 100644
--- a/spec/ruby/core/array/reject_spec.rb
+++ b/spec/ruby/core/array/reject_spec.rb
@@ -2,6 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative 'shared/delete_if'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#reject" do
@@ -9,9 +10,9 @@ describe "Array#reject" do
ary = [1, 2, 3, 4, 5]
ary.reject { true }.should == []
ary.reject { false }.should == ary
- ary.reject { false }.should_not equal ary
+ ary.reject { false }.should_not.equal? ary
ary.reject { nil }.should == ary
- ary.reject { nil }.should_not equal ary
+ ary.reject { nil }.should_not.equal? ary
ary.reject { 5 }.should == []
ary.reject { |i| i < 3 }.should == [3, 4, 5]
ary.reject { |i| i % 2 == 0 }.should == [1, 3, 5]
@@ -34,7 +35,7 @@ describe "Array#reject" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].reject { |x| x % 2 == 0 }.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].reject { |x| x % 2 == 0 }.should.instance_of?(Array)
end
it "does not retain instance variables" do
@@ -47,10 +48,14 @@ describe "Array#reject" do
it_behaves_like :enumeratorized_with_origin_size, :reject, [1,2,3]
end
+describe "Array#reject" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :reject
+end
+
describe "Array#reject!" do
it "removes elements for which block is true" do
a = [3, 4, 5, 6, 7, 8, 9, 10, 11]
- a.reject! { |i| i % 2 == 0 }.should equal(a)
+ a.reject! { |i| i % 2 == 0 }.should.equal?(a)
a.should == [3, 5, 7, 9, 11]
a.reject! { |i| i > 8 }
a.should == [3, 5, 7]
@@ -100,15 +105,20 @@ describe "Array#reject!" do
end
it "returns an Enumerator if no block given, and the array is frozen" do
- ArraySpecs.frozen_array.reject!.should be_an_instance_of(Enumerator)
+ ArraySpecs.frozen_array.reject!.should.instance_of?(Enumerator)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.reject! {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.reject! {} }.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.reject! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = ArraySpecs.frozen_array.reject!
+ -> { enum.each {} }.should.raise(FrozenError)
end
it "does not truncate the array is the block raises an exception" do
@@ -121,25 +131,28 @@ describe "Array#reject!" do
a.should == [1, 2, 3]
end
- ruby_version_is "2.4" do
- it "only removes elements for which the block returns true, keeping the element which raised an error." do
- a = [1, 2, 3, 4]
- begin
- a.reject! do |x|
- case x
- when 2 then true
- when 3 then raise StandardError, 'Oops'
- else false
- end
+ it "only removes elements for which the block returns true, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.reject! do |x|
+ case x
+ when 2 then true
+ when 3 then raise StandardError, 'Oops'
+ else false
end
- rescue StandardError
end
-
- a.should == [1, 3, 4]
+ rescue StandardError
end
+
+ a.should == [1, 3, 4]
end
it_behaves_like :enumeratorize, :reject!
it_behaves_like :enumeratorized_with_origin_size, :reject!, [1,2,3]
it_behaves_like :delete_if, :reject!
end
+
+describe "Array#reject!" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :reject!
+end
diff --git a/spec/ruby/core/array/repeated_combination_spec.rb b/spec/ruby/core/array/repeated_combination_spec.rb
index 373b7bb6e5..a714f05f54 100644
--- a/spec/ruby/core/array/repeated_combination_spec.rb
+++ b/spec/ruby/core/array/repeated_combination_spec.rb
@@ -6,16 +6,16 @@ describe "Array#repeated_combination" do
end
it "returns an enumerator when no block is provided" do
- @array.repeated_combination(2).should be_an_instance_of(Enumerator)
+ @array.repeated_combination(2).should.instance_of?(Enumerator)
end
it "returns self when a block is given" do
- @array.repeated_combination(2){}.should equal(@array)
+ @array.repeated_combination(2){}.should.equal?(@array)
end
it "yields nothing for negative length and return self" do
- @array.repeated_combination(-1){ fail }.should equal(@array)
- @array.repeated_combination(-10){ fail }.should equal(@array)
+ @array.repeated_combination(-1){ fail }.should.equal?(@array)
+ @array.repeated_combination(-10){ fail }.should.equal?(@array)
end
it "yields the expected repeated_combinations" do
@@ -68,7 +68,7 @@ describe "Array#repeated_combination" do
[].repeated_combination(0).size.should == 1
end
- it "returns the binomial coeficient between combination_size and array size + combination_size -1" do
+ it "returns the binomial coefficient between combination_size and array size + combination_size -1" do
@array.repeated_combination(5).size.should == 21
@array.repeated_combination(4).size.should == 15
@array.repeated_combination(3).size.should == 10
diff --git a/spec/ruby/core/array/repeated_permutation_spec.rb b/spec/ruby/core/array/repeated_permutation_spec.rb
index a165fda09e..c54a8c0c2b 100644
--- a/spec/ruby/core/array/repeated_permutation_spec.rb
+++ b/spec/ruby/core/array/repeated_permutation_spec.rb
@@ -10,13 +10,13 @@ describe "Array#repeated_permutation" do
it "returns an Enumerator of all repeated permutations of given length when called without a block" do
enum = @numbers.repeated_permutation(2)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == @permutations
end
it "yields all repeated_permutations to the block then returns self when called with block but no arguments" do
yielded = []
- @numbers.repeated_permutation(2) {|n| yielded << n}.should equal(@numbers)
+ @numbers.repeated_permutation(2) {|n| yielded << n}.should.equal?(@numbers)
yielded.sort.should == @permutations
end
diff --git a/spec/ruby/core/array/replace_spec.rb b/spec/ruby/core/array/replace_spec.rb
index 2f53338f5e..ee6a98a646 100644
--- a/spec/ruby/core/array/replace_spec.rb
+++ b/spec/ruby/core/array/replace_spec.rb
@@ -1,7 +1,63 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/replace'
describe "Array#replace" do
- it_behaves_like :array_replace, :replace
+ it "replaces the elements with elements from other array" do
+ a = [1, 2, 3, 4, 5]
+ b = ['a', 'b', 'c']
+ a.replace(b).should.equal?(a)
+ a.should == b
+ a.should_not.equal?(b)
+
+ a.replace([4] * 10)
+ a.should == [4] * 10
+
+ a.replace([])
+ a.should == []
+ end
+
+ it "properly handles recursive arrays" do
+ orig = [1, 2, 3]
+ empty = ArraySpecs.empty_recursive_array
+ orig.replace(empty)
+ orig.should == empty
+
+ array = ArraySpecs.recursive_array
+ orig.replace(array)
+ orig.should == array
+ end
+
+ it "returns self" do
+ ary = [1, 2, 3]
+ other = [:a, :b, :c]
+ ary.replace(other).should.equal?(ary)
+ end
+
+ it "does not make self dependent to the original array" do
+ ary = [1, 2, 3]
+ other = [:a, :b, :c]
+ ary.replace(other)
+ ary.should == [:a, :b, :c]
+ ary << :d
+ ary.should == [:a, :b, :c, :d]
+ other.should == [:a, :b, :c]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('to_ary')
+ obj.stub!(:to_ary).and_return([1, 2, 3])
+ [].replace(obj).should == [1, 2, 3]
+ end
+
+ it "does not call #to_ary on Array subclasses" do
+ obj = ArraySpecs::ToAryArray[5, 6, 7]
+ obj.should_not_receive(:to_ary)
+ [].replace(ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
+ end
+
+ it "raises a FrozenError on a frozen array" do
+ -> {
+ ArraySpecs.frozen_array.replace(ArraySpecs.frozen_array)
+ }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/array/reverse_each_spec.rb b/spec/ruby/core/array/reverse_each_spec.rb
index 28b8bfcb34..8fa5ce6da1 100644
--- a/spec/ruby/core/array/reverse_each_spec.rb
+++ b/spec/ruby/core/array/reverse_each_spec.rb
@@ -5,7 +5,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#reverse_each" do
before :each do
@@ -19,7 +19,7 @@ describe "Array#reverse_each" do
it "returns self" do
a = [:a, :b, :c]
- a.reverse_each { |x| }.should equal(a)
+ a.reverse_each { |x| }.should.equal?(a)
end
it "yields only the top level element of an empty recursive arrays" do
@@ -38,6 +38,20 @@ describe "Array#reverse_each" do
[1, 2, 3].reverse_each.size.should == 3
end
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.reverse_each do |e|
+ ScratchPad << e
+ array.prepend i if i < 100
+ i += 1
+ end
+
+ ScratchPad.recorded.should == [:c, :a, 1]
+ end
+
it_behaves_like :enumeratorize, :reverse_each
it_behaves_like :enumeratorized_with_origin_size, :reverse_each, [1,2,3]
end
diff --git a/spec/ruby/core/array/reverse_spec.rb b/spec/ruby/core/array/reverse_spec.rb
index d8ff26639d..f25a484be8 100644
--- a/spec/ruby/core/array/reverse_spec.rb
+++ b/spec/ruby/core/array/reverse_spec.rb
@@ -16,14 +16,14 @@ describe "Array#reverse" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].reverse.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].reverse.should.instance_of?(Array)
end
end
describe "Array#reverse!" do
it "reverses the elements in place" do
a = [6, 3, 4, 2, 1]
- a.reverse!.should equal(a)
+ a.reverse!.should.equal?(a)
a.should == [1, 2, 4, 3, 6]
[].reverse!.should == []
end
@@ -36,7 +36,7 @@ describe "Array#reverse!" do
array.reverse!.should == [array, array, array, array, array, 3.0, 'two', 1]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.reverse! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.reverse! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/rindex_spec.rb b/spec/ruby/core/array/rindex_spec.rb
index 175c7bcfe2..858c39dc92 100644
--- a/spec/ruby/core/array/rindex_spec.rb
+++ b/spec/ruby/core/array/rindex_spec.rb
@@ -4,7 +4,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#rindex" do
it "returns the first index backwards from the end where element == to object" do
@@ -41,7 +41,7 @@ describe "Array#rindex" do
it "properly handles empty recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.rindex(empty).should == 0
- empty.rindex(1).should be_nil
+ empty.rindex(1).should == nil
end
it "properly handles recursive arrays" do
@@ -68,10 +68,25 @@ describe "Array#rindex" do
seen.should == [3]
end
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.rindex do |e|
+ ScratchPad << e
+ array.prepend i if i < 100
+ i += 1
+ false
+ end
+
+ ScratchPad.recorded.should == [:c, :a, 1]
+ end
+
describe "given no argument and no block" do
it "produces an Enumerator" do
enum = [4, 2, 1, 5, 1, 3].rindex
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |x| x < 2 }.should == 4
end
end
diff --git a/spec/ruby/core/array/rotate_spec.rb b/spec/ruby/core/array/rotate_spec.rb
index 6450d3892b..009ce5ed49 100644
--- a/spec/ruby/core/array/rotate_spec.rb
+++ b/spec/ruby/core/array/rotate_spec.rb
@@ -27,12 +27,12 @@ describe "Array#rotate" do
end
it "raises a TypeError if not passed an integer-like argument" do
- lambda {
+ -> {
[1, 2].rotate(nil)
- }.should raise_error(TypeError)
- lambda {
+ }.should.raise(TypeError)
+ -> {
[1, 2].rotate("4")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
@@ -46,22 +46,22 @@ describe "Array#rotate" do
end
it "does not mutate the receiver" do
- lambda {
+ -> {
[].freeze.rotate
[2].freeze.rotate(2)
[1,2,3].freeze.rotate(-3)
- }.should_not raise_error
+ }.should_not.raise
end
it "does not return self" do
a = [1, 2, 3]
- a.rotate.should_not equal(a)
+ a.rotate.should_not.equal?(a)
a = []
- a.rotate(0).should_not equal(a)
+ a.rotate(0).should_not.equal?(a)
end
it "does not return subclass instance for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].rotate.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].rotate.should.instance_of?(Array)
end
end
@@ -69,7 +69,7 @@ describe "Array#rotate!" do
describe "when passed no argument" do
it "moves the first element to the end and returns self" do
a = [1, 2, 3, 4, 5]
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == [2, 3, 4, 5, 1]
end
end
@@ -77,11 +77,11 @@ describe "Array#rotate!" do
describe "with an argument n" do
it "moves the first (n % size) elements at the end and returns self" do
a = [1, 2, 3, 4, 5]
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == [3, 4, 5, 1, 2]
- a.rotate!(-12).should equal(a)
+ a.rotate!(-12).should.equal?(a)
a.should == [1, 2, 3, 4, 5]
- a.rotate!(13).should equal(a)
+ a.rotate!(13).should.equal?(a)
a.should == [4, 5, 1, 2, 3]
end
@@ -94,36 +94,36 @@ describe "Array#rotate!" do
end
it "raises a TypeError if not passed an integer-like argument" do
- lambda {
+ -> {
[1, 2].rotate!(nil)
- }.should raise_error(TypeError)
- lambda {
+ }.should.raise(TypeError)
+ -> {
[1, 2].rotate!("4")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
it "does nothing and returns self when the length is zero or one" do
a = [1]
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == [1]
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == [1]
- a.rotate!(-21).should equal(a)
+ a.rotate!(-21).should.equal?(a)
a.should == [1]
a = []
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == []
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == []
- a.rotate!(-21).should equal(a)
+ a.rotate!(-21).should.equal?(a)
a.should == []
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { [1, 2, 3].freeze.rotate!(0) }.should raise_error(frozen_error_class)
- lambda { [1].freeze.rotate!(42) }.should raise_error(frozen_error_class)
- lambda { [].freeze.rotate! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { [1, 2, 3].freeze.rotate!(0) }.should.raise(FrozenError)
+ -> { [1].freeze.rotate!(42) }.should.raise(FrozenError)
+ -> { [].freeze.rotate! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/sample_spec.rb b/spec/ruby/core/array/sample_spec.rb
index 3bd5d046cc..fd443b47de 100644
--- a/spec/ruby/core/array/sample_spec.rb
+++ b/spec/ruby/core/array/sample_spec.rb
@@ -3,24 +3,34 @@ require_relative 'fixtures/classes'
describe "Array#sample" do
it "samples evenly" do
- ary = [0, 1, 2, 3]
- 3.times do |i|
- counts = [0, 0, 0, 0]
- 4000.times do
- counts[ary.sample(3)[i]] += 1
- end
- counts.each do |count|
- (800..1200).should include(count)
- end
- end
+ ArraySpecs.measure_sample_fairness(4, 1, 400)
+ ArraySpecs.measure_sample_fairness(4, 2, 400)
+ ArraySpecs.measure_sample_fairness(4, 3, 400)
+ ArraySpecs.measure_sample_fairness(40, 3, 400)
+ ArraySpecs.measure_sample_fairness(40, 4, 400)
+ ArraySpecs.measure_sample_fairness(40, 8, 400)
+ ArraySpecs.measure_sample_fairness(40, 16, 400)
+ ArraySpecs.measure_sample_fairness_large_sample_size(100, 80, 4000)
end
it "returns nil for an empty Array" do
- [].sample.should be_nil
+ [].sample.should == nil
+ end
+
+ it "returns nil for an empty array when called without n and a Random is given" do
+ [].sample(random: Random.new(42)).should == nil
end
it "returns a single value when not passed a count" do
- [4].sample.should equal(4)
+ [4].sample.should.equal?(4)
+ end
+
+ it "returns a single value when not passed a count and a Random is given" do
+ [4].sample(random: Random.new(42)).should.equal?(4)
+ end
+
+ it "returns a single value when not passed a count and a Random class is given" do
+ [4].sample(random: Random).should.equal?(4)
end
it "returns an empty Array when passed zero" do
@@ -28,12 +38,12 @@ describe "Array#sample" do
end
it "returns an Array of elements when passed a count" do
- [1, 2, 3, 4].sample(3).should be_an_instance_of(Array)
+ [1, 2, 3, 4].sample(3).should.instance_of?(Array)
end
it "returns elements from the Array" do
array = [1, 2, 3, 4]
- array.sample(3).all? { |x| array.should include(x) }
+ array.sample(3).all? { |x| array.should.include?(x) }
end
it "returns at most the number of elements in the Array" do
@@ -57,46 +67,29 @@ describe "Array#sample" do
end
it "raises ArgumentError when passed a negative count" do
- lambda { [1, 2].sample(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].sample(-1) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].sample(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].sample(2).should.instance_of?(Array)
end
describe "with options" do
- it "calls #to_hash to convert the passed Object" do
- obj = mock("array_sample")
- obj.should_receive(:to_hash).and_return({})
- obj.should_not_receive(:to_int)
-
- [1, 2].sample(obj).should be_an_instance_of(Fixnum)
- end
-
- it "calls #to_int on the first argument and #to_hash on the second when passed Objects" do
- count = mock("array_sample_count")
- count.should_receive(:to_int).and_return(2)
- options = mock("array_sample_options")
- options.should_receive(:to_hash).and_return({})
-
- [1, 2].sample(count, options).size.should == 2
- end
-
it "calls #rand on the Object passed by the :random key in the arguments Hash" do
obj = mock("array_sample_random")
obj.should_receive(:rand).and_return(0.5)
- [1, 2].sample(random: obj).should be_an_instance_of(Fixnum)
+ [1, 2].sample(random: obj).should.instance_of?(Integer)
end
it "raises a NoMethodError if an object passed for the RNG does not define #rand" do
obj = BasicObject.new
- lambda { [1, 2].sample(random: obj) }.should raise_error(NoMethodError)
+ -> { [1, 2].sample(random: obj) }.should.raise(NoMethodError)
end
- describe "when the object returned by #rand is a Fixnum" do
- it "uses the fixnum as index" do
+ describe "when the object returned by #rand is an Integer" do
+ it "uses the integer as index" do
random = mock("array_sample_random_ret")
random.should_receive(:rand).and_return(0)
@@ -112,19 +105,26 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(-1)
- lambda { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
it "raises a RangeError if the value is equal to the Array size" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(2)
- lambda { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
+ end
+
+ it "raises a RangeError if the value is greater than the Array size" do
+ random = mock("array_sample_random")
+ random.should_receive(:rand).and_return(3)
+
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
end
end
- describe "when the object returned by #rand is not a Fixnum but responds to #to_int" do
+ describe "when the object returned by #rand is not an Integer but responds to #to_int" do
it "calls #to_int on the Object" do
value = mock("array_sample_random_value")
value.should_receive(:to_int).and_return(1)
@@ -140,7 +140,7 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(value)
- lambda { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
it "raises a RangeError if the value is equal to the Array size" do
@@ -149,7 +149,7 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(value)
- lambda { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
end
end
diff --git a/spec/ruby/core/array/select_spec.rb b/spec/ruby/core/array/select_spec.rb
index 298b591744..57ec0b2540 100644
--- a/spec/ruby/core/array/select_spec.rb
+++ b/spec/ruby/core/array/select_spec.rb
@@ -1,13 +1,42 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
+require_relative '../enumerable/shared/enumeratorized'
+require_relative 'fixtures/classes'
+require_relative 'shared/enumeratorize'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+require_relative 'shared/keep_if'
describe "Array#select" do
- it_behaves_like :array_select, :select
+ it_behaves_like :enumeratorize, :select
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :select
+
+ before :each do
+ @object = [1,2,3]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :select
+
+ it "returns a new array of elements for which block is true" do
+ [1, 3, 4, 5, 6, 9].select { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6]
+ end
+
+ it "does not return subclass instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].select { true }.should.instance_of?(Array)
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.select { true }.should == empty
+ empty.select { false }.should == []
+
+ array = ArraySpecs.recursive_array
+ array.select { true }.should == [1, 'two', 3.0, array, array, array, array, array]
+ array.select { false }.should == []
+ end
end
describe "Array#select!" do
it "returns nil if no changes were made in the array" do
- [1, 2, 3].select! { true }.should be_nil
+ [1, 2, 3].select! { true }.should == nil
end
it_behaves_like :keep_if, :select!
diff --git a/spec/ruby/core/array/shared/clone.rb b/spec/ruby/core/array/shared/clone.rb
index 95d0d0a3d5..1a45c2fe2c 100644
--- a/spec/ruby/core/array/shared/clone.rb
+++ b/spec/ruby/core/array/shared/clone.rb
@@ -1,14 +1,14 @@
describe :array_clone, shared: true do
it "returns an Array or a subclass instance" do
- [].send(@method).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2].send(@method).should be_an_instance_of(ArraySpecs::MyArray)
+ [].send(@method).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2].send(@method).should.instance_of?(ArraySpecs::MyArray)
end
it "produces a shallow copy where the references are directly copied" do
a = [mock('1'), mock('2')]
b = a.send @method
- b.first.should equal a.first
- b.last.should equal a.last
+ b.first.should.equal? a.first
+ b.last.should.equal? a.last
end
it "creates a new array containing all elements or the original" do
@@ -17,26 +17,4 @@ describe :array_clone, shared: true do
b.should == a
b.__id__.should_not == a.__id__
end
-
- it "copies taint status from the original" do
- a = [1, 2, 3, 4]
- b = [1, 2, 3, 4]
- a.taint
- aa = a.send @method
- bb = b.send @method
-
- aa.tainted?.should == true
- bb.tainted?.should == false
- end
-
- it "copies untrusted status from the original" do
- a = [1, 2, 3, 4]
- b = [1, 2, 3, 4]
- a.untrust
- aa = a.send @method
- bb = b.send @method
-
- aa.untrusted?.should == true
- bb.untrusted?.should == false
- end
end
diff --git a/spec/ruby/core/array/shared/collect.rb b/spec/ruby/core/array/shared/collect.rb
deleted file mode 100644
index 8ad6e61855..0000000000
--- a/spec/ruby/core/array/shared/collect.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-require_relative '../../enumerable/shared/enumeratorized'
-
-describe :array_collect, shared: true do
- it "returns a copy of array with each element replaced by the value returned by block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) { |i| i + '!' }
- b.should == ["a!", "b!", "c!", "d!"]
- b.should_not equal a
- end
-
- it "does not return subclass instance" do
- ArraySpecs::MyArray[1, 2, 3].send(@method) { |x| x + 1 }.should be_an_instance_of(Array)
- end
-
- it "does not change self" do
- a = ['a', 'b', 'c', 'd']
- a.send(@method) { |i| i + '!' }
- a.should == ['a', 'b', 'c', 'd']
- end
-
- it "returns the evaluated value of block if it broke in the block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) {|i|
- if i == 'c'
- break 0
- else
- i + '!'
- end
- }
- b.should == 0
- end
-
- it "returns an Enumerator when no block given" do
- a = [1, 2, 3]
- a.send(@method).should be_an_instance_of(Enumerator)
- end
-
- it "raises an ArgumentError when no block and with arguments" do
- a = [1, 2, 3]
- lambda {
- a.send(@method, :foo)
- }.should raise_error(ArgumentError)
- end
-
- it "does not copy tainted status" do
- a = [1, 2, 3]
- a.taint
- a.send(@method){|x| x}.tainted?.should be_false
- end
-
- it "does not copy untrusted status" do
- a = [1, 2, 3]
- a.untrust
- a.send(@method){|x| x}.untrusted?.should be_false
- end
-
- before :all do
- @object = [1, 2, 3, 4]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
-
-describe :array_collect_b, shared: true do
- it "replaces each element with the value returned by block" do
- a = [7, 9, 3, 5]
- a.send(@method) { |i| i - 1 }.should equal(a)
- a.should == [6, 8, 2, 4]
- end
-
- it "returns self" do
- a = [1, 2, 3, 4, 5]
- b = a.send(@method) {|i| i+1 }
- a.should equal b
- end
-
- it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) {|i|
- if i == 'c'
- break 0
- else
- i + '!'
- end
- }
- b.should == 0
- a.should == ['a!', 'b!', 'c', 'd']
- end
-
- it "returns an Enumerator when no block given, and the enumerator can modify the original array" do
- a = [1, 2, 3]
- enum = a.send(@method)
- enum.should be_an_instance_of(Enumerator)
- enum.each{|i| "#{i}!" }
- a.should == ["1!", "2!", "3!"]
- end
-
- it "keeps tainted status" do
- a = [1, 2, 3]
- a.taint
- a.tainted?.should be_true
- a.send(@method){|x| x}
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- a = [1, 2, 3]
- a.untrust
- a.send(@method){|x| x}
- a.untrusted?.should be_true
- end
-
- describe "when frozen" do
- it "raises a #{frozen_error_class}" do
- lambda { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(frozen_error_class)
- end
-
- it "raises a #{frozen_error_class} when empty" do
- lambda { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(frozen_error_class)
- end
-
- it "raises a #{frozen_error_class} when calling #each on the returned Enumerator" do
- enumerator = ArraySpecs.frozen_array.send(@method)
- lambda { enumerator.each {|x| x } }.should raise_error(frozen_error_class)
- end
-
- it "raises a #{frozen_error_class} when calling #each on the returned Enumerator when empty" do
- enumerator = ArraySpecs.empty_frozen_array.send(@method)
- lambda { enumerator.each {|x| x } }.should raise_error(frozen_error_class)
- end
- end
-
- before :all do
- @object = [1, 2, 3, 4]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
diff --git a/spec/ruby/core/array/shared/difference.rb b/spec/ruby/core/array/shared/difference.rb
new file mode 100644
index 0000000000..3fe22331bd
--- /dev/null
+++ b/spec/ruby/core/array/shared/difference.rb
@@ -0,0 +1,78 @@
+describe :array_binary_difference, shared: true do
+ it "creates an array minus any items from other array" do
+ [].send(@method, [ 1, 2, 4 ]).should == []
+ [1, 2, 4].send(@method, []).should == [1, 2, 4]
+ [ 1, 2, 3, 4, 5 ].send(@method, [ 1, 2, 4 ]).should == [3, 5]
+ end
+
+ it "removes multiple items on the lhs equal to one on the rhs" do
+ [1, 1, 2, 2, 3, 3, 4, 5].send(@method, [1, 2, 4]).should == [3, 3, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == []
+
+ [].send(@method, ArraySpecs.recursive_array).should == []
+
+ array = ArraySpecs.recursive_array
+ array.send(@method, array).should == []
+ end
+
+ it "tries to convert the passed arguments to Arrays using #to_ary" do
+ obj = mock('[2,3,3,4]')
+ obj.should_receive(:to_ary).and_return([2, 3, 3, 4])
+ [1, 1, 2, 2, 3, 4].send(@method, obj).should == [1, 1]
+ end
+
+ it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
+ obj = mock('not an array')
+ -> { [1, 2, 3].send(@method, obj) }.should.raise(TypeError)
+ end
+
+ it "does not return subclass instance for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[]).should.instance_of?(Array)
+ [1, 2, 3].send(@method, ArraySpecs::MyArray[]).should.instance_of?(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6, 7].send(@method, ArraySpecs::ToAryArray[7]).should == [5, 6]
+ end
+
+ it "removes an item identified as equivalent via #hash and #eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == []
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == []
+ end
+
+ it "doesn't remove an item with the same hash but not #eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1, obj1]
+ end
+
+ it "removes an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == []
+ end
+
+ it "is not destructive" do
+ a = [1, 2, 3]
+ a.send(@method, [1])
+ a.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/array/shared/enumeratorize.rb b/spec/ruby/core/array/shared/enumeratorize.rb
index a19a5d3b9b..5beab5c4c4 100644
--- a/spec/ruby/core/array/shared/enumeratorize.rb
+++ b/spec/ruby/core/array/shared/enumeratorize.rb
@@ -1,5 +1,5 @@
describe :enumeratorize, shared: true do
it "returns an Enumerator if no block given" do
- [1,2].send(@method).should be_an_instance_of(Enumerator)
+ [1,2].send(@method).should.instance_of?(Enumerator)
end
end
diff --git a/spec/ruby/core/array/shared/eql.rb b/spec/ruby/core/array/shared/eql.rb
index b5d9128434..5e770bf167 100644
--- a/spec/ruby/core/array/shared/eql.rb
+++ b/spec/ruby/core/array/shared/eql.rb
@@ -1,59 +1,59 @@
describe :array_eql, shared: true do
it "returns true if other is the same array" do
a = [1]
- a.send(@method, a).should be_true
+ a.send(@method, a).should == true
end
it "returns true if corresponding elements are #eql?" do
- [].send(@method, []).should be_true
- [1, 2, 3, 4].send(@method, [1, 2, 3, 4]).should be_true
+ [].send(@method, []).should == true
+ [1, 2, 3, 4].send(@method, [1, 2, 3, 4]).should == true
end
it "returns false if other is shorter than self" do
- [1, 2, 3, 4].send(@method, [1, 2, 3]).should be_false
+ [1, 2, 3, 4].send(@method, [1, 2, 3]).should == false
end
it "returns false if other is longer than self" do
- [1, 2, 3, 4].send(@method, [1, 2, 3, 4, 5]).should be_false
+ [1, 2, 3, 4].send(@method, [1, 2, 3, 4, 5]).should == false
end
it "returns false immediately when sizes of the arrays differ" do
obj = mock('1')
obj.should_not_receive(@method)
- [] .send(@method, [obj] ).should be_false
- [obj] .send(@method, [] ).should be_false
+ [] .send(@method, [obj] ).should == false
+ [obj] .send(@method, [] ).should == false
end
it "handles well recursive arrays" do
a = ArraySpecs.empty_recursive_array
- a .send(@method, [a] ).should be_true
- a .send(@method, [[a]] ).should be_true
- [a] .send(@method, a ).should be_true
- [[a]] .send(@method, a ).should be_true
+ a .send(@method, [a] ).should == true
+ a .send(@method, [[a]] ).should == true
+ [a] .send(@method, a ).should == true
+ [[a]] .send(@method, a ).should == true
# These may be surprising, but no difference can be
# found between these arrays, so they are ==.
# There is no "path" that will lead to a difference
# (contrary to other examples below)
a2 = ArraySpecs.empty_recursive_array
- a .send(@method, a2 ).should be_true
- a .send(@method, [a2] ).should be_true
- a .send(@method, [[a2]] ).should be_true
- [a] .send(@method, a2 ).should be_true
- [[a]] .send(@method, a2 ).should be_true
+ a .send(@method, a2 ).should == true
+ a .send(@method, [a2] ).should == true
+ a .send(@method, [[a2]] ).should == true
+ [a] .send(@method, a2 ).should == true
+ [[a]] .send(@method, a2 ).should == true
back = []
forth = [back]; back << forth;
- back .send(@method, a ).should be_true
+ back .send(@method, a ).should == true
x = []; x << x << x
- x .send(@method, a ).should be_false # since x.size != a.size
- x .send(@method, [a, a] ).should be_false # since x[0].size != [a, a][0].size
- x .send(@method, [x, a] ).should be_false # since x[1].size != [x, a][1].size
- [x, a] .send(@method, [a, x] ).should be_false # etc...
- x .send(@method, [x, x] ).should be_true
- x .send(@method, [[x, x], [x, x]] ).should be_true
+ x .send(@method, a ).should == false # since x.size != a.size
+ x .send(@method, [a, a] ).should == false # since x[0].size != [a, a][0].size
+ x .send(@method, [x, a] ).should == false # since x[1].size != [x, a][1].size
+ [x, a] .send(@method, [a, x] ).should == false # etc...
+ x .send(@method, [x, x] ).should == true
+ x .send(@method, [[x, x], [x, x]] ).should == true
tree = [];
branch = []; branch << tree << tree; tree << branch
@@ -62,31 +62,31 @@ describe :array_eql, shared: true do
forest = [tree, branch, :bird, a]; forest << forest
forest2 = [tree2, branch2, :bird, a2]; forest2 << forest2
- forest .send(@method, forest2 ).should be_true
- forest .send(@method, [tree2, branch, :bird, a, forest2]).should be_true
+ forest .send(@method, forest2 ).should == true
+ forest .send(@method, [tree2, branch, :bird, a, forest2]).should == true
diffforest = [branch2, tree2, :bird, a2]; diffforest << forest2
- forest .send(@method, diffforest ).should be_false # since forest[0].size == 1 != 3 == diffforest[0]
- forest .send(@method, [nil] ).should be_false
- forest .send(@method, [forest] ).should be_false
+ forest .send(@method, diffforest ).should == false # since forest[0].size == 1 != 3 == diffforest[0]
+ forest .send(@method, [nil] ).should == false
+ forest .send(@method, [forest] ).should == false
end
it "does not call #to_ary on its argument" do
obj = mock('to_ary')
obj.should_not_receive(:to_ary)
- [1, 2, 3].send(@method, obj).should be_false
+ [1, 2, 3].send(@method, obj).should == false
end
it "does not call #to_ary on Array subclasses" do
ary = ArraySpecs::ToAryArray[5, 6, 7]
ary.should_not_receive(:to_ary)
- [5, 6, 7].send(@method, ary).should be_true
+ [5, 6, 7].send(@method, ary).should == true
end
it "ignores array class differences" do
- ArraySpecs::MyArray[1, 2, 3].send(@method, [1, 2, 3]).should be_true
- ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_true
- [1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_true
+ ArraySpecs::MyArray[1, 2, 3].send(@method, [1, 2, 3]).should == true
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should == true
+ [1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should == true
end
end
diff --git a/spec/ruby/core/array/shared/index.rb b/spec/ruby/core/array/shared/index.rb
deleted file mode 100644
index a9896554f2..0000000000
--- a/spec/ruby/core/array/shared/index.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-describe :array_index, shared: true do
- it "returns the index of the first element == to object" do
- x = mock('3')
- def x.==(obj) 3 == obj; end
-
- [2, x, 3, 1, 3, 1].send(@method, 3).should == 1
- [2, 3.0, 3, x, 1, 3, 1].send(@method, x).should == 1
- end
-
- it "returns 0 if first element == to object" do
- [2, 1, 3, 2, 5].send(@method, 2).should == 0
- end
-
- it "returns size-1 if only last element == to object" do
- [2, 1, 3, 1, 5].send(@method, 5).should == 4
- end
-
- it "returns nil if no element == to object" do
- [2, 1, 1, 1, 1].send(@method, 3).should == nil
- end
-
- it "accepts a block instead of an argument" do
- [4, 2, 1, 5, 1, 3].send(@method) {|x| x < 2}.should == 2
- end
-
- it "ignores the block if there is an argument" do
- -> {
- [4, 2, 1, 5, 1, 3].send(@method, 5) {|x| x < 2}.should == 3
- }.should complain(/given block not used/)
- end
-
- describe "given no argument and no block" do
- it "produces an Enumerator" do
- [].send(@method).should be_an_instance_of(Enumerator)
- end
- end
-end
diff --git a/spec/ruby/core/array/shared/inspect.rb b/spec/ruby/core/array/shared/inspect.rb
deleted file mode 100644
index 1bcc9f9ca8..0000000000
--- a/spec/ruby/core/array/shared/inspect.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-require_relative '../fixtures/encoded_strings'
-
-describe :array_inspect, shared: true do
- it "returns a string" do
- [1, 2, 3].send(@method).should be_an_instance_of(String)
- end
-
- it "returns '[]' for an empty Array" do
- [].send(@method).should == "[]"
- end
-
- it "calls inspect on its elements and joins the results with commas" do
- items = Array.new(3) do |i|
- obj = mock(i.to_s)
- obj.should_receive(:inspect).and_return(i.to_s)
- obj
- end
- items.send(@method).should == "[0, 1, 2]"
- end
-
- it "does not call #to_s on a String returned from #inspect" do
- str = "abc"
- str.should_not_receive(:to_s)
-
- [str].send(@method).should == '["abc"]'
- end
-
- it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
- obj = mock("Array#inspect/to_s calls #to_s")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return("abc")
-
- [obj].send(@method).should == "[abc]"
- end
-
- it "does not call #to_str on the object returned from #inspect when it is not a String" do
- obj = mock("Array#inspect/to_s does not call #to_str")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_not_receive(:to_str)
-
- [obj].send(@method).should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
- end
-
- it "does not call #to_str on the object returned from #to_s when it is not a String" do
- obj = mock("Array#inspect/to_s does not call #to_str on #to_s result")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return(obj)
- obj.should_not_receive(:to_str)
-
- [obj].send(@method).should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
- end
-
- it "does not swallow exceptions raised by #to_s" do
- obj = mock("Array#inspect/to_s does not swallow #to_s exceptions")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_raise(Exception)
-
- lambda { [obj].send(@method) }.should raise_error(Exception)
- end
-
- it "represents a recursive element with '[...]'" do
- ArraySpecs.recursive_array.send(@method).should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]"
- ArraySpecs.head_recursive_array.send(@method).should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]"
- ArraySpecs.empty_recursive_array.send(@method).should == "[[...]]"
- end
-
- it "taints the result if the Array is non-empty and tainted" do
- [1, 2].taint.send(@method).tainted?.should be_true
- end
-
- it "does not taint the result if the Array is tainted but empty" do
- [].taint.send(@method).tainted?.should be_false
- end
-
- it "taints the result if an element is tainted" do
- ["str".taint].send(@method).tainted?.should be_true
- end
-
- it "untrusts the result if the Array is untrusted" do
- [1, 2].untrust.send(@method).untrusted?.should be_true
- end
-
- it "does not untrust the result if the Array is untrusted but empty" do
- [].untrust.send(@method).untrusted?.should be_false
- end
-
- it "untrusts the result if an element is untrusted" do
- ["str".untrust].send(@method).untrusted?.should be_true
- end
-
- describe "with encoding" do
- before :each do
- @default_external_encoding = Encoding.default_external
- end
-
- after :each do
- Encoding.default_external = @default_external_encoding
- end
-
- it "returns a US-ASCII string for an empty Array" do
- [].send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "use the default external encoding if it is ascii compatible" do
- Encoding.default_external = Encoding.find('UTF-8')
-
- utf8 = "utf8".encode("UTF-8")
- jp = "jp".encode("EUC-JP")
- array = [jp, utf8]
-
- array.send(@method).encoding.name.should == "UTF-8"
- end
-
- it "use US-ASCII encoding if the default external encoding is not ascii compatible" do
- Encoding.default_external = Encoding.find('UTF-32')
-
- utf8 = "utf8".encode("UTF-8")
- jp = "jp".encode("EUC-JP")
- array = [jp, utf8]
-
- array.send(@method).encoding.name.should == "US-ASCII"
- end
-
- it "does not raise if inspected result is not default external encoding" do
- utf_16be = mock("utf_16be")
- utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
-
- [utf_16be].send(@method).should == '["utf_16be \u3042"]'
- end
- end
-end
diff --git a/spec/ruby/core/array/shared/intersection.rb b/spec/ruby/core/array/shared/intersection.rb
new file mode 100644
index 0000000000..dda72e8bd7
--- /dev/null
+++ b/spec/ruby/core/array/shared/intersection.rb
@@ -0,0 +1,85 @@
+describe :array_intersection, shared: true do
+ it "creates an array with elements common to both arrays (intersection)" do
+ [].send(@method, []).should == []
+ [1, 2].send(@method, []).should == []
+ [].send(@method, [1, 2]).should == []
+ [ 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).should == [1, 3]
+ end
+
+ it "creates an array with no duplicates" do
+ [ 1, 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).uniq!.should == nil
+ end
+
+ it "creates an array with elements in order they are first encountered" do
+ [ 1, 2, 3, 2, 5, 6, 7, 8 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5] # array > other
+ [ 5, 2, 3, 4 ].send(@method, [ 1, 2, 3, 2, 5, 6, 7, 8 ]).should == [5, 2, 3] # array < other
+ end
+
+ it "does not modify the original Array" do
+ a = [1, 1, 3, 5]
+ a.send(@method, [1, 2, 3]).should == [1, 3]
+ a.should == [1, 1, 3, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == empty
+
+ ArraySpecs.recursive_array.send(@method, []).should == []
+ [].send(@method, ArraySpecs.recursive_array).should == []
+
+ ArraySpecs.recursive_array.send(@method, ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+ [1, 2].send(@method, obj).should == ([1, 2])
+ end
+
+ it "determines equivalence between elements in the sense of eql?" do
+ not_supported_on :opal do
+ [5.0, 4.0].send(@method, [5, 4]).should == []
+ end
+
+ str = "x"
+ [str].send(@method, [str.dup]).should == [str]
+
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1]
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == []
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj2]
+ end
+
+ it "does return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6].send(@method, ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6]
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == [x]
+ end
+end
diff --git a/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb
new file mode 100644
index 0000000000..3e73bad44b
--- /dev/null
+++ b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb
@@ -0,0 +1,25 @@
+describe :array_iterable_and_tolerating_size_increasing, shared: true do
+ before do
+ @value_to_return ||= -> _ { nil }
+ end
+
+ it "tolerates increasing an array size during iteration" do
+ # The goal is to trigger potential reallocation of internal array storage, so we:
+ # - use elements of different types, starting with the less generic (Integer)
+ # - add reasonably big number of new elements (~ 100)
+ array = [1, 2, 3] # to test some methods we need several uniq elements
+ array_to_join = [:a, :b, :c] + (4..100).to_a
+
+ ScratchPad.record []
+ i = 0
+
+ array.send(@method) do |e|
+ ScratchPad << e
+ array << array_to_join[i] if i < array_to_join.size
+ i += 1
+ @value_to_return.call(e)
+ end
+
+ ScratchPad.recorded.should == [1, 2, 3] + array_to_join
+ end
+end
diff --git a/spec/ruby/core/array/shared/join.rb b/spec/ruby/core/array/shared/join.rb
index 0fd2e0ff9b..93d5329ee3 100644
--- a/spec/ruby/core/array/shared/join.rb
+++ b/spec/ruby/core/array/shared/join.rb
@@ -1,116 +1,6 @@
require_relative '../fixtures/classes'
require_relative '../fixtures/encoded_strings'
-describe :array_join_with_default_separator, shared: true do
- before :each do
- @separator = $,
- end
-
- after :each do
- $, = @separator
- end
-
- it "returns an empty string if the Array is empty" do
- [].send(@method).should == ''
- end
-
- it "returns a US-ASCII string for an empty Array" do
- [].send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "returns a string formed by concatenating each String element separated by $," do
- $, = " | "
- ["1", "2", "3"].send(@method).should == "1 | 2 | 3"
- end
-
- it "attempts coercion via #to_str first" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return("foo")
- [obj].send(@method).should == "foo"
- end
-
- it "attempts coercion via #to_ary second" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return(nil)
- obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"])
- [obj].send(@method).should == "foo"
- end
-
- it "attempts coercion via #to_s third" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return(nil)
- obj.should_receive(:to_ary).any_number_of_times.and_return(nil)
- obj.should_receive(:to_s).any_number_of_times.and_return("foo")
- [obj].send(@method).should == "foo"
- end
-
- it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do
- obj = mock('o')
- class << obj; undef :to_s; end
- lambda { [1, obj].send(@method) }.should raise_error(NoMethodError)
- end
-
- it "raises an ArgumentError when the Array is recursive" do
- lambda { ArraySpecs.recursive_array.send(@method) }.should raise_error(ArgumentError)
- lambda { ArraySpecs.head_recursive_array.send(@method) }.should raise_error(ArgumentError)
- lambda { ArraySpecs.empty_recursive_array.send(@method) }.should raise_error(ArgumentError)
- end
-
- it "taints the result if the Array is tainted and non-empty" do
- [1, 2].taint.send(@method).tainted?.should be_true
- end
-
- it "does not taint the result if the Array is tainted but empty" do
- [].taint.send(@method).tainted?.should be_false
- end
-
- it "taints the result if the result of coercing an element is tainted" do
- s = mock("taint")
- s.should_receive(:to_s).and_return("str".taint)
- [s].send(@method).tainted?.should be_true
- end
-
- it "untrusts the result if the Array is untrusted and non-empty" do
- [1, 2].untrust.send(@method).untrusted?.should be_true
- end
-
- it "does not untrust the result if the Array is untrusted but empty" do
- [].untrust.send(@method).untrusted?.should be_false
- end
-
- it "untrusts the result if the result of coercing an element is untrusted" do
- s = mock("untrust")
- s.should_receive(:to_s).and_return("str".untrust)
- [s].send(@method).untrusted?.should be_true
- end
-
- it "uses the first encoding when other strings are compatible" do
- ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings
- ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings
- ary3 = ArraySpecs.array_with_utf8_and_7bit_ascii8bit_strings
- ary4 = ArraySpecs.array_with_usascii_and_7bit_ascii8bit_strings
-
- ary1.send(@method).encoding.should == Encoding::UTF_8
- ary2.send(@method).encoding.should == Encoding::US_ASCII
- ary3.send(@method).encoding.should == Encoding::UTF_8
- ary4.send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "uses the widest common encoding when other strings are incompatible" do
- ary1 = ArraySpecs.array_with_utf8_and_usascii_strings
- ary2 = ArraySpecs.array_with_usascii_and_utf8_strings
-
- ary1.send(@method).encoding.should == Encoding::UTF_8
- ary2.send(@method).encoding.should == Encoding::UTF_8
- end
-
- it "fails for arrays with incompatibly-encoded strings" do
- ary_utf8_bad_ascii8bit = ArraySpecs.array_with_utf8_and_ascii8bit_strings
-
- lambda { ary_utf8_bad_ascii8bit.send(@method) }.should raise_error(EncodingError)
- end
-end
-
describe :array_join_with_string_separator, shared: true do
it "returns a string formed by concatenating each element.to_str separated by separator" do
obj = mock('foo')
@@ -122,40 +12,4 @@ describe :array_join_with_string_separator, shared: true do
[1, [2, [3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
[1, [2, ArraySpecs::MyArray[3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
end
-
- describe "with a tainted separator" do
- before :each do
- @sep = ":".taint
- end
-
- it "does not taint the result if the array is empty" do
- [].send(@method, @sep).tainted?.should be_false
- end
-
- it "does not taint the result if the array has only one element" do
- [1].send(@method, @sep).tainted?.should be_false
- end
-
- it "taints the result if the array has two or more elements" do
- [1, 2].send(@method, @sep).tainted?.should be_true
- end
- end
-
- describe "with an untrusted separator" do
- before :each do
- @sep = ":".untrust
- end
-
- it "does not untrust the result if the array is empty" do
- [].send(@method, @sep).untrusted?.should be_false
- end
-
- it "does not untrust the result if the array has only one element" do
- [1].send(@method, @sep).untrusted?.should be_false
- end
-
- it "untrusts the result if the array has two or more elements" do
- [1, 2].send(@method, @sep).untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/array/shared/keep_if.rb b/spec/ruby/core/array/shared/keep_if.rb
index 906ad9b9e2..44625eebd1 100644
--- a/spec/ruby/core/array/shared/keep_if.rb
+++ b/spec/ruby/core/array/shared/keep_if.rb
@@ -1,14 +1,15 @@
require_relative '../../enumerable/shared/enumeratorized'
+require_relative '../shared/iterable_and_tolerating_size_increasing'
describe :keep_if, shared: true do
it "deletes elements for which the block returns a false value" do
array = [1, 2, 3, 4, 5]
- array.send(@method) {|item| item > 3 }.should equal(array)
+ array.send(@method) {|item| item > 3 }.should.equal?(array)
array.should == [4, 5]
end
it "returns an enumerator if no block is given" do
- [1, 2, 3].send(@method).should be_an_instance_of(Enumerator)
+ [1, 2, 3].send(@method).should.instance_of?(Enumerator)
end
it "updates the receiver after all blocks" do
@@ -32,29 +33,63 @@ describe :keep_if, shared: true do
end
it "returns an Enumerator if no block is given" do
- @frozen.send(@method).should be_an_instance_of(Enumerator)
+ @frozen.send(@method).should.instance_of?(Enumerator)
end
describe "with truthy block" do
it "keeps elements after any exception" do
- lambda { @frozen.send(@method) { true } }.should raise_error(Exception)
+ -> { @frozen.send(@method) { true } }.should.raise(Exception)
@frozen.should == @origin
end
- it "raises a #{frozen_error_class}" do
- lambda { @frozen.send(@method) { true } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { @frozen.send(@method) { true } }.should.raise(FrozenError)
end
end
describe "with falsy block" do
it "keeps elements after any exception" do
- lambda { @frozen.send(@method) { false } }.should raise_error(Exception)
+ -> { @frozen.send(@method) { false } }.should.raise(Exception)
@frozen.should == @origin
end
- it "raises a #{frozen_error_class}" do
- lambda { @frozen.send(@method) { false } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { @frozen.send(@method) { false } }.should.raise(FrozenError)
end
end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = @frozen.send(@method)
+ -> { enum.each {} }.should.raise(FrozenError)
+ end
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.send(@method) { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.send(@method) do |e|
+ case e
+ when 2 then false
+ when 3 then raise StandardError, 'Oops'
+ else true
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 3, 4]
+ end
+
+ @value_to_return = -> _ { true }
+ it_should_behave_like :array_iterable_and_tolerating_size_increasing
end
diff --git a/spec/ruby/core/array/shared/length.rb b/spec/ruby/core/array/shared/length.rb
deleted file mode 100644
index f84966d0ba..0000000000
--- a/spec/ruby/core/array/shared/length.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-describe :array_length, shared: true do
- it "returns the number of elements" do
- [].send(@method).should == 0
- [1, 2, 3].send(@method).should == 3
- end
-
- it "properly handles recursive arrays" do
- ArraySpecs.empty_recursive_array.send(@method).should == 1
- ArraySpecs.recursive_array.send(@method).should == 8
- end
-end
diff --git a/spec/ruby/core/array/shared/push.rb b/spec/ruby/core/array/shared/push.rb
deleted file mode 100644
index effa632890..0000000000
--- a/spec/ruby/core/array/shared/push.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-describe :array_push, shared: true do
- it "appends the arguments to the array" do
- a = [ "a", "b", "c" ]
- a.send(@method, "d", "e", "f").should equal(a)
- a.send(@method).should == ["a", "b", "c", "d", "e", "f"]
- a.send(@method, 5)
- a.should == ["a", "b", "c", "d", "e", "f", 5]
-
- a = [0, 1]
- a.send(@method, 2)
- a.should == [0, 1, 2]
- end
-
- it "isn't confused by previous shift" do
- a = [ "a", "b", "c" ]
- a.shift
- a.send(@method, "foo")
- a.should == ["b", "c", "foo"]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method, :last).should == [empty, :last]
-
- array = ArraySpecs.recursive_array
- array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
- end
-
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class)
- lambda { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class)
- end
-end
diff --git a/spec/ruby/core/array/shared/replace.rb b/spec/ruby/core/array/shared/replace.rb
deleted file mode 100644
index b8dae8d33e..0000000000
--- a/spec/ruby/core/array/shared/replace.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-describe :array_replace, shared: true do
- it "replaces the elements with elements from other array" do
- a = [1, 2, 3, 4, 5]
- b = ['a', 'b', 'c']
- a.send(@method, b).should equal(a)
- a.should == b
- a.should_not equal(b)
-
- a.send(@method, [4] * 10)
- a.should == [4] * 10
-
- a.send(@method, [])
- a.should == []
- end
-
- it "properly handles recursive arrays" do
- orig = [1, 2, 3]
- empty = ArraySpecs.empty_recursive_array
- orig.send(@method, empty)
- orig.should == empty
-
- array = ArraySpecs.recursive_array
- orig.send(@method, array)
- orig.should == array
- end
-
- it "returns self" do
- ary = [1, 2, 3]
- other = [:a, :b, :c]
- ary.send(@method, other).should equal(ary)
- end
-
- it "does not make self dependent to the original array" do
- ary = [1, 2, 3]
- other = [:a, :b, :c]
- ary.send(@method, other)
- ary.should == [:a, :b, :c]
- ary << :d
- ary.should == [:a, :b, :c, :d]
- other.should == [:a, :b, :c]
- end
-
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('to_ary')
- obj.stub!(:to_ary).and_return([1, 2, 3])
- [].send(@method, obj).should == [1, 2, 3]
- end
-
- it "does not call #to_ary on Array subclasses" do
- obj = ArraySpecs::ToAryArray[5, 6, 7]
- obj.should_not_receive(:to_ary)
- [].send(@method, ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
- end
-
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda {
- ArraySpecs.frozen_array.send(@method, ArraySpecs.frozen_array)
- }.should raise_error(frozen_error_class)
- end
-end
diff --git a/spec/ruby/core/array/shared/select.rb b/spec/ruby/core/array/shared/select.rb
deleted file mode 100644
index 09101e8ab5..0000000000
--- a/spec/ruby/core/array/shared/select.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/classes'
-require_relative '../shared/enumeratorize'
-require_relative '../shared/keep_if'
-require_relative '../../enumerable/shared/enumeratorized'
-
-describe :array_select, shared: true do
- it_should_behave_like :enumeratorize
-
- before :each do
- @object = [1,2,3]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-
- it "returns a new array of elements for which block is true" do
- [1, 3, 4, 5, 6, 9].send(@method) { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6]
- end
-
- it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].send(@method) { true }.should be_an_instance_of(Array)
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method) { true }.should == empty
- empty.send(@method) { false }.should == []
-
- array = ArraySpecs.recursive_array
- array.send(@method) { true }.should == [1, 'two', 3.0, array, array, array, array, array]
- array.send(@method) { false }.should == []
- end
-end
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
deleted file mode 100644
index b3f4ccb9a6..0000000000
--- a/spec/ruby/core/array/shared/slice.rb
+++ /dev/null
@@ -1,459 +0,0 @@
-describe :array_slice, shared: true do
- it "returns the element at index with [index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1).should == "b"
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0).should == 1
- a.send(@method, 1).should == 2
- a.send(@method, 2).should == 3
- a.send(@method, 3).should == 4
- a.send(@method, 4).should == nil
- a.send(@method, 10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the element at index from the end of the array with [-index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -2).should == "d"
-
- a = [1, 2, 3, 4]
-
- a.send(@method, -1).should == 4
- a.send(@method, -2).should == 3
- a.send(@method, -3).should == 2
- a.send(@method, -4).should == 1
- a.send(@method, -5).should == nil
- a.send(@method, -10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns count elements starting from index with [index, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 2, 3).should == ["c", "d", "e"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0, 0).should == []
- a.send(@method, 0, 1).should == [1]
- a.send(@method, 0, 2).should == [1, 2]
- a.send(@method, 0, 4).should == [1, 2, 3, 4]
- a.send(@method, 0, 6).should == [1, 2, 3, 4]
- a.send(@method, 0, -1).should == nil
- a.send(@method, 0, -2).should == nil
- a.send(@method, 0, -4).should == nil
-
- a.send(@method, 2, 0).should == []
- a.send(@method, 2, 1).should == [3]
- a.send(@method, 2, 2).should == [3, 4]
- a.send(@method, 2, 4).should == [3, 4]
- a.send(@method, 2, -1).should == nil
-
- a.send(@method, 4, 0).should == []
- a.send(@method, 4, 2).should == []
- a.send(@method, 4, -1).should == nil
-
- a.send(@method, 5, 0).should == nil
- a.send(@method, 5, 2).should == nil
- a.send(@method, 5, -1).should == nil
-
- a.send(@method, 6, 0).should == nil
- a.send(@method, 6, 2).should == nil
- a.send(@method, 6, -1).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns count elements starting at index from the end of array with [-index, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -2, 2).should == ["d", "e"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, -1, 0).should == []
- a.send(@method, -1, 1).should == [4]
- a.send(@method, -1, 2).should == [4]
- a.send(@method, -1, -1).should == nil
-
- a.send(@method, -2, 0).should == []
- a.send(@method, -2, 1).should == [3]
- a.send(@method, -2, 2).should == [3, 4]
- a.send(@method, -2, 4).should == [3, 4]
- a.send(@method, -2, -1).should == nil
-
- a.send(@method, -4, 0).should == []
- a.send(@method, -4, 1).should == [1]
- a.send(@method, -4, 2).should == [1, 2]
- a.send(@method, -4, 4).should == [1, 2, 3, 4]
- a.send(@method, -4, 6).should == [1, 2, 3, 4]
- a.send(@method, -4, -1).should == nil
-
- a.send(@method, -5, 0).should == nil
- a.send(@method, -5, 1).should == nil
- a.send(@method, -5, 10).should == nil
- a.send(@method, -5, -1).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the first count elements with [0, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 0, 3).should == ["a", "b", "c"]
- end
-
- it "returns the subarray which is independent to self with [index,count]" do
- a = [1, 2, 3]
- sub = a.send(@method, 1,2)
- sub.replace([:a, :b])
- a.should == [1, 2, 3]
- end
-
- it "tries to convert the passed argument to an Integer using #to_int" do
- obj = mock('to_int')
- obj.stub!(:to_int).and_return(2)
-
- a = [1, 2, 3, 4]
- a.send(@method, obj).should == 3
- a.send(@method, obj, 1).should == [3]
- a.send(@method, obj, obj).should == [3, 4]
- a.send(@method, 0, obj).should == [1, 2]
- end
-
- it "returns the elements specified by Range indexes with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1..3).should == ["b", "c", "d"]
- [ "a", "b", "c", "d", "e" ].send(@method, 4..-1).should == ['e']
- [ "a", "b", "c", "d", "e" ].send(@method, 3..3).should == ['d']
- [ "a", "b", "c", "d", "e" ].send(@method, 3..-2).should == ['d']
- ['a'].send(@method, 0..-1).should == ['a']
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0..-10).should == []
- a.send(@method, 0..0).should == [1]
- a.send(@method, 0..1).should == [1, 2]
- a.send(@method, 0..2).should == [1, 2, 3]
- a.send(@method, 0..3).should == [1, 2, 3, 4]
- a.send(@method, 0..4).should == [1, 2, 3, 4]
- a.send(@method, 0..10).should == [1, 2, 3, 4]
-
- a.send(@method, 2..-10).should == []
- a.send(@method, 2..0).should == []
- a.send(@method, 2..2).should == [3]
- a.send(@method, 2..3).should == [3, 4]
- a.send(@method, 2..4).should == [3, 4]
-
- a.send(@method, 3..0).should == []
- a.send(@method, 3..3).should == [4]
- a.send(@method, 3..4).should == [4]
-
- a.send(@method, 4..0).should == []
- a.send(@method, 4..4).should == []
- a.send(@method, 4..5).should == []
-
- a.send(@method, 5..0).should == nil
- a.send(@method, 5..5).should == nil
- a.send(@method, 5..6).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns elements specified by Range indexes except the element at index n with [m...n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1...3).should == ["b", "c"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0...-10).should == []
- a.send(@method, 0...0).should == []
- a.send(@method, 0...1).should == [1]
- a.send(@method, 0...2).should == [1, 2]
- a.send(@method, 0...3).should == [1, 2, 3]
- a.send(@method, 0...4).should == [1, 2, 3, 4]
- a.send(@method, 0...10).should == [1, 2, 3, 4]
-
- a.send(@method, 2...-10).should == []
- a.send(@method, 2...0).should == []
- a.send(@method, 2...2).should == []
- a.send(@method, 2...3).should == [3]
- a.send(@method, 2...4).should == [3, 4]
-
- a.send(@method, 3...0).should == []
- a.send(@method, 3...3).should == []
- a.send(@method, 3...4).should == [4]
-
- a.send(@method, 4...0).should == []
- a.send(@method, 4...4).should == []
- a.send(@method, 4...5).should == []
-
- a.send(@method, 5...0).should == nil
- a.send(@method, 5...5).should == nil
- a.send(@method, 5...6).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns elements that exist if range start is in the array but range end is not with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 4..7).should == ["e"]
- end
-
- it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do
- a = [1, 2, 3, 4]
-
- a.send(@method, -1..-1).should == [4]
- a.send(@method, -1...-1).should == []
- a.send(@method, -1..3).should == [4]
- a.send(@method, -1...3).should == []
- a.send(@method, -1..4).should == [4]
- a.send(@method, -1...4).should == [4]
- a.send(@method, -1..10).should == [4]
- a.send(@method, -1...10).should == [4]
- a.send(@method, -1..0).should == []
- a.send(@method, -1..-4).should == []
- a.send(@method, -1...-4).should == []
- a.send(@method, -1..-6).should == []
- a.send(@method, -1...-6).should == []
-
- a.send(@method, -2..-2).should == [3]
- a.send(@method, -2...-2).should == []
- a.send(@method, -2..-1).should == [3, 4]
- a.send(@method, -2...-1).should == [3]
- a.send(@method, -2..10).should == [3, 4]
- a.send(@method, -2...10).should == [3, 4]
-
- a.send(@method, -4..-4).should == [1]
- a.send(@method, -4..-2).should == [1, 2, 3]
- a.send(@method, -4...-2).should == [1, 2]
- a.send(@method, -4..-1).should == [1, 2, 3, 4]
- a.send(@method, -4...-1).should == [1, 2, 3]
- a.send(@method, -4..3).should == [1, 2, 3, 4]
- a.send(@method, -4...3).should == [1, 2, 3]
- a.send(@method, -4..4).should == [1, 2, 3, 4]
- a.send(@method, -4...4).should == [1, 2, 3, 4]
- a.send(@method, -4...4).should == [1, 2, 3, 4]
- a.send(@method, -4..0).should == [1]
- a.send(@method, -4...0).should == []
- a.send(@method, -4..1).should == [1, 2]
- a.send(@method, -4...1).should == [1]
-
- a.send(@method, -5..-5).should == nil
- a.send(@method, -5...-5).should == nil
- a.send(@method, -5..-4).should == nil
- a.send(@method, -5..-1).should == nil
- a.send(@method, -5..10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the subarray which is independent to self with [m..n]" do
- a = [1, 2, 3]
- sub = a.send(@method, 1..2)
- sub.replace([:a, :b])
- a.should == [1, 2, 3]
- end
-
- it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do
- from = mock('from')
- to = mock('to')
-
- # So we can construct a range out of them...
- def from.<=>(o) 0 end
- def to.<=>(o) 0 end
-
- def from.to_int() 1 end
- def to.to_int() -2 end
-
- a = [1, 2, 3, 4]
-
- a.send(@method, from..to).should == [2, 3]
- a.send(@method, from...to).should == [2]
- a.send(@method, 1..0).should == []
- a.send(@method, 1...0).should == []
-
- lambda { a.send(@method, "a" .. "b") }.should raise_error(TypeError)
- lambda { a.send(@method, "a" ... "b") }.should raise_error(TypeError)
- lambda { a.send(@method, from .. "b") }.should raise_error(TypeError)
- lambda { a.send(@method, from ... "b") }.should raise_error(TypeError)
- end
-
- it "returns the same elements as [m..n] and [m...n] with Range subclasses" do
- a = [1, 2, 3, 4]
- range_incl = ArraySpecs::MyRange.new(1, 2)
- range_excl = ArraySpecs::MyRange.new(-3, -1, true)
-
- a.send(@method, range_incl).should == [2, 3]
- a.send(@method, range_excl).should == [2, 3]
- end
-
- it "returns nil for a requested index not in the array with [index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 5).should == nil
- end
-
- it "returns [] if the index is valid but length is zero with [index, length]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 0, 0).should == []
- [ "a", "b", "c", "d", "e" ].send(@method, 2, 0).should == []
- end
-
- it "returns nil if length is zero but index is invalid with [index, length]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 100, 0).should == nil
- [ "a", "b", "c", "d", "e" ].send(@method, -50, 0).should == nil
- end
-
- # This is by design. It is in the official documentation.
- it "returns [] if index == array.size with [index, length]" do
- %w|a b c d e|.send(@method, 5, 2).should == []
- end
-
- it "returns nil if index > array.size with [index, length]" do
- %w|a b c d e|.send(@method, 6, 2).should == nil
- end
-
- it "returns nil if length is negative with [index, length]" do
- %w|a b c d e|.send(@method, 3, -1).should == nil
- %w|a b c d e|.send(@method, 2, -2).should == nil
- %w|a b c d e|.send(@method, 1, -100).should == nil
- end
-
- it "returns nil if no requested index is in the array with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 6..10).should == nil
- end
-
- it "returns nil if range start is not in the array with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -10..2).should == nil
- [ "a", "b", "c", "d", "e" ].send(@method, 10..12).should == nil
- end
-
- it "returns an empty array when m == n with [m...n]" do
- [1, 2, 3, 4, 5].send(@method, 1...1).should == []
- end
-
- it "returns an empty array with [0...0]" do
- [1, 2, 3, 4, 5].send(@method, 0...0).should == []
- end
-
- it "returns a subarray where m, n negatives and m < n with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -3..-2).should == ["c", "d"]
- end
-
- it "returns an array containing the first element with [0..0]" do
- [1, 2, 3, 4, 5].send(@method, 0..0).should == [1]
- end
-
- it "returns the entire array with [0..-1]" do
- [1, 2, 3, 4, 5].send(@method, 0..-1).should == [1, 2, 3, 4, 5]
- end
-
- it "returns all but the last element with [0...-1]" do
- [1, 2, 3, 4, 5].send(@method, 0...-1).should == [1, 2, 3, 4]
- end
-
- it "returns [3] for [2..-1] out of [1, 2, 3]" do
- [1,2,3].send(@method, 2..-1).should == [3]
- end
-
- it "returns an empty array when m > n and m, n are positive with [m..n]" do
- [1, 2, 3, 4, 5].send(@method, 3..2).should == []
- end
-
- it "returns an empty array when m > n and m, n are negative with [m..n]" do
- [1, 2, 3, 4, 5].send(@method, -2..-3).should == []
- end
-
- it "does not expand array when the indices are outside of the array bounds" do
- a = [1, 2]
- a.send(@method, 4).should == nil
- a.should == [1, 2]
- a.send(@method, 4, 0).should == nil
- a.should == [1, 2]
- a.send(@method, 6, 1).should == nil
- a.should == [1, 2]
- a.send(@method, 8...8).should == nil
- a.should == [1, 2]
- a.send(@method, 10..10).should == nil
- a.should == [1, 2]
- end
-
- describe "with a subclass of Array" do
- before :each do
- ScratchPad.clear
-
- @array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
- end
-
- it "returns a subclass instance with [n, m]" do
- @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n, m]" do
- @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n..m]" do
- @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n...m]" do
- @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n..-m]" do
- @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n...-m]" do
- @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns an empty array when m == n with [m...n]" do
- @array.send(@method, 1...1).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array with [0...0]" do
- @array.send(@method, 0...0).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array when m > n and m, n are positive with [m..n]" do
- @array.send(@method, 3..2).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array when m > n and m, n are negative with [m..n]" do
- @array.send(@method, -2..-3).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns [] if index == array.size with [index, length]" do
- @array.send(@method, 5, 2).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns [] if the index is valid but length is zero with [index, length]" do
- @array.send(@method, 0, 0).should == []
- @array.send(@method, 2, 0).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "does not call #initialize on the subclass instance" do
- @array.send(@method, 0, 3).should == [1, 2, 3]
- ScratchPad.recorded.should be_nil
- end
- end
-
- it "raises a RangeError when the start index is out of range of Fixnum" do
- array = [1, 2, 3, 4, 5, 6]
- obj = mock('large value')
- obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000)
- lambda { array.send(@method, obj) }.should raise_error(RangeError)
-
- obj = 8e19
- lambda { array.send(@method, obj) }.should raise_error(RangeError)
- end
-
- it "raises a RangeError when the length is out of range of Fixnum" do
- array = [1, 2, 3, 4, 5, 6]
- obj = mock('large value')
- obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000)
- lambda { array.send(@method, 1, obj) }.should raise_error(RangeError)
-
- obj = 8e19
- lambda { array.send(@method, 1, obj) }.should raise_error(RangeError)
- end
-end
diff --git a/spec/ruby/core/array/shared/union.rb b/spec/ruby/core/array/shared/union.rb
new file mode 100644
index 0000000000..0b225b9a31
--- /dev/null
+++ b/spec/ruby/core/array/shared/union.rb
@@ -0,0 +1,79 @@
+describe :array_binary_union, shared: true do
+ it "returns an array of elements that appear in either array (union)" do
+ [].send(@method, []).should == []
+ [1, 2].send(@method, []).should == [1, 2]
+ [].send(@method, [1, 2]).should == [1, 2]
+ [ 1, 2, 3, 4 ].send(@method, [ 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
+ end
+
+ it "creates an array with no duplicates" do
+ [ 1, 2, 3, 1, 4, 5 ].send(@method, [ 1, 3, 4, 5, 3, 6 ]).should == [1, 2, 3, 4, 5, 6]
+ end
+
+ it "creates an array with elements in order they are first encountered" do
+ [ 1, 2, 3, 1 ].send(@method, [ 1, 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == empty
+
+ array = ArraySpecs.recursive_array
+ array.send(@method, []).should == [1, 'two', 3.0, array]
+ [].send(@method, array).should == [1, 'two', 3.0, array]
+ array.send(@method, array).should == [1, 'two', 3.0, array]
+ array.send(@method, empty).should == [1, 'two', 3.0, array, empty]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+ [0].send(@method, obj).should == ([0] | [1, 2, 3])
+ end
+
+ # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Integer/Symbol
+ it "acts as if using an intermediate hash to collect values" do
+ not_supported_on :opal do
+ [5.0, 4.0].send(@method, [5, 4]).should == [5.0, 4.0, 5, 4]
+ end
+
+ str = "x"
+ [str].send(@method, [str.dup]).should == [str]
+
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj2.should_receive(:eql?).at_least(1).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1]
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj2.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == [obj1, obj2]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1, obj2]
+ end
+
+ it "does not return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [1, 2].send(@method, ArraySpecs::ToAryArray[5, 6]).should == [1, 2, 5, 6]
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == [x]
+ end
+end
diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb
deleted file mode 100644
index d7464cdaca..0000000000
--- a/spec/ruby/core/array/shared/unshift.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-describe :array_unshift, shared: true do
- it "prepends object to the original array" do
- a = [1, 2, 3]
- a.send(@method, "a").should equal(a)
- a.should == ['a', 1, 2, 3]
- a.send(@method).should equal(a)
- a.should == ['a', 1, 2, 3]
- a.send(@method, 5, 4, 3)
- a.should == [5, 4, 3, 'a', 1, 2, 3]
-
- # shift all but one element
- a = [1, 2]
- a.shift
- a.send(@method, 3, 4)
- a.should == [3, 4, 2]
-
- # now shift all elements
- a.shift
- a.shift
- a.shift
- a.send(@method, 3, 4)
- a.should == [3, 4]
- end
-
- it "quietly ignores unshifting nothing" do
- [].send(@method).should == []
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method, :new).should == [:new, empty]
-
- array = ArraySpecs.recursive_array
- array.send(@method, :new)
- array[0..5].should == [:new, 1, 'two', 3.0, array, array]
- end
-
- it "raises a #{frozen_error_class} on a frozen array when the array is modified" do
- lambda { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class)
- end
-
- # see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do
- lambda { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class)
- end
-end
diff --git a/spec/ruby/core/array/shift_spec.rb b/spec/ruby/core/array/shift_spec.rb
index 26bce8aeb3..09dfa79c45 100644
--- a/spec/ruby/core/array/shift_spec.rb
+++ b/spec/ruby/core/array/shift_spec.rb
@@ -30,11 +30,11 @@ describe "Array#shift" do
array[0..2].should == ['two', 3.0, array]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.shift }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.shift }.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.shift }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.shift }.should.raise(FrozenError)
end
describe "passed a number n as an argument" do
@@ -72,7 +72,7 @@ describe "Array#shift" do
popped2.should == []
a.should == []
- popped1.should_not equal(popped2)
+ popped1.should_not.equal?(popped2)
end
it "returns whole elements if n exceeds size of the array" do
@@ -83,14 +83,14 @@ describe "Array#shift" do
it "does not return self even when it returns whole elements" do
a = [1, 2, 3, 4, 5]
- a.shift(5).should_not equal(a)
+ a.shift(5).should_not.equal?(a)
a = [1, 2, 3, 4, 5]
- a.shift(6).should_not equal(a)
+ a.shift(6).should_not.equal?(a)
end
it "raises an ArgumentError if n is negative" do
- lambda{ [1, 2, 3].shift(-1) }.should raise_error(ArgumentError)
+ ->{ [1, 2, 3].shift(-1) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -105,30 +105,16 @@ describe "Array#shift" do
end
it "raises a TypeError when the passed n cannot be coerced to Integer" do
- lambda{ [1, 2].shift("cat") }.should raise_error(TypeError)
- lambda{ [1, 2].shift(nil) }.should raise_error(TypeError)
+ ->{ [1, 2].shift("cat") }.should.raise(TypeError)
+ ->{ [1, 2].shift(nil) }.should.raise(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
- lambda{ [1, 2].shift(1, 2) }.should raise_error(ArgumentError)
+ ->{ [1, 2].shift(1, 2) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].shift(2).should be_an_instance_of(Array)
- end
-
- it "returns an untainted array even if the array is tainted" do
- ary = [1, 2].taint
- ary.shift(2).tainted?.should be_false
- ary.shift(0).tainted?.should be_false
- end
-
- it "keeps taint status" do
- a = [1, 2].taint
- a.shift(2)
- a.tainted?.should be_true
- a.shift(2)
- a.tainted?.should be_true
+ ArraySpecs::MyArray[1, 2, 3].shift(2).should.instance_of?(Array)
end
end
end
diff --git a/spec/ruby/core/array/shuffle_spec.rb b/spec/ruby/core/array/shuffle_spec.rb
index 4f793acf19..9bc9df73ac 100644
--- a/spec/ruby/core/array/shuffle_spec.rb
+++ b/spec/ruby/core/array/shuffle_spec.rb
@@ -10,7 +10,7 @@ describe "Array#shuffle" do
s.sort.should == a
different ||= (a != s)
end
- different.should be_true # Will fail once in a blue moon (4!^10)
+ different.should == true # Will fail once in a blue moon (4!^10)
end
it "is not destructive" do
@@ -22,13 +22,7 @@ describe "Array#shuffle" do
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].shuffle.should be_an_instance_of(Array)
- end
-
- it "attempts coercion via #to_hash" do
- obj = mock('hash')
- obj.should_receive(:to_hash).once.and_return({})
- [2, 3].shuffle(obj)
+ ArraySpecs::MyArray[1, 2, 3].shuffle.should.instance_of?(Array)
end
it "calls #rand on the Object passed by the :random key in the arguments Hash" do
@@ -37,20 +31,24 @@ describe "Array#shuffle" do
result = [1, 2].shuffle(random: obj)
result.size.should == 2
- result.should include(1, 2)
+ result.sort.should == [1, 2]
end
it "raises a NoMethodError if an object passed for the RNG does not define #rand" do
obj = BasicObject.new
- lambda { [1, 2].shuffle(random: obj) }.should raise_error(NoMethodError)
+ -> { [1, 2].shuffle(random: obj) }.should.raise(NoMethodError)
end
it "accepts a Float for the value returned by #rand" do
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(0.3)
- [1, 2].shuffle(random: random).should be_an_instance_of(Array)
+ [1, 2].shuffle(random: random).should.instance_of?(Array)
+ end
+
+ it "accepts a Random class for the value for random: argument" do
+ [1, 2].shuffle(random: Random).should.instance_of?(Array)
end
it "calls #to_int on the Object returned by #rand" do
@@ -59,7 +57,7 @@ describe "Array#shuffle" do
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(value)
- [1, 2].shuffle(random: random).should be_an_instance_of(Array)
+ [1, 2].shuffle(random: random).should.instance_of?(Array)
end
it "raises a RangeError if the value is less than zero" do
@@ -68,16 +66,25 @@ describe "Array#shuffle" do
random = mock("array_shuffle_random")
random.should_receive(:rand).and_return(value)
- lambda { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
+ end
+
+ it "raises a RangeError if the value is equal to the Array size" do
+ value = mock("array_shuffle_random_value")
+ value.should_receive(:to_int).at_least(1).times.and_return(2)
+ random = mock("array_shuffle_random")
+ random.should_receive(:rand).at_least(1).times.and_return(value)
+
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
end
- it "raises a RangeError if the value is equal to one" do
+ it "raises a RangeError if the value is greater than the Array size" do
value = mock("array_shuffle_random_value")
- value.should_receive(:to_int).at_least(1).times.and_return(1)
+ value.should_receive(:to_int).at_least(1).times.and_return(3)
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(value)
- lambda { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
end
end
@@ -91,12 +98,22 @@ describe "Array#shuffle!" do
a.sort.should == [1, 2, 3, 4]
different ||= (a != [1, 2, 3, 4])
end
- different.should be_true # Will fail once in a blue moon (4!^10)
- a.should equal(original)
+ different.should == true # Will fail once in a blue moon (4!^10)
+ a.should.equal?(original)
+ end
+
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.shuffle! }.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.shuffle! }.should.raise(FrozenError)
+ end
+
+ it "matches CRuby with random:" do
+ %w[a b c].shuffle(random: Random.new(1)).should == %w[a c b]
+ (0..10).to_a.shuffle(random: Random.new(10)).should == [2, 6, 8, 5, 7, 10, 3, 1, 0, 4, 9]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.shuffle! }.should raise_error(frozen_error_class)
- lambda { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(frozen_error_class)
+ it "matches CRuby with srand" do
+ srand(123)
+ %w[a b c d e f g h i j k].shuffle.should == %w[a e f h i j d b g k c]
end
end
diff --git a/spec/ruby/core/array/size_spec.rb b/spec/ruby/core/array/size_spec.rb
index d68f956a83..83e8969012 100644
--- a/spec/ruby/core/array/size_spec.rb
+++ b/spec/ruby/core/array/size_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Array#size" do
- it_behaves_like :array_length, :size
+ it "is an alias of Array#length" do
+ Array.instance_method(:size).should == Array.instance_method(:length)
+ end
end
diff --git a/spec/ruby/core/array/slice_spec.rb b/spec/ruby/core/array/slice_spec.rb
index cd16b3892c..230d1dc5d1 100644
--- a/spec/ruby/core/array/slice_spec.rb
+++ b/spec/ruby/core/array/slice_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/slice'
describe "Array#slice!" do
it "removes and return the element at index" do
@@ -116,8 +115,8 @@ describe "Array#slice!" do
a.slice!(from .. to).should == [2, 3, 4]
a.should == [1, 5]
- lambda { a.slice!("a" .. "b") }.should raise_error(TypeError)
- lambda { a.slice!(from .. "b") }.should raise_error(TypeError)
+ -> { a.slice!("a" .. "b") }.should.raise(TypeError)
+ -> { a.slice!(from .. "b") }.should.raise(TypeError)
end
it "returns last element for consecutive calls at zero index" do
@@ -150,11 +149,71 @@ describe "Array#slice!" do
a.should == [1, 2]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.slice!(0, 0) }.should.raise(FrozenError)
+ end
+
+ it "works with endless ranges" do
+ a = [1, 2, 3]
+ a.slice!(eval("(1..)")).should == [2, 3]
+ a.should == [1]
+
+ a = [1, 2, 3]
+ a.slice!(eval("(2...)")).should == [3]
+ a.should == [1, 2]
+
+ a = [1, 2, 3]
+ a.slice!(eval("(-2..)")).should == [2, 3]
+ a.should == [1]
+
+ a = [1, 2, 3]
+ a.slice!(eval("(-1...)")).should == [3]
+ a.should == [1, 2]
+ end
+
+ it "works with beginless ranges" do
+ a = [0,1,2,3,4]
+ a.slice!((..3)).should == [0, 1, 2, 3]
+ a.should == [4]
+
+ a = [0,1,2,3,4]
+ a.slice!((...-2)).should == [0, 1, 2]
+ a.should == [3, 4]
+ end
+
+ describe "with a subclass of Array" do
+ before :each do
+ @array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
+ end
+
+ it "returns a Array instance with [n, m]" do
+ @array.slice!(0, 2).should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n, m]" do
+ @array.slice!(-3, 2).should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n..m]" do
+ @array.slice!(1..3).should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n...m]" do
+ @array.slice!(1...3).should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n..-m]" do
+ @array.slice!(-3..-1).should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n...-m]" do
+ @array.slice!(-3...-1).should.instance_of?(Array)
+ end
end
end
describe "Array#slice" do
- it_behaves_like :array_slice, :slice
+ it "is an alias of Array#[]" do
+ Array.instance_method(:slice).should == Array.instance_method(:[])
+ end
end
diff --git a/spec/ruby/core/array/sort_by_spec.rb b/spec/ruby/core/array/sort_by_spec.rb
index 6428194dfb..132abb028a 100644
--- a/spec/ruby/core/array/sort_by_spec.rb
+++ b/spec/ruby/core/array/sort_by_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#sort_by!" do
@@ -10,25 +11,30 @@ describe "Array#sort_by!" do
end
it "returns an Enumerator if not given a block" do
- (1..10).to_a.sort_by!.should be_an_instance_of(Enumerator)
+ (1..10).to_a.sort_by!.should.instance_of?(Enumerator)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
a.sort_by!{ 1 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
a.sort_by!{ 0 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
a.sort_by!{ -1 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.sort_by! {}}.should.raise(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- lambda { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = ArraySpecs.frozen_array.sort_by!
+ -> { enum.each {} }.should.raise(FrozenError)
end
it "returns the specified value when it would break in the given block" do
@@ -41,12 +47,39 @@ describe "Array#sort_by!" do
ary.sort_by!{|x,y| break if x==i; x<=>y}
ary
}
- partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should be_true
+ partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should == true
end
it "changes nothing when called on a single element array" do
[1].sort_by!(&:to_s).should == [1]
end
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.sort_by! { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "doesn't change array if error is raised" do
+ a = [4, 3, 2, 1]
+ begin
+ a.sort_by! do |e|
+ raise StandardError, 'Oops' if e == 1
+ e
+ end
+ rescue StandardError
+ end
+
+ a.should == [4, 3, 2, 1]
+ end
+
it_behaves_like :enumeratorized_with_origin_size, :sort_by!, [1,2,3]
end
+
+describe "Array#sort_by!" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :sort_by!
+end
diff --git a/spec/ruby/core/array/sort_spec.rb b/spec/ruby/core/array/sort_spec.rb
index c0d6628549..27300c3385 100644
--- a/spec/ruby/core/array/sort_spec.rb
+++ b/spec/ruby/core/array/sort_spec.rb
@@ -42,7 +42,7 @@ describe "Array#sort" do
a = [1, 2, 3]
sorted = a.sort
sorted.should == a
- sorted.should_not equal(a)
+ sorted.should_not.equal?(a)
end
it "properly handles recursive arrays" do
@@ -58,17 +58,17 @@ describe "Array#sort" do
b = ArraySpecs::MockForCompared.new
c = ArraySpecs::MockForCompared.new
- ArraySpecs::MockForCompared.compared?.should == false
+ ArraySpecs::MockForCompared.should_not.compared?
[a, b, c].sort.should == [c, b, a]
- ArraySpecs::MockForCompared.compared?.should == true
+ ArraySpecs::MockForCompared.should.compared?
end
it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do
o = Object.new
- lambda {
+ -> {
[o, 1].sort
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "may take a block which is used to determine the order of objects a and b described as -1, 0 or +1" do
@@ -78,43 +78,43 @@ describe "Array#sort" do
end
it "raises an error when a given block returns nil" do
- lambda { [1, 2].sort {} }.should raise_error(ArgumentError)
+ -> { [1, 2].sort {} }.should.raise(ArgumentError)
end
it "does not call #<=> on contained objects when invoked with a block" do
a = Array.new(25)
(0...25).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "does not call #<=> on elements when invoked with a block even if Array is large (Rubinius #412)" do
a = Array.new(1500)
(0...1500).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
- a.sort { 1 }.should be_an_instance_of(Array)
- a.sort { 0 }.should be_an_instance_of(Array)
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { 1 }.should.instance_of?(Array)
+ a.sort { 0 }.should.instance_of?(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "does not freezes self during being sorted" do
a = [1, 2, 3]
- a.sort { |x,y| a.frozen?.should == false; x <=> y }
+ a.sort { |x,y| a.should_not.frozen?; x <=> y }
end
it "returns the specified value when it would break in the given block" do
[1, 2, 3].sort{ break :a }.should == :a
end
- it "uses the sign of Bignum block results as the sort result" do
+ it "uses the sign of Integer block results as the sort result" do
a = [1, 2, 5, 10, 7, -4, 12]
begin
- class Bignum;
+ class Integer
alias old_spaceship <=>
def <=>(other)
raise
@@ -122,7 +122,7 @@ describe "Array#sort" do
end
a.sort {|n, m| (n - m) * (2 ** 200)}.should == [-4, 1, 2, 5, 7, 10, 12]
ensure
- class Bignum
+ class Integer
alias <=> old_spaceship
end
end
@@ -132,11 +132,11 @@ describe "Array#sort" do
a = [1, 2, 5, 10, 7, -4, 12]
a.sort { |n, m| n - m }.should == [-4, 1, 2, 5, 7, 10, 12]
a.sort { |n, m|
- ArraySpecs::ComparableWithFixnum.new(n-m)
+ ArraySpecs::ComparableWithInteger.new(n-m)
}.should == [-4, 1, 2, 5, 7, 10, 12]
- lambda {
+ -> {
a.sort { |n, m| (n - m).to_s }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "sorts an array that has a value shifted off without a block" do
@@ -155,7 +155,7 @@ describe "Array#sort" do
it "raises an error if objects can't be compared" do
a=[ArraySpecs::Uncomparable.new, ArraySpecs::Uncomparable.new]
- lambda {a.sort}.should raise_error(ArgumentError)
+ -> {a.sort}.should.raise(ArgumentError)
end
# From a strange Rubinius bug
@@ -166,7 +166,7 @@ describe "Array#sort" do
it "does not return subclass instance on Array subclasses" do
ary = ArraySpecs::MyArray[1, 2, 3]
- ary.sort.should be_an_instance_of(Array)
+ ary.sort.should.instance_of?(Array)
end
end
@@ -184,13 +184,13 @@ describe "Array#sort!" do
it "returns self if the order of elements changed" do
a = [6, 7, 2, 3, 7]
- a.sort!.should equal(a)
+ a.sort!.should.equal?(a)
a.should == [2, 3, 6, 7, 7]
end
it "returns self even if makes no modification" do
a = [1, 2, 3, 4, 5]
- a.sort!.should equal(a)
+ a.sort!.should.equal?(a)
a.should == [1, 2, 3, 4, 5]
end
@@ -207,34 +207,34 @@ describe "Array#sort!" do
b = ArraySpecs::MockForCompared.new
c = ArraySpecs::MockForCompared.new
- ArraySpecs::MockForCompared.compared?.should == false
+ ArraySpecs::MockForCompared.should_not.compared?
[a, b, c].sort!.should == [c, b, a]
- ArraySpecs::MockForCompared.compared?.should == true
+ ArraySpecs::MockForCompared.should.compared?
end
it "does not call #<=> on contained objects when invoked with a block" do
a = Array.new(25)
(0...25).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort! { -1 }.should be_an_instance_of(Array)
+ a.sort! { -1 }.should.instance_of?(Array)
end
it "does not call #<=> on elements when invoked with a block even if Array is large (Rubinius #412)" do
a = Array.new(1500)
(0...1500).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort! { -1 }.should be_an_instance_of(Array)
+ a.sort! { -1 }.should.instance_of?(Array)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
- a.sort!{ 1 }.should be_an_instance_of(Array)
- a.sort!{ 0 }.should be_an_instance_of(Array)
- a.sort!{ -1 }.should be_an_instance_of(Array)
+ a.sort!{ 1 }.should.instance_of?(Array)
+ a.sort!{ 0 }.should.instance_of?(Array)
+ a.sort!{ -1 }.should.instance_of?(Array)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- lambda { ArraySpecs.frozen_array.sort! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.sort! }.should.raise(FrozenError)
end
it "returns the specified value when it would break in the given block" do
@@ -247,6 +247,6 @@ describe "Array#sort!" do
ary.sort!{|x,y| break if x==i; x<=>y}
ary
}
- partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should be_true
+ partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should == true
end
end
diff --git a/spec/ruby/core/array/sum_spec.rb b/spec/ruby/core/array/sum_spec.rb
index 71b8b9dc78..cd4ba4c2d8 100644
--- a/spec/ruby/core/array/sum_spec.rb
+++ b/spec/ruby/core/array/sum_spec.rb
@@ -1,44 +1,88 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
-ruby_version_is '2.4' do
- describe "Array#sum" do
- it "returns the sum of elements" do
- [1, 2, 3].sum.should == 6
- end
+describe "Array#sum" do
+ it "returns the sum of elements" do
+ [1, 2, 3].sum.should == 6
+ end
+
+ it "applies a block to each element before adding if it's given" do
+ [1, 2, 3].sum { |i| i * 10 }.should == 60
+ end
+
+ it "doesn't apply the block init" do
+ [1, 2, 3].sum(1) { |i| i * 10 }.should == 61
+ end
+
+ # https://bugs.ruby-lang.org/issues/12217
+ # https://github.com/ruby/ruby/blob/master/doc/ChangeLog/ChangeLog-2.4.0#L6208-L6214
+ it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do
+ floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5]
+ naive_sum = floats.reduce { |sum, e| sum + e }
+ naive_sum.should == 50.00000000000001
+ floats.sum.should == 50.0
+ end
+
+ it "handles infinite values and NaN" do
+ [1.0, Float::INFINITY].sum.should == Float::INFINITY
+ [1.0, -Float::INFINITY].sum.should == -Float::INFINITY
+ [1.0, Float::NAN].sum.should.nan?
+
+ [Float::INFINITY, 1.0].sum.should == Float::INFINITY
+ [-Float::INFINITY, 1.0].sum.should == -Float::INFINITY
+ [Float::NAN, 1.0].sum.should.nan?
+
+ [Float::NAN, Float::INFINITY].sum.should.nan?
+ [Float::INFINITY, Float::NAN].sum.should.nan?
+
+ [Float::INFINITY, -Float::INFINITY].sum.should.nan?
+ [-Float::INFINITY, Float::INFINITY].sum.should.nan?
- it "applies a block to each element before adding if it's given" do
- [1, 2, 3].sum { |i| i * 10 }.should == 60
- end
+ [Float::INFINITY, Float::INFINITY].sum.should == Float::INFINITY
+ [-Float::INFINITY, -Float::INFINITY].sum.should == -Float::INFINITY
+ [Float::NAN, Float::NAN].sum.should.nan?
+ end
- it "returns init value if array is empty" do
- [].sum(-1).should == -1
- end
+ it "returns init value if array is empty" do
+ [].sum(-1).should == -1
+ end
- it "returns 0 if array is empty and init is omitted" do
- [].sum.should == 0
- end
+ it "returns 0 if array is empty and init is omitted" do
+ [].sum.should == 0
+ end
- it "adds init value to the sum of elemens" do
- [1, 2, 3].sum(10).should == 16
- end
+ it "adds init value to the sum of elements" do
+ [1, 2, 3].sum(10).should == 16
+ end
- it "can be used for non-numeric objects by providing init value" do
- ["a", "b", "c"].sum("").should == "abc"
- end
+ it "can be used for non-numeric objects by providing init value" do
+ ["a", "b", "c"].sum("").should == "abc"
+ end
- it 'raises TypeError if any element are not numeric' do
- lambda { ["a"].sum }.should raise_error(TypeError)
- end
+ it 'raises TypeError if any element are not numeric' do
+ -> { ["a"].sum }.should.raise(TypeError)
+ end
- it 'raises TypeError if any element cannot be added to init value' do
- lambda { [1].sum([]) }.should raise_error(TypeError)
- end
+ it 'raises TypeError if any element cannot be added to init value' do
+ -> { [1].sum([]) }.should.raise(TypeError)
+ end
+
+ it "calls + to sum the elements" do
+ a = mock("a")
+ b = mock("b")
+ a.should_receive(:+).with(b).and_return(42)
+ [b].sum(a).should == 42
+ end
- it "calls + to sum the elements" do
- a = mock("a")
- b = mock("b")
- a.should_receive(:+).with(b).and_return(42)
- [b].sum(a).should == 42
- end
+ it "calls + on the init value" do
+ a = mock("a")
+ b = mock("b")
+ a.should_receive(:+).with(42).and_return(b)
+ [42].sum(a).should == b
end
end
+
+describe "Array#sum" do
+ @value_to_return = -> _ { 1 }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :sum
+end
diff --git a/spec/ruby/core/array/take_spec.rb b/spec/ruby/core/array/take_spec.rb
index 2c9e3f5cfe..837c734b77 100644
--- a/spec/ruby/core/array/take_spec.rb
+++ b/spec/ruby/core/array/take_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "Array#take" do
it "returns the first specified number of elements" do
@@ -22,6 +23,10 @@ describe "Array#take" do
end
it "raises an ArgumentError when the argument is negative" do
- lambda{ [1].take(-3) }.should raise_error(ArgumentError)
+ ->{ [1].take(-3) }.should.raise(ArgumentError)
+ end
+
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/take_while_spec.rb b/spec/ruby/core/array/take_while_spec.rb
index f159e6f251..7811edab9e 100644
--- a/spec/ruby/core/array/take_while_spec.rb
+++ b/spec/ruby/core/array/take_while_spec.rb
@@ -1,4 +1,6 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#take_while" do
it "returns all elements until the block returns false" do
@@ -12,4 +14,13 @@ describe "Array#take_while" do
it "returns all elements until the block returns false" do
[1, 2, false, 4].take_while{ |element| element }.should == [1, 2]
end
+
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should.instance_of?(Array)
+ end
+end
+
+describe "Array#take_while" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :take_while
end
diff --git a/spec/ruby/core/array/to_a_spec.rb b/spec/ruby/core/array/to_a_spec.rb
index 49d0a4782e..078de1638a 100644
--- a/spec/ruby/core/array/to_a_spec.rb
+++ b/spec/ruby/core/array/to_a_spec.rb
@@ -5,12 +5,12 @@ describe "Array#to_a" do
it "returns self" do
a = [1, 2, 3]
a.to_a.should == [1, 2, 3]
- a.should equal(a.to_a)
+ a.should.equal?(a.to_a)
end
it "does not return subclass instance on Array subclasses" do
e = ArraySpecs::MyArray.new(1, 2)
- e.to_a.should be_an_instance_of(Array)
+ e.to_a.should.instance_of?(Array)
e.to_a.should == [1, 2]
end
diff --git a/spec/ruby/core/array/to_ary_spec.rb b/spec/ruby/core/array/to_ary_spec.rb
index 314699b709..dc5193158d 100644
--- a/spec/ruby/core/array/to_ary_spec.rb
+++ b/spec/ruby/core/array/to_ary_spec.rb
@@ -4,9 +4,9 @@ require_relative 'fixtures/classes'
describe "Array#to_ary" do
it "returns self" do
a = [1, 2, 3]
- a.should equal(a.to_ary)
+ a.should.equal?(a.to_ary)
a = ArraySpecs::MyArray[1, 2, 3]
- a.should equal(a.to_ary)
+ a.should.equal?(a.to_ary)
end
it "properly handles recursive arrays" do
diff --git a/spec/ruby/core/array/to_h_spec.rb b/spec/ruby/core/array/to_h_spec.rb
index e845d2c950..1d626763c2 100644
--- a/spec/ruby/core/array/to_h_spec.rb
+++ b/spec/ruby/core/array/to_h_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#to_h" do
it "converts empty array to empty hash" do
@@ -24,21 +25,67 @@ describe "Array#to_h" do
end
it "raises TypeError if an element is not an array" do
- lambda { [:x].to_h }.should raise_error(TypeError)
+ -> { [:x].to_h }.should.raise(TypeError)
end
it "raises ArgumentError if an element is not a [key, value] pair" do
- lambda { [[:x]].to_h }.should raise_error(ArgumentError)
+ -> { [[:x]].to_h }.should.raise(ArgumentError)
end
it "does not accept arguments" do
- lambda { [].to_h(:a, :b) }.should raise_error(ArgumentError)
+ -> { [].to_h(:a, :b) }.should.raise(ArgumentError)
end
- ruby_version_is "2.6" do
- it "converts [key, value] pairs returned by the block to a hash" do
- i = 0
- [:a, :b].to_h {|k| [k, i += 1]}.should == { a: 1, b: 2 }
+ it "produces a hash that returns nil for a missing element" do
+ [[:a, 1], [:b, 2]].to_h[:c].should == nil
+ end
+
+ context "with block" do
+ it "converts [key, value] pairs returned by the block to a Hash" do
+ [:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
+ end
+
+ it "passes to a block each element as a single argument" do
+ ScratchPad.record []
+ [[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
+ end
+
+ it "raises ArgumentError if block returns longer or shorter array" do
+ -> do
+ [:a, :b].to_h { |k| [k, k.to_s, 1] }
+ end.should.raise(ArgumentError, /wrong array length at 0/)
+
+ -> do
+ [:a, :b].to_h { |k| [k] }
+ end.should.raise(ArgumentError, /wrong array length at 0/)
+ end
+
+ it "raises TypeError if block returns something other than Array" do
+ -> do
+ [:a, :b].to_h { |k| "not-array" }
+ end.should.raise(TypeError, /wrong element type String at 0/)
+ end
+
+ it "coerces returned pair to Array with #to_ary" do
+ x = mock('x')
+ x.stub!(:to_ary).and_return([:b, 'b'])
+
+ [:a].to_h { |k| x }.should == { :b => 'b' }
+ end
+
+ it "does not coerce returned pair to Array with #to_a" do
+ x = mock('x')
+ x.stub!(:to_a).and_return([:b, 'b'])
+
+ -> do
+ [:a].to_h { |k| x }
+ end.should.raise(TypeError, /wrong element type MockObject at 0/)
end
end
end
+
+describe "Array#to_h" do
+ @value_to_return = -> e { [e, e.to_s] }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :to_h
+end
diff --git a/spec/ruby/core/array/to_s_spec.rb b/spec/ruby/core/array/to_s_spec.rb
index e8476702ec..483e14f902 100644
--- a/spec/ruby/core/array/to_s_spec.rb
+++ b/spec/ruby/core/array/to_s_spec.rb
@@ -1,8 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/join'
-require_relative 'shared/inspect'
describe "Array#to_s" do
- it_behaves_like :array_inspect, :to_s
+ it "is an alias of Array#inspect" do
+ Array.instance_method(:to_s).should == Array.instance_method(:inspect)
+ end
end
diff --git a/spec/ruby/core/array/transpose_spec.rb b/spec/ruby/core/array/transpose_spec.rb
index c7bd7e7338..d45e9c351c 100644
--- a/spec/ruby/core/array/transpose_spec.rb
+++ b/spec/ruby/core/array/transpose_spec.rb
@@ -32,7 +32,7 @@ describe "Array#transpose" do
end
it "raises a TypeError if the passed Argument does not respond to #to_ary" do
- lambda { [Object.new, [:a, :b]].transpose }.should raise_error(TypeError)
+ -> { [Object.new, [:a, :b]].transpose }.should.raise(TypeError)
end
it "does not call to_ary on array subclass elements" do
@@ -41,13 +41,13 @@ describe "Array#transpose" do
end
it "raises an IndexError if the arrays are not of the same length" do
- lambda { [[1, 2], [:a]].transpose }.should raise_error(IndexError)
+ -> { [[1, 2], [:a]].transpose }.should.raise(IndexError)
end
it "does not return subclass instance on Array subclasses" do
result = ArraySpecs::MyArray[ArraySpecs::MyArray[1, 2, 3], ArraySpecs::MyArray[4, 5, 6]].transpose
- result.should be_an_instance_of(Array)
- result[0].should be_an_instance_of(Array)
- result[1].should be_an_instance_of(Array)
+ result.should.instance_of?(Array)
+ result[0].should.instance_of?(Array)
+ result[1].should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/try_convert_spec.rb b/spec/ruby/core/array/try_convert_spec.rb
index 5f653b6807..3eaa0f4b7c 100644
--- a/spec/ruby/core/array/try_convert_spec.rb
+++ b/spec/ruby/core/array/try_convert_spec.rb
@@ -4,47 +4,47 @@ require_relative 'fixtures/classes'
describe "Array.try_convert" do
it "returns the argument if it's an Array" do
x = Array.new
- Array.try_convert(x).should equal(x)
+ Array.try_convert(x).should.equal?(x)
end
it "returns the argument if it's a kind of Array" do
x = ArraySpecs::MyArray[]
- Array.try_convert(x).should equal(x)
+ Array.try_convert(x).should.equal?(x)
end
it "returns nil when the argument does not respond to #to_ary" do
- Array.try_convert(Object.new).should be_nil
+ Array.try_convert(Object.new).should == nil
end
it "sends #to_ary to the argument and returns the result if it's nil" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(nil)
- Array.try_convert(obj).should be_nil
+ Array.try_convert(obj).should == nil
end
it "sends #to_ary to the argument and returns the result if it's an Array" do
x = Array.new
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(x)
- Array.try_convert(obj).should equal(x)
+ Array.try_convert(obj).should.equal?(x)
end
it "sends #to_ary to the argument and returns the result if it's a kind of Array" do
x = ArraySpecs::MyArray[]
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(x)
- Array.try_convert(obj).should equal(x)
+ Array.try_convert(obj).should.equal?(x)
end
it "sends #to_ary to the argument and raises TypeError if it's not a kind of Array" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(Object.new)
- lambda { Array.try_convert obj }.should raise_error(TypeError)
+ -> { Array.try_convert obj }.should raise_consistent_error(TypeError, "can't convert MockObject into Array (MockObject#to_ary gives Object)")
end
it "does not rescue exceptions raised by #to_ary" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_raise(RuntimeError)
- lambda { Array.try_convert obj }.should raise_error(RuntimeError)
+ -> { Array.try_convert obj }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/array/union_spec.rb b/spec/ruby/core/array/union_spec.rb
index 0e177715e5..110894e83d 100644
--- a/spec/ruby/core/array/union_spec.rb
+++ b/spec/ruby/core/array/union_spec.rb
@@ -1,82 +1,25 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/union'
describe "Array#|" do
- it "returns an array of elements that appear in either array (union)" do
- ([] | []).should == []
- ([1, 2] | []).should == [1, 2]
- ([] | [1, 2]).should == [1, 2]
- ([ 1, 2, 3, 4 ] | [ 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
- end
-
- it "creates an array with no duplicates" do
- ([ 1, 2, 3, 1, 4, 5 ] | [ 1, 3, 4, 5, 3, 6 ]).should == [1, 2, 3, 4, 5, 6]
- end
-
- it "creates an array with elements in order they are first encountered" do
- ([ 1, 2, 3, 1 ] | [ 1, 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty | empty).should == empty
-
- array = ArraySpecs.recursive_array
- (array | []).should == [1, 'two', 3.0, array]
- ([] | array).should == [1, 'two', 3.0, array]
- (array | array).should == [1, 'two', 3.0, array]
- (array | empty).should == [1, 'two', 3.0, array, empty]
- end
-
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('[1,2,3]')
- obj.should_receive(:to_ary).and_return([1, 2, 3])
- ([0] | obj).should == ([0] | [1, 2, 3])
- end
-
- # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Fixnum/Symbol
- it "acts as if using an intermediate hash to collect values" do
- not_supported_on :opal do
- ([5.0, 4.0] | [5, 4]).should == [5.0, 4.0, 5, 4]
- end
-
- str = "x"
- ([str] | [str.dup]).should == [str]
-
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj2.should_receive(:eql?).at_least(1).and_return(true)
-
- ([obj1] | [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] | [obj2]).should == [obj1]
+ it_behaves_like :array_binary_union, :|
+end
- obj1 = mock('3')
- obj2 = mock('4')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj2.should_receive(:eql?).at_least(1).and_return(false)
+describe "Array#union" do
+ it_behaves_like :array_binary_union, :union
- ([obj1] | [obj2]).should == [obj1, obj2]
- ([obj1, obj1, obj2, obj2] | [obj2]).should == [obj1, obj2]
+ it "returns unique elements when given no argument" do
+ x = [1, 2, 3, 2]
+ x.union.should == [1, 2, 3]
end
it "does not return subclass instances for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] | []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] | ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- ([] | ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- end
-
- it "does not call to_ary on array subclasses" do
- ([1, 2] | ArraySpecs::ToAryArray[5, 6]).should == [1, 2, 5, 6]
+ ArraySpecs::MyArray[1, 2, 3].union.should.instance_of?(Array)
end
- it "properly handles an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
-
- ([x] | [x]).should == [x]
+ it "accepts multiple arguments" do
+ x = [1, 2, 3]
+ x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4]
end
end
diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb
index 471717b8e2..0289bee7c2 100644
--- a/spec/ruby/core/array/uniq_spec.rb
+++ b/spec/ruby/core/array/uniq_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#uniq" do
it "returns an array with no duplicates" do
@@ -45,10 +46,6 @@ describe "Array#uniq" do
obj.should_receive(:hash).at_least(1).and_return(0)
def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
false
end
@@ -56,18 +53,12 @@ describe "Array#uniq" do
end
a.uniq.should == a
- a[0].tainted?.should == true
- a[1].tainted?.should == true
a = Array.new(2) do
obj = mock('0')
obj.should_receive(:hash).at_least(1).and_return(0)
def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
true
end
@@ -75,8 +66,6 @@ describe "Array#uniq" do
end
a.uniq.size.should == 1
- a[0].tainted?.should == true
- a[1].tainted?.should == true
end
it "compares elements based on the value returned from the block" do
@@ -96,8 +85,8 @@ describe "Array#uniq" do
[false, nil, 42].uniq { :bar }.should == [false]
end
- it "returns subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray)
+ it "returns Array instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].uniq.should.instance_of?(Array)
end
it "properly handles an identical item even when its #eql? isn't reflexive" do
@@ -135,6 +124,11 @@ describe "Array#uniq" do
end
end
+describe "Array#uniq" do
+ @value_to_return = -> e { e }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :uniq
+end
+
describe "Array#uniq!" do
it "modifies the array in place" do
a = [ "a", "a", "b", "b", "c" ]
@@ -144,7 +138,7 @@ describe "Array#uniq!" do
it "returns self" do
a = [ "a", "a", "b", "b", "c" ]
- a.should equal(a.uniq!)
+ a.should.equal?(a.uniq!)
end
it "properly handles recursive arrays" do
@@ -188,20 +182,20 @@ describe "Array#uniq!" do
[ "a", "b", "c" ].uniq!.should == nil
end
- it "raises a #{frozen_error_class} on a frozen array when the array is modified" do
+ it "raises a FrozenError on a frozen array when the array is modified" do
dup_ary = [1, 1, 2]
dup_ary.freeze
- lambda { dup_ary.uniq! }.should raise_error(frozen_error_class)
+ -> { dup_ary.uniq! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do
- lambda { ArraySpecs.frozen_array.uniq!}.should raise_error(frozen_error_class)
- lambda { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.uniq!}.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.uniq!}.should.raise(FrozenError)
end
it "doesn't yield to the block on a frozen array" do
- lambda { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(frozen_error_class)
+ -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should.raise(FrozenError)
end
it "compares elements based on the value returned from the block" do
@@ -218,4 +212,32 @@ describe "Array#uniq!" do
a.uniq!
a.should == [x]
end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.send(@method) { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "doesn't change array if error is raised" do
+ a = [1, 1, 2, 2, 3, 3, 4, 4]
+ begin
+ a.send(@method) do |e|
+ raise StandardError, 'Oops' if e == 3
+ e
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 1, 2, 2, 3, 3, 4, 4]
+ end
+end
+
+describe "Array#uniq!" do
+ @value_to_return = -> e { e }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :uniq!
end
diff --git a/spec/ruby/core/array/unshift_spec.rb b/spec/ruby/core/array/unshift_spec.rb
index b8b675e5f8..c190db4d02 100644
--- a/spec/ruby/core/array/unshift_spec.rb
+++ b/spec/ruby/core/array/unshift_spec.rb
@@ -1,7 +1,67 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/unshift'
describe "Array#unshift" do
- it_behaves_like :array_unshift, :unshift
+ it "prepends object to the original array" do
+ a = [1, 2, 3]
+ a.unshift("a").should.equal?(a)
+ a.should == ['a', 1, 2, 3]
+ a.unshift.should.equal?(a)
+ a.should == ['a', 1, 2, 3]
+ a.unshift(5, 4, 3)
+ a.should == [5, 4, 3, 'a', 1, 2, 3]
+
+ # shift all but one element
+ a = [1, 2]
+ a.shift
+ a.unshift(3, 4)
+ a.should == [3, 4, 2]
+
+ # now shift all elements
+ a.shift
+ a.shift
+ a.shift
+ a.unshift(3, 4)
+ a.should == [3, 4]
+ end
+
+ it "returns self" do
+ a = [1, 2, 3]
+ a.unshift("a").should.equal?(a)
+ end
+
+ it "quietly ignores unshifting nothing" do
+ [].unshift.should == []
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.unshift(:new).should == [:new, empty]
+
+ array = ArraySpecs.recursive_array
+ array.unshift(:new)
+ array[0..5].should == [:new, 1, 'two', 3.0, array, array]
+ end
+
+ it "raises a FrozenError on a frozen array when the array is modified" do
+ -> { ArraySpecs.frozen_array.unshift(1) }.should.raise(FrozenError)
+ end
+
+ # see [ruby-core:23666]
+ it "raises a FrozenError on a frozen array when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.unshift }.should.raise(FrozenError)
+ end
+
+ # https://github.com/truffleruby/truffleruby/issues/2772
+ it "doesn't rely on Array#[]= so it can be overridden" do
+ subclass = Class.new(Array) do
+ def []=(*)
+ raise "[]= is called"
+ end
+ end
+
+ array = subclass.new
+ array.unshift(1)
+ array.should == [1]
+ end
end
diff --git a/spec/ruby/core/array/values_at_spec.rb b/spec/ruby/core/array/values_at_spec.rb
index 13860150bb..e11e7e4451 100644
--- a/spec/ruby/core/array/values_at_spec.rb
+++ b/spec/ruby/core/array/values_at_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Should be synchronized with core/struct/values_at_spec.rb
describe "Array#values_at" do
it "returns an array of elements at the indexes when passed indexes" do
[1, 2, 3, 4, 5].values_at().should == []
@@ -58,6 +59,16 @@ describe "Array#values_at" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should.instance_of?(Array)
+ end
+
+ it "works when given endless ranges" do
+ [1, 2, 3, 4].values_at(eval("(1..)")).should == [2, 3, 4]
+ [1, 2, 3, 4].values_at(eval("(3...)")).should == [4]
+ end
+
+ it "works when given beginless ranges" do
+ [1, 2, 3, 4].values_at((..2)).should == [1, 2, 3]
+ [1, 2, 3, 4].values_at((...2)).should == [1, 2]
end
end
diff --git a/spec/ruby/core/array/zip_spec.rb b/spec/ruby/core/array/zip_spec.rb
index f0de864ed4..3ccdf143d6 100644
--- a/spec/ruby/core/array/zip_spec.rb
+++ b/spec/ruby/core/array/zip_spec.rb
@@ -42,7 +42,7 @@ describe "Array#zip" do
[1, 2].zip(10.upto(Float::INFINITY)).should == [[1, 10], [2, 11]]
end
- it "fills nil when the given enumereator is shorter than self" do
+ it "fills nil when the given enumerator is shorter than self" do
obj = Object.new
def obj.each
yield 10
@@ -60,6 +60,12 @@ describe "Array#zip" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should.instance_of?(Array)
+ end
+
+ it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
+ -> { [1, 2, 3].zip(Object.new) }.should.raise(TypeError, "wrong argument type Object (must respond to :each)")
+ -> { [1, 2, 3].zip(1) }.should.raise(TypeError, "wrong argument type Integer (must respond to :each)")
+ -> { [1, 2, 3].zip(true) }.should.raise(TypeError, "wrong argument type TrueClass (must respond to :each)")
end
end
diff --git a/spec/ruby/core/basicobject/__send___spec.rb b/spec/ruby/core/basicobject/__send___spec.rb
index 005b1d0d90..2f814e448c 100644
--- a/spec/ruby/core/basicobject/__send___spec.rb
+++ b/spec/ruby/core/basicobject/__send___spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/basicobject/send'
describe "BasicObject#__send__" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:__send__)
+ BasicObject.public_instance_methods(false).should.include?(:__send__)
end
it_behaves_like :basicobject_send, :__send__
diff --git a/spec/ruby/core/basicobject/basicobject_spec.rb b/spec/ruby/core/basicobject/basicobject_spec.rb
index 860ad93e89..af28de0687 100644
--- a/spec/ruby/core/basicobject/basicobject_spec.rb
+++ b/spec/ruby/core/basicobject/basicobject_spec.rb
@@ -8,19 +8,23 @@ describe "BasicObject" do
end
it "raises NameError when referencing built-in constants" do
- lambda { class BasicObjectSpecs::BOSubclass; Kernel; end }.should raise_error(NameError)
+ -> { class BasicObjectSpecs::BOSubclass; Kernel; end }.should.raise(NameError)
end
it "does not define built-in constants (according to const_defined?)" do
- BasicObject.const_defined?(:Kernel).should be_false
+ BasicObject.const_defined?(:Kernel).should == false
end
it "does not define built-in constants (according to defined?)" do
- BasicObjectSpecs::BOSubclass.kernel_defined?.should be_nil
+ BasicObjectSpecs::BOSubclass.kernel_defined?.should == nil
+ end
+
+ it "is included in Object's list of constants" do
+ Object.constants(false).should.include?(:BasicObject)
end
it "includes itself in its list of constants" do
- BasicObject.constants.should include(:BasicObject)
+ BasicObject.constants(false).should.include?(:BasicObject)
end
end
@@ -30,11 +34,11 @@ describe "BasicObject metaclass" do
end
it "is an instance of Class" do
- @meta.should be_an_instance_of(Class)
+ @meta.should.instance_of?(Class)
end
it "has Class as superclass" do
- @meta.superclass.should equal(Class)
+ @meta.superclass.should.equal?(Class)
end
it "contains methods for the BasicObject class" do
@@ -53,11 +57,11 @@ describe "BasicObject instance metaclass" do
end
it "is an instance of Class" do
- @meta.should be_an_instance_of(Class)
+ @meta.should.instance_of?(Class)
end
it "has BasicObject as superclass" do
- @meta.superclass.should equal(BasicObject)
+ @meta.superclass.should.equal?(BasicObject)
end
it "contains methods defined for the BasicObject instance" do
@@ -81,7 +85,7 @@ describe "BasicObject subclass" do
describe "BasicObject references" do
it "can refer to BasicObject from within itself" do
- lambda { BasicObject::BasicObject }.should_not raise_error
+ -> { BasicObject::BasicObject }.should_not.raise
end
end
end
diff --git a/spec/ruby/core/basicobject/equal_spec.rb b/spec/ruby/core/basicobject/equal_spec.rb
index 3c1ad56d4a..c0f41dc0c0 100644
--- a/spec/ruby/core/basicobject/equal_spec.rb
+++ b/spec/ruby/core/basicobject/equal_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/kernel/equal'
describe "BasicObject#equal?" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:equal?)
+ BasicObject.public_instance_methods(false).should.include?(:equal?)
end
it_behaves_like :object_equal, :equal?
@@ -11,9 +11,11 @@ describe "BasicObject#equal?" do
it "is unaffected by overriding __id__" do
o1 = mock("object")
o2 = mock("object")
- def o1.__id__; 10; end
- def o2.__id__; 10; end
- o1.equal?(o2).should be_false
+ suppress_warning {
+ def o1.__id__; 10; end
+ def o2.__id__; 10; end
+ }
+ o1.equal?(o2).should == false
end
it "is unaffected by overriding object_id" do
@@ -21,7 +23,7 @@ describe "BasicObject#equal?" do
o1.stub!(:object_id).and_return(10)
o2 = mock("object")
o2.stub!(:object_id).and_return(10)
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
end
it "is unaffected by overriding ==" do
@@ -29,12 +31,12 @@ describe "BasicObject#equal?" do
o1 = mock("object")
o1.stub!(:==).and_return(true)
o2 = mock("object")
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
# same objects, overriding == to return false
o3 = mock("object")
o3.stub!(:==).and_return(false)
- o3.equal?(o3).should be_true
+ o3.equal?(o3).should == true
end
it "is unaffected by overriding eql?" do
@@ -42,11 +44,11 @@ describe "BasicObject#equal?" do
o1 = mock("object")
o1.stub!(:eql?).and_return(true)
o2 = mock("object")
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
# same objects, overriding eql? to return false
o3 = mock("object")
o3.stub!(:eql?).and_return(false)
- o3.equal?(o3).should be_true
+ o3.equal?(o3).should == true
end
end