Skip to content

Commit

Permalink
Showing 139 changed files with 1,362 additions and 598 deletions.
13 changes: 10 additions & 3 deletions core/src/main/java/org/jruby/exceptions/RaiseException.java
Original file line number Diff line number Diff line change
@@ -203,11 +203,19 @@ private void preRaise(ThreadContext context, StackTraceElement[] javaTrace) {

if (RubyInstanceConfig.LOG_EXCEPTIONS) TraceType.dumpException(exception);

if (context.exceptionRequiresBacktrace) {
if (requiresBacktrace(context)) {
exception.prepareIntegratedBacktrace(context, javaTrace);
}
}

private boolean requiresBacktrace(ThreadContext context) {
IRubyObject debugMode = context.runtime.getGlobalVariables().get("$DEBUG");
// We can only omit backtraces of descendents of Standard error for 'foo rescue nil'
return context.exceptionRequiresBacktrace ||
(debugMode != null && debugMode.isTrue()) ||
!exception.kind_of_p(context, context.runtime.getStandardError()).isTrue();
}

private void preRaise(ThreadContext context, IRubyObject backtrace) {
context.runtime.incrementExceptionCount();
doSetLastError(context);
@@ -216,8 +224,7 @@ private void preRaise(ThreadContext context, IRubyObject backtrace) {
if (RubyInstanceConfig.LOG_EXCEPTIONS) TraceType.dumpException(exception);

// We can only omit backtraces of descendents of Standard error for 'foo rescue nil'
if (!exception.kind_of_p(context, context.runtime.getStandardError()).isTrue() ||
context.exceptionRequiresBacktrace) {
if (requiresBacktrace(context)) {
if (backtrace == null) {
exception.prepareBacktrace(context, nativeException);
} else {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -3036,7 +3036,7 @@ public Operand buildRescue(RescueNode node) {

private boolean canBacktraceBeRemoved(RescueNode rescueNode) {
// For now we will only contemplate 'foo rescue nil' cases but simple non-mod rescue forms can be added later.
if (!(rescueNode instanceof RescueModNode)) return false;
if (RubyInstanceConfig.FULL_TRACE_ENABLED || !(rescueNode instanceof RescueModNode)) return false;

// FIXME: This MIGHT be able to expand to more complicated expressions like Hash or Array if they
// contain only SideEffectFree nodes. Constructing a literal out of these should be safe from
20 changes: 19 additions & 1 deletion core/src/main/java/org/jruby/util/JRubyClassLoader.java
Original file line number Diff line number Diff line change
@@ -35,8 +35,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;

import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
@@ -60,10 +62,26 @@ public class JRubyClassLoader extends ClassDefiningJRubyClassLoader {

private Runnable unloader;

private File tempdir;

public JRubyClassLoader(ClassLoader parent) {
super(parent);
}

private File getTempDir() {
if (tempdir == null) {
String processName = ManagementFactory.getRuntimeMXBean().getName();
long pid = Long.parseLong(processName.split("@")[0]);
File dir = new File(System.getProperty("java.io.tmpdir"), "jruby-" + pid);
if (dir.mkdirs()) {
dir.deleteOnExit();
}
;
tempdir = dir;
}
return tempdir;
}

// Change visibility so others can see it
@Override
public void addURL(URL url) {
@@ -74,7 +92,7 @@ public void addURL(URL url) {
OutputStream out = null;
try
{
File f = File.createTempFile( "jruby", new File(url.getFile()).getName());
File f = File.createTempFile("jruby", new File(url.getFile()).getName(), getTempDir());
f.deleteOnExit();
out = new BufferedOutputStream( new FileOutputStream( f ) );
in = new BufferedInputStream( url.openStream() );
4 changes: 0 additions & 4 deletions spec/jruby.2.2.mspec
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ class MSpecScript
# Core library specs
set :core, [
SPEC_DIR + '/core',
'^' + SPEC_DIR + '/core/continuation'
]

set :fast, [
@@ -106,9 +105,6 @@ class MSpecScript
# This set of files is run by mspec ci
set :ci_files, get(:language) + get(:core) + get(:command_line) + get(:library)

# Optional library specs
set :ffi, SPEC_DIR + '/optional/ffi'

# A list of _all_ optional library specs
set :optional, [get(:ffi)]

25 changes: 14 additions & 11 deletions spec/mspec/lib/mspec/helpers/ruby_exe.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'mspec/utils/ruby_name'
require 'mspec/guards/platform'
require 'mspec/helpers/tmp'

# The ruby_exe helper provides a wrapper for invoking the
# same Ruby interpreter as the one running the specs and
@@ -124,6 +125,13 @@ def ruby_exe(code, opts = {})
ENV[key] = value
end

escape = opts.delete(:escape)
if escape
tmpfile = tmp("rubyexe.rb")
File.open(tmpfile, "w") { |f| f.write(code) }
code = tmpfile
end

begin
platform_is_not :opal do
`#{ruby_cmd(code, opts)}`
@@ -134,25 +142,20 @@ def ruby_exe(code, opts = {})
key = key.to_s
ENV.delete key unless saved_env.key? key
end
File.delete tmpfile if escape
end
end
end

def ruby_cmd(code, opts = {})
body = code

if code and not File.exist?(code)
if opts[:escape]
heredoc_separator = "END_OF_RUBYCODE"
lines = code.lines
until lines.none? {|line| line.start_with? heredoc_separator }
heredoc_separator << heredoc_separator
end
if opts[:escape]
raise "escape: true is no longer supported in ruby_cmd, use ruby_exe or a fixture"
end

body = %Q!-e "$(cat <<'#{heredoc_separator}'\n#{code}\n#{heredoc_separator}\n)"!
else
body = "-e #{code.inspect}"
end
if code and not File.exist?(code)
body = "-e #{code.inspect}"
end

[RUBY_EXE, ENV['RUBY_FLAGS'], opts[:options], body, opts[:args]].compact.join(' ')
2 changes: 1 addition & 1 deletion spec/mspec/lib/mspec/runner/actions/filter.rb
Original file line number Diff line number Diff line change
@@ -14,14 +14,14 @@ def initialize(tags=nil, descs=nil)
@tags = Array(tags)
descs = Array(descs)
@sfilter = MatchFilter.new(nil, *descs) unless descs.empty?
@tfilter = nil
end

def ===(string)
@sfilter === string or @tfilter === string
end

def load
@tfilter = nil
return if @tags.empty?

desc = MSpec.read_tags(@tags).map { |t| t.description }
2 changes: 2 additions & 0 deletions spec/mspec/lib/mspec/runner/mspec.rb
Original file line number Diff line number Diff line change
@@ -16,7 +16,9 @@ module MSpec
@leave = nil
@load = nil
@unload = nil
@tagged = nil
@current = nil
@example = nil
@modes = []
@shared = {}
@guarded = []
14 changes: 10 additions & 4 deletions spec/mspec/lib/mspec/runner/tag.rb
Original file line number Diff line number Diff line change
@@ -13,13 +13,19 @@ def parse(string)

def unescape(str)
return unless str
str = str[1..-2] if str[0] == ?" and str[-1] == ?"
str.gsub(/\\n/, "\n")
if str[0] == ?" and str[-1] == ?"
str[1..-2].gsub('\n', "\n")
else
str
end
end

def escape(str)
str = %["#{str.gsub(/\n/, '\n')}"] if /\n/ =~ str
str
if str.include? "\n"
%["#{str.gsub("\n", '\n')}"]
else
str
end
end

def to_s
1 change: 1 addition & 0 deletions spec/mspec/spec/helpers/io_spec.rb
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@
describe Object, "#new_fd" do
before :each do
@name = tmp("io_specs")
@io = nil
end

after :each do
5 changes: 5 additions & 0 deletions spec/mspec/spec/runner/exception_spec.rb
Original file line number Diff line number Diff line change
@@ -87,6 +87,10 @@
end

describe ExceptionState, "#message" do
before :each do
@state = ExampleState.new ContextState.new("C#m"), "works"
end

it "returns <No message> if the exception message is empty" do
exc = ExceptionState.new @state, "", Exception.new("")
exc.message.should == "<No message>"
@@ -111,6 +115,7 @@

describe ExceptionState, "#backtrace" do
before :each do
@state = ExampleState.new ContextState.new("C#m"), "works"
begin
raise Exception
rescue Exception => @exception
4 changes: 2 additions & 2 deletions spec/mspec/spec/runner/formatters/method_spec.rb
Original file line number Diff line number Diff line change
@@ -120,8 +120,8 @@
@formatter.before state

exc = SpecExpectationNotMetError.new "failed"
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.exception ExceptionState.new(@state, nil, exc)
@formatter.exception ExceptionState.new(state, nil, exc)
@formatter.exception ExceptionState.new(state, nil, exc)

@formatter.after state
h = @formatter.methods["Some#method"]
1 change: 0 additions & 1 deletion spec/mspec/spec/runner/mspec_spec.rb
Original file line number Diff line number Diff line change
@@ -95,7 +95,6 @@
before :each do
MSpec.clear_current
@cs = ContextState.new "C#m"
@cs.stub(:state).and_return(@es)
@cs.parent = MSpec.current

@es = ExampleState.new @cs, "runs"
12 changes: 12 additions & 0 deletions spec/mspec/spec/runner/tag_spec.rb
Original file line number Diff line number Diff line change
@@ -109,3 +109,15 @@
[one].==([two]).should == true
end
end

describe SpecTag, "#unescape" do
it "replaces \\n by LF when the description is quoted" do
tag = SpecTag.new 'tag:"desc with\nnew line"'
tag.description.should == "desc with\nnew line"
end

it "does not replaces \\n by LF when the description is not quoted " do
tag = SpecTag.new 'tag:desc with\nnew line'
tag.description.should == "desc with\\nnew line"
end
end
20 changes: 8 additions & 12 deletions spec/ruby/command_line/dash_s_spec.rb
Original file line number Diff line number Diff line change
@@ -3,27 +3,23 @@
describe "The -s command line option" do
describe "when using -- to stop parsing" do
it "sets the value to true without an explicit value" do
ruby_exe("p $n", escape: true,
options: "-s",
args: "-- -n").chomp.should == "true"
ruby_exe(nil, options: "-s -e 'p $n'",
args: "-- -n").chomp.should == "true"
end

it "parses single letter args into globals" do
ruby_exe("puts $n", escape: true,
options: "-s",
args: "-- -n=blah").chomp.should == "blah"
ruby_exe(nil, options: "-s -e 'puts $n'",
args: "-- -n=blah").chomp.should == "blah"
end

it "parses long args into globals" do
ruby_exe("puts $_name", escape: true,
options: "-s",
args: "-- --name=blah").chomp.should == "blah"
ruby_exe(nil, options: "-s -e 'puts $_name'",
args: "-- --name=blah").chomp.should == "blah"
end

it "converts extra dashes into underscores" do
ruby_exe("puts $___name__test__", escape: true,
options: "-s",
args: "-- ----name--test--=blah").chomp.should == "blah"
ruby_exe(nil, options: "-s -e 'puts $___name__test__'",
args: "-- ----name--test--=blah").chomp.should == "blah"
end
end

14 changes: 7 additions & 7 deletions spec/ruby/core/array/any_spec.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Array#any?" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
it "is false if the array is empty" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
it "is false if the array is empty" do
empty_array = []
empty_array.any?.should == false
end

it "is false if the array is not empty, but all the members of the array are falsy" do
it "is false if the array is not empty, but all the members of the array are falsy" do
falsy_array = [false, nil, false]
falsy_array.any?.should == false
end
@@ -18,18 +18,18 @@
end
end

describe 'with a block given' do
it 'is false if the array is empty' do
describe 'with a block given' do
it 'is false if the array is empty' do
empty_array = []
empty_array.any? {|v| 1 == 1 }.should == false
end

it 'is true if the block returns true for any member of the array' do
it 'is true if the block returns true for any member of the array' do
array_with_members = [false, false, true, false]
array_with_members.any? {|v| v == true }.should == true
end

it 'is false if the block returns false for all members of the array' do
it 'is false if the block returns false for all members of the array' do
array_with_members = [false, false, true, false]
array_with_members.any? {|v| v == 42 }.should == false
end
3 changes: 3 additions & 0 deletions spec/ruby/core/basicobject/__send___spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../shared/basicobject/send', __FILE__)

describe "BasicObject#__send__" do
it "is a public instance method" do
BasicObject.should have_public_instance_method(:__send__)
end

it_behaves_like(:basicobject_send, :__send__)
end
26 changes: 25 additions & 1 deletion spec/ruby/core/basicobject/method_missing_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require File.expand_path('../../../shared/kernel/method_missing', __FILE__)
require File.expand_path('../../../shared/basicobject/method_missing', __FILE__)

describe "BasicObject#method_missing" do
it "is a private method" do
@@ -13,3 +13,27 @@
describe "BasicObject#method_missing" do
it_behaves_like :method_missing_instance, nil, BasicObject
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_defined_module, nil, KernelSpecs::ModuleMM
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_module, nil, KernelSpecs::ModuleNoMM
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_defined_class, nil, KernelSpecs::ClassMM
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_class, nil, KernelSpecs::ClassNoMM
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_defined_instance, nil, KernelSpecs::ClassMM
end

describe "BasicObject#method_missing" do
it_behaves_like :method_missing_instance, nil, KernelSpecs::ClassNoMM
end
37 changes: 37 additions & 0 deletions spec/ruby/core/binding/local_variables_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.2" do
describe "Binding#local_variables" do
it "returns an Array" do
binding.local_variables.should be_kind_of(Array)
end

it "includes local variables in the current scope" do
a = 1
b = nil
binding.local_variables.should == [:a, :b]
end

it "includes local variables defined after calling binding.local_variables" do
binding.local_variables.should == [:a, :b]
a = 1
b = 2
end

it "includes local variables of inherited scopes and eval'ed context" do
p = proc { |a| b = 1; eval("c = 2; binding.local_variables") }
p.call.should == [:c, :a, :b, :p]
end

it "includes shadowed local variables only once" do
a = 1
proc { |a| binding.local_variables }.call(2).should == [:a]
end

it "includes new variables defined in the binding" do
b = binding
b.local_variable_set :a, 42
b.local_variables.should == [:a, :b]
end
end
end
13 changes: 13 additions & 0 deletions spec/ruby/core/binding/receiver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "2.2" do
describe "Binding#receiver" do
it "returns the object to which binding is bound" do
obj = BindingSpecs::Demo.new(1)
obj.get_binding.receiver.should == obj

binding.receiver.should == self
end
end
end
8 changes: 0 additions & 8 deletions spec/ruby/core/continuation/call_spec.rb

This file was deleted.

8 changes: 0 additions & 8 deletions spec/ruby/core/continuation/element_reference_spec.rb

This file was deleted.

8 changes: 0 additions & 8 deletions spec/ruby/core/continuation/new_spec.rb

This file was deleted.

2 changes: 1 addition & 1 deletion spec/ruby/core/enumerable/each_cons_spec.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
acc.should == @in_threes
end

it "raises an Argument Error if there is not a single parameter > 0" do
it "raises an ArgumentError if there is not a single parameter > 0" do
lambda{ @enum.each_cons(0){} }.should raise_error(ArgumentError)
lambda{ @enum.each_cons(-2){} }.should raise_error(ArgumentError)
lambda{ @enum.each_cons{} }.should raise_error(ArgumentError)
2 changes: 1 addition & 1 deletion spec/ruby/core/enumerable/each_entry_spec.rb
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
ScratchPad.recorded.should == [[:a, 0], [:b, 1]]
end

it "raises an Argument error when extra arguments" do
it "raises an ArgumentError when extra arguments" do
lambda { @enum.each_entry("one").to_a }.should raise_error(ArgumentError)
lambda { @enum.each_entry("one"){}.to_a }.should raise_error(ArgumentError)
end
2 changes: 1 addition & 1 deletion spec/ruby/core/enumerable/each_slice_spec.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
acc.should == @sliced
end

it "raises an Argument Error if there is not a single parameter > 0" do
it "raises an ArgumentError if there is not a single parameter > 0" do
lambda{ @enum.each_slice(0){} }.should raise_error(ArgumentError)
lambda{ @enum.each_slice(-2){} }.should raise_error(ArgumentError)
lambda{ @enum.each_slice{} }.should raise_error(ArgumentError)
10 changes: 5 additions & 5 deletions spec/ruby/core/enumerable/grep_v_spec.rb
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ def (@odd_matcher = BasicObject.new).===(obj)
obj.odd?
end
end

describe "without block" do
it "returns an Array of matched elements" do
@numerous.grep_v(@odd_matcher).should == [0, 2, 4, 6, 8]
@@ -19,22 +19,22 @@ def (@odd_matcher = BasicObject.new).===(obj)
(unmatcher = Object.new).stub!(:===).and_return(false)
EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher).should == EnumerableSpecs::YieldsMixed2.gathered_yields
end

it "raises an ArgumentError when not given a pattern" do
-> { @numerous.grep_v }.should raise_error(ArgumentError)
end
end

describe "with block" do
it "returns an Array of matched elements that mapped by the block" do
@numerous.grep_v(@odd_matcher) { |n| n * 2 }.should == [0, 4, 8, 12, 16]
end

it "calls the block with gathered array when yielded with multiple arguments" do
(unmatcher = Object.new).stub!(:===).and_return(false)
EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields
end

it "raises an ArgumentError when not given a pattern" do
-> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError)
end
40 changes: 40 additions & 0 deletions spec/ruby/core/enumerable/max_by_spec.rb
Original file line number Diff line number Diff line change
@@ -40,4 +40,44 @@
end

it_behaves_like :enumerable_enumeratorized_with_origin_size, :max_by

ruby_version_is "2.2" do
context "when called with an argument n" do
before :each do
@enum = EnumerableSpecs::Numerous.new(101, 55, 1, 20, 33, 500, 60)
end

context "without a block" do
it "returns an enumerator" do
@enum.max_by(2).should be_an_instance_of(enumerator_class)
end
end

context "with a block" do
it "returns an array containing the maximum n elements based on the block's value" do
result = @enum.max_by(3) { |i| i.to_s }
result.should == [60, 55, 500]
end

context "on a enumerable of length x where x < n" do
it "returns an array containing the maximum n elements of length n" do
result = @enum.max_by(500) { |i| i.to_s }
result.length.should == 7
end
end

context "when n is negative" do
it "raises an ArgumentError" do
lambda { @enum.max_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError)
end
end
end

context "when n is nil" do
it "returns the maximum element" do
@enum.max_by(nil) { |i| i.to_s }.should == 60
end
end
end
end
end
65 changes: 50 additions & 15 deletions spec/ruby/core/enumerable/max_spec.rb
Original file line number Diff line number Diff line change
@@ -3,13 +3,11 @@

describe "Enumerable#max" do
before :each do
@a = EnumerableSpecs::EachDefiner.new( 2, 4, 6, 8, 10 )

@e_strs = EnumerableSpecs::EachDefiner.new("333", "22", "666666", "1", "55555", "1010101010")
@e_ints = EnumerableSpecs::EachDefiner.new( 333, 22, 666666, 55555, 1010101010)
end

it "max should return the maximum element" do
it "returns the maximum element" do
EnumerableSpecs::Numerous.new.max.should == 6
end

@@ -52,24 +50,25 @@
end.should raise_error(ArgumentError)
end

it "returns the maximum element (with block)" do
# with a block
EnumerableSpecs::EachDefiner.new("2","33","4","11").max {|a,b| a <=> b }.should == "4"
EnumerableSpecs::EachDefiner.new( 2 , 33 , 4 , 11 ).max {|a,b| a <=> b }.should == 33
context "when passed a block" do
it "returns the maximum element" do
EnumerableSpecs::EachDefiner.new("2","33","4","11").max {|a,b| a <=> b }.should == "4"
EnumerableSpecs::EachDefiner.new( 2 , 33 , 4 , 11 ).max {|a,b| a <=> b }.should == 33

EnumerableSpecs::EachDefiner.new("2","33","4","11").max {|a,b| b <=> a }.should == "11"
EnumerableSpecs::EachDefiner.new( 2 , 33 , 4 , 11 ).max {|a,b| b <=> a }.should == 2
EnumerableSpecs::EachDefiner.new("2","33","4","11").max {|a,b| b <=> a }.should == "11"
EnumerableSpecs::EachDefiner.new( 2 , 33 , 4 , 11 ).max {|a,b| b <=> a }.should == 2

@e_strs.max {|a,b| a.length <=> b.length }.should == "1010101010"
@e_strs.max {|a,b| a.length <=> b.length }.should == "1010101010"

@e_strs.max {|a,b| a <=> b }.should == "666666"
@e_strs.max {|a,b| a.to_i <=> b.to_i }.should == "1010101010"
@e_strs.max {|a,b| a <=> b }.should == "666666"
@e_strs.max {|a,b| a.to_i <=> b.to_i }.should == "1010101010"

@e_ints.max {|a,b| a <=> b }.should == 1010101010
@e_ints.max {|a,b| a.to_s <=> b.to_s }.should == 666666
@e_ints.max {|a,b| a <=> b }.should == 1010101010
@e_ints.max {|a,b| a.to_s <=> b.to_s }.should == 666666
end
end

it "returns the minimum for enumerables that contain nils" do
it "returns the maximum for enumerables that contain nils" do
arr = EnumerableSpecs::Numerous.new(nil, nil, true)
arr.max { |a, b|
x = a.nil? ? 1 : a ? 0 : -1
@@ -83,4 +82,40 @@
multi.max.should == [6, 7, 8, 9]
end

ruby_version_is "2.2" do
context "when called with an argument n" do
context "without a block" do
it "returns an array containing the maximum n elements" do
result = @e_ints.max(2)
result.should == [1010101010, 666666]
end
end

context "with a block" do
it "returns an array containing the maximum n elements" do
result = @e_ints.max(2) { |a, b| a * 2 <=> b * 2 }
result.should == [1010101010, 666666]
end
end

context "on a enumerable of length x where x < n" do
it "returns an array containing the maximum n elements of length x" do
result = @e_ints.max(500)
result.length.should == 5
end
end

context "that is negative" do
it "raises an ArgumentError" do
lambda { @e_ints.max(-1) }.should raise_error(ArgumentError)
end
end
end

context "that is nil" do
it "returns the maximum element" do
@e_ints.max(nil).should == 1010101010
end
end
end
end
45 changes: 42 additions & 3 deletions spec/ruby/core/enumerable/min_by_spec.rb
Original file line number Diff line number Diff line change
@@ -11,8 +11,7 @@
EnumerableSpecs::Empty.new.min_by {|o| o.nonesuch }.should == nil
end


it "returns the object for whom the value returned by block is the largest" do
it "returns the object for whom the value returned by block is the smallest" do
EnumerableSpecs::Numerous.new(*%w[3 2 1]).min_by {|obj| obj.to_i }.should == '1'
EnumerableSpecs::Numerous.new(*%w[five three]).min_by {|obj| obj.length }.should == 'five'
end
@@ -29,7 +28,7 @@
EnumerableSpecs::Numerous.new(a, b, c).min_by {|obj| obj }.should == c
end

it "is able to return the maximum for enums that contain nils" do
it "is able to return the minimum for enums that contain nils" do
enum = EnumerableSpecs::Numerous.new(nil, nil, true)
enum.min_by {|o| o.nil? ? 0 : 1 }.should == nil
enum.min_by {|o| o.nil? ? 1 : 0 }.should == true
@@ -41,4 +40,44 @@
end

it_behaves_like :enumerable_enumeratorized_with_origin_size, :min_by

ruby_version_is "2.2" do
context "when called with an argument n" do
before :each do
@enum = EnumerableSpecs::Numerous.new(101, 55, 1, 20, 33, 500, 60)
end

context "without a block" do
it "returns an enumerator" do
@enum.min_by(2).should be_an_instance_of(enumerator_class)
end
end

context "with a block" do
it "returns an array containing the minimum n elements based on the block's value" do
result = @enum.min_by(3) { |i| i.to_s }
result.should == [1, 101, 20]
end

context "on a enumerable of length x where x < n" do
it "returns an array containing the minimum n elements of length n" do
result = @enum.min_by(500) { |i| i.to_s }
result.length.should == 7
end
end

context "when n is negative" do
it "raises an ArgumentError" do
lambda { @enum.min_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError)
end
end
end

context "when n is nil" do
it "returns the minimum element" do
@enum.min_by(nil) { |i| i.to_s }.should == 1
end
end
end
end
end
38 changes: 36 additions & 2 deletions spec/ruby/core/enumerable/min_spec.rb
Original file line number Diff line number Diff line change
@@ -3,8 +3,6 @@

describe "Enumerable#min" do
before :each do
@a = EnumerableSpecs::EachDefiner.new( 2, 4, 6, 8, 10 )

@e_strs = EnumerableSpecs::EachDefiner.new("333", "22", "666666", "1", "55555", "1010101010")
@e_ints = EnumerableSpecs::EachDefiner.new( 333, 22, 666666, 55555, 1010101010)
end
@@ -88,4 +86,40 @@
multi.min.should == [1, 2]
end

ruby_version_is "2.2" do
context "when called with an argument n" do
context "without a block" do
it "returns an array containing the minimum n elements" do
result = @e_ints.min(2)
result.should == [22, 333]
end
end

context "with a block" do
it "returns an array containing the minimum n elements" do
result = @e_ints.min(2) { |a, b| a * 2 <=> b * 2 }
result.should == [22, 333]
end
end

context "on a enumerable of length x where x < n" do
it "returns an array containing the minimum n elements of length x" do
result = @e_ints.min(500)
result.length.should == 5
end
end

context "that is negative" do
it "raises an ArgumentError" do
lambda { @e_ints.min(-1) }.should raise_error(ArgumentError)
end
end
end

context "that is nil" do
it "returns the minimum element" do
@e_ints.min(nil).should == 22
end
end
end
end
55 changes: 55 additions & 0 deletions spec/ruby/core/enumerable/slice_after_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "2.2" do
describe "Enumerable#slice_after" do
before :each do
@enum = EnumerableSpecs::Numerous.new(7, 6, 5, 4, 3, 2, 1)
end

describe "when given an argument and no block" do
it "calls === on the argument to determine when to yield" do
arg = mock("filter")
arg.should_receive(:===).and_return(false, true, false, false, false, true, false)
e = @enum.slice_after(arg)
e.should be_an_instance_of(enumerator_class)
e.to_a.should == [[7, 6], [5, 4, 3, 2], [1]]
end

it "doesn't yield an empty array if the filter matches the first entry or the last entry" do
arg = mock("filter")
arg.should_receive(:===).and_return(true).exactly(7)
e = @enum.slice_after(arg)
e.to_a.should == [[7], [6], [5], [4], [3], [2], [1]]
end

it "uses standard boolean as a test" do
arg = mock("filter")
arg.should_receive(:===).and_return(false, :foo, nil, false, false, 42, false)
e = @enum.slice_after(arg)
e.to_a.should == [[7, 6], [5, 4, 3, 2], [1]]
end
end

describe "when given a block" do
describe "and no argument" do
it "calls the block to determine when to yield" do
e = @enum.slice_after{ |i| i == 6 || i == 2 }
e.should be_an_instance_of(enumerator_class)
e.to_a.should == [[7, 6], [5, 4, 3, 2], [1]]
end
end

describe "and an argument" do
it "raises an ArgumentError" do
lambda { @enum.slice_after(42) { |i| i == 6 } }.should raise_error(ArgumentError)
end
end
end

it "raises an ArgumentError when given an incorrect number of arguments" do
lambda { @enum.slice_after("one", "two") }.should raise_error(ArgumentError)
lambda { @enum.slice_after }.should raise_error(ArgumentError)
end
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/enumerable/slice_before_spec.rb
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@
end
end

it "raises an Argument error when given an incorrect number of arguments" do
it "raises an ArgumentError when given an incorrect number of arguments" do
lambda { @enum.slice_before("one", "two") }.should raise_error(ArgumentError)
lambda { @enum.slice_before }.should raise_error(ArgumentError)
end
38 changes: 38 additions & 0 deletions spec/ruby/core/enumerable/slice_when_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "2.2" do
describe "Enumerable#slice_when" do
before :each do
ary = [10, 9, 7, 6, 4, 3, 2, 1]
@enum = EnumerableSpecs::Numerous.new *ary
@result = @enum.slice_when { |i, j| i - 1 != j }
@enum_length = ary.length
end

context "when given a block" do
it "returns an enumerator" do
@result.should be_an_instance_of(enumerator_class)
end

it "splits chunks between adjacent elements i and j where the block returns true" do
@result.to_a.should == [[10, 9], [7, 6], [4, 3, 2, 1]]
end

it "calls the block for length of the receiver enumerable minus one times" do
times_called = 0
@enum.slice_when do |i, j|
times_called += 1
i - 1 != j
end.to_a
times_called.should == (@enum_length - 1)
end
end

context "when not given a block" do
it "raises an ArgumentError" do
lambda { @enum.slice_when }.should raise_error(ArgumentError)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/exception/receiver_spec.rb
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
end
)
end

it "raises an ArgumentError when the receiver is none" do
-> { NameError.new.receiver }.should raise_error(ArgumentError)
end
60 changes: 60 additions & 0 deletions spec/ruby/core/file/birthtime_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.2" do
describe "File.birthtime" do
before :each do
@file = __FILE__
end

after :each do
@file = nil
end

platform_is :windows, :darwin do
it "returns the birth time for the named file as a Time object" do
File.birthtime(@file)
File.birthtime(@file).should be_kind_of(Time)
end

it "accepts an object that has a #to_path method" do
File.birthtime(mock_to_path(@file))
end

it "raises an Errno::ENOENT exception if the file is not found" do
lambda { File.birthtime('bogus') }.should raise_error(Errno::ENOENT)
end
end

platform_is :linux, :openbsd, :freebsd, :netbsd do
it "raises an NotImplementedError" do
lambda { File.birthtime(@file) }.should raise_error(NotImplementedError)
end
end
end
end

ruby_version_is "2.2" do
describe "File#birthtime" do
before :each do
@file = File.open(__FILE__)
end

after :each do
@file.close
@file = nil
end

platform_is :windows, :darwin do
it "returns the birth time for self" do
@file.birthtime
@file.birthtime.should be_kind_of(Time)
end
end

platform_is :linux, :openbsd, :freebsd, :netbsd do
it "raises an NotImplementedError" do
lambda { @file.birthtime }.should raise_error(NotImplementedError)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/file/ctime_spec.rb
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
@file = File.open(__FILE__)
end

after:each do
after :each do
@file.close
@file = nil
end
38 changes: 21 additions & 17 deletions spec/ruby/core/file/flock_spec.rb
Original file line number Diff line number Diff line change
@@ -30,33 +30,37 @@
it "returns false if trying to lock an exclusively locked file" do
@file.flock File::LOCK_EX

File.open(@name, "w") do |f2|
f2.flock(File::LOCK_EX | File::LOCK_NB).should == false
end
ruby_exe(<<-END_OF_CODE, escape: true).should == "false"
File.open('#{@name}', "w") do |f2|
print f2.flock(File::LOCK_EX | File::LOCK_NB).to_s
end
END_OF_CODE
end

it "blocks if trying to lock an exclusively locked file" do
@file.flock File::LOCK_EX

running = false
t = Thread.new do
ScratchPad << :before
out = ruby_exe(<<-END_OF_CODE, escape: true)
running = false
running = true
File.open(@name, "w") do |f2|
f2.flock(File::LOCK_EX)
t = Thread.new do
File.open('#{@name}', "w") do |f2|
puts "before"
running = true
f2.flock(File::LOCK_EX)
puts "after"
end
end
ScratchPad << :after
end

Thread.pass until running
sleep 0.5
Thread.pass until running
Thread.pass while t.status and t.status != "sleep"
sleep 0.1
t.kill
t.join
t.kill
t.join
END_OF_CODE

ScratchPad.recorded.should == [:before]
out.should == "before\n"
end

it "returns 0 if trying to lock a non-exclusively locked file" do
29 changes: 29 additions & 0 deletions spec/ruby/core/file/stat/birthtime_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require File.expand_path('../../../../spec_helper', __FILE__)

ruby_version_is "2.2" do
describe "File::Stat#birthtime" do
before :each do
@file = tmp('i_exist')
touch(@file) { |f| f.write "rubinius" }
end

after :each do
rm_r @file
end

platform_is :windows, :darwin do
it "returns the birthtime of a File::Stat object" do
st = File.stat(@file)
st.birthtime.should be_kind_of(Time)
st.birthtime.should <= Time.now
end
end

platform_is :linux, :openbsd, :freebsd, :netbsd do
it "raises an NotImplementedError" do
st = File.stat(@file)
lambda { st.birthtime }.should raise_error(NotImplementedError)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/file/stat/comparison_spec.rb
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
end

it "is able to compare files by the same modification times" do
now = Time.now
now = Time.now - 1 # 1 second ago to avoid NFS cache issue
File.utime(now, now, @name1)
File.utime(now, now, @name2)
(@file1.stat <=> @file2.stat).should == 0
28 changes: 14 additions & 14 deletions spec/ruby/core/float/constants_spec.rb
Original file line number Diff line number Diff line change
@@ -1,60 +1,60 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Float#CONSTANTS" do
specify "the DIG value is 15" do
describe "Float constant" do
it "DIG is 15" do
Float::DIG.should == 15
end

it "the EPSILON value is" do
it "EPSILON is" do
Float::EPSILON.should == eval("0.0000000000000002220446049250313080847263336181640625")
end

it "the MANT_DIG is 53" do
it "MANT_DIG is 53" do
Float::MANT_DIG.should == 53
end

it "the MAX_10_EXP is 308" do
it "MAX_10_EXP is 308" do
Float::MAX_10_EXP.should == 308
end

it "the MIN_10_EXP is -308" do
it "MIN_10_EXP is -308" do
Float::MIN_10_EXP.should == -307
end

it "the MAX_EXP is 1024" do
it "MAX_EXP is 1024" do
Float::MAX_EXP.should == 1024
end

it "the MIN_EXP is -1021" do
it "MIN_EXP is -1021" do
Float::MIN_EXP.should == -1021
end

it "the MAX is 1.79769313486232e+308" do
it "MAX is 1.79769313486232e+308" do
Float::MAX.should == eval("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0")
end

not_compliant_on :jruby do
it "the MIN is 2.2250738585072e-308" do
it "MIN is 2.2250738585072e-308" do
Float::MIN.should == eval("2.225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625e-308")
end
end

# TODO: Does this actually constitute noncompliance?
deviates_on :jruby do
it "the MIN is 4.9e-324" do
it "MIN is 4.9e-324" do
Float::MIN.should == 4.9e-324
end
end

it "the RADIX is 2" do
it "RADIX is 2" do
Float::RADIX.should == 2
end

it "the INFINITY is the positive infinity" do
it "INFINITY is the positive infinity" do
Float::INFINITY.infinite?.should == 1
end

it "the NAN is 'not a number'" do
it "NAN is 'not a number'" do
Float::NAN.nan?.should be_true
end
end
46 changes: 46 additions & 0 deletions spec/ruby/core/float/next_float_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.2" do
describe "Float#next_float" do
it "returns a float the smallest possible step greater than the receiver" do
barely_positive = 0.0.next_float
barely_positive.should == 0.0.next_float

barely_positive.should > 0.0
barely_positive.should < barely_positive.next_float

midpoint = barely_positive / 2
[0.0, barely_positive].should include midpoint
end

it "steps directly between MAX and INFINITY" do
(-Float::INFINITY).next_float.should == -Float::MAX
Float::MAX.next_float.should == Float::INFINITY
end

it "steps directly between 1.0 and 1.0 + EPSILON" do
1.0.next_float.should == 1.0 + Float::EPSILON
end

it "steps directly between -1.0 and -1.0 + EPSILON/2" do
(-1.0).next_float.should == -1.0 + Float::EPSILON/2
end

it "reverses the effect of prev_float" do
num = rand
num.prev_float.next_float.should == num
end

it "returns negative zero when stepping upward from just below zero" do
x = 0.0.prev_float.next_float
(1/x).should == -Float::INFINITY
x = (-0.0).prev_float.next_float
(1/x).should == -Float::INFINITY
x.next_float.should > 0
end

it "returns NAN if NAN was the receiver" do
Float::NAN.next_float.nan?.should == true
end
end
end
46 changes: 46 additions & 0 deletions spec/ruby/core/float/prev_float_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.2" do
describe "Float#prev_float" do
it "returns a float the smallest possible step smaller than the receiver" do
barely_negative = 0.0.prev_float
barely_negative.should == 0.0.prev_float

barely_negative.should < 0.0
barely_negative.should > barely_negative.prev_float

midpoint = barely_negative / 2
[0.0, barely_negative].should include midpoint
end

it "steps directly between MAX and INFINITY" do
Float::INFINITY.prev_float.should == Float::MAX
(-Float::MAX).prev_float.should == -Float::INFINITY
end

it "steps directly between 1.0 and 1.0 - EPSILON/2" do
1.0.prev_float.should == 1.0 - Float::EPSILON/2
end

it "steps directly between -1.0 and -1.0 - EPSILON" do
(-1.0).prev_float.should == -1.0 - Float::EPSILON
end

it "reverses the effect of next_float" do
num = rand
num.next_float.prev_float.should == num
end

it "returns positive zero when stepping downward from just above zero" do
x = 0.0.next_float.prev_float
(1/x).should == Float::INFINITY
x = (-0.0).next_float.prev_float
(1/x).should == Float::INFINITY
x.prev_float.should < 0
end

it "returns NAN if NAN was the receiver" do
Float::NAN.prev_float.nan?.should == true
end
end
end
7 changes: 0 additions & 7 deletions spec/ruby/core/kernel/__send___spec.rb

This file was deleted.

16 changes: 1 addition & 15 deletions spec/ruby/core/kernel/autoload_spec.rb
Original file line number Diff line number Diff line change
@@ -57,22 +57,8 @@ def check_autoload(const)
end

describe "when Object is frozen" do
before :each do
non_existent = fixture __FILE__, "no_autoload.rb"

@script = <<-"EOD"
Object.freeze
begin
autoload :ANY_CONSTANT, "#{non_existent}"
rescue Exception => e
print e.class, " - ", defined?(ANY_CONSTANT).inspect
end
EOD
end

it "raises a RuntimeError before defining the constant" do
ruby_exe(@script, args: "2>&1", escape: true).should == "RuntimeError - nil"
ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "RuntimeError - nil"
end
end
end
15 changes: 0 additions & 15 deletions spec/ruby/core/kernel/callcc_spec.rb

This file was deleted.

7 changes: 7 additions & 0 deletions spec/ruby/core/kernel/fixtures/autoload_frozen.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Object.freeze

begin
autoload :ANY_CONSTANT, "no_autoload.rb"
rescue Exception => e
print e.class, " - ", defined?(ANY_CONSTANT).inspect
end
14 changes: 13 additions & 1 deletion spec/ruby/core/kernel/lambda_spec.rb
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@

describe "Kernel.lambda" do
it_behaves_like(:kernel_lambda, :lambda)
it_behaves_like(:kernel_lambda_return_like_method, :lambda)

it "is a private method" do
Kernel.should have_private_instance_method(:lambda)
@@ -58,5 +57,18 @@
}.should_not raise_error(ArgumentError)
end

it "returns from the lambda itself, not the creation site of the lambda" do
@reached_end_of_method = nil
def test
send(@method) { return }.call
@reached_end_of_method = true
end
test
@reached_end_of_method.should be_true
end

it "allows long returns to flow through it" do
KernelSpecs::Lambda.new.outer(@method).should == :good
end
end

25 changes: 0 additions & 25 deletions spec/ruby/core/kernel/method_missing_spec.rb

This file was deleted.

4 changes: 2 additions & 2 deletions spec/ruby/core/kernel/public_send_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/send', __FILE__)
require File.expand_path('../../../shared/basicobject/send', __FILE__)

describe "Kernel#public_send" do
it "invokes the named public method" do
@@ -70,5 +70,5 @@ def bar
}.should raise_error(NoMethodError)
end

it_behaves_like(:kernel_send, :public_send)
it_behaves_like(:basicobject_send, :public_send)
end
4 changes: 2 additions & 2 deletions spec/ruby/core/kernel/send_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/send', __FILE__)
require File.expand_path('../../../shared/basicobject/send', __FILE__)

describe "Kernel#send" do
it "invokes the named public method" do
@@ -64,5 +64,5 @@ def bar
KernelSpecs::Foo.new.send(:aka).should == 'done2'
end

it_behaves_like(:kernel_send, :send)
it_behaves_like(:basicobject_send, :send)
end
17 changes: 0 additions & 17 deletions spec/ruby/core/kernel/shared/lambda.rb
Original file line number Diff line number Diff line change
@@ -6,21 +6,4 @@
it "raises an ArgumentError when no block is given" do
lambda { send(@method) }.should raise_error(ArgumentError)
end

end

describe :kernel_lambda_return_like_method, shared: true do
it "returns from the #{@method} itself, not the creation site of the #{@method}" do
@reached_end_of_method = nil
def test
send(@method) { return }.call
@reached_end_of_method = true
end
test
@reached_end_of_method.should be_true
end

it "allows long returns to flow through it" do
KernelSpecs::Lambda.new.outer(@method).should == :good
end
end
116 changes: 0 additions & 116 deletions spec/ruby/core/kernel/shared/send.rb

This file was deleted.

28 changes: 0 additions & 28 deletions spec/ruby/core/kernel/singleton_class_spec.rb
Original file line number Diff line number Diff line change
@@ -25,31 +25,3 @@
lambda { :foo.singleton_class }.should raise_error(TypeError)
end
end

ruby_version_is "2.1" do
describe "Kernel#singleton_class?" do
it "returns true for singleton classes" do
xs = self.singleton_class
xs.singleton_class?.should == true
end

it "returns false for other objects" do
c = Class.new
c.singleton_class?.should == false
end

describe("with singleton values") do
it "returns false for nil's singleton class" do
NilClass.singleton_class?.should == false
end

it "returns false for true's singleton class" do
TrueClass.singleton_class?.should == false
end

it "returns false for false's singleton class" do
FalseClass.singleton_class?.should == false
end
end
end
end
6 changes: 6 additions & 0 deletions spec/ruby/core/kernel/throw_spec.rb
Original file line number Diff line number Diff line change
@@ -45,6 +45,12 @@
lambda { throw :blah }.should raise_error(ArgumentError)
end

ruby_version_is "2.2" do
it "raises an UncaughtThrowError if there is no catch block for the symbol" do
lambda { throw :blah }.should raise_error(UncaughtThrowError)
end
end

it "raises ArgumentError if 3 or more arguments provided" do
lambda {
catch :blah do
6 changes: 0 additions & 6 deletions spec/ruby/core/kernel/type_spec.rb

This file was deleted.

27 changes: 0 additions & 27 deletions spec/ruby/core/main/def_spec.rb

This file was deleted.

36 changes: 6 additions & 30 deletions spec/ruby/core/math/atan2_spec.rb
Original file line number Diff line number Diff line change
@@ -33,40 +33,16 @@
Math.atan2(0.0, 0.0).should be_positive_zero
end

platform_is_not :solaris do
it "returns negative zero when passed -0.0, 0.0" do
Math.atan2(-0.0, 0.0).should be_negative_zero
end
it "returns negative zero when passed -0.0, 0.0" do
Math.atan2(-0.0, 0.0).should be_negative_zero
end

platform_is :solaris do
it "returns positive zero when passed -0.0, 0.0" do
Math.atan2(-0.0, 0.0).should be_positive_zero
end
it "returns Pi when passed 0.0, -0.0" do
Math.atan2(0.0, -0.0).should == Math::PI
end

platform_is_not :solaris do
it "returns Pi when passed 0.0, -0.0" do
Math.atan2(0.0, -0.0).should == Math::PI
end
end

platform_is :solaris do
it "returns positive zero when passed 0.0, -0.0" do
Math.atan2(0.0, -0.0).should be_positive_zero
end
end

platform_is_not :solaris do
it "returns -Pi when passed -0.0, -0.0" do
Math.atan2(-0.0, -0.0).should == -Math::PI
end
end

platform_is :solaris do
it "returns positive zero when passed -0.0, -0.0" do
Math.atan2(-0.0, -0.0).should be_positive_zero
end
it "returns -Pi when passed -0.0, -0.0" do
Math.atan2(-0.0, -0.0).should == -Math::PI
end

end
38 changes: 38 additions & 0 deletions spec/ruby/core/method/curry_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "2.2" do
describe "Method#curry" do
it "returns a curried proc" do
x = Object.new
def x.foo(a,b,c); [a,b,c]; end

c = x.method(:foo).curry
c.should be_kind_of(Proc)
c.(1).(2, 3).should == [1,2,3]
end

describe "with optional arity argument" do
before(:each) do
@obj = MethodSpecs::Methods.new
end

it "returns a curried proc when given correct arity" do
@obj.method(:one_req).curry(1).should be_kind_of(Proc)
@obj.method(:zero_with_splat).curry(100).should be_kind_of(Proc)
@obj.method(:two_req_with_splat).curry(2).should be_kind_of(Proc)
end

it "raises ArgumentError when the method requires less arguments than the given arity" do
lambda { @obj.method(:zero).curry(1) }.should raise_error(ArgumentError)
lambda { @obj.method(:one_req_one_opt).curry(3) }.should raise_error(ArgumentError)
lambda { @obj.method(:two_req_one_opt_with_block).curry(4) }.should raise_error(ArgumentError)
end

it "raises ArgumentError when the method requires more arguments than the given arity" do
lambda { @obj.method(:two_req_with_splat).curry(1) }.should raise_error(ArgumentError)
lambda { @obj.method(:one_req).curry(0) }.should raise_error(ArgumentError)
end
end
end
end
12 changes: 12 additions & 0 deletions spec/ruby/core/method/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -99,12 +99,24 @@ class A
def baz(a, b)
self.class
end
def overridden; end
end

class B < A
def overridden; end
end

module BetweenBAndC
def overridden; end
end

class C < B
include BetweenBAndC
def overridden; end
end

module OverrideAgain
def overridden; end
end

class D
41 changes: 41 additions & 0 deletions spec/ruby/core/method/super_method_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Method#super_method" do
ruby_version_is "2.2" do
it "returns the method that would be called by super in the method" do
obj = MethodSpecs::C.new
obj.extend MethodSpecs::OverrideAgain
meth = obj.method(:overridden)

s_meth = meth.super_method
s_meth.owner.should == MethodSpecs::C
s_meth.receiver.should == obj
s_meth.name.should == :overridden

ss_meth = meth.super_method.super_method
ss_meth.owner.should == MethodSpecs::BetweenBAndC
ss_meth.receiver.should == obj
ss_meth.name.should == :overridden

sss_meth = meth.super_method.super_method.super_method
sss_meth.owner.should == MethodSpecs::B
sss_meth.receiver.should == obj
sss_meth.name.should == :overridden
end

it "returns nil when there's no super method in the parent" do
method = Object.new.method(:method)
method.super_method.should == nil
end

it "returns nil when the parent's method is removed" do
object = MethodSpecs::B.new
method = object.method(:overridden)

MethodSpecs::A.class_eval { undef :overridden }

method.super_method.should == nil
end
end
end
12 changes: 6 additions & 6 deletions spec/ruby/core/module/deprecate_constant_spec.rb
Original file line number Diff line number Diff line change
@@ -12,34 +12,34 @@
@module.deprecate_constant :PRIVATE
@pattern = /deprecated/
end

describe "when accessing the deprecated module" do
it "passes the accessing" do
@module.deprecate_constant :PUBLIC1

@module::PUBLIC1.should equal(@value)
lambda { @module::PRIVATE }.should raise_error(NameError)
end

it "warns with a message" do
@module.deprecate_constant :PUBLIC1

lambda { @module::PUBLIC1 }.should complain(@pattern)
lambda { @module.const_get :PRIVATE }.should complain(@pattern)
end
end

it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2

lambda { @module::PUBLIC1 }.should complain(@pattern)
lambda { @module::PUBLIC2 }.should complain(@pattern)
end

it "returns self" do
@module.deprecate_constant(:PUBLIC1).should equal(@module)
end

it "raises a NameError when given an undefined name" do
lambda { @module.deprecate_constant :UNDEFINED }.should raise_error(NameError)
end
29 changes: 29 additions & 0 deletions spec/ruby/core/module/singleton_class_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.1" do
describe "Module#singleton_class?" do
it "returns true for singleton classes" do
xs = self.singleton_class
xs.singleton_class?.should == true
end

it "returns false for other classes" do
c = Class.new
c.singleton_class?.should == false
end

describe "with singleton values" do
it "returns false for nil's singleton class" do
NilClass.singleton_class?.should == false
end

it "returns false for true's singleton class" do
TrueClass.singleton_class?.should == false
end

it "returns false for false's singleton class" do
FalseClass.singleton_class?.should == false
end
end
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/numeric/negative_spec.rb
Original file line number Diff line number Diff line change
@@ -8,14 +8,14 @@
0.1.negative?.should be_false
end
end

describe "on zero" do
it "returns false" do
0.negative?.should be_false
0.0.negative?.should be_false
end
end

describe "on negative numbers" do
it "returns true" do
-1.negative?.should be_true
4 changes: 2 additions & 2 deletions spec/ruby/core/numeric/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -8,14 +8,14 @@
0.1.positive?.should be_true
end
end

describe "on zero" do
it "returns false" do
0.positive?.should be_false
0.0.positive?.should be_false
end
end

describe "on negative numbers" do
it "returns false" do
-1.positive?.should be_false
2 changes: 1 addition & 1 deletion spec/ruby/core/objectspace/each_object_spec.rb
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ class ObjectSpaceSpecEachOtherObject; end

it "finds an object stored in a local variable set in a binding manually" do
b = binding
b.local_variable_set(:local, ObjectSpaceFixtures::ObjectToBeFound.new(:local_in_manual_binding))
b.eval("local = ObjectSpaceFixtures::ObjectToBeFound.new(:local_in_manual_binding)")
ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_manual_binding)
end

1 change: 1 addition & 0 deletions spec/ruby/core/proc/curry_spec.rb
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@
it "raises an ArgumentError if called on a lambda that requires fewer than _arity_ arguments" do
lambda { @lambda_add.curry(4) }.should raise_error(ArgumentError)
lambda { lambda { true }.curry(1) }.should raise_error(ArgumentError)
lambda { lambda {|a, b=nil|}.curry(5) }.should raise_error(ArgumentError)
end

it "calls the curried proc with the arguments if _arity_ arguments have been given" do
6 changes: 3 additions & 3 deletions spec/ruby/core/string/end_with_spec.rb
Original file line number Diff line number Diff line change
@@ -14,9 +14,9 @@
s.end_with?('ll').should be_false
end

it "returns true if other is empty" do
s = 'hello'
s.end_with?('').should be_true
it "returns true if the search string is empty" do
"hello".end_with?("").should be_true
"".end_with?("").should be_true
end

it "returns true only if any ending match" do
1 change: 1 addition & 0 deletions spec/ruby/core/string/start_with_spec.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

it "returns true if the search string is empty" do
"hello".start_with?("").should be_true
"".start_with?("").should be_true
end

it "converts its argument using :to_str" do
3 changes: 3 additions & 0 deletions spec/ruby/core/unboundmethod/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -73,11 +73,14 @@ class A
def baz(a, b)
return [__FILE__, self.class]
end
def overridden; end
end

class B < A
def overridden; end
end

class C < B
def overridden; end
end
end
28 changes: 28 additions & 0 deletions spec/ruby/core/unboundmethod/super_method_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "UnboundMethod#super_method" do
ruby_version_is "2.2" do
it "returns the method that would be called by super in the method" do
meth = UnboundMethodSpecs::C.instance_method(:overridden)
meth = meth.super_method
meth.should == UnboundMethodSpecs::B.instance_method(:overridden)
meth = meth.super_method
meth.should == UnboundMethodSpecs::A.instance_method(:overridden)
end

it "returns nil when there's no super method in the parent" do
method = Object.instance_method(:method)
method.super_method.should == nil
end

it "returns nil when the parent's method is removed" do
object = UnboundMethodSpecs::B
method = object.instance_method(:overridden)

UnboundMethodSpecs::A.class_eval { undef :overridden }

method.super_method.should == nil
end
end
end
File renamed without changes.
12 changes: 12 additions & 0 deletions spec/ruby/fixtures/class.rb
Original file line number Diff line number Diff line change
@@ -108,6 +108,18 @@ def self.example_class_method
class L; end

class M < L; end

# Can't use a method here because of class definition in method body error
ANON_CLASS_FOR_NEW = lambda do
Class.new do
class NamedInModule
end

def self.get_class_name
NamedInModule.name
end
end
end
end

class Class
14 changes: 14 additions & 0 deletions spec/ruby/language/and_spec.rb
Original file line number Diff line number Diff line change
@@ -9,6 +9,13 @@
end

it "evaluates to the first condition not to be true" do
value = nil
(value && nil).should == nil
(value && false).should == nil
value = false
(value && nil).should == false
(value && false).should == false

("yes" && 1 && nil && true).should == nil
("yes" && 1 && false && true).should == false
end
@@ -41,6 +48,13 @@
end

it "evaluates to the first condition not to be true" do
value = nil
(value and nil).should == nil
(value and false).should == nil
value = false
(value and nil).should == false
(value and false).should == false

("yes" and 1 and nil and true).should == nil
("yes" and 1 and false and true).should == false
end
19 changes: 19 additions & 0 deletions spec/ruby/language/block_spec.rb
Original file line number Diff line number Diff line change
@@ -812,6 +812,25 @@ def m(a) yield a end
[a, b, c, d]
end.call(2, 3).should == [2, 6, [], 3]
end

ruby_version_is "2.2" do
describe "with a circular argument reference" do
it "shadows an existing local with the same name as the argument" do
a = 1
proc { |a=a| a }.call.should == nil
end

it "shadows an existing method with the same name as the argument" do
def a; 1; end
proc { |a=a| a }.call.should == nil
end

it "calls an existing method with the same name as the argument if explicitly using ()" do
def a; 1; end
proc { |a=a()| a }.call.should == 1
end
end
end
end

describe "with pattern matching" do
54 changes: 54 additions & 0 deletions spec/ruby/language/class_spec.rb
Original file line number Diff line number Diff line change
@@ -125,6 +125,60 @@ class ClassSpecs::Twenty; 20; end.should == 20
class ClassSpecs::Plus; 10 + 20; end.should == 30
class ClassSpecs::Singleton; class << self; :singleton; end; end.should == :singleton
end

describe "within a block creates a new class in the lexical scope" do
it "for named classes at the toplevel" do
klass = Class.new do
class Howdy
end

def self.get_class_name
Howdy.name
end
end

Howdy.name.should == 'Howdy'
klass.get_class_name.should == 'Howdy'
end

it "for named classes in a module" do
klass = ClassSpecs::ANON_CLASS_FOR_NEW.call

ClassSpecs::NamedInModule.name.should == 'ClassSpecs::NamedInModule'
klass.get_class_name.should == 'ClassSpecs::NamedInModule'
end

it "for anonymous classes" do
klass = Class.new do
def self.get_class
Class.new do
def self.foo
'bar'
end
end
end

def self.get_result
get_class.foo
end
end

klass.get_result.should == 'bar'
end

it "for anonymous classes assigned to a constant" do
klass = Class.new do
AnonWithConstant = Class.new

def self.get_class_name
AnonWithConstant.name
end
end

AnonWithConstant.name.should == 'AnonWithConstant'
klass.get_class_name.should == 'AnonWithConstant'
end
end
end

describe "An outer class definition" do
13 changes: 12 additions & 1 deletion spec/ruby/language/def_spec.rb
Original file line number Diff line number Diff line change
@@ -188,7 +188,7 @@ def foo(bar = bar)
end

ruby_version_is "2.2" do
it "does not call a method with the same name as the local" do
it "shadows an existing method with the same name as the local" do
def bar
1
end
@@ -198,6 +198,17 @@ def foo(bar = bar)
foo.should == nil
foo(2).should == 2
end

it "calls a method with the same name as the local when explicitly using ()" do
def bar
1
end
def foo(bar = bar())
bar
end
foo.should == 1
foo(2).should == 2
end
end
end

9 changes: 8 additions & 1 deletion spec/ruby/language/hash_spec.rb
Original file line number Diff line number Diff line change
@@ -74,10 +74,17 @@
end

it "accepts mixed 'key: value' and 'key => value' syntax" do
h = {a: 1, b: 2, "c" => 3}
h = {:a => 1, :b => 2, "c" => 3}
{a: 1, b: 2, "c" => 3}.should == h
end

ruby_version_is "2.2" do
it "accepts mixed 'key: value', 'key => value' and '\"key\"': value' syntax" do
h = {:a => 1, :b => 2, "c" => 3, :d => 4}
eval('{a: 1, :b => 2, "c" => 3, "d": 4}').should == h
end
end

it "expands an '**{}' element into the containing Hash literal initialization" do
{a: 1, **{b: 2}, c: 3}.should == {a: 1, b: 2, c: 3}
end
19 changes: 19 additions & 0 deletions spec/ruby/language/lambda_spec.rb
Original file line number Diff line number Diff line change
@@ -249,6 +249,25 @@ def create_lambda
result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l]
end
end

ruby_version_is "2.2" do
describe "with circular optional argument reference" do
it "shadows an existing local with the same name as the argument" do
a = 1
-> (a=a) { a }.call.should == nil
end

it "shadows an existing method with the same name as the argument" do
def a; 1; end
-> (a=a) { a }.call.should == nil
end

it "calls an existing method with the same name as the argument if explicitly using ()" do
def a; 1; end
-> (a=a()) { a }.call.should == 1
end
end
end
end
end

2 changes: 1 addition & 1 deletion spec/ruby/language/predefined/data_spec.rb
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
str.chomp.should == "data only"
end

platform_is_not :windows do
platform_is_not :windows, :solaris do
it "succeeds in locking the file DATA came from" do
path = fixture(__FILE__, "data_flock.rb")

4 changes: 0 additions & 4 deletions spec/ruby/library/bigdecimal/new_spec.rb
Original file line number Diff line number Diff line change
@@ -18,10 +18,6 @@
}
end

it "doesn't segfault when using a very large string to build the number" do
BigDecimal.new("1" + "0"*10000000)._dump.should == "10000017:0.1E10000001"
end

it "Number of significant digits >= given precision" do
BigDecimal.new("3.1415923", 10).precs[1].should >= 10
end
2 changes: 1 addition & 1 deletion spec/ruby/library/continuation/call_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../shared/continuation/call', __FILE__)
require File.expand_path('../shared/call', __FILE__)

with_feature :continuation_library do
require 'continuation'
2 changes: 1 addition & 1 deletion spec/ruby/library/continuation/element_reference_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../shared/continuation/call', __FILE__)
require File.expand_path('../shared/call', __FILE__)

with_feature :continuation_library do
require 'continuation'
File renamed without changes.
70 changes: 67 additions & 3 deletions spec/ruby/library/continuation/kernel/callcc_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,76 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../../../fixtures/kernel/callcc', __FILE__)
require File.expand_path('../../../../shared/kernel/callcc', __FILE__)
require File.expand_path('../../fixtures/callcc', __FILE__)

with_feature :continuation_library do
require 'continuation'

describe :kernel_callcc, shared: true do
it "is possible to exit a loop like a break" do
i = 0
@object.callcc do |x|
loop do
i += 1
x.call() if i == 5
end
end.should == nil
i.should == 5
end

it "is possible to call a continuation multiple times" do
i = 0
cont = nil
@cont = nil
@object.callcc {|cont| @cont = cont}
i += 1
@cont.call() if i < 5
i.should == 5
end

it "returns the results of a block if continuation is not called" do
cont = nil
a = @object.callcc {|cont| 0}
a.should == 0
end

it "returns the results of continuation once called" do
cont = nil
@cont = nil
a = @object.callcc {|cont| @cont = cont; 0}
@cont.call(1) if a == 0
a.should == 1
end

it "returns the arguments to call" do
@object.callcc {|cont| cont.call }.should == nil
@object.callcc {|cont| cont.call 1 }.should == 1
@object.callcc {|cont| cont.call 1,2,3 }.should == [1,2,3]
end

it "preserves changes to block-local scope" do
i = "before"
cont = @object.callcc { |c| c }
if cont # nil the second time
i = "after"
cont.call
end
i.should == "after"
end

it "preserves changes to method-local scope" do
# This spec tests that a continuation shares the same locals
# tuple as the scope that created it.
KernelSpecs.before_and_after.should == "after"
end

it "raises a LocalJumpError if callcc is not given a block" do
lambda { @object.callcc }.should raise_error(LocalJumpError)
end
end

describe "Kernel#callcc" do
it_behaves_like :kernel_instance_callcc, :callcc
it "is a private method" do
Kernel.should have_private_instance_method(:callcc)
end

it_behaves_like :kernel_callcc, :callcc, KernelSpecs::Method.new
end
5 changes: 3 additions & 2 deletions spec/ruby/library/continuation/new_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../shared/continuation/new', __FILE__)

with_feature :continuation_library do
require 'continuation'

describe "Continuation.new" do
it_behaves_like :continuation_new, :new
it "raises a NoMethodError" do
lambda { Continuation.new }.should raise_error(NoMethodError)
end
end
end
File renamed without changes.
7 changes: 6 additions & 1 deletion spec/ruby/library/matrix/to_a_spec.rb
Original file line number Diff line number Diff line change
@@ -2,5 +2,10 @@
require 'matrix'

describe "Matrix#to_a" do
it "needs to be reviewed for spec completeness"
it "returns the array of arrays that describe the rows of the matrix" do
Matrix[].to_a.should == []
Matrix[[]].to_a.should == [[]]
Matrix[[1]].to_a.should == [[1]]
Matrix[[1, 2], [3, 4]].to_a.should == [[1, 2],[3, 4]]
end
end
4 changes: 2 additions & 2 deletions spec/ruby/library/net/ftp/system_spec.rb
Original file line number Diff line number Diff line change
@@ -19,11 +19,11 @@

it "sends the SYST command to the server" do
@ftp.system
@ftp.last_response.should == "215 FTP Dummy Server (SYST)\n"
@ftp.last_response.should =~ /\A215 FTP Dummy Server \(SYST\)\Z/
end

it "returns the received information" do
@ftp.system.should == "FTP Dummy Server (SYST)\n"
@ftp.system.should =~ /\AFTP Dummy Server \(SYST\)\Z/
end

it "raises a Net::FTPPermError when the response code is 500" do
25 changes: 25 additions & 0 deletions spec/ruby/library/pp/pp_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require File.expand_path('../../../spec_helper', __FILE__)
require 'pp'

describe "PP.pp" do
it 'works with default arguments' do
array = [1, 2, 3]

lambda {
PP.pp array
}.should output "[1, 2, 3]\n"
end

it 'allows specifying out explicitly' do
array = [1, 2, 3]
other_out = IOStub.new

lambda {
PP.pp array, other_out
}.should output "" # no output on stdout

other_out.to_s.should == "[1, 2, 3]\n"
end

it "needs to be reviewed for spec completeness"
end
2 changes: 1 addition & 1 deletion spec/ruby/optional/capi/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ def compile_extension(name)
cc = RbConfig::CONFIG["CC"]
cflags = (ENV["CFLAGS"] || RbConfig::CONFIG["CFLAGS"]).dup
cflags += " #{RbConfig::CONFIG["ARCH_FLAG"]}" if RbConfig::CONFIG["ARCH_FLAG"]
cflags += " -fPIC" unless cflags.include?("-fPIC")
cflags += " #{RbConfig::CONFIG["CCDLFLAGS"]}" if RbConfig::CONFIG["CCDLFLAGS"]
incflags = "-I#{path} -I#{hdrdir}"
incflags << " -I#{arch_hdrdir}" if arch_hdrdir
incflags << " -I#{ruby_hdrdir}" if ruby_hdrdir
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../../fixtures/kernel/classes', __FILE__)
require File.expand_path('../../../fixtures/basicobject/method_missing', __FILE__)

describe :method_missing_defined_module, shared: true do
describe "for a Module with #method_missing defined" do
@@ -24,7 +24,7 @@
describe :method_missing_module, shared: true do
describe "for a Module" do
it "raises a NoMethodError when an undefined method is called" do
lambda { @object.method_undefined }.should raise_error(NoMethodError)
lambda { @object.no_such_method }.should raise_error(NoMethodError)
end

it "raises a NoMethodError when a protected method is called" do
@@ -44,7 +44,7 @@
end

it "is called when an undefined method is called" do
@object.method_undefined.should == :class_method_missing
@object.no_such_method.should == :class_method_missing
end

it "is called when an protected method is called" do
@@ -60,7 +60,7 @@
describe :method_missing_class, shared: true do
describe "for a Class" do
it "raises a NoMethodError when an undefined method is called" do
lambda { @object.method_undefined }.should raise_error(NoMethodError)
lambda { @object.no_such_method }.should raise_error(NoMethodError)
end

it "raises a NoMethodError when a protected method is called" do
@@ -84,7 +84,7 @@
end

it "is called when an undefined method is called" do
@instance.method_undefined.should == :instance_method_missing
@instance.no_such_method.should == :instance_method_missing
end

it "is called when an protected method is called" do
@@ -100,7 +100,7 @@
describe :method_missing_instance, shared: true do
describe "for an instance" do
it "raises a NoMethodError when an undefined method is called" do
lambda { @object.new.method_undefined }.should raise_error(NoMethodError)
lambda { @object.new.no_such_method }.should raise_error(NoMethodError)
end

it "raises a NoMethodError when a protected method is called" do
110 changes: 110 additions & 0 deletions spec/ruby/shared/basicobject/send.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
module SendSpecs
end

describe :basicobject_send, shared: true do
it "invokes the named method" do
class SendSpecs::Foo
def bar
'done'
end
end
SendSpecs::Foo.new.send(@method, :bar).should == 'done'
end

it "accepts a String method name" do
class SendSpecs::Foo
def bar
'done'
end
end
SendSpecs::Foo.new.send(@method, 'bar').should == 'done'
end

it "invokes a class method if called on a class" do
class SendSpecs::Foo
def self.bar
'done'
end
end
SendSpecs::Foo.send(@method, :bar).should == 'done'
end

it "raises a NameError if the corresponding method can't be found" do
class SendSpecs::Foo
def bar
'done'
end
end
lambda { SendSpecs::Foo.new.send(@method, :syegsywhwua) }.should raise_error(NameError)
end

it "raises a NameError if the corresponding singleton method can't be found" do
class SendSpecs::Foo
def self.bar
'done'
end
end
lambda { SendSpecs::Foo.send(@method, :baz) }.should raise_error(NameError)
end

it "raises an ArgumentError if no arguments are given" do
class SendSpecs::Foo; end
lambda { SendSpecs::Foo.new.send @method }.should raise_error(ArgumentError)
end

it "raises an ArgumentError if called with more arguments than available parameters" do
class SendSpecs::Foo
def bar; end
end

lambda { SendSpecs::Foo.new.send(@method, :bar, :arg) }.should raise_error(ArgumentError)
end

it "raises an ArgumentError if called with fewer arguments than required parameters" do
class SendSpecs::Foo
def foo(arg); end
end

lambda { SendSpecs::Foo.new.send(@method, :foo) }.should raise_error(ArgumentError)
end

it "succeeds if passed an arbitrary number of arguments as a splat parameter" do
class SendSpecs::Foo
def baz(*args) args end
end

begin
SendSpecs::Foo.new.send(@method, :baz).should == []
SendSpecs::Foo.new.send(@method, :baz, :quux).should == [:quux]
SendSpecs::Foo.new.send(@method, :baz, :quux, :foo).should == [:quux, :foo]
rescue
fail
end
end

it "succeeds when passing 1 or more arguments as a required and a splat parameter" do
class SendSpecs::Foo
def baz(first, *rest) [first, *rest] end
end

SendSpecs::Foo.new.send(@method, :baz, :quux).should == [:quux]
SendSpecs::Foo.new.send(@method, :baz, :quux, :foo).should == [:quux, :foo]
end

it "succeeds when passing 0 arguments to a method with one parameter with a default" do
class SendSpecs::Foo
def foo(first = true) first end
end

begin
SendSpecs::Foo.new.send(@method, :foo).should == true
SendSpecs::Foo.new.send(@method, :foo, :arg).should == :arg
rescue
fail
end
end

it "has a negative arity" do
method(@method).arity.should < 0
end
end
5 changes: 0 additions & 5 deletions spec/ruby/shared/continuation/new.rb

This file was deleted.

68 changes: 0 additions & 68 deletions spec/ruby/shared/kernel/callcc.rb

This file was deleted.

1 change: 1 addition & 0 deletions spec/tags/ruby/core/enumerable/each_cons_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fails:Enumerable#each_cons raises an Argument Error if there is not a single parameter > 0
fails:Enumerable#each_cons raises an ArgumentError if there is not a single parameter > 0
1 change: 1 addition & 0 deletions spec/tags/ruby/core/enumerable/each_slice_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fails:Enumerable#each_slice raises an Argument Error if there is not a single parameter > 0
fails:Enumerable#each_slice raises an ArgumentError if there is not a single parameter > 0
2 changes: 2 additions & 0 deletions spec/tags/ruby/core/enumerable/max_by_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fails:Enumerable#max_by when called with an argument n without a block returns an enumerator
fails:Enumerable#max_by when called with an argument n when n is nil returns the maximum element
1 change: 1 addition & 0 deletions spec/tags/ruby/core/enumerable/max_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Enumerable#max that is nil returns the maximum element
2 changes: 2 additions & 0 deletions spec/tags/ruby/core/enumerable/min_by_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fails:Enumerable#min_by when called with an argument n without a block returns an enumerator
fails:Enumerable#min_by when called with an argument n when n is nil returns the minimum element
1 change: 1 addition & 0 deletions spec/tags/ruby/core/enumerable/min_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Enumerable#min that is nil returns the minimum element
4 changes: 4 additions & 0 deletions spec/tags/ruby/core/enumerable/slice_when_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#slice_when when given a block returns an enumerator
fails:Enumerable#slice_when when given a block splits chunks between adjacent elements i and j where the block returns true
fails:Enumerable#slice_when when given a block calls the block for length of the receiver enumerable minus one times
fails:Enumerable#slice_when when not given a block raises an ArgumentError
2 changes: 2 additions & 0 deletions spec/tags/ruby/core/file/birthtime_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fails:File.birthtime raises an NotImplementedError
fails:File#birthtime raises an NotImplementedError
1 change: 1 addition & 0 deletions spec/tags/ruby/core/file/stat/birthtime_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:File::Stat#birthtime raises an NotImplementedError
1 change: 1 addition & 0 deletions spec/tags/ruby/core/kernel/eval_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
fails:Kernel#eval allows a binding to be captured inside an eval
fails:Kernel#eval raises a LocalJumpError if there is no lambda-style closure in the chain
fails:Kernel#eval unwinds through a Proc-style closure and returns from a lambda-style closure in the closure chain
1 change: 1 addition & 0 deletions spec/tags/ruby/core/kernel/throw_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Kernel.throw raises an UncaughtThrowError if there is no catch block for the symbol
1 change: 1 addition & 0 deletions spec/tags/ruby/core/method/curry_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Method#curry with optional arity argument raises ArgumentError when the method requires less arguments than the given arity
17 changes: 17 additions & 0 deletions spec/tags/ruby/core/objectspace/each_object_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
fails:ObjectSpace.each_object calls the block once for each living, non-immediate object in the Ruby process
fails:ObjectSpace.each_object returns an enumerator if not given a block
fails:ObjectSpace.each_object doesn't find an object stored in a WeakRef that should have been cleared
fails:ObjectSpace.each_object finds an object stored in a global variable
fails:ObjectSpace.each_object finds an object stored in a top-level constant
fails:ObjectSpace.each_object finds an object stored in a second-level constant
fails:ObjectSpace.each_object finds an object stored in a local variable
fails:ObjectSpace.each_object finds an object stored in a local variable captured in a block explicitly
fails:ObjectSpace.each_object finds an object stored in a local variable captured in a block implicitly
fails:ObjectSpace.each_object finds an object stored in a local variable captured in a Proc#binding
fails:ObjectSpace.each_object finds an object stored in a local variable captured in a Kernel#binding
fails:ObjectSpace.each_object finds an object stored in a local variable set in a binding manually
fails:ObjectSpace.each_object finds an object stored in an array
fails:ObjectSpace.each_object finds an object stored in a hash key
fails:ObjectSpace.each_object finds an object stored in a hash value
fails:ObjectSpace.each_object finds an object stored in an instance variable
fails:ObjectSpace.each_object finds an object stored in a thread local
fails:ObjectSpace.each_object finds an object stored in a fiber local
fails:ObjectSpace.each_object finds an object captured in an at_exit handler
fails:ObjectSpace.each_object finds an object captured in finalizer
2 changes: 2 additions & 0 deletions spec/tags/ruby/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -8,3 +8,5 @@ fails:A block yielded a single Array assigns symbol keys from a Hash to keyword
fails:A block yielded a single Array assigns symbol keys from a Hash returned by #to_hash to keyword arguments
fails:A block yielded a single Array calls #to_hash on the argument but does not use the result when no keywords are present
fails:A block yielded a single Array assigns non-symbol keys to non-keyword arguments
fails:Post-args with optional args with a circular argument reference shadows an existing local with the same name as the argument
fails:Post-args with optional args with a circular argument reference shadows an existing method with the same name as the argument
1 change: 1 addition & 0 deletions spec/tags/ruby/language/def_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fails:An instance method with a default argument does not call a method with the same name as the local
fails:An instance method with a default argument shadows an existing method with the same name as the local
2 changes: 2 additions & 0 deletions spec/tags/ruby/language/lambda_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
fails:A lambda expression 'lambda { ... }' with an implicit block can be created
fails:A lambda literal -> () { } assigns variables from parameters with circular optional argument reference shadows an existing local with the same name as the argument
fails:A lambda literal -> () { } assigns variables from parameters with circular optional argument reference shadows an existing method with the same name as the argument
6 changes: 6 additions & 0 deletions spec/truffle/tags/core/basicobject/method_missing_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fails:BasicObject#method_missing for a Module with #method_missing defined is called when a protected method is called
fails:BasicObject#method_missing for a Module with #method_missing defined is called when a private method is called
fails:BasicObject#method_missing for a Class with #method_missing defined is called when an protected method is called
fails:BasicObject#method_missing for a Class with #method_missing defined is called when an private method is called
fails:BasicObject#method_missing for an instance with #method_missing defined is called when an protected method is called
fails:BasicObject#method_missing for an instance with #method_missing defined is called when an private method is called
1 change: 1 addition & 0 deletions spec/truffle/tags/core/binding/local_variables_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Binding#local_variables includes shadowed local variables only once
1 change: 1 addition & 0 deletions spec/truffle/tags/core/binding/receiver_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Binding#receiver returns the object to which binding is bound
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/enumerable/max_by_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#max_by when called with an argument n without a block returns an enumerator
fails:Enumerable#max_by when called with an argument n with a block returns an array containing the maximum n elements based on the block's value
fails:Enumerable#max_by when called with an argument n with a block on a enumerable of length x where x < n returns an array containing the maximum n elements of length n
fails:Enumerable#max_by when called with an argument n when n is nil returns the maximum element
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/enumerable/max_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#max when called with an argument n without a block returns an array containing the maximum n elements
fails:Enumerable#max when called with an argument n with a block returns an array containing the maximum n elements
fails:Enumerable#max when called with an argument n on a enumerable of length x where x < n returns an array containing the maximum n elements of length x
fails:Enumerable#max that is nil returns the maximum element
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/enumerable/min_by_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#min_by when called with an argument n without a block returns an enumerator
fails:Enumerable#min_by when called with an argument n with a block returns an array containing the minimum n elements based on the block's value
fails:Enumerable#min_by when called with an argument n with a block on a enumerable of length x where x < n returns an array containing the minimum n elements of length n
fails:Enumerable#min_by when called with an argument n when n is nil returns the minimum element
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/enumerable/min_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#min when called with an argument n without a block returns an array containing the minimum n elements
fails:Enumerable#min when called with an argument n with a block returns an array containing the minimum n elements
fails:Enumerable#min when called with an argument n on a enumerable of length x where x < n returns an array containing the minimum n elements of length x
fails:Enumerable#min that is nil returns the minimum element
6 changes: 6 additions & 0 deletions spec/truffle/tags/core/enumerable/slice_after_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fails:Enumerable#slice_after raises an ArgumentError when given an incorrect number of arguments
fails:Enumerable#slice_after when given an argument and no block calls === on the argument to determine when to yield
fails:Enumerable#slice_after when given an argument and no block doesn't yield an empty array if the filter matches the first entry or the last entry
fails:Enumerable#slice_after when given an argument and no block uses standard boolean as a test
fails:Enumerable#slice_after when given a block and no argument calls the block to determine when to yield
fails:Enumerable#slice_after when given a block and an argument raises an ArgumentError
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/enumerable/slice_when_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Enumerable#slice_when when given a block returns an enumerator
fails:Enumerable#slice_when when given a block splits chunks between adjacent elements i and j where the block returns true
fails:Enumerable#slice_when when given a block calls the block for length of the receiver enumerable minus one times
fails:Enumerable#slice_when when not given a block raises an ArgumentError
2 changes: 2 additions & 0 deletions spec/truffle/tags/core/file/birthtime_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fails:File.birthtime raises an NotImplementedError
fails:File#birthtime raises an NotImplementedError
1 change: 1 addition & 0 deletions spec/truffle/tags/core/file/flock_tags.txt
Original file line number Diff line number Diff line change
@@ -2,3 +2,4 @@ fails:File#flock blocks if trying to lock an exclusively locked file
fails:File#flock returns 0 if trying to lock a non-exclusively locked file
fails:File#flock fails with EBADF acquiring exclusive lock on read-only File
fails:File#flock fails with EBADF acquiring shared lock on read-only File
slow:File#flock returns false if trying to lock an exclusively locked file
1 change: 1 addition & 0 deletions spec/truffle/tags/core/file/stat/birthtime_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:File::Stat#birthtime raises an NotImplementedError
7 changes: 7 additions & 0 deletions spec/truffle/tags/core/float/next_float_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fails:Float#next_float returns a float the smallest possible step greater than the receiver
fails:Float#next_float steps directly between MAX and INFINITY
fails:Float#next_float steps directly between 1.0 and 1.0 + EPSILON
fails:Float#next_float steps directly between -1.0 and -1.0 + EPSILON/2
fails:Float#next_float reverses the effect of prev_float
fails:Float#next_float returns negative zero when stepping upward from just below zero
fails:Float#next_float returns NAN if NAN was the receiver
7 changes: 7 additions & 0 deletions spec/truffle/tags/core/float/prev_float_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fails:Float#prev_float returns a float the smallest possible step smaller than the receiver
fails:Float#prev_float steps directly between MAX and INFINITY
fails:Float#prev_float steps directly between 1.0 and 1.0 - EPSILON/2
fails:Float#prev_float steps directly between -1.0 and -1.0 - EPSILON
fails:Float#prev_float reverses the effect of next_float
fails:Float#prev_float returns positive zero when stepping downward from just above zero
fails:Float#prev_float returns NAN if NAN was the receiver
1 change: 1 addition & 0 deletions spec/truffle/tags/core/kernel/throw_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Kernel.throw raises an UncaughtThrowError if there is no catch block for the symbol
4 changes: 4 additions & 0 deletions spec/truffle/tags/core/method/curry_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fails:Method#curry returns a curried proc
fails:Method#curry with optional arity argument returns a curried proc when given correct arity
fails:Method#curry with optional arity argument raises ArgumentError when the method requires less arguments than the given arity
fails:Method#curry with optional arity argument raises ArgumentError when the method requires more arguments than the given arity
3 changes: 3 additions & 0 deletions spec/truffle/tags/core/method/super_method_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fails:Method#super_method returns the method that would be called by super in the method
fails:Method#super_method returns nil when there's no super method in the parent
fails:Method#super_method returns nil when the parent's method is removed
1 change: 1 addition & 0 deletions spec/truffle/tags/core/proc/curry_tags.txt
Original file line number Diff line number Diff line change
@@ -20,3 +20,4 @@ fails:Proc#curry with arity argument can be specified multiple times on the same
fails:Proc#curry with arity argument raises an ArgumentError if passed more than _arity_ arguments when created from a lambda
fails:Proc#curry with arity argument returns Procs with arities of -1 regardless of the value of _arity_
fails:Proc#curry combines arguments and calculates incoming arity accurately for successively currying
fails:Proc#curry with arity argument raises an ArgumentError if called on a lambda that requires fewer than _arity_ arguments
3 changes: 3 additions & 0 deletions spec/truffle/tags/core/unboundmethod/super_method_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fails:UnboundMethod#super_method returns the method that would be called by super in the method
fails:UnboundMethod#super_method returns nil when there's no super method in the parent
fails:UnboundMethod#super_method returns nil when the parent's method is removed
1 change: 1 addition & 0 deletions spec/truffle/tags/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -21,3 +21,4 @@ fails:A block yielded a single Array assigns symbol keys from a Hash to keyword
fails:A block yielded a single Array assigns symbol keys from a Hash returned by #to_hash to keyword arguments
fails:A block yielded a single Array calls #to_hash on the argument but does not use the result when no keywords are present
fails:A block yielded a single Array assigns non-symbol keys to non-keyword arguments
fails:Post-args with optional args with a circular argument reference shadows an existing method with the same name as the argument
1 change: 1 addition & 0 deletions spec/truffle/tags/language/def_tags.txt
Original file line number Diff line number Diff line change
@@ -5,3 +5,4 @@ fails:A method definition in an eval creates an instance method
fails:A method definition in an eval creates a class method
fails:A method definition in an eval creates a singleton method
fails:An instance method with a default argument does not call a method with the same name as the local
fails:An instance method with a default argument shadows an existing method with the same name as the local
1 change: 1 addition & 0 deletions spec/truffle/tags/language/lambda_tags.txt
Original file line number Diff line number Diff line change
@@ -18,3 +18,4 @@ fails:"A lambda expression 'lambda { ... }' assigns variables from parameters fo
fails:"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a, b=1, *c, d, e:, f: 2, g:, **k, &l|\n [a, b, c, d, e, f, g, k, l]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (**) { }"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a, b) { [a, b] }"
fails:A lambda literal -> () { } assigns variables from parameters with circular optional argument reference shadows an existing method with the same name as the argument
32 changes: 1 addition & 31 deletions spec/truffle/truffle.mspec
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ class MSpecScript
"spec/ruby/language"
]

core = [
set :core, [
"spec/ruby/core",

# Can't load these - so tags aren't enough to exclude them. The problem is
@@ -39,36 +39,6 @@ class MSpecScript
"^spec/ruby/core/io/advise_spec.rb",
]

core += [
# Windows
"^spec/ruby/core/method/source_location_spec.rb",
"^spec/ruby/core/struct/each_spec.rb",
"^spec/ruby/core/struct/element_reference_spec.rb",
"^spec/ruby/core/struct/element_set_spec.rb",
"^spec/ruby/core/struct/eql_spec.rb",
"^spec/ruby/core/struct/equal_value_spec.rb",
"^spec/ruby/core/struct/hash_spec.rb",
"^spec/ruby/core/struct/initialize_copy_spec.rb",
"^spec/ruby/core/struct/initialize_spec.rb",
"^spec/ruby/core/struct/inspect_spec.rb",
"^spec/ruby/core/struct/instance_variables_spec.rb",
"^spec/ruby/core/struct/length_spec.rb",
"^spec/ruby/core/struct/members_spec.rb",
"^spec/ruby/core/struct/new_spec.rb",
"^spec/ruby/core/struct/select_spec.rb",
"^spec/ruby/core/struct/size_spec.rb",
"^spec/ruby/core/struct/struct_spec.rb",
"^spec/ruby/core/struct/to_a_spec.rb",
"^spec/ruby/core/struct/to_h_spec.rb",
"^spec/ruby/core/struct/to_s_spec.rb",
"^spec/ruby/core/struct/values_at_spec.rb",
"^spec/ruby/core/struct/values_spec.rb",
"^spec/ruby/core/symbol/versions/encoding_1.9_spec.rb",
"^spec/ruby/core/unboundmethod/source_location_spec.rb",
] if windows?

set :core, core

set :library, [
"spec/ruby/library",

2 changes: 1 addition & 1 deletion test/mri_truffle.index
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ ruby/test_signal.rb
ruby/test_sprintf.rb

# ruby/test_sprintf_comb.rb # almost all failing / regression
ruby/test_string.rb
# ruby/test_string.rb # String#inspect not 100% passing.
ruby/test_stringchar.rb
ruby/test_struct.rb
ruby/test_super.rb
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ public DynamicObject splat(VirtualFrame frame, Object object) {
}

// MRI tries to call dynamic respond_to? here.
Object respondToResult = respondToToA.call(frame, object, "respond_to?", null, Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), StringOperations.encodeByteList(method, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null), true);
Object respondToResult = respondToToA.call(frame, object, "respond_to?", null, makeMethodNameString(method), true);
if (respondToResult != DispatchNode.MISSING && respondToCast.executeBoolean(frame, respondToResult)) {
final Object array = toA.call(frame, object, method, null);

@@ -115,4 +115,9 @@ object, getContext().getCoreLibrary().getArrayClass(), method, array, this)
return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), new Object[]{object}, 1);
}

@CompilerDirectives.TruffleBoundary
private DynamicObject makeMethodNameString(String methodName) {
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), StringOperations.encodeByteList(methodName, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);
}

}
Original file line number Diff line number Diff line change
@@ -9,17 +9,20 @@
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CompilerDirectives;
import java.util.Set;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNode;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNodeGen;
@@ -283,17 +286,21 @@ public LocalVariablesNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization
public DynamicObject localVariables(DynamicObject binding) {
final DynamicObject array = Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), null, 0);

