mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Update to ruby/spec@41bf282
This commit is contained in:
		
							parent
							
								
									5d21050182
								
							
						
					
					
						commit
						a0f5ff4c3c
					
				
					 75 changed files with 851 additions and 143 deletions
				
			
		| 
						 | 
				
			
			@ -53,6 +53,8 @@ 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.
 | 
			
		||||
 | 
			
		||||
#### Comparison matchers
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
(1 + 2).should == 3 # Calls #==
 | 
			
		||||
(1 + 2).should_not == 5
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +68,11 @@ File.should equal(File) # Calls #equal? (tests identity)
 | 
			
		|||
4.should > 3
 | 
			
		||||
 | 
			
		||||
"Hello".should =~ /l{2}/ # Calls #=~ (Regexp match)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Predicate matchers
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
[].should be_empty # Calls #empty?
 | 
			
		||||
[1,2,3].should include(2) # Calls #include?
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -82,8 +88,13 @@ Numeric.should be_ancestor_of(Float) # Float.ancestors.include?(Numeric)
 | 
			
		|||
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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, etc.
 | 
			
		||||
 | 
			
		||||
#### Exception matchers
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
-> {
 | 
			
		||||
  raise "oops"
 | 
			
		||||
}.should raise_error(RuntimeError, /oops/)
 | 
			
		||||
| 
						 | 
				
			
			@ -95,11 +106,20 @@ Array.should have_method(:new)
 | 
			
		|||
  e.message.should include("oops")
 | 
			
		||||
  e.cause.should == nil
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
**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.
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
-> { ... }.should_not raise_error
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Warning matcher
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
-> {
 | 
			
		||||
  Fixnum
 | 
			
		||||
}.should complain(/constant ::Fixnum is deprecated/) # Expect a warning
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +130,8 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +140,11 @@ end
 | 
			
		|||
ruby_version_is "2.4" do
 | 
			
		||||
  # Specs for RUBY_VERSION >= 2.4
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Platform guards
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
platform_is :windows do
 | 
			
		||||
  # Specs only valid on Windows
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -140,18 +166,25 @@ end
 | 
			
		|||
big_endian do
 | 
			
		||||
  # Big-endian platform
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
#### Guard for bug
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
ruby_bug '#13669', ''...'2.5' do
 | 
			
		||||
  it "works like this" do
 | 
			
		||||
    # Specify the expected behavior here, not the bug
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Combining guards
 | 
			
		||||
 | 
			
		||||
# Combining guards
 | 
			
		||||
```ruby
 | 
			
		||||
guard -> { platform_is :windows and ruby_version_is ""..."2.5" } do
 | 
			
		||||
  # Windows and RUBY_VERSION < 2.5
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -159,8 +192,11 @@ end
 | 
			
		|||
guard_not -> { platform_is :windows and ruby_version_is ""..."2.5" } do
 | 
			
		||||
  # The opposite
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Custom guard
 | 
			
		||||
#### Custom guard
 | 
			
		||||
 | 
			
		||||
```ruby
 | 
			
		||||
max_uint = (1 << 32) - 1
 | 
			
		||||
guard -> { max_uint <= fixnum_max } do
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -168,6 +204,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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
# The Ruby Spec Suite
 | 
			
		||||
 | 
			
		||||
