98286e9850
This fixes various issues when a module is included in or prepended to a module or class, and then refined, or refined and then included or prepended to a module or class. Implement by renaming ensure_origin to rb_ensure_origin, making it non-static, and calling it when refining a module. Fix Module#initialize_copy to handle origins correctly. Previously, Module#initialize_copy did not handle origins correctly. For example, this code: ```ruby module B; end class A def b; 2 end prepend B end a = A.dup.new class A def b; 1 end end p a.b ``` Printed 1 instead of 2. This is because the super chain for a.singleton_class was: ``` a.singleton_class A.dup B(iclass) B(iclass origin) A(origin) # not A.dup(origin) ``` The B iclasses would not be modified, so the includer entry would be still be set to A and not A.dup. This modifies things so that if the class/module has an origin, all iclasses between the class/module and the origin are duplicated and have the correct includer entry set, and the correct origin is created. This requires other changes to make sure all tests still pass: * rb_undef_methods_from doesn't automatically handle classes with origins, so pass it the origin for Comparable when undefing methods in Complex. This fixed a failure in the Complex tests. * When adding a method, the method cache was not cleared correctly if klass has an origin. Clear the method cache for the klass before switching to the origin of klass. This fixed failures in the autoload tests related to overridding require, without breaking the optimization tests. Also clear the method cache for both the module and origin when removing a method. * Module#include? is fixed to skip origin iclasses. * Refinements are fixed to use the origin class of the module that has an origin. * RCLASS_REFINED_BY_ANY is removed as it was only used in a single place and is no longer needed. * Marshal#dump is fixed to skip iclass origins. * rb_method_entry_make is fixed to handled overridden optimized methods for modules that have origins. Fixes [Bug #16852] |
||
---|---|---|
.. | ||
command_line | ||
core | ||
fixtures | ||
language | ||
library | ||
optional/capi | ||
security | ||
shared | ||
.gitignore | ||
.mspec.constants | ||
.rubocop.yml | ||
.rubocop_todo.yml | ||
CONTRIBUTING.md | ||
default.mspec | ||
LICENSE | ||
README.md | ||
spec_helper.rb | ||
TODO |
The Ruby Spec Suite
The Ruby Spec Suite, abbreviated ruby/spec
, is a test suite for the behavior of the Ruby programming language.
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.
Every example code has a textual description, which presents several advantages:
- It is easier to understand the intent of the author
- It documents how recent versions of Ruby should behave
- It helps Ruby implementations to agree on a common behavior
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 project.
The specs describe the language syntax, the core library, the standard library, the C API for extensions and the command line flags. 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 on 30 platforms and 4 versions
- JRuby for both 1.7 and 9.x
- TruffleRuby
- Opal
ruby/spec describes the behavior of Ruby 2.5 and more recent Ruby versions. More precisely, every latest stable MRI release should pass all specs of ruby/spec (2.5.x, 2.6.x, 2.7.x, etc), and those are tested in TravisCI.
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 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.
For testing a Ruby implementation, one should always test against the 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 in a Ruby implementation can be done with:
$ cd ruby_implementation/spec/ruby
# Add ../ruby_implementation/bin in PATH, or pass -t /path/to/bin/ruby
$ ../mspec/bin/mspec
For older specs try these commits:
- Ruby 2.0.0-p647 - Suite using MSpec (may encounter 2 failures)
- Ruby 2.1.9 - Suite using MSpec
- Ruby 2.2.10 - Suite using MSpec
- Ruby 2.3.8 - Suite using MSpec
- Ruby 2.4.10 - Suite using MSpec
Running the specs
First, clone this repository:
$ git clone https://github.com/ruby/spec.git
Then move to it:
$ cd spec
Clone MSpec:
$ git clone https://github.com/ruby/mspec.git ../mspec
And run the spec suite:
$ ../mspec/bin/mspec
This will execute all the specs using the executable named ruby
on your current PATH.
Running Specs with a Specific Ruby Implementation
Use the -t
option to specify the Ruby implementation with which to run the specs.
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
Running Selected Specs
To run a single spec file, pass the filename to mspec
:
$ ../mspec/bin/mspec core/kernel/kind_of_spec.rb
You can also pass a directory, in which case all specs in that directories will be run:
$ ../mspec/bin/mspec core/kernel
Finally, you can also run them per group as defined in default.mspec
.
The following command will run all language specs:
$ ../mspec/bin/mspec :language
In similar fashion, the following commands run the respective specs:
$ ../mspec/bin/mspec :core
$ ../mspec/bin/mspec :library
$ ../mspec/bin/mspec :capi
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
Contributing and Writing Specs
See CONTRIBUTING.md for documentation about contributing and writing specs (guards, matchers, etc).
Socket specs from rubysl-socket
Most specs under library/socket
were imported from the rubysl-socket project.
The 3 copyright holders of rubysl-socket, Yorick Peterse, Chuck Remes and
Brian Shirai, agreed to relicense those specs
under the MIT license in ruby/spec.
History and RubySpec
This project was originally born from Rubinius tests being converted to the spec style. The revision history of these specs is available here. 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. A couple months later, the different repositories were merged and the project was revived. On 12 January 2016, the name was changed to "The Ruby Spec Suite" for clarity and to let the RubySpec ideology rest in peace.