1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
This commit is contained in:
Benoit Daloze 2020-09-17 11:42:26 +02:00
parent ce888bfa23
commit 3f6c0a6d74
27 changed files with 296 additions and 134 deletions

View file

@ -5,6 +5,8 @@
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.
@ -30,13 +32,15 @@ ruby/spec is known to be tested in these implementations for every commit:
ruby/spec describes the behavior of Ruby 2.5 and more recent Ruby versions.
More precisely, every latest stable MRI release should [pass](https://travis-ci.org/ruby/spec) all specs of ruby/spec (2.5.x, 2.6.x, 2.7.x, etc), and those are tested in TravisCI.
### Synchronization with Ruby Implementations
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.
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 in a Ruby implementation can be done with:
Running specs on a Ruby implementation can be done with:
```
$ cd ruby_implementation/spec/ruby
@ -44,6 +48,8 @@ $ cd ruby_implementation/spec/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)

View file

@ -37,11 +37,16 @@ describe "The --enable and --disable flags" do
ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false"
end
it "can be used with all" do
it "can be used with all for enable" do
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
env = {'RUBYOPT' => '-w'}
ruby_exe(e, options: "--enable=all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
# 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
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: "--disable=all", env: env).chomp.should == "[nil, nil, false, false]"
ruby_exe(e, options: "--disable-all", env: env).chomp.should == "[nil, nil, false, false]"
end

View file

@ -0,0 +1,12 @@
require_relative '../../spec_helper'
describe "Complex#to_c" do
it "returns self" do
value = Complex(1, 5)
value.to_c.should equal(value)
end
it 'returns the same value' do
Complex(1, 5).to_c.should == Complex(1, 5)
end
end

View file

@ -0,0 +1,33 @@
require_relative '../../spec_helper'
ruby_version_is "3.0" do
describe "Hash#except" do
before :each do
@hash = { a: 1, b: 2, c: 3 }
end
it "returns a new duplicate hash without arguments" do
ret = @hash.except
ret.should_not equal(@hash)
ret.should == @hash
end
it "returns a hash without the requested subset" do
@hash.except(:c, :a).should == { b: 2 }
end
it "ignores keys not present in the original hash" do
@hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
end
it "returns an instance of a subclass" do
klass = Class.new(Hash)
h = klass.new
h[:bar] = 12
h[:foo] = 42
r = h.except(:foo)
r.should == {bar: 12}
r.class.should == klass
end
end
end

View file

@ -0,0 +1,13 @@
require_relative '../../spec_helper'
describe "NilClass#===" do
it "returns true for nil" do
(nil === nil).should == true
end
it "returns false for non-nil object" do
(nil === 1).should == false
(nil === "").should == false
(nil === Object).should == false
end
end

View file

@ -0,0 +1,25 @@
require_relative '../../spec_helper'
describe "Numeric#clone" do
it "returns self" do
value = 1
value.clone.should equal(value)
subclass = Class.new(Numeric)
value = subclass.new
value.clone.should equal(value)
end
it "does not change frozen status" do
1.clone.frozen?.should == true
end
it "accepts optonal keyword argument :freeze" do
value = 1
value.clone(freeze: true).should equal(value)
end
it "raises ArgumentError if passed freeze: false" do
-> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/)
end
end

View file

@ -0,0 +1,16 @@
require_relative '../../spec_helper'
describe "Numeric#dup" do
it "returns self" do
value = 1
value.dup.should equal(value)
subclass = Class.new(Numeric)
value = subclass.new
value.dup.should equal(value)
end
it "does not change frozen status" do
1.dup.frozen?.should == true
end
end

View file

@ -1,56 +1,8 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../../shared/string/end_with'
describe "String#end_with?" do
it "returns true only if ends match" do
s = "hello"
s.should.end_with?('o')
s.should.end_with?('llo')
end
it 'returns false if the end does not match' do
s = 'hello'
s.should_not.end_with?('ll')
end
it "returns true if the search string is empty" do
"hello".should.end_with?("")
"".should.end_with?("")
end
it "returns true only if any ending match" do
"hello".should.end_with?('x', 'y', 'llo', 'z')
end
it "converts its argument using :to_str" do
s = "hello"
find = mock('o')
find.should_receive(:to_str).and_return("o")
s.should.end_with?(find)
end
it "ignores arguments not convertible to string" do
"hello".should_not.end_with?()
-> { "hello".end_with?(1) }.should raise_error(TypeError)
-> { "hello".end_with?(["o"]) }.should raise_error(TypeError)
-> { "hello".end_with?(1, nil, "o") }.should raise_error(TypeError)
end
it "uses only the needed arguments" do
find = mock('h')
find.should_not_receive(:to_str)
"hello".should.end_with?("o",find)
end
it "works for multibyte strings" do
"céréale".should.end_with?("réale")
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "".encode Encoding::EUC_JP
-> do
"あれ".end_with?(pat)
end.should raise_error(Encoding::CompatibilityError)
end
it_behaves_like :end_with, :to_s
end

View file

@ -1,74 +1,8 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../../shared/string/start_with'
describe "String#start_with?" do
it "returns true only if beginning match" do
s = "hello"
s.should.start_with?('h')
s.should.start_with?('hel')
s.should_not.start_with?('el')
end
it "returns true only if any beginning match" do
"hello".should.start_with?('x', 'y', 'he', 'z')
end
it "returns true if the search string is empty" do
"hello".should.start_with?("")
"".should.start_with?("")
end
it "converts its argument using :to_str" do
s = "hello"
find = mock('h')
find.should_receive(:to_str).and_return("h")
s.should.start_with?(find)
end
it "ignores arguments not convertible to string" do
"hello".should_not.start_with?()
-> { "hello".start_with?(1) }.should raise_error(TypeError)
-> { "hello".start_with?(["h"]) }.should raise_error(TypeError)
-> { "hello".start_with?(1, nil, "h") }.should raise_error(TypeError)
end
it "uses only the needed arguments" do
find = mock('h')
find.should_not_receive(:to_str)
"hello".should.start_with?("h",find)
end
it "works for multibyte strings" do
"céréale".should.start_with?("cér")
end
it "supports regexps" do
regexp = /[h1]/
"hello".should.start_with?(regexp)
"1337".should.start_with?(regexp)
"foxes are 1337".should_not.start_with?(regexp)
"chunky\n12bacon".should_not.start_with?(/12/)
end
it "supports regexps with ^ and $ modifiers" do
regexp1 = /^\d{2}/
regexp2 = /\d{2}$/
"12test".should.start_with?(regexp1)
"test12".should_not.start_with?(regexp1)
"12test".should_not.start_with?(regexp2)
"test12".should_not.start_with?(regexp2)
end
it "sets Regexp.last_match if it returns true" do
regexp = /test-(\d+)/
"test-1337".start_with?(regexp).should be_true
Regexp.last_match.should_not be_nil
Regexp.last_match[1].should == "1337"
$1.should == "1337"
"test-asdf".start_with?(regexp).should be_false
Regexp.last_match.should be_nil
$1.should be_nil
end
it_behaves_like :start_with, :to_s
end

View file

@ -69,4 +69,11 @@ describe 'String#-@' do
(-dynamic).should equal(-"this string is frozen".freeze)
end
end
ruby_version_is "3.0" do
it "interns the provided string if it is frozen" do
dynamic = "this string is unique and frozen #{rand}".freeze
(-dynamic).should equal(dynamic)
end
end
end

View file

@ -0,0 +1,10 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative '../../shared/string/end_with'
ruby_version_is "2.7" do
describe "Symbol#end_with?" do
it_behaves_like :end_with, :to_sym
end
end

View file

@ -0,0 +1,10 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../../shared/string/start_with'
ruby_version_is "2.7" do
describe "Symbol#start_with?" do
it_behaves_like :start_with, :to_sym
end
end

View file

@ -0,0 +1,13 @@
require_relative '../../spec_helper'
describe "TrueClass#===" do
it "returns true for true" do
(true === true).should == true
end
it "returns false for non-true object" do
(true === 1).should == false
(true === "").should == false
(true === Object).should == false
end
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_get'
describe "Net::HTTP#get2" do
it_behaves_like :net_ftp_request_get, :get2
it_behaves_like :net_http_request_get, :get2
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_head'
describe "Net::HTTP#head2" do
it_behaves_like :net_ftp_request_head, :head2
it_behaves_like :net_http_request_head, :head2
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_post'
describe "Net::HTTP#post2" do
it_behaves_like :net_ftp_request_post, :post2
it_behaves_like :net_http_request_post, :post2
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_put'
describe "Net::HTTP#put2" do
it_behaves_like :net_ftp_request_put, :put2
it_behaves_like :net_http_request_put, :put2
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_get'
describe "Net::HTTP#request_get" do
it_behaves_like :net_ftp_request_get, :get2
it_behaves_like :net_http_request_get, :get2
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_head'
describe "Net::HTTP#request_head" do
it_behaves_like :net_ftp_request_head, :request_head
it_behaves_like :net_http_request_head, :request_head
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_post'
describe "Net::HTTP#request_post" do
it_behaves_like :net_ftp_request_post, :request_post
it_behaves_like :net_http_request_post, :request_post
end

View file

@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_put'
describe "Net::HTTP#request_put" do
it_behaves_like :net_ftp_request_put, :request_put
it_behaves_like :net_http_request_put, :request_put
end

View file

@ -1,4 +1,4 @@
describe :net_ftp_request_get, shared: true do
describe :net_http_request_get, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)

View file

@ -1,4 +1,4 @@
describe :net_ftp_request_head, shared: true do
describe :net_http_request_head, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)

View file

@ -1,4 +1,4 @@
describe :net_ftp_request_post, shared: true do
describe :net_http_request_post, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)

View file

@ -1,4 +1,4 @@
describe :net_ftp_request_put, shared: true do
describe :net_http_request_put, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)

View file

@ -0,0 +1,54 @@
describe :end_with, shared: true do
# the @method should either be :to_s or :to_sym
it "returns true only if ends match" do
s = "hello".send(@method)
s.should.end_with?('o')
s.should.end_with?('llo')
end
it 'returns false if the end does not match' do
s = 'hello'.send(@method)
s.should_not.end_with?('ll')
end
it "returns true if the search string is empty" do
"hello".send(@method).should.end_with?("")
"".send(@method).should.end_with?("")
end
it "returns true only if any ending match" do
"hello".send(@method).should.end_with?('x', 'y', 'llo', 'z')
end
it "converts its argument using :to_str" do
s = "hello".send(@method)
find = mock('o')
find.should_receive(:to_str).and_return("o")
s.should.end_with?(find)
end
it "ignores arguments not convertible to string" do
"hello".send(@method).should_not.end_with?()
-> { "hello".send(@method).end_with?(1) }.should raise_error(TypeError)
-> { "hello".send(@method).end_with?(["o"]) }.should raise_error(TypeError)
-> { "hello".send(@method).end_with?(1, nil, "o") }.should raise_error(TypeError)
end
it "uses only the needed arguments" do
find = mock('h')
find.should_not_receive(:to_str)
"hello".send(@method).should.end_with?("o",find)
end
it "works for multibyte strings" do
"céréale".send(@method).should.end_with?("réale")
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "".encode Encoding::EUC_JP
-> do
"あれ".send(@method).end_with?(pat)
end.should raise_error(Encoding::CompatibilityError)
end
end

View file

@ -0,0 +1,72 @@
describe :start_with, shared: true do
# the @method should either be :to_s or :to_sym
it "returns true only if beginning match" do
s = "hello".send(@method)
s.should.start_with?('h')
s.should.start_with?('hel')
s.should_not.start_with?('el')
end
it "returns true only if any beginning match" do
"hello".send(@method).should.start_with?('x', 'y', 'he', 'z')
end
it "returns true if the search string is empty" do
"hello".send(@method).should.start_with?("")
"".send(@method).should.start_with?("")
end
it "converts its argument using :to_str" do
s = "hello".send(@method)
find = mock('h')
find.should_receive(:to_str).and_return("h")
s.should.start_with?(find)
end
it "ignores arguments not convertible to string" do
"hello".send(@method).should_not.start_with?()
-> { "hello".send(@method).start_with?(1) }.should raise_error(TypeError)
-> { "hello".send(@method).start_with?(["h"]) }.should raise_error(TypeError)
-> { "hello".send(@method).start_with?(1, nil, "h") }.should raise_error(TypeError)
end
it "uses only the needed arguments" do
find = mock('h')
find.should_not_receive(:to_str)
"hello".send(@method).should.start_with?("h",find)
end
it "works for multibyte strings" do
"céréale".send(@method).should.start_with?("cér")
end
it "supports regexps" do
regexp = /[h1]/
"hello".send(@method).should.start_with?(regexp)
"1337".send(@method).should.start_with?(regexp)
"foxes are 1337".send(@method).should_not.start_with?(regexp)
"chunky\n12bacon".send(@method).should_not.start_with?(/12/)
end
it "supports regexps with ^ and $ modifiers" do
regexp1 = /^\d{2}/
regexp2 = /\d{2}$/
"12test".send(@method).should.start_with?(regexp1)
"test12".send(@method).should_not.start_with?(regexp1)
"12test".send(@method).should_not.start_with?(regexp2)
"test12".send(@method).should_not.start_with?(regexp2)
end
it "sets Regexp.last_match if it returns true" do
regexp = /test-(\d+)/
"test-1337".send(@method).start_with?(regexp).should be_true
Regexp.last_match.should_not be_nil
Regexp.last_match[1].should == "1337"
$1.should == "1337"
"test-asdf".send(@method).start_with?(regexp).should be_false
Regexp.last_match.should be_nil
$1.should be_nil
end
end