[](https://github.com/ruby/spec/actions)
 | 
			
		||||
[](https://github.com/ruby/spec/actions)
 | 
			
		||||
[](https://github.com/ruby/spec/actions)
 | 
			
		||||
[](https://gitter.im/ruby/spec)
 | 
			
		||||
 | 
			
		||||
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								spec/ruby/command_line/dash_l_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								spec/ruby/command_line/dash_l_spec.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
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", escape: true,
 | 
			
		||||
             args: " < #{@names}").should ==
 | 
			
		||||
        "false\nfalse\nfalse\n"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ruby_version_is "2.5" do
 | 
			
		||||
    it "chomps last line based on $/" do
 | 
			
		||||
      ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l", escape: true,
 | 
			
		||||
               args: " < #{@names}").should ==
 | 
			
		||||
          "alice j\nbob field\njames grey\n"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "sets $\\ to the value of $/" do
 | 
			
		||||
    ruby_exe("puts $\\ == $/", options: "-W0 -n -l", escape: true,
 | 
			
		||||
             args: " < #{@names}").should ==
 | 
			
		||||
        "true\ntrue\ntrue\n"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "sets $-l" do
 | 
			
		||||
    ruby_exe("puts $-l", options: "-n -l", escape: true,
 | 
			
		||||
                         args: " < #{@names}").should ==
 | 
			
		||||
      "true\ntrue\ntrue\n"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +461,7 @@ describe :array_slice, shared: true do
 | 
			
		|||
  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)
 | 
			
		||||
    obj.should_receive(:to_int).and_return(bignum_value)
 | 
			
		||||
    -> { array.send(@method, obj) }.should raise_error(RangeError)
 | 
			
		||||
 | 
			
		||||
    obj = 8e19
 | 
			
		||||
| 
						 | 
				
			
			@ -471,10 +471,19 @@ describe :array_slice, shared: true do
 | 
			
		|||
  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)
 | 
			
		||||
    obj.should_receive(:to_int).and_return(bignum_value)
 | 
			
		||||
    -> { array.send(@method, 1, obj) }.should raise_error(RangeError)
 | 
			
		||||
 | 
			
		||||
    obj = 8e19
 | 
			
		||||
    -> { array.send(@method, 1, obj) }.should raise_error(RangeError)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "raises a type error if a range is passed with a length" do
 | 
			
		||||
    ->{ [1, 2, 3].send(@method, 1..2, 1) }.should raise_error(TypeError)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "raises a RangeError if passed a range with a bound that is too large" do
 | 
			
		||||
    -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
 | 
			
		||||
    -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -131,4 +131,10 @@ describe "Binding#eval" do
 | 
			
		|||
    bind, meth = obj.get_binding_with_send_and_method
 | 
			
		||||
    bind.eval("__method__").should == meth
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "reflects refinements activated in the binding scope" do
 | 
			
		||||
    bind = BindingSpecs::Refined.refined_binding
 | 
			
		||||
 | 
			
		||||
    bind.eval("'bar'.foo").should == "foo"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,4 +49,18 @@ module BindingSpecs
 | 
			
		|||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  module AddFooToString
 | 
			
		||||
    refine(String) do
 | 
			
		||||
      def foo
 | 
			
		||||
        "foo"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  class Refined
 | 
			
		||||
    using AddFooToString
 | 
			
		||||
    def self.refined_binding
 | 
			
		||||
      binding
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,12 @@ platform_is_not :windows do
 | 
			
		|||
    it "raises Errno::ENOENT if the symlink points to an absent file" do
 | 
			
		||||
      -> { File.realpath(@fake_link) }.should raise_error(Errno::ENOENT)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "converts the argument with #to_path" do
 | 
			
		||||
      path = mock("path")
 | 
			
		||||
      path.should_receive(:to_path).and_return(__FILE__)
 | 
			
		||||
      File.realpath(path).should == File.realpath(__FILE__ )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,5 +41,14 @@ platform_is_not :windows do
 | 
			
		|||
      st.file?.should == true
 | 
			
		||||
      st.symlink?.should == false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns an error when given missing non-ASCII path" do
 | 
			
		||||
      missing_path = "/missingfilepath\xE3E4".force_encoding("ASCII-8BIT")
 | 
			
		||||
      -> {
 | 
			
		||||
        File.stat(missing_path)
 | 
			
		||||
      }.should raise_error(Errno::ENOENT) { |e|
 | 
			
		||||
        e.message.should include(missing_path)
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,11 @@ describe "Integer#<=" do
 | 
			
		|||
      (@bignum <= (@bignum + 0.5)).should == false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns true for bignums compare to a bigger float" do
 | 
			
		||||
      (18446744073709551616 <= 1.8446744073709552e+19).should == true
 | 
			
		||||
      (@bignum <= (@bignum + 9999.0)).should == true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an ArgumentError when given a non-Integer" do
 | 
			
		||||
      -> { @bignum <= "4" }.should raise_error(ArgumentError)
 | 
			
		||||
      -> { @bignum <= mock('str') }.should raise_error(ArgumentError)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,14 @@ describe 'Kernel#caller_locations' do
 | 
			
		|||
    locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ruby_version_is "2.6" do
 | 
			
		||||
    it "works with endless ranges" do
 | 
			
		||||
      locations1 = caller_locations(0)
 | 
			
		||||
      locations2 = caller_locations(eval("(2..)"))
 | 
			
		||||
      locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a range whose end is negative" do
 | 
			
		||||
    locations1 = caller_locations(0)
 | 
			
		||||
    locations2 = caller_locations(2..-1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,4 +43,12 @@ describe 'Kernel#caller' do
 | 
			
		|||
      "#{path}:2:in `block in <main>'\n"
 | 
			
		||||
    ]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ruby_version_is "2.6" do
 | 
			
		||||
    it "works with endless ranges" do
 | 
			
		||||
      locations1 = KernelSpecs::CallerTest.locations(0)
 | 
			
		||||
      locations2 = KernelSpecs::CallerTest.locations(eval("(2..)"))
 | 
			
		||||
      locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -373,4 +373,44 @@ CODE
 | 
			
		|||
      EvalSpecs.send :remove_const, :Vπstring_not_frozen
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "activates refinements from the eval scope" do
 | 
			
		||||
    refinery = Module.new do
 | 
			
		||||
      refine EvalSpecs::A do
 | 
			
		||||
        def foo
 | 
			
		||||
          "bar"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result = nil
 | 
			
		||||
 | 
			
		||||
    Module.new do
 | 
			
		||||
      using refinery
 | 
			
		||||
 | 
			
		||||
      result = eval "EvalSpecs::A.new.foo"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result.should == "bar"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "activates refinements from the binding" do
 | 
			
		||||
    refinery = Module.new do
 | 
			
		||||
      refine EvalSpecs::A do
 | 
			
		||||
        def foo
 | 
			
		||||
          "bar"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    b = nil
 | 
			
		||||
    m = Module.new do
 | 
			
		||||
      using refinery
 | 
			
		||||
      b = binding
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result = eval "EvalSpecs::A.new.foo", b
 | 
			
		||||
 | 
			
		||||
    result.should == "bar"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,12 @@ describe "Module#name" do
 | 
			
		|||
    m::N.name.should =~ /\A#<Module:0x[0-9a-f]+>::N\z/
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "returns nil for a singleton class" do
 | 
			
		||||
    Module.new.singleton_class.name.should be_nil
 | 
			
		||||
    String.singleton_class.name.should be_nil
 | 
			
		||||
    Object.new.singleton_class.name.should be_nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "changes when the module is reachable through a constant path" do
 | 
			
		||||
    m = Module.new
 | 
			
		||||
    module m::N; end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,4 +112,48 @@ describe :module_class_eval, shared: true do
 | 
			
		|||
    a.attribute.should == "A"
 | 
			
		||||
    b.attribute.should == "B"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "activates refinements from the eval scope" do
 | 
			
		||||
    refinery = Module.new do
 | 
			
		||||
      refine ModuleSpecs::NamedClass do
 | 
			
		||||
        def foo
 | 
			
		||||
          "bar"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    mid = @method
 | 
			
		||||
    result = nil
 | 
			
		||||
 | 
			
		||||
    Class.new do
 | 
			
		||||
      using refinery
 | 
			
		||||
 | 
			
		||||
      result = send(mid, "ModuleSpecs::NamedClass.new.foo")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result.should == "bar"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "activates refinements from the eval scope with block" do
 | 
			
		||||
    refinery = Module.new do
 | 
			
		||||
      refine ModuleSpecs::NamedClass do
 | 
			
		||||
        def foo
 | 
			
		||||
          "bar"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    mid = @method
 | 
			
		||||
    result = nil
 | 
			
		||||
 | 
			
		||||
    Class.new do
 | 
			
		||||
      using refinery
 | 
			
		||||
 | 
			
		||||
      result = send(mid) do
 | 
			
		||||
        ModuleSpecs::NamedClass.new.foo
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result.should == "bar"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,5 +15,9 @@ ruby_version_is "2.6" do
 | 
			
		|||
        (o =~ true).should       be_nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "should not warn" do
 | 
			
		||||
      -> { nil =~ /a/ }.should_not complain(verbose: true)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,6 +121,8 @@ describe :string_slice_index_length, shared: true do
 | 
			
		|||
 | 
			
		||||
    "x".send(@method, -2,0).should == nil
 | 
			
		||||
    "x".send(@method, -2,1).should == nil
 | 
			
		||||
 | 
			
		||||
    "x".send(@method, fixnum_max, 1).should == nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "returns nil if the length is negative" do
 | 
			
		||||
| 
						 | 
				
			
			@ -293,6 +295,24 @@ describe :string_slice_range, shared: true do
 | 
			
		|||
    "hello world".send(@method, 6..5).send(@method, -1..-1).should == nil
 | 
			
		||||
    "hello world".send(@method, 6..5).send(@method, 1..1).should == nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "raises a type error if a range is passed with a length" do
 | 
			
		||||
    ->{ "hello".send(@method, 1..2, 1) }.should raise_error(TypeError)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "raises a RangeError if one of the bound is too big" do
 | 
			
		||||
    -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
 | 
			
		||||
    -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ruby_version_is "2.6" do
 | 
			
		||||
    it "works with endless ranges" do
 | 
			
		||||
      "hello there".send(@method, eval("(2..)")).should == "llo there"
 | 
			
		||||
      "hello there".send(@method, eval("(2...)")).should == "llo there"
 | 
			
		||||
      "hello there".send(@method, eval("(-4..)")).should == "here"
 | 
			
		||||
      "hello there".send(@method, eval("(-4...)")).should == "here"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
describe :string_slice_regexp, shared: true do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ describe "Struct.new" do
 | 
			
		|||
    second = nil
 | 
			
		||||
    -> {
 | 
			
		||||
      second = Struct.new('Person', :hair, :sex)
 | 
			
		||||
    }.should complain(/redefining constant/)
 | 
			
		||||
    }.should complain(/constant/)
 | 
			
		||||
    second.should == Struct::Person
 | 
			
		||||
 | 
			
		||||
    first.members.should_not == second.members
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,28 +22,33 @@ describe "Thread#backtrace_locations" do
 | 
			
		|||
  it "can be called with a number of locations to omit" do
 | 
			
		||||
    locations1 = Thread.current.backtrace_locations
 | 
			
		||||
    locations2 = Thread.current.backtrace_locations(2)
 | 
			
		||||
    locations1[2..-1].length.should == locations2.length
 | 
			
		||||
    locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
    locations2.length.should == locations1[2..-1].length
 | 
			
		||||
    locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a maximum number of locations to return as second parameter" do
 | 
			
		||||
    locations1 = Thread.current.backtrace_locations
 | 
			
		||||
    locations2 = Thread.current.backtrace_locations(2, 3)
 | 
			
		||||
    locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
    locations2.map(&:to_s).should == locations1[2..4].map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a range" do
 | 
			
		||||
    locations1 = Thread.current.backtrace_locations
 | 
			
		||||
    locations2 = Thread.current.backtrace_locations(2..4)
 | 
			
		||||
    locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
    locations2.map(&:to_s).should == locations1[2..4].map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a range whose end is negative" do
 | 
			
		||||
    locations1 = Thread.current.backtrace_locations
 | 
			
		||||
    locations2 = Thread.current.backtrace_locations(2..-1)
 | 
			
		||||
    locations3 = Thread.current.backtrace_locations(2..-2)
 | 
			
		||||
    locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
    locations1[2..-2].map(&:to_s).should == locations3.map(&:to_s)
 | 
			
		||||
    Thread.current.backtrace_locations(2..-1).map(&:to_s).should == Thread.current.backtrace_locations[2..-1].map(&:to_s)
 | 
			
		||||
    Thread.current.backtrace_locations(2..-2).map(&:to_s).should == Thread.current.backtrace_locations[2..-2].map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ruby_version_is "2.6" do
 | 
			
		||||
    it "can be called with an endless range" do
 | 
			
		||||
      locations1 = Thread.current.backtrace_locations(0)
 | 
			
		||||
      locations2 = Thread.current.backtrace_locations(eval("(2..)"))
 | 
			
		||||
      locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "returns nil if omitting more locations than available" do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,4 +32,38 @@ describe "Thread#backtrace" do
 | 
			
		|||
    t.join
 | 
			
		||||
    backtrace.should be_kind_of(Array)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a number of locations to omit" do
 | 
			
		||||
    locations1 = Thread.current.backtrace
 | 
			
		||||
    locations2 = Thread.current.backtrace(2)
 | 
			
		||||
    locations1[2..-1].length.should == locations2.length
 | 
			
		||||
    locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a maximum number of locations to return as second parameter" do
 | 
			
		||||
    locations1 = Thread.current.backtrace
 | 
			
		||||
    locations2 = Thread.current.backtrace(2, 3)
 | 
			
		||||
    locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a range" do
 | 
			
		||||
    locations1 = Thread.current.backtrace
 | 
			
		||||
    locations2 = Thread.current.backtrace(2..4)
 | 
			
		||||
    locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "can be called with a range whose end is negative" do
 | 
			
		||||
    Thread.current.backtrace(2..-1).should == Thread.current.backtrace[2..-1]
 | 
			
		||||
    Thread.current.backtrace(2..-2).should == Thread.current.backtrace[2..-2]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "returns nil if omitting more locations than available" do
 | 
			
		||||
    Thread.current.backtrace(100).should == nil
 | 
			
		||||
    Thread.current.backtrace(100..-1).should == nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "returns [] if omitting exactly the number of locations available" do
 | 
			
		||||
    omit = Thread.current.backtrace.length
 | 
			
		||||
    Thread.current.backtrace(omit).should == []
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,10 +36,11 @@ ruby_version_is "2.7" do
 | 
			
		|||
    it "copies own timezone to the returning value" do
 | 
			
		||||
      @time.zone.should == @time.ceil.zone
 | 
			
		||||
 | 
			
		||||
      with_timezone "JST-9" do
 | 
			
		||||
        time = Time.at 0, 1
 | 
			
		||||
        time.zone.should == time.ceil.zone
 | 
			
		||||
      time = with_timezone "JST-9" do
 | 
			
		||||
        Time.at 0, 1
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      time.zone.should == time.ceil.zone
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,10 +28,11 @@ ruby_version_is "2.7" do
 | 
			
		|||
    it "copies own timezone to the returning value" do
 | 
			
		||||
      @time.zone.should == @time.floor.zone
 | 
			
		||||
 | 
			
		||||
      with_timezone "JST-9" do
 | 
			
		||||
        time = Time.at 0, 1
 | 
			
		||||
        time.zone.should == time.floor.zone
 | 
			
		||||
      time = with_timezone "JST-9" do
 | 
			
		||||
        Time.at 0, 1
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      time.zone.should == time.floor.zone
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										41
									
								
								spec/ruby/language/delegation_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								spec/ruby/language/delegation_spec.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
