Skip to content

Commit cee62c6

Browse files
andrykonchineregon
authored andcommitted
1 parent d7af8af commit cee62c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+886
-170
lines changed

spec/ruby/CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,13 @@ describe :kernel_sprintf, shared: true do
277277
end
278278

279279
describe "Kernel#sprintf" do
280-
it_behaves_like :kernel_sprintf, -> (format, *args) {
280+
it_behaves_like :kernel_sprintf, -> format, *args {
281281
sprintf(format, *args)
282282
}
283283
end
284284

285285
describe "Kernel.sprintf" do
286-
it_behaves_like :kernel_sprintf, -> (format, *args) {
286+
it_behaves_like :kernel_sprintf, -> format, *args {
287287
Kernel.sprintf(format, *args)
288288
}
289289
end

spec/ruby/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ More precisely, every latest stable MRI release should [pass](https://github.com
3535

3636
### Synchronization with Ruby Implementations
3737

38-
The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby,
38+
The specs are synchronized both ways around once a month by @andrykonchin between ruby/spec, MRI, JRuby and TruffleRuby,
3939
using [this script](https://github.com/ruby/mspec/blob/master/tool/sync/sync-rubyspec.rb).
4040
Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs.
4141
Any of these repositories can be used to add or edit specs, use what is most convenient for you.

spec/ruby/core/array/each_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
88
# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
99
# CRuby simply reads the array storage and checks the size for every iteration;
10-
# like `i = 0; while i < size; yield self[i]; end`
10+
# like `i = 0; while i < size; yield self[i]; i += 1; end`
1111

1212
describe "Array#each" do
1313
it "yields each element to the block" do

spec/ruby/core/array/plus_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
2222
end
2323

24-
it "raises a Typeerror if the given argument can't be converted to an array" do
24+
it "raises a TypeError if the given argument can't be converted to an array" do
2525
-> { [1, 2, 3] + nil }.should raise_error(TypeError)
2626
-> { [1, 2, 3] + "abc" }.should raise_error(TypeError)
2727
end

spec/ruby/core/array/to_h_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
4646
end
4747

48+
it "passes to a block each element as a single argument" do
49+
ScratchPad.record []
50+
[[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
51+
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
52+
end
53+
4854
it "raises ArgumentError if block returns longer or shorter array" do
4955
-> do
5056
[:a, :b].to_h { |k| [k, k.to_s, 1] }

spec/ruby/core/enumerable/shared/inject.rb

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@
1616

1717
it "can take two argument" do
1818
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-).should == 4
19+
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, "-").should == 4
20+
21+
[1, 2, 3].send(@method, 10, :-).should == 4
22+
[1, 2, 3].send(@method, 10, "-").should == 4
23+
end
24+
25+
it "converts non-Symbol method name argument to String with #to_str if two arguments" do
26+
name = Object.new
27+
def name.to_str; "-"; end
28+
29+
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, name).should == 4
30+
[1, 2, 3].send(@method, 10, name).should == 4
31+
end
32+
33+
it "raises TypeError when the second argument is not Symbol or String and it cannot be converted to String if two arguments" do
34+
-> { EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
35+
-> { [1, 2, 3].send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
1936
end
2037

2138
it "ignores the block if two arguments" do
@@ -39,6 +56,25 @@
3956

4057
it "can take a symbol argument" do
4158
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, :-).should == 4
59+
[10, 1, 2, 3].send(@method, :-).should == 4
60+
end
61+
62+
it "can take a String argument" do
63+
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, "-").should == 4
64+
[10, 1, 2, 3].send(@method, "-").should == 4
65+
end
66+
67+
it "converts non-Symbol method name argument to String with #to_str" do
68+
name = Object.new
69+
def name.to_str; "-"; end
70+
71+
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, name).should == 4
72+
[10, 1, 2, 3].send(@method, name).should == 4
73+
end
74+
75+
it "raises TypeError when passed not Symbol or String method name argument and it cannot be converted to String" do
76+
-> { EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
77+
-> { [10, 1, 2, 3].send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
4278
end
4379

4480
it "without argument takes a block with an accumulator (with first element as initial value) and the current element. Value of block becomes new accumulator" do
@@ -77,7 +113,6 @@
77113
EnumerableSpecs::EachDefiner.new('a','b','c').send(@method) {|result, i| i+result}.should == "cba"
78114
EnumerableSpecs::EachDefiner.new(3, 4, 5).send(@method) {|result, i| result*i}.should == 60
79115
EnumerableSpecs::EachDefiner.new([1], 2, 'a','b').send(@method){|r,i| r<<i}.should == [1, 2, 'a', 'b']
80-
81116
end
82117
83118
it "returns nil when fails(legacy rubycon)" do

spec/ruby/core/enumerable/to_h_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ def enum.each(*args)
5353
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
5454
end
5555

56+
it "passes to a block each element as a single argument" do
57+
enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2])
58+
59+
ScratchPad.record []
60+
enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
61+
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
62+
end
63+
5664
it "raises ArgumentError if block returns longer or shorter array" do
5765
-> do
5866
@enum.to_h { |k| [k, k.to_s, 1] }

spec/ruby/core/env/to_h_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@
1818
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
1919
end
2020

21+
it "passes to a block each pair's key and value as separate arguments" do
22+
ENV.replace("a" => "b", "c" => "d")
23+
24+
ScratchPad.record []
25+
ENV.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
26+
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
27+
28+
ScratchPad.record []
29+
ENV.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
30+
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
31+
end
32+
2133
it "does not require the array elements to be strings" do
2234
ENV.replace("a" => "b", "c" => "d")
2335
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }

spec/ruby/core/exception/detailed_message_spec.rb

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@ def exception.detailed_message(**)
1515
exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>"
1616
end
1717

18-
it "accepts highlight keyword argument and adds escape control sequences" do
19-
RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
20-
end
21-
22-
it "allows and ignores other keyword arguments" do
23-
RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
24-
end
25-
2618
it "returns just a message if exception class is anonymous" do
2719
Class.new(RuntimeError).new("message").detailed_message.should == "message"
2820
end
@@ -31,13 +23,30 @@ def exception.detailed_message(**)
3123
RuntimeError.new("").detailed_message.should == "unhandled exception"
3224
end
3325

34-
it "returns just class name for an instance of RuntimeError subclass with empty message" do
26+
it "returns just class name for an instance other than RuntimeError with empty message" do
3527
DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
28+
StandardError.new("").detailed_message.should == "StandardError"
3629
end
3730

3831
it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do
3932
klass = Class.new(RuntimeError)
4033
klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
4134
end
35+
36+
it "accepts highlight keyword argument and adds escape control sequences" do
37+
RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
38+
end
39+
40+
it "accepts highlight keyword argument and adds escape control sequences for an instance of RuntimeError with empty message" do
41+
RuntimeError.new("").detailed_message(highlight: true).should == "\e[1;4munhandled exception\e[m"
42+
end
43+
44+
it "accepts highlight keyword argument and adds escape control sequences for an instance other than RuntimeError with empty message" do
45+
StandardError.new("").detailed_message(highlight: true).should == "\e[1;4mStandardError\e[m"
46+
end
47+
48+
it "allows and ignores other keyword arguments" do
49+
RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
50+
end
4251
end
4352
end

spec/ruby/core/hash/replace_spec.rb

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,70 @@
11
require_relative '../../spec_helper'
22
require_relative 'fixtures/classes'
3-
require_relative 'shared/replace'
43

54
describe "Hash#replace" do
6-
it_behaves_like :hash_replace, :replace
5+
it "replaces the contents of self with other" do
6+
h = { a: 1, b: 2 }
7+
h.replace(c: -1, d: -2).should equal(h)
8+
h.should == { c: -1, d: -2 }
9+
end
10+
11+
it "tries to convert the passed argument to a hash using #to_hash" do
12+
obj = mock('{1=>2,3=>4}')
13+
obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
14+
15+
h = {}
16+
h.replace(obj)
17+
h.should == { 1 => 2, 3 => 4 }
18+
end
19+
20+
it "calls to_hash on hash subclasses" do
21+
h = {}
22+
h.replace(HashSpecs::ToHashHash[1 => 2])
23+
h.should == { 1 => 2 }
24+
end
25+
26+
it "transfers the compare_by_identity flag" do
27+
hash_a = { a: 1 }
28+
hash_b = { b: 2 }
29+
hash_b.compare_by_identity
30+
hash_a.should_not.compare_by_identity?
31+
hash_a.replace(hash_b)
32+
hash_a.should.compare_by_identity?
33+
34+
hash_a = { a: 1 }
35+
hash_b = { b: 2 }
36+
hash_a.compare_by_identity
37+
hash_a.should.compare_by_identity?
38+
hash_a.replace(hash_b)
39+
hash_a.should_not.compare_by_identity?
40+
end
41+
42+
it "does not transfer default values" do
43+
hash_a = {}
44+
hash_b = Hash.new(5)
45+
hash_a.replace(hash_b)
46+
hash_a.default.should == 5
47+
48+
hash_a = {}
49+
hash_b = Hash.new { |h, k| k * 2 }
50+
hash_a.replace(hash_b)
51+
hash_a.default(5).should == 10
52+
53+
hash_a = Hash.new { |h, k| k * 5 }
54+
hash_b = Hash.new(-> { raise "Should not invoke lambda" })
55+
hash_a.replace(hash_b)
56+
hash_a.default.should == hash_b.default
57+
end
58+
59+
it "raises a FrozenError if called on a frozen instance that would not be modified" do
60+
-> do
61+
HashSpecs.frozen_hash.replace(HashSpecs.frozen_hash)
62+
end.should raise_error(FrozenError)
63+
end
64+
65+
it "raises a FrozenError if called on a frozen instance that is modified" do
66+
-> do
67+
HashSpecs.frozen_hash.replace(HashSpecs.empty_frozen_hash)
68+
end.should raise_error(FrozenError)
69+
end
770
end

0 commit comments

Comments
 (0)