MaterializedFrame frame = Layouts.BINDING.getFrame(binding);

return listLocalVariables(getContext(), frame);
}

@TruffleBoundary
public static DynamicObject listLocalVariables(RubyContext context, Frame frame) {
final DynamicObject array = Layouts.ARRAY.createArray(context.getCoreLibrary().getArrayFactory(), null, 0);

while (frame != null) {
for (Object name : frame.getFrameDescriptor().getIdentifiers()) {
if (name instanceof String) {
ArrayOperations.append(array, getSymbol((String) name));
for (FrameSlot slot : frame.getFrameDescriptor().getSlots()) {
if (slot.getIdentifier() instanceof String) {
ArrayOperations.append(array, context.getSymbol((String) slot.getIdentifier()));
}
}

Original file line number Diff line number Diff line change
@@ -1231,21 +1231,9 @@ public LocalVariablesNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public DynamicObject localVariables() {
final DynamicObject array = Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), null, 0);

Frame frame = RubyCallStack.getCallerFrame(getContext()).getFrame(FrameInstance.FrameAccess.READ_ONLY, false);

while (frame != null) {
for (Object name : frame.getFrameDescriptor().getIdentifiers()) {
if (name instanceof String) {
ArrayOperations.append(array, getSymbol((String) name));
}
}

frame = RubyArguments.getDeclarationFrame(frame.getArguments());
}

return array;
return BindingNodes.LocalVariablesNode.listLocalVariables(getContext(), frame);
}

}
Original file line number Diff line number Diff line change
@@ -1156,7 +1156,7 @@ public DynamicObject forceEncoding(VirtualFrame frame, DynamicObject string, Obj

}

@CoreMethod(names = "getbyte", required = 1)
@CoreMethod(names = "getbyte", required = 1, lowerFixnumParameters = 0)
public abstract static class GetByteNode extends CoreMethodArrayArgumentsNode {

private final ConditionProfile negativeIndexProfile = ConditionProfile.createBinaryProfile();
Original file line number Diff line number Diff line change
@@ -342,7 +342,7 @@ public DynamicObject stringCheckNullSafe(DynamicObject string) {

}

@RubiniusPrimitive(name = "string_chr_at")
@RubiniusPrimitive(name = "string_chr_at", lowerFixnumParameters = 0)
public static abstract class StringChrAtPrimitiveNode extends RubiniusPrimitiveNode {

@Child private StringByteSubstringPrimitiveNode stringByteSubstringNode;
@@ -655,7 +655,7 @@ public Object stringIndex(VirtualFrame frame, DynamicObject string, DynamicObjec

}

@RubiniusPrimitive(name = "string_character_byte_index", needsSelf = false, lowerFixnumParameters = {1, 2})
@RubiniusPrimitive(name = "string_character_byte_index", needsSelf = false, lowerFixnumParameters = { 0, 1 })
@ImportStatic(StringGuards.class)
public static abstract class CharacterByteIndexNode extends RubiniusPrimitiveNode {

@@ -829,7 +829,7 @@ public Object stringCharacterIndex(DynamicObject string, DynamicObject pattern,

}

@RubiniusPrimitive(name = "string_byte_index", needsSelf = false, lowerFixnumParameters = {1, 2})
@RubiniusPrimitive(name = "string_byte_index", needsSelf = false, lowerFixnumParameters = { 0, 1 })
public static abstract class StringByteIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringByteIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
@@ -956,7 +956,7 @@ public Object stringPreviousByteIndex(DynamicObject string, int index) {

}

@RubiniusPrimitive(name = "string_copy_from", needsSelf = false, lowerFixnumParameters = {2, 3, 4})
@RubiniusPrimitive(name = "string_copy_from", needsSelf = false, lowerFixnumParameters = { 2, 3, 4 })
public static abstract class StringCopyFromPrimitiveNode extends RubiniusPrimitiveNode {

public StringCopyFromPrimitiveNode(RubyContext context, SourceSection sourceSection) {
@@ -1076,7 +1076,7 @@ public Object stringRindex(DynamicObject string, DynamicObject pattern, int star

}

@RubiniusPrimitive(name = "string_pattern", lowerFixnumParameters = {0, 1})
@RubiniusPrimitive(name = "string_pattern", lowerFixnumParameters = { 0, 1 })
public static abstract class StringPatternPrimitiveNode extends RubiniusPrimitiveNode {

@Child private AllocateObjectNode allocateObjectNode;
@@ -1154,7 +1154,7 @@ public DynamicObject stringByteAppend(DynamicObject string, DynamicObject other)

}

@RubiniusPrimitive(name = "string_substring", lowerFixnumParameters = { 1, 2 })
@RubiniusPrimitive(name = "string_substring", lowerFixnumParameters = { 0, 1 })
@ImportStatic(StringGuards.class)
public static abstract class StringSubstringPrimitiveNode extends RubiniusPrimitiveNode {

@@ -1294,7 +1294,7 @@ private DynamicObject makeSubstring(DynamicObject string, int beg, int len) {

}

@RubiniusPrimitive(name = "string_from_bytearray", needsSelf = false, lowerFixnumParameters = {1, 2})
@RubiniusPrimitive(name = "string_from_bytearray", needsSelf = false, lowerFixnumParameters = { 1, 2 })
public static abstract class StringFromByteArrayPrimitiveNode extends RubiniusPrimitiveNode {

public StringFromByteArrayPrimitiveNode(RubyContext context, SourceSection sourceSection) {

0 comments on commit 2359c8c

Please sign in to comment.