require_relative '../spec_helper'
 | 
			
		||||
require_relative 'fixtures/delegation'
 | 
			
		||||
 | 
			
		||||
ruby_version_is "2.7" do
 | 
			
		||||
  describe "delegation with def(...)" do
 | 
			
		||||
    it "delegates rest and kwargs" do
 | 
			
		||||
      a = Class.new(DelegationSpecs::Target)
 | 
			
		||||
      a.class_eval(<<-RUBY)
 | 
			
		||||
        def delegate(...)
 | 
			
		||||
          target(...)
 | 
			
		||||
        end
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      a.new.delegate(1, b: 2).should == [[1], {b: 2}]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "delegates block" do
 | 
			
		||||
      a = Class.new(DelegationSpecs::Target)
 | 
			
		||||
      a.class_eval(<<-RUBY)
 | 
			
		||||
        def delegate_block(...)
 | 
			
		||||
          target_block(...)
 | 
			
		||||
        end
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "parses as open endless Range when brackets are ommitted" do
 | 
			
		||||
      a = Class.new(DelegationSpecs::Target)
 | 
			
		||||
      suppress_warning do
 | 
			
		||||
        a.class_eval(<<-RUBY)
 | 
			
		||||
          def delegate(...)
 | 
			
		||||
            target ...
 | 
			
		||||
          end
 | 
			
		||||
         RUBY
 | 
			
		||||
       end
 | 
			
		||||
 | 
			
		||||
       a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										11
									
								
								spec/ruby/language/fixtures/delegation.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								spec/ruby/language/fixtures/delegation.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
module DelegationSpecs
 | 
			
		||||
  class Target
 | 
			
		||||
    def target(*args, **kwargs)
 | 
			
		||||
      [args, kwargs]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def target_block(*args, **kwargs)
 | 
			
		||||
      yield [kwargs, args]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +402,17 @@ ruby_version_is "2.7" do
 | 
			
		|||
          RUBY
 | 
			
		||||
        }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it "support undescore prefixed variables in alternation" do
 | 
			
		||||
        eval(<<~RUBY).should == true
 | 
			
		||||
          case [0, 1]
 | 
			
		||||
            in [1, _]
 | 
			
		||||
              false
 | 
			
		||||
            in [0, 0] | [0, _a]
 | 
			
		||||
              true
 | 
			
		||||
          end
 | 
			
		||||
        RUBY
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    describe "AS pattern" do
 | 
			
		||||
| 
						 | 
				
			
			@ -962,5 +973,79 @@ ruby_version_is "2.7" do
 | 
			
		|||
        RUBY
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    describe "refinements" do
 | 
			
		||||
      it "are used for #deconstruct" do
 | 
			
		||||
        refinery = Module.new do
 | 
			
		||||
          refine Array do
 | 
			
		||||
            def deconstruct
 | 
			
		||||
              [0]
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result = nil
 | 
			
		||||
        Module.new do
 | 
			
		||||
          using refinery
 | 
			
		||||
 | 
			
		||||
          result = eval(<<~RUBY)
 | 
			
		||||
            case []
 | 
			
		||||
              in [0]
 | 
			
		||||
                true
 | 
			
		||||
            end
 | 
			
		||||
          RUBY
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result.should == true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it "are used for #deconstruct_keys" do
 | 
			
		||||
        refinery = Module.new do
 | 
			
		||||
          refine Hash do
 | 
			
		||||
            def deconstruct_keys(_)
 | 
			
		||||
              {a: 0}
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result = nil
 | 
			
		||||
        Module.new do
 | 
			
		||||
          using refinery
 | 
			
		||||
 | 
			
		||||
          result = eval(<<~RUBY)
 | 
			
		||||
            case {}
 | 
			
		||||
              in a: 0
 | 
			
		||||
                true
 | 
			
		||||
            end
 | 
			
		||||
          RUBY
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result.should == true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it "are used for #=== in constant pattern" do
 | 
			
		||||
        refinery = Module.new do
 | 
			
		||||
          refine Array.singleton_class do
 | 
			
		||||
            def ===(obj)
 | 
			
		||||
              obj.is_a?(Hash)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result = nil
 | 
			
		||||
        Module.new do
 | 
			
		||||
          using refinery
 | 
			
		||||
 | 
			
		||||
          result = eval(<<~RUBY)
 | 
			
		||||
            case {}
 | 
			
		||||
              in Array
 | 
			
		||||
                true
 | 
			
		||||
            end
 | 
			
		||||
          RUBY
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result.should == true
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -354,6 +354,16 @@ describe "Multiple assignment" do
 | 
			
		|||
      a.should be_an_instance_of(Array)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "unfreezes the array returned from calling 'to_a' on the splatted value" do
 | 
			
		||||
      obj = Object.new
 | 
			
		||||
      def obj.to_a
 | 
			
		||||
        [1,2].freeze
 | 
			
		||||
      end
 | 
			
		||||
      res = *obj
 | 
			
		||||
      res.should == [1,2]
 | 
			
		||||
      res.frozen?.should == false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "consumes values for an anonymous splat" do
 | 
			
		||||
      a = 1
 | 
			
		||||
      (* = *a).should == [1]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,10 @@ describe "CGI.escapeHTML" do
 | 
			
		|||
    CGI.escapeHTML(%[& < > " ']).should == '& < > " ''
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "escapes invalid encoding" do
 | 
			
		||||
    CGI.escapeHTML(%[<\xA4??>]).should == "<\xA4??>"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "does not escape any other characters" do
 | 
			
		||||
    chars = " !\#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
 | 
			
		||||
    CGI.escapeHTML(chars).should == chars
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,4 +6,18 @@ describe "StringIO#binmode" do
 | 
			
		|||
    io = StringIO.new("example")
 | 
			
		||||
    io.binmode.should equal(io)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "changes external encoding to BINARY" do
 | 
			
		||||
    io = StringIO.new
 | 
			
		||||
    io.external_encoding.should == Encoding.find('locale')
 | 
			
		||||
    io.binmode
 | 
			
		||||
    io.external_encoding.should == Encoding::BINARY
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "does not set internal encoding" do
 | 
			
		||||
    io = StringIO.new
 | 
			
		||||
    io.internal_encoding.should == nil
 | 
			
		||||
    io.binmode
 | 
			
		||||
    io.internal_encoding.should == nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								spec/ruby/library/stringio/inspect_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								spec/ruby/library/stringio/inspect_spec.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require "stringio"
 | 
			
		||||
 | 
			
		||||
describe "StringIO#inspect" do
 | 
			
		||||
  it "returns the same as #to_s" do
 | 
			
		||||
    io = StringIO.new("example")
 | 
			
		||||
    io.inspect.should == io.to_s
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "does not include the contents" do
 | 
			
		||||
    io = StringIO.new("contents")
 | 
			
		||||
    io.inspect.should_not include("contents")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "uses the regular Object#inspect without any instance variable" do
 | 
			
		||||
    io = StringIO.new("example")
 | 
			
		||||
    io.inspect.should =~ /\A#<StringIO:0x\h+>\z/
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
require_relative '../../spec_helper'
 | 
			
		||||
require_relative 'fixtures/common'
 | 
			
		||||
| 
						 | 
				
			
			@ -8,9 +8,6 @@ specs:
 | 
			
		|||
    optional/capi/array_spec.rb
 | 
			
		||||
2.  Put the C file containing the C functions for array_spec.rb in
 | 
			
		||||
    optional/capi/ext/array_spec.c
 | 
			
		||||
3.  Add a '#define HAVE_RB_ARY_NEW  1' to rubyspec.h
 | 
			
		||||
4.  Name the C extension class 'CApiArraySpecs'.
 | 
			
		||||
5.  Name the C functions 'array_spec_rb_ary_new'.
 | 
			
		||||
6.  Wrap the code in the optional/capi/ext/array_spec.c in
 | 
			
		||||
    '#ifdef HAVE_RB_ARY_NEW'
 | 
			
		||||
7.  Attach the C function to the class using the name 'rb_ary_new'
 | 
			
		||||
3.  Name the C extension class 'CApiArraySpecs'.
 | 
			
		||||
4.  Name the C functions 'array_spec_rb_ary_new'.
 | 
			
		||||
5.  Attach the C function to the class using the name 'rb_ary_new'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -272,6 +272,16 @@ describe "C-API Array function" do
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "RARRAY_ASET" do
 | 
			
		||||
    # This macro does NOT do any bounds checking!
 | 
			
		||||
    it "writes an element in the array" do
 | 
			
		||||
      ary = [1, 2, 3]
 | 
			
		||||
      @s.RARRAY_ASET(ary, 0, 0)
 | 
			
		||||
      @s.RARRAY_ASET(ary, 2, 42)
 | 
			
		||||
      ary.should == [0, 2, 42]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "rb_assoc_new" do
 | 
			
		||||
    it "returns an array containing the two elements" do
 | 
			
		||||
      @s.rb_assoc_new(1, 2).should == [1, 2]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,11 @@ static VALUE array_spec_RARRAY_AREF(VALUE self, VALUE array, VALUE index) {
 | 
			
		|||
  return RARRAY_AREF(array, FIX2INT(index));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE array_spec_RARRAY_ASET(VALUE self, VALUE array, VALUE index, VALUE value) {
 | 
			
		||||
  RARRAY_ASET(array, FIX2INT(index), value);
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE array_spec_rb_ary_aref(int argc, VALUE *argv, VALUE self) {
 | 
			
		||||
  VALUE ary, args;
 | 
			
		||||
  rb_scan_args(argc, argv, "1*", &ary, &args);
 | 
			
		||||
| 
						 | 
				
			
			@ -244,6 +249,7 @@ void Init_array_spec(void) {
 | 
			
		|||
  rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2);
 | 
			
		||||
  rb_define_method(cls, "RARRAY_PTR_memcpy", array_spec_RARRAY_PTR_memcpy, 2);
 | 
			
		||||
  rb_define_method(cls, "RARRAY_AREF", array_spec_RARRAY_AREF, 2);
 | 
			
		||||
  rb_define_method(cls, "RARRAY_ASET", array_spec_RARRAY_ASET, 3);
 | 
			
		||||
  rb_define_method(cls, "rb_ary_aref", array_spec_rb_ary_aref, -1);
 | 
			
		||||
  rb_define_method(cls, "rb_ary_clear", array_spec_rb_ary_clear, 1);
 | 
			
		||||
  rb_define_method(cls, "rb_ary_delete", array_spec_rb_ary_delete, 2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,7 +65,7 @@ static VALUE bignum_spec_rb_big_pack_array(VALUE self, VALUE val, VALUE len) {
 | 
			
		|||
  long long_len = NUM2LONG(len);
 | 
			
		||||
 | 
			
		||||
  VALUE ary = rb_ary_new_capa(long_len);
 | 
			
		||||
  unsigned long *buf = malloc(long_len * SIZEOF_LONG);
 | 
			
		||||
  unsigned long *buf = (unsigned long*) malloc(long_len * SIZEOF_LONG);
 | 
			
		||||
 | 
			
		||||
  /* The array should be filled with recognisable junk so we can check
 | 
			
		||||
     it is all cleared properly. */
 | 
			
		||||
| 
						 | 
				
			
			@ -102,5 +102,5 @@ void Init_bignum_spec(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,5 +29,5 @@ void Init_boolean_spec(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,13 @@
 | 
			
		|||
#include "ruby.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void Init_class_id_under_autoload_spec(void) {
 | 
			
		||||
  rb_define_class_id_under(rb_cObject, rb_intern("ClassIdUnderAutoload"), rb_cObject);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ static VALUE class_spec_rb_class_new_instance(VALUE self,
 | 
			
		|||
                                      VALUE nargs, VALUE args,
 | 
			
		||||
                                      VALUE klass) {
 | 
			
		||||
  int c_nargs = FIX2INT(nargs);
 | 
			
		||||
  VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
 | 
			
		||||
  VALUE *c_args = (VALUE*)alloca(sizeof(VALUE) * c_nargs);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < c_nargs; i++)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,13 @@
 | 
			
		|||
#include "ruby.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void Init_class_under_autoload_spec(void) {
 | 
			
		||||
  rb_define_class_under(rb_cObject, "ClassUnderAutoload", rb_cObject);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ void sample_wrapped_struct_mark(void* st) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
VALUE sdaf_alloc_func(VALUE klass) {
 | 
			
		||||
  struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  bar->foo = 42;
 | 
			
		||||
  return Data_Wrap_Struct(klass, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ VALUE sdaf_get_struct(VALUE self) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_wrap_struct(VALUE self, VALUE val) {
 | 
			
		||||
  struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  bar->foo = FIX2INT(val);
 | 
			
		||||
  return Data_Wrap_Struct(rb_cObject, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +58,9 @@ VALUE sws_get_struct_data_ptr(VALUE self, VALUE obj) {
 | 
			
		|||
 | 
			
		||||
VALUE sws_change_struct(VALUE self, VALUE obj, VALUE new_val) {
 | 
			
		||||
  struct sample_wrapped_struct *old_struct, *new_struct;
 | 
			
		||||
  new_struct = malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  new_struct = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
 | 
			
		||||
  new_struct->foo = FIX2INT(new_val);
 | 
			
		||||
  old_struct = RDATA(obj)->data;
 | 
			
		||||
  old_struct = (struct sample_wrapped_struct*) RDATA(obj)->data;
 | 
			
		||||
  free(old_struct);
 | 
			
		||||
  RDATA(obj)->data = new_struct;
 | 
			
		||||
  return Qnil;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,15 +16,15 @@ static VALUE registered_reference_address(VALUE self) {
 | 
			
		|||
  return registered_reference_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE gc_spec_rb_gc_enable() {
 | 
			
		||||
static VALUE gc_spec_rb_gc_enable(VALUE self) {
 | 
			
		||||
  return rb_gc_enable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE gc_spec_rb_gc_disable() {
 | 
			
		||||
static VALUE gc_spec_rb_gc_disable(VALUE self) {
 | 
			
		||||
  return rb_gc_disable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE gc_spec_rb_gc() {
 | 
			
		||||
static VALUE gc_spec_rb_gc(VALUE self) {
 | 
			
		||||
  rb_gc();
 | 
			
		||||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,16 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
VALUE g_hooked_var;
 | 
			
		||||
 | 
			
		||||
VALUE var_2x_getter(ID id, VALUE *data) {
 | 
			
		||||
  return *data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void var_2x_setter(VALUE val, ID id, VALUE *var) {
 | 
			
		||||
    *var = INT2NUM(NUM2INT(val) * 2);
 | 
			
		||||
  *var = INT2NUM(NUM2INT(val) * 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE sb_define_hooked_variable(VALUE self, VALUE var_name) {
 | 
			
		||||
  rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, 0, var_2x_setter);
 | 
			
		||||
  rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, var_2x_getter, var_2x_setter);
 | 
			
		||||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,5 +30,5 @@ void Init_integer_spec(void) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ VALUE io_spec_rb_io_addstr(VALUE self, VALUE io, VALUE str) {
 | 
			
		|||
 | 
			
		||||
VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) {
 | 
			
		||||
  long argc = RARRAY_LEN(ary);
 | 
			
		||||
  VALUE *argv = alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < argc; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) {
 | 
			
		|||
 | 
			
		||||
VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) {
 | 
			
		||||
  long argc = RARRAY_LEN(ary);
 | 
			
		||||
  VALUE *argv = alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < argc; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) {
 | 
			
		|||
 | 
			
		||||
VALUE io_spec_rb_io_puts(VALUE self, VALUE io, VALUE ary) {
 | 
			
		||||
  long argc = RARRAY_LEN(ary);
 | 
			
		||||
  VALUE *argv = alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < argc; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ VALUE rb_block_call_extra_data(VALUE self, VALUE object) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
VALUE kernel_spec_rb_block_call_no_func(VALUE self, VALUE ary) {
 | 
			
		||||
  return rb_block_call(ary, rb_intern("map"), 0, NULL, NULL, Qnil);
 | 
			
		||||
  return rb_block_call(ary, rb_intern("map"), 0, NULL, (rb_block_call_func_t)NULL, Qnil);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,6 +153,10 @@ VALUE kernel_spec_rb_rescue(VALUE self, VALUE main_proc, VALUE arg,
 | 
			
		|||
  rb_ary_push(main_array, main_proc);
 | 
			
		||||
  rb_ary_push(main_array, arg);
 | 
			
		||||
 | 
			
		||||
  if (raise_proc == Qnil) {
 | 
			
		||||
    return rb_rescue(kernel_spec_call_proc, main_array, NULL, arg2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  raise_array = rb_ary_new();
 | 
			
		||||
  rb_ary_push(raise_array, raise_proc);
 | 
			
		||||
  rb_ary_push(raise_array, arg2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								spec/ruby/optional/capi/ext/language_spec.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								spec/ruby/optional/capi/ext/language_spec.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
#include "ruby.h"
 | 
			
		||||
#include "rubyspec.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static VALUE language_spec_switch(VALUE self, VALUE value) {
 | 
			
		||||
  if (value == ID2SYM(rb_intern("undef"))) {
 | 
			
		||||
    value = Qundef;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (value) {
 | 
			
		||||
    case Qtrue:
 | 
			
		||||
      return ID2SYM(rb_intern("true"));
 | 
			
		||||
    case Qfalse:
 | 
			
		||||
      return ID2SYM(rb_intern("false"));
 | 
			
		||||
    case Qnil:
 | 
			
		||||
      return ID2SYM(rb_intern("nil"));
 | 
			
		||||
    case Qundef:
 | 
			
		||||
      return ID2SYM(rb_intern("undef"));
 | 
			
		||||
    default:
 | 
			
		||||
      return ID2SYM(rb_intern("default"));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init_language_spec(void) {
 | 
			
		||||
  VALUE cls = rb_define_class("CApiLanguageSpecs", rb_cObject);
 | 
			
		||||
  rb_define_method(cls, "switch", language_spec_switch, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,15 @@
 | 
			
		|||
#include "ruby.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void Init_module_under_autoload_spec(void) {
 | 
			
		||||
  VALUE specs = rb_const_get(rb_cObject, rb_intern("CApiModuleSpecs"));
 | 
			
		||||
  rb_define_module_under(specs, "ModuleUnderAutoload");
 | 
			
		||||
  rb_define_module_under(specs, "RubyUnderAutoload");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,10 @@ static VALUE numeric_spec_NUM2LONG(VALUE self, VALUE num) {
 | 
			
		|||
  return LONG2NUM(NUM2LONG(num));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE numeric_spec_NUM2SHORT(VALUE self, VALUE num) {
 | 
			
		||||
  return LONG2NUM(NUM2SHORT(num));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE numeric_spec_NUM2UINT(VALUE self, VALUE num) {
 | 
			
		||||
  return ULONG2NUM(NUM2UINT(num));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +113,7 @@ void Init_numeric_spec(void) {
 | 
			
		|||
  rb_define_method(cls, "NUM2DBL", numeric_spec_NUM2DBL, 1);
 | 
			
		||||
  rb_define_method(cls, "NUM2INT", numeric_spec_NUM2INT, 1);
 | 
			
		||||
  rb_define_method(cls, "NUM2LONG", numeric_spec_NUM2LONG, 1);
 | 
			
		||||
  rb_define_method(cls, "NUM2SHORT", numeric_spec_NUM2SHORT, 1);
 | 
			
		||||
  rb_define_method(cls, "INT2NUM", numeric_spec_INT2NUM, 1);
 | 
			
		||||
  rb_define_method(cls, "NUM2UINT", numeric_spec_NUM2UINT, 1);
 | 
			
		||||
  rb_define_method(cls, "NUM2ULONG", numeric_spec_NUM2ULONG, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -102,7 +102,7 @@ static VALUE so_rb_obj_dup(VALUE self, VALUE klass) {
 | 
			
		|||
static VALUE so_rb_obj_call_init(VALUE self, VALUE object,
 | 
			
		||||
                                 VALUE nargs, VALUE args) {
 | 
			
		||||
  int c_nargs = FIX2INT(nargs);
 | 
			
		||||
  VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
 | 
			
		||||
  VALUE *c_args = (VALUE*) alloca(sizeof(VALUE) * c_nargs);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < c_nargs; i++)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,10 @@ VALUE proc_spec_rb_proc_call(VALUE self, VALUE prc, VALUE args) {
 | 
			
		|||
  return rb_proc_call(prc, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE proc_spec_rb_obj_is_proc(VALUE self, VALUE prc) {
 | 
			
		||||
  return rb_obj_is_proc(prc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This helper is not strictly necessary but reflects the code in wxRuby that
 | 
			
		||||
 * originally exposed issues with this Proc.new behavior.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +65,7 @@ void Init_proc_spec(void) {
 | 
			
		|||
  rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1);
 | 
			
		||||
  rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2);
 | 
			
		||||
  rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
 | 
			
		||||
  rb_define_method(cls, "rb_obj_is_proc", proc_spec_rb_obj_is_proc, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,10 @@
 | 
			
		|||
   (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \
 | 
			
		||||
   (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny)))
 | 
			
		||||
 | 
			
		||||
#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 7)
 | 
			
		||||
#define RUBY_VERSION_IS_2_7
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 6)
 | 
			
		||||
#define RUBY_VERSION_IS_2_6
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -31,4 +35,26 @@
 | 
			
		|||
#define RUBY_VERSION_IS_2_4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus) && !defined(RUBY_VERSION_IS_2_7)
 | 
			
		||||
/* Ruby < 2.7 needs this to let these function with callbacks and compile in C++ code */
 | 
			
		||||
#define rb_define_method(mod, name, func, argc) rb_define_method(mod, name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_define_protected_method(mod, name, func, argc) rb_define_protected_method(mod, name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_define_private_method(mod, name, func, argc) rb_define_private_method(mod, name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_define_singleton_method(mod, name, func, argc) rb_define_singleton_method(mod, name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_define_module_function(mod, name, func, argc) rb_define_module_function(mod, name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_define_global_function(name, func, argc) rb_define_global_function(name, RUBY_METHOD_FUNC(func), argc)
 | 
			
		||||
#define rb_iterate(function, arg1, block, arg2) rb_iterate(function, arg1, RUBY_METHOD_FUNC(block), arg2)
 | 
			
		||||
#define rb_hash_foreach(hash, func, farg) rb_hash_foreach(hash, (int (*)(...))func, farg)
 | 
			
		||||
#define st_foreach(tab, func, arg) st_foreach(tab, (int (*)(...))func, arg)
 | 
			
		||||
#define rb_block_call(object, name, args_count, args, block_call_func, data) rb_block_call(object, name, args_count, args, RUBY_METHOD_FUNC(block_call_func), data)
 | 
			
		||||
#define rb_ensure(b_proc, data1, e_proc, data2) rb_ensure(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
 | 
			
		||||
#define rb_rescue(b_proc, data1, e_proc, data2) rb_rescue(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
 | 
			
		||||
#define rb_rescue2(b_proc, data1, e_proc, data2, ...) rb_rescue2(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2, __VA_ARGS__)
 | 
			
		||||
#define rb_catch(tag, func, data) rb_catch(tag, RUBY_METHOD_FUNC(func), data)
 | 
			
		||||
#define rb_catch_obj(tag, func, data) rb_catch_obj(tag, RUBY_METHOD_FUNC(func), data)
 | 
			
		||||
#define rb_proc_new(fn, arg) rb_proc_new(RUBY_METHOD_FUNC(fn), arg)
 | 
			
		||||
#define rb_thread_create(fn, arg) rb_thread_create(RUBY_METHOD_FUNC(fn), arg)
 | 
			
		||||
#define rb_define_hooked_variable(name, var, getter, setter) rb_define_hooked_variable(name, var, RUBY_METHOD_FUNC(getter), (void (*)(...))setter)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -284,6 +284,26 @@ VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) {
 | 
			
		|||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE string_spec_RSTRING_PTR_iterate_uint32(VALUE self, VALUE str) {
 | 
			
		||||
  int i;
 | 
			
		||||
  uint32_t* ptr;
 | 
			
		||||
  int l = RSTRING_LEN(str) / sizeof(uint32_t);
 | 
			
		||||
 | 
			
		||||
  ptr = (uint32_t *)RSTRING_PTR(str);
 | 
			
		||||
  for(i = 0; i < l; i++) {
 | 
			
		||||
    rb_yield(UINT2NUM(ptr[i]));
 | 
			
		||||
  }
 | 
			
		||||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE string_spec_RSTRING_PTR_short_memcpy(VALUE self, VALUE str) {
 | 
			
		||||
  // Short memcpy operations may be optimised by the compiler to a single write.
 | 
			
		||||
  if (RSTRING_LEN(str) >= 8) {
 | 
			
		||||
    memcpy(RSTRING_PTR(str), "Infinity", 8);
 | 
			
		||||
  }
 | 
			
		||||
  return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) {
 | 
			
		||||
  int i;
 | 
			
		||||
  char c;
 | 
			
		||||
| 
						 | 
				
			
			@ -362,11 +382,11 @@ static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE r
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static VALUE string_spec_rb_sprintf3(VALUE self, VALUE str) {
 | 
			
		||||
  return rb_sprintf("Result: %"PRIsVALUE".", str);
 | 
			
		||||
  return rb_sprintf("Result: %" PRIsVALUE ".", str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE string_spec_rb_sprintf4(VALUE self, VALUE str) {
 | 
			
		||||
  return rb_sprintf("Result: %+"PRIsVALUE".", str);
 | 
			
		||||
  return rb_sprintf("Result: %+" PRIsVALUE ".", str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) {
 | 
			
		||||
| 
						 | 
				
			
			@ -477,6 +497,8 @@ void Init_string_spec(void) {
 | 
			
		|||
  rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_iterate_uint32", string_spec_RSTRING_PTR_iterate_uint32, 1);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_short_memcpy", string_spec_RSTRING_PTR_short_memcpy, 1);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_set", string_spec_RSTRING_PTR_set, 3);
 | 
			
		||||
  rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,10 @@
 | 
			
		|||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
VALUE symbol_spec_SYMBOL_P(VALUE self, VALUE obj) {
 | 
			
		||||
  return SYMBOL_P(obj) ? Qtrue : Qfalse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE symbol_spec_rb_intern(VALUE self, VALUE string) {
 | 
			
		||||
  return ID2SYM(rb_intern(RSTRING_PTR(string)));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +77,7 @@ VALUE symbol_spec_rb_sym2str(VALUE self, VALUE sym) {
 | 
			
		|||
 | 
			
		||||
void Init_symbol_spec(void) {
 | 
			
		||||
  VALUE cls = rb_define_class("CApiSymbolSpecs", rb_cObject);
 | 
			
		||||
  rb_define_method(cls, "SYMBOL_P", symbol_spec_SYMBOL_P, 1);
 | 
			
		||||
  rb_define_method(cls, "rb_intern", symbol_spec_rb_intern, 1);
 | 
			
		||||
  rb_define_method(cls, "rb_intern2", symbol_spec_rb_intern2, 2);
 | 
			
		||||
  rb_define_method(cls, "rb_intern_const", symbol_spec_rb_intern_const, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@
 | 
			
		|||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static VALUE thread_spec_rb_thread_alone() {
 | 
			
		||||
static VALUE thread_spec_rb_thread_alone(VALUE self) {
 | 
			
		||||
  return rb_thread_alone() ? Qtrue : Qfalse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +89,7 @@ static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) {
 | 
			
		|||
  return (VALUE)ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE thread_spec_rb_thread_current() {
 | 
			
		||||
static VALUE thread_spec_rb_thread_current(VALUE self) {
 | 
			
		||||
  return rb_thread_current();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
struct sample_typed_wrapped_struct_parent {
 | 
			
		||||
    int foo;
 | 
			
		||||
  int foo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void sample_typed_wrapped_struct_parent_free(void* st) {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_parent_data_type = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct sample_typed_wrapped_struct {
 | 
			
		||||
    int foo;
 | 
			
		||||
  int foo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void sample_typed_wrapped_struct_free(void* st) {
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_data_type = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct sample_typed_wrapped_struct_other {
 | 
			
		||||
    int foo;
 | 
			
		||||
  int foo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void sample_typed_wrapped_struct_other_free(void* st) {
 | 
			
		||||
| 
						 | 
				
			
			@ -86,43 +86,45 @@ static const rb_data_type_t sample_typed_wrapped_struct_other_data_type = {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
VALUE sdaf_alloc_typed_func(VALUE klass) {
 | 
			
		||||
    struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
    bar->foo = 42;
 | 
			
		||||
    return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
  bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
  bar->foo = 42;
 | 
			
		||||
  return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sdaf_typed_get_struct(VALUE self) {
 | 
			
		||||
    struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
    TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
  TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
 | 
			
		||||
    return INT2FIX((*bar).foo);
 | 
			
		||||
  return INT2FIX((*bar).foo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_wrap_struct(VALUE self, VALUE val) {
 | 
			
		||||
    struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
    bar->foo = FIX2INT(val);
 | 
			
		||||
    return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
  bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
  bar->foo = FIX2INT(val);
 | 
			
		||||
  return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_get_struct(VALUE self, VALUE obj) {
 | 
			
		||||
    struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
    TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct* bar;
 | 
			
		||||
  TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
 | 
			
		||||
 | 
			
		||||
    return INT2FIX((*bar).foo);
 | 
			
		||||
  return INT2FIX((*bar).foo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_get_struct_different_type(VALUE self, VALUE obj) {
 | 
			
		||||
    struct sample_typed_wrapped_struct_other* bar;
 | 
			
		||||
    TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct_other* bar;
 | 
			
		||||
  TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar);
 | 
			
		||||
 | 
			
		||||
    return INT2FIX((*bar).foo);
 | 
			
		||||
  return INT2FIX((*bar).foo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_get_struct_parent_type(VALUE self, VALUE obj) {
 | 
			
		||||
    struct sample_typed_wrapped_struct_parent* bar;
 | 
			
		||||
    TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar);
 | 
			
		||||
  struct sample_typed_wrapped_struct_parent* bar;
 | 
			
		||||
  TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar);
 | 
			
		||||
 | 
			
		||||
    return INT2FIX((*bar).foo);
 | 
			
		||||
  return INT2FIX((*bar).foo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_get_struct_rdata(VALUE self, VALUE obj) {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,11 +140,10 @@ VALUE sws_typed_get_struct_data_ptr(VALUE self, VALUE obj) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
VALUE sws_typed_change_struct(VALUE self, VALUE obj, VALUE new_val) {
 | 
			
		||||
  struct sample_typed_wrapped_struct *old_struct, *new_struct;
 | 
			
		||||
  new_struct = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
  struct sample_typed_wrapped_struct *new_struct;
 | 
			
		||||
  new_struct = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
 | 
			
		||||
  new_struct->foo = FIX2INT(new_val);
 | 
			
		||||
  old_struct = RTYPEDDATA(obj)->data;
 | 
			
		||||
  free(old_struct);
 | 
			
		||||
  free(RTYPEDDATA(obj)->data);
 | 
			
		||||
  RTYPEDDATA(obj)->data = new_struct;
 | 
			
		||||
  return Qnil;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,8 +60,8 @@ static VALUE util_spec_rb_get_kwargs(VALUE self, VALUE keyword_hash, VALUE keys,
 | 
			
		|||
  int values_len = req + (opt < 0 ? -1 - opt : opt);
 | 
			
		||||
  int i = 0;
 | 
			
		||||
 | 
			
		||||
  ID *ids = malloc(sizeof(VALUE) * len);
 | 
			
		||||
  VALUE *results = malloc(sizeof(VALUE) * values_len);
 | 
			
		||||
  ID *ids = (ID*) malloc(sizeof(VALUE) * len);
 | 
			
		||||
  VALUE *results = (VALUE*) malloc(sizeof(VALUE) * values_len);
 | 
			
		||||
  int extracted = 0;
 | 
			
		||||
  VALUE ary = Qundef;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -261,28 +261,28 @@ describe "C-API Kernel function" do
 | 
			
		|||
  describe "rb_protect" do
 | 
			
		||||
    it "will run a function with an argument" do
 | 
			
		||||
      proof = [] # Hold proof of work performed after the yield.
 | 
			
		||||
      res = @s.rb_protect_yield(7, proof) { |x| x + 1 }
 | 
			
		||||
      res.should == 8
 | 
			
		||||
      res = @s.rb_protect_yield(77, proof) { |x| x + 1 }
 | 
			
		||||
      res.should == 78
 | 
			
		||||
      proof[0].should == 23
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "will allow cleanup code to run after break" do
 | 
			
		||||
      proof = [] # Hold proof of work performed after the yield.
 | 
			
		||||
      @s.rb_protect_yield(7, proof) { |x| break }
 | 
			
		||||
      @s.rb_protect_yield(77, proof) { |x| break }
 | 
			
		||||
      proof[0].should == 23
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "will allow cleanup code to run after break with value" do
 | 
			
		||||
      proof = [] # Hold proof of work performed after the yield.
 | 
			
		||||
      res = @s.rb_protect_yield(7, proof) { |x| break x + 1 }
 | 
			
		||||
      res.should == 8
 | 
			
		||||
      res = @s.rb_protect_yield(77, proof) { |x| break x + 1 }
 | 
			
		||||
      res.should == 78
 | 
			
		||||
      proof[0].should == 23
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "will allow cleanup code to run after a raise" do
 | 
			
		||||
      proof = [] # Hold proof of work performed after the yield.
 | 
			
		||||
      -> do
 | 
			
		||||
        @s.rb_protect_yield(7, proof) { |x| raise NameError}
 | 
			
		||||
        @s.rb_protect_yield(77, proof) { |x| raise NameError}
 | 
			
		||||
      end.should raise_error(NameError)
 | 
			
		||||
      proof[0].should == 23
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +290,7 @@ describe "C-API Kernel function" do
 | 
			
		|||
    it "will return nil if an error was raised" do
 | 
			
		||||
      proof = [] # Hold proof of work performed after the yield.
 | 
			
		||||
      -> do
 | 
			
		||||
        @s.rb_protect_yield(7, proof) { |x| raise NameError}
 | 
			
		||||
        @s.rb_protect_yield(77, proof) { |x| raise NameError}
 | 
			
		||||
      end.should raise_error(NameError)
 | 
			
		||||
      proof[0].should == 23
 | 
			
		||||
      proof[1].should == nil
 | 
			
		||||
| 
						 | 
				
			
			@ -316,47 +316,47 @@ describe "C-API Kernel function" do
 | 
			
		|||
  describe "rb_rescue" do
 | 
			
		||||
    before :each do
 | 
			
		||||
      @proc = -> x { x }
 | 
			
		||||
      @raise_proc_returns_sentinel = -> *_ { :raise_proc_executed }
 | 
			
		||||
      @raise_proc_returns_arg = -> *a { a }
 | 
			
		||||
      @rescue_proc_returns_sentinel = -> *_ { :rescue_proc_executed }
 | 
			
		||||
      @rescue_proc_returns_arg = -> *a { a }
 | 
			
		||||
      @arg_error_proc = -> *_ { raise ArgumentError, '' }
 | 
			
		||||
      @std_error_proc = -> *_ { raise StandardError, '' }
 | 
			
		||||
      @exc_error_proc = -> *_ { raise Exception, '' }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "executes passed function" do
 | 
			
		||||
      @s.rb_rescue(@proc, :no_exc, @raise_proc_returns_arg, :exc).should == :no_exc
 | 
			
		||||
      @s.rb_rescue(@proc, :no_exc, @rescue_proc_returns_arg, :exc).should == :no_exc
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "executes passed 'raise function' if a StandardError exception is raised" do
 | 
			
		||||
      @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed
 | 
			
		||||
      @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed
 | 
			
		||||
    it "executes the passed 'rescue function' if a StandardError exception is raised" do
 | 
			
		||||
      @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed
 | 
			
		||||
      @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "passes the user supplied argument to the 'raise function' if a StandardError exception is raised" do
 | 
			
		||||
      arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc1)
 | 
			
		||||
    it "passes the user supplied argument to the 'rescue function' if a StandardError exception is raised" do
 | 
			
		||||
      arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc1)
 | 
			
		||||
      arg1.should == :exc1
 | 
			
		||||
 | 
			
		||||
      arg2, _ = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc2)
 | 
			
		||||
      arg2, _ = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc2)
 | 
			
		||||
      arg2.should == :exc2
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "passes the raised exception to the 'raise function' if a StandardError exception is raised" do
 | 
			
		||||
      _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc)
 | 
			
		||||
    it "passes the raised exception to the 'rescue function' if a StandardError exception is raised" do
 | 
			
		||||
      _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc)
 | 
			
		||||
      exc1.class.should == ArgumentError
 | 
			
		||||
 | 
			
		||||
      _, exc2 = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc)
 | 
			
		||||
      _, exc2 = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc)
 | 
			
		||||
      exc2.class.should == StandardError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an exception if passed function raises an exception other than StandardError" do
 | 
			
		||||
      -> { @s.rb_rescue(@exc_error_proc, nil, @raise_proc_returns_arg, nil) }.should raise_error(Exception)
 | 
			
		||||
      -> { @s.rb_rescue(@exc_error_proc, nil, @rescue_proc_returns_arg, nil) }.should raise_error(Exception)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an exception if any exception is raised inside 'raise function'" do
 | 
			
		||||
    it "raises an exception if any exception is raised inside the 'rescue function'" do
 | 
			
		||||
      -> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "makes $! available only during 'raise function' execution" do
 | 
			
		||||
    it "makes $! available only during the 'rescue function' execution" do
 | 
			
		||||
      @s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError
 | 
			
		||||
      $!.should == nil
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -368,6 +368,10 @@ describe "C-API Kernel function" do
 | 
			
		|||
 | 
			
		||||
      proc_caller { break :value }.should == :value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns nil if the 'rescue function' is null" do
 | 
			
		||||
      @s.rb_rescue(@std_error_proc, nil, nil, nil).should == nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "rb_rescue2" do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								spec/ruby/optional/capi/language_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								spec/ruby/optional/capi/language_spec.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
require_relative 'spec_helper'
 | 
			
		||||
 | 
			
		||||
load_extension("language")
 | 
			
		||||
 | 
			
		||||
describe "C language construct" do
 | 
			
		||||
  before :each do
 | 
			
		||||
    @s = CApiLanguageSpecs.new
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "switch (VALUE)" do
 | 
			
		||||
    it "works for Qtrue" do
 | 
			
		||||
      @s.switch(true).should == :true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works for Qfalse" do
 | 
			
		||||
      @s.switch(false).should == :false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works for Qnil" do
 | 
			
		||||
      @s.switch(nil).should == :nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works for Qundef" do
 | 
			
		||||
      @s.switch(:undef).should == :undef
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works for the default case" do
 | 
			
		||||
      @s.switch(Object.new).should == :default
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +143,34 @@ describe "CApiNumericSpecs" do
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "NUM2SHORT" do
 | 
			
		||||
    it "raises a TypeError if passed nil" do
 | 
			
		||||
      -> { @s.NUM2SHORT(nil) }.should raise_error(TypeError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "converts a Float" do
 | 
			
		||||
      @s.NUM2SHORT(4.2).should == 4
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "converts a Fixnum" do
 | 
			
		||||
      @s.NUM2SHORT(5).should == 5
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "converts -1 to an signed number" do
 | 
			
		||||
      @s.NUM2SHORT(-1).should == -1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises a RangeError if the value is more than 32bits" do
 | 
			
		||||
      -> { @s.NUM2SHORT(0xffff_ffff+1) }.should raise_error(RangeError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "calls #to_int to coerce the value" do
 | 
			
		||||
      obj = mock("number")
 | 
			
		||||
      obj.should_receive(:to_int).and_return(2)
 | 
			
		||||
      @s.NUM2SHORT(obj).should == 2
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "INT2NUM" do
 | 
			
		||||
    it "raises a TypeError if passed nil" do
 | 
			
		||||
      -> { @s.INT2NUM(nil) }.should raise_error(TypeError)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,25 @@ describe "C-API Proc function" do
 | 
			
		|||
      @p.rb_proc_call(prc, [6, 7]).should == 42
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "rb_obj_is_proc" do
 | 
			
		||||
    it "returns true for Proc" do
 | 
			
		||||
      prc = Proc.new {|a,b| a * b }
 | 
			
		||||
      @p.rb_obj_is_proc(prc).should be_true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns true for subclass of Proc" do
 | 
			
		||||
      prc = Class.new(Proc).new {}
 | 
			
		||||
      @p.rb_obj_is_proc(prc).should be_true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns false for non Proc instances" do
 | 
			
		||||
      @p.rb_obj_is_proc("aoeui").should be_false
 | 
			
		||||
      @p.rb_obj_is_proc(123).should be_false
 | 
			
		||||
      @p.rb_obj_is_proc(true).should be_false
 | 
			
		||||
      @p.rb_obj_is_proc([]).should be_false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
describe "C-API when calling Proc.new from a C function" do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,12 +8,17 @@ require 'rbconfig'
 | 
			
		|||
OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__)
 | 
			
		||||
 | 
			
		||||
def object_path
 | 
			
		||||
  mkdir_p(OBJDIR)
 | 
			
		||||
  OBJDIR
 | 
			
		||||
  path = OBJDIR
 | 
			
		||||
  if ENV['SPEC_CAPI_CXX'] == 'true'
 | 
			
		||||
    path = "#{path}/cxx"
 | 
			
		||||
  end
 | 
			
		||||
  mkdir_p(path)
 | 
			
		||||
  path
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def compile_extension(name)
 | 
			
		||||
  debug = false
 | 
			
		||||
  cxx = ENV['SPEC_CAPI_CXX'] == 'true'
 | 
			
		||||
  run_mkmf_in_process = RUBY_ENGINE == 'truffleruby'
 | 
			
		||||
 | 
			
		||||
  core_ext_dir = File.expand_path("../ext", __FILE__)
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +59,11 @@ def compile_extension(name)
 | 
			
		|||
  Dir.mkdir(tmpdir)
 | 
			
		||||
  begin
 | 
			
		||||
    ["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"].each do |file|
 | 
			
		||||
      cp file, "#{tmpdir}/#{File.basename(file)}"
 | 
			
		||||
      if cxx and file.end_with?('.c')
 | 
			
		||||
        cp file, "#{tmpdir}/#{File.basename(file, '.c')}.cpp"
 | 
			
		||||
      else
 | 
			
		||||
        cp file, "#{tmpdir}/#{File.basename(file)}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Dir.chdir(tmpdir) do
 | 
			
		||||
| 
						 | 
				
			
			@ -64,11 +73,13 @@ def compile_extension(name)
 | 
			
		|||
        init_mkmf unless required
 | 
			
		||||
        create_makefile(ext, tmpdir)
 | 
			
		||||
      else
 | 
			
		||||
        File.write("extconf.rb", "require 'mkmf'\n" +
 | 
			
		||||
          "$ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')\n" +
 | 
			
		||||
        File.write("extconf.rb", <<-RUBY)
 | 
			
		||||
          require 'mkmf'
 | 
			
		||||
          $ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')
 | 
			
		||||
          # MRI magic to consider building non-bundled extensions
 | 
			
		||||
          "$extout = nil\n" +
 | 
			
		||||
          "create_makefile(#{ext.inspect})\n")
 | 
			
		||||
          $extout = nil
 | 
			
		||||
          create_makefile(#{ext.inspect})
 | 
			
		||||
        RUBY
 | 
			
		||||
        output = ruby_exe("extconf.rb")
 | 
			
		||||
        raise "extconf failed:\n#{output}" unless $?.success?
 | 
			
		||||
        $stderr.puts output if debug
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -513,6 +513,24 @@ describe "C-API String function" do
 | 
			
		|||
      end
 | 
			
		||||
      chars.should == [55, 48, 227, 131, 145, 227, 130, 175]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns a pointer which can be cast and used as another type" do
 | 
			
		||||
      s = "70パク".
 | 
			
		||||
        encode(Encoding::UTF_16LE).
 | 
			
		||||
        force_encoding(Encoding::UTF_16LE).
 | 
			
		||||
        encode(Encoding::UTF_8)
 | 
			
		||||
 | 
			
		||||
      ints = []
 | 
			
		||||
      @s.RSTRING_PTR_iterate_uint32(s) do |i|
 | 
			
		||||
        ints << i
 | 
			
		||||
      end
 | 
			
		||||
      ints.should == s.unpack('LL')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows a short memcpy to the string which may be converted to a single write operation by the compiler" do
 | 
			
		||||
      str = "        "
 | 
			
		||||
      @s.RSTRING_PTR_short_memcpy(str).should == "Infinity"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "RSTRING_LEN" do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,16 @@ describe "C-API Symbol function" do
 | 
			
		|||
    @s = CApiSymbolSpecs.new
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "SYMBOL_P" do
 | 
			
		||||
    it "returns true for a Symbol" do
 | 
			
		||||
      @s.SYMBOL_P(:foo).should == true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns false for non-Symbols" do
 | 
			
		||||
      @s.SYMBOL_P('bar').should == false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "rb_intern" do
 | 
			
		||||
    it "converts a string to a symbol, uniquely" do
 | 
			
		||||
      @s.rb_intern("test_symbol").should == :test_symbol
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue