Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin' into mcjit
Browse files Browse the repository at this point in the history
brixen committed Jan 25, 2016
2 parents bab0934 + fa397f8 commit 0699fba
Showing 101 changed files with 1,496 additions and 368 deletions.
23 changes: 5 additions & 18 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -3,12 +3,15 @@ sudo: required
dist: trusty
compiler:
- clang
os:
- linux
- osx
ruby: 2.2.0
before_install:
- echo $LANG
- echo $LC_ALL
- if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update && sudo apt-get install -y libedit-dev llvm-3.6; fi
- if [ $TRAVIS_OS_NAME == linux ]; then ./scripts/llvm.sh; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install llvm; fi
- rvm use $RVM --install --binary --fuzzy
- gem update --system
- gem --version
before_script:
@@ -21,8 +24,6 @@ after_success:
branches:
only:
- master
- 1.8.7
- 2.2
- "/^v\\d+\\./"
notifications:
email: false
@@ -37,24 +38,10 @@ notifications:
on_success: change
on_failure: always
on_start: always
matrix:
exclude:
- compiler: clang
- os: linux
- os: osx
include:
- env: RVM=rbx-2
os: osx
- env: RVM=2.2.0
os: linux
compiler: clang
env:
global:
- LANG="en_US.UTF-8"
- RBXOPT=-Xint
- secure: olbok/GN6rOYvPnHBYWGz7giCoCdLFpT/7WSBHukYO3E0uNeqAUOOgW2BFOwCVWdSEJ/iTvJXZQ4qVZHX+6jRfvILZeGv+D2P93VdD8UFQRoTOfFC7esAo525s9fuKm9ehUGWZxlzGOBHHckky1jn6pEf8mlXAVM5e76dlH0fck=
- secure: aqG9eB/PrzQ7XJQN6YX/00sNVvwSB77saxXQzguL2WFjAXB74h6168Hzq+awHtNX/vfOb6ta7fpWLHrA0D+gmZnvTR29VlP6nd0vs1tkdX1/jWbiBHjamRffp+NWVdKbJKYn5iLOGXcuUMOzY/opLKOdvxKZfkxGMxR2tTNLZUE=
- secure: eElvNLjuFZAuixJdgom4Kv8RDziE4ArFcSEwYctvprMe/414CAaJcFkjQKg0RrJzAxZ51oGjdcZhEfmjNXcUU1gA5l++IdnlQm0x4kt8r7aql+q2geHzrrjhhwPujT9a8JNtXs6dHnbi+quNlxyVItWzeGJsjyhJzH8hxiFhCYI=
os:
- linux
- osx
2 changes: 1 addition & 1 deletion Gemfile.installed
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ gem "daedalus-core", "~> 0.1"
gem "rubinius-build_tools", "~> 2.0"
gem "rubinius-developer_tools", "~> 2.0"

gem "rubysl", "~> 2.0"
gem "rubysl", "~> 2.2"
gem "rubysl-test-unit", "~> 2.0"
gem "minitest", "~> 4.7"
gem "racc", "~> 1.4"
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
daedalus-core (0.5.0)
rake (10.4.2)
rake (10.5.0)
redcard (1.1.0)
rubinius-ast (2.3.2)
rubinius-bridge (1.1.0)
21 changes: 13 additions & 8 deletions README
Original file line number Diff line number Diff line change
@@ -11,10 +11,15 @@ Rubinius runs on Mac OS X and many Unix/Linux operating systems. Microsoft
Windows is not yet supported.


2. The Ruby Programming Language
2. Code of Conduct

Participation in the Rubinius project is governed by the Rubinius Code of
Conduct. See http://rubinius.com/code-of-conduct/

3. The Ruby Programming Language

Many popular Ruby applications, like Rails, run on Rubinius, which aims to be
compatible with Ruby version 2.1.
compatible with Ruby version 2.2.

Rubinius includes a Ruby parser, Ruby bytecode compiler, Ruby core library,
and C-API compatibility for native C extensions. The Ruby core library is
@@ -33,13 +38,13 @@ The following Ruby features are not supported on Rubinius:
* $SAFE levels


3. License
4. License

Rubinius uses the MPL-2.0 license. See LICENSE for details. Contributions made
prior to January 3rd, 2016 are licensed under the old BSD 3-clause license. A
copy of this license can be found in the file "BSD_LICENSE".

4. Installing Rubinius from Source
5. Installing Rubinius from Source

To install Rubinius, use the following steps:

@@ -56,21 +61,21 @@ information see http://rubinius.com/doc/en/getting-started/requirements/
and http://rubinius.com/doc/en/getting-started/building/.


5. Using RubyGems
6. Using RubyGems

Rubinius comes with RubyGems built-in. To install a gem, run the following:

$ rbx -S gem install <gem_name>


6. Documentation
7. Documentation

The Rubinius documentation is available at the Rubinius website:

http://rubinius.com


7. Issues & Support
8. Issues & Support

Please file tickets for bugs or problems. The issue tracker is:

@@ -81,7 +86,7 @@ For additional help, visit the Rubinius Gitter chat room:
https://gitter.im/rubinius/rubinius


8. Contributing
9. Contributing

The Rubinius team welcomes contributions. For more information, read the
CONTRIBUTING file in the root directory of Rubinius.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -9,10 +9,15 @@ Rubinius includes a bytecode virtual machine, generational garbage collector, an
Rubinius runs on Mac OS X and many Unix/Linux operating systems. Microsoft Windows is not yet supported.


### Code of Conduct

Participation in the Rubinius project is governed by the Rubinius [Code of
Conduct](http://rubinius.com/code-of-conduct/).

### The Ruby Programming Language

Many popular Ruby applications, like Rails, run on Rubinius, which aims to be
compatible with Ruby version 2.1.
compatible with Ruby version 2.2.

Rubinius includes a Ruby parser, Ruby bytecode compiler, Ruby core library,
and C-API compatibility for native C extensions. The Ruby core library is
6 changes: 6 additions & 0 deletions configure
Original file line number Diff line number Diff line change
@@ -77,6 +77,7 @@ class Configure
@dtrace_const = false
@have_lchmod = false
@have_lchown = false
@have_mkfifo = false
@debug_build = false
@include_dirs = []
@lib_dirs = []
@@ -1280,6 +1281,10 @@ int main() { return tgetnum(""); }
if has_function("lchown", ["sys/stat.h", "unistd.h"])
@have_lchown = true
end

if has_function("mkfifo", ["sys/stat.h", "sys/types.h"])
@have_mkfifo = true
end
end

def detect_structures
@@ -1641,6 +1646,7 @@ int main() { return tgetnum(""); }
#define RBX_LIBC "#{@libc}"
#define RBX_HAVE_LCHMOD #{@have_lchmod}
#define RBX_HAVE_LCHOWN #{@have_lchown}
#define RBX_HAVE_MKFIFO #{@have_mkfifo}
#define RBX_DEBUG_BUILD #{@debug_build.inspect}
EOC

8 changes: 0 additions & 8 deletions dockerfiles/ubuntu/14.04/Dockerfile

This file was deleted.

8 changes: 0 additions & 8 deletions dockerfiles/ubuntu/15.10/Dockerfile

This file was deleted.

9 changes: 5 additions & 4 deletions gems_list.txt
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ json-1.8.3.gem
minitest-4.7.5.gem
psych-2.0.17.gem
racc-1.4.14.gem
rake-10.4.2.gem
rake-10.5.0.gem
rb-readline-0.5.3.gem
rdoc-4.2.1.gem
redcard-1.1.0.gem
@@ -20,7 +20,7 @@ rubinius-melbourne-2.3.1.0.gem
rubinius-processor-2.3.0.gem
rubinius-profiler-2.0.2.gem
rubinius-toolset-2.3.1.gem
rubysl-2.1.0.gem
rubysl-2.2.0.gem
rubysl-abbrev-2.0.4.gem
rubysl-base64-2.0.0.gem
rubysl-benchmark-2.0.1.gem
@@ -70,9 +70,9 @@ rubysl-net-smtp-2.0.1.gem
rubysl-net-telnet-2.0.0.gem
rubysl-nkf-2.0.1.gem
rubysl-observer-2.0.0.gem
rubysl-open-uri-2.0.0.gem
rubysl-open3-2.0.0.gem
rubysl-openssl-2.8.0.gem
rubysl-open-uri-2.0.0.gem
rubysl-optparse-2.0.1.gem
rubysl-ostruct-2.1.0.gem
rubysl-pathname-2.1.0.gem
@@ -93,7 +93,7 @@ rubysl-securerandom-2.0.0.gem
rubysl-set-2.0.1.gem
rubysl-shellwords-2.0.0.gem
rubysl-singleton-2.0.0.gem
rubysl-socket-2.1.0.gem
rubysl-socket-2.1.1.gem
rubysl-stringio-2.0.0.gem
rubysl-strscan-2.0.0.gem
rubysl-sync-2.0.0.gem
@@ -107,6 +107,7 @@ rubysl-timeout-2.0.0.gem
rubysl-tmpdir-2.0.1.gem
rubysl-tsort-2.0.1.gem
rubysl-un-2.0.0.gem
rubysl-unicode_normalize-2.0.gem
rubysl-uri-2.0.0.gem
rubysl-weakref-2.0.0.gem
rubysl-webrick-2.0.0.gem
7 changes: 0 additions & 7 deletions kernel/bootstrap/io.rb
Original file line number Diff line number Diff line change
@@ -145,13 +145,6 @@ def socket_recv(bytes, flags, type)
raise PrimitiveFailure, "io_socket_read failed"
end

module Socketable
def accept
Rubinius.primitive :io_accept
raise PrimitiveFailure, "io_accept failed"
end
end

module TransferIO
def send_io
Rubinius.primitive :io_send_io
22 changes: 22 additions & 0 deletions kernel/common/argf.rb
Original file line number Diff line number Diff line change
@@ -330,6 +330,7 @@ def readbyte
def read(bytes=nil, output=nil)
# The user might try to pass in nil, so we have to check here
output ||= default_value
output.clear

if bytes
bytes_left = bytes
@@ -401,6 +402,27 @@ def readlines(sep=$/)

alias_method :to_a, :readlines

def readpartial(maxlen, output=nil)
output ||= default_value

unless advance!
output.clear
raise EOFError, "ARGF at end"
end

begin
@stream.readpartial(maxlen, output)
rescue EOFError => e
raise e if @use_stdin_only

@stream.close
@advance = true
advance! or raise e
end

return output
end

#
# Rewind the stream to its beginning.
#
61 changes: 42 additions & 19 deletions kernel/common/array.rb
Original file line number Diff line number Diff line change
@@ -300,28 +300,30 @@ def <=>(other)

def ==(other)
return true if equal?(other)
unless other.kind_of? Array
return false unless other.respond_to? :to_ary

unless other.kind_of?(Array)
return false unless other.respond_to?(:to_ary)
return other == self
end

return false unless size == other.size

Thread.detect_recursion self, other do
m = Rubinius::Mirror::Array.reflect other
Thread.detect_recursion(self, other) do
mirror = Rubinius::Mirror::Array.reflect(other)

md = @tuple
od = m.tuple
self_tuple = @tuple
other_tuple = mirror.tuple

i = @start
j = m.start
self_idx = @start
other_idx = mirror.start

total = i + @total
total = self_idx + @total

while i < total
return false unless md[i] == od[j]
i += 1
j += 1
while self_idx < total
return false unless self_tuple[self_idx] == other_tuple[other_idx]

self_idx += 1
other_idx += 1
end
end

@@ -338,8 +340,20 @@ def assoc(obj)
nil
end

def bsearch
return to_enum :bsearch unless block_given?
def bsearch(&block)
return to_enum :bsearch unless block

i = bsearch_index(&block)
return unless i

m = Rubinius::Mirror::Array.reflect self
tuple = m.tuple

tuple.at(i)
end

def bsearch_index
return to_enum :bsearch_index unless block_given?

m = Rubinius::Mirror::Array.reflect self

@@ -354,7 +368,7 @@ def bsearch
while max >= min and i >= start and i < total
x = yield tuple.at(i)

return tuple.at(i) if x == 0
return i if x == 0

case x
when Numeric
@@ -369,14 +383,14 @@ def bsearch
when false, nil
min = i + 1
else
raise TypeError, "Array#bsearch block must return Numeric or boolean"
raise TypeError, "block must return Numeric or boolean"
end

i = min + (max - min) / 2
end

return tuple.at(i) if max > min
return tuple.at(last_true) if last_true
return i if max > min
return last_true if last_true

nil
end
@@ -583,6 +597,15 @@ def delete_if
self
end

def dig(index, *remaining_indeces)
item = self[index]
return item if remaining_indeces.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*remaining_indeces)
end

def each_index
return to_enum(:each_index) { size } unless block_given?

2 changes: 1 addition & 1 deletion kernel/common/binding.rb
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ def from_proc?
end

def self.self_context(recv, variables)
recv.equal?(Kernel) ? recv : variables.self
Rubinius::Type.object_equal(recv, Kernel) ? recv : variables.self
end
private :self_context

10 changes: 3 additions & 7 deletions kernel/common/comparable.rb
Original file line number Diff line number Diff line change
@@ -3,15 +3,11 @@ def ==(other)
return true if equal?(other)

return false if Thread.detect_recursion(self, other) do
begin
unless comp = (self <=> other)
return false
end

return Comparable.compare_int(comp) == 0
rescue StandardError
unless comp = (self <=> other)
return false
end

return Comparable.compare_int(comp) == 0
end
end

2 changes: 2 additions & 0 deletions kernel/common/complex.rb
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ class Complex < Numeric
undef_method :step
undef_method :truncate
undef_method :i
undef_method :positive?
undef_method :negative?

def self.convert(real, imag = undefined)
if real.equal?(nil) || imag.equal?(nil)
71 changes: 42 additions & 29 deletions kernel/common/enumerable.rb
Original file line number Diff line number Diff line change
@@ -4,19 +4,13 @@
# these methods can be written *in those classes* to override these.

module Enumerable
def chunk(initial_state = nil, &original_block)
def chunk
raise ArgumentError, "no block given" unless block_given?
::Enumerator.new do |yielder|
previous = nil
accumulate = []
block = if initial_state.nil?
original_block
else
duplicated_initial_state = initial_state.dup
Proc.new{ |val| original_block.yield(val, duplicated_initial_state)}
end
each do |element|
key = block.yield(element)
key = yield(element)
if key.nil? || (key.is_a?(Symbol) && key.to_s[0, 1] == "_")
yielder.yield [previous, accumulate] unless accumulate.empty?
accumulate = []
@@ -136,18 +130,18 @@ def group_by
h
end

def slice_before(arg = undefined, &block)
if block_given?
has_init = !(undefined.equal? arg)
else
raise ArgumentError, "wrong number of arguments (0 for 1)" if undefined.equal? arg
block = Proc.new{ |elem| arg === elem }
end
def slice_before(pattern = undefined, &block)
pattern_given = !(undefined.equal? pattern)

raise ArgumentError, "cannot pass both pattern and block" if pattern_given && block_given?
raise ArgumentError, "a pattern or a block must be provided" if !pattern_given && !block_given?

block = Proc.new{ |elem| pattern === elem } if pattern_given

Enumerator.new do |yielder|
init = arg.dup if has_init
accumulator = nil
each do |element|
start_new = has_init ? block.yield(element, init) : block.yield(element)
start_new = block.yield(element)
if start_new
yielder.yield accumulator if accumulator
accumulator = [element]
@@ -164,7 +158,7 @@ def slice_after(pattern = undefined, &block)
pattern_given = !undefined.equal?(pattern)

raise ArgumentError, "cannot pass both pattern and block" if pattern_given && block_given?
raise ArgumentError, "wrong number of arguments (0 for 1)" if !pattern_given && !block_given?
raise ArgumentError, "a pattern or a block must be provided" if !pattern_given && !block_given?

block = Proc.new { |elem| pattern === elem } if pattern_given

@@ -212,6 +206,12 @@ def slice_when(&block)
end
end

def chunk_while(&block)
raise ArgumentError, "no block given" unless block_given?

slice_when { |before, after| !(yield before, after) }
end

def to_a(*arg)
ary = []
each(*arg) do
@@ -293,19 +293,30 @@ def each_with_index(*args)
def grep(pattern)
ary = []

if block_given?
each do
element = Rubinius.single_block_arg
if pattern === element
Regexp.set_block_last_match
each do
element = Rubinius.single_block_arg
if pattern === element
Regexp.set_block_last_match
if block_given?
ary << yield(element)
else
ary << element
end
end
else
each do
element = Rubinius.single_block_arg
if pattern === element
Regexp.set_block_last_match
end

ary
end

def grep_v(pattern)
ary = []

each do
element = Rubinius.single_block_arg
unless pattern === element
if block_given?
ary << yield(element)
else
ary << element
end
end
@@ -563,7 +574,9 @@ def find_index(value=undefined)

def first(n=undefined)
return __take__(n) unless undefined.equal?(n)
each { |element| return element }
each do
return Rubinius.single_block_arg
end
nil
end

30 changes: 20 additions & 10 deletions kernel/common/enumerator.rb
Original file line number Diff line number Diff line change
@@ -347,19 +347,29 @@ def reject
end

def grep(pattern)
if block_given?
Lazy.new(self, nil) do |yielder, *args|
val = args.length >= 2 ? args : args.first
if pattern === val
Regexp.set_block_last_match
Lazy.new(self, nil) do |yielder, *args|
val = args.length >= 2 ? args : args.first

if pattern === val
Regexp.set_block_last_match

if block_given?
yielder.yield yield(val)
else
yielder.yield val
end
end
else
Lazy.new(self, nil) do |yielder, *args|
val = args.length >= 2 ? args : args.first
if pattern === val
Regexp.set_block_last_match
end
end

def grep_v(pattern)
Lazy.new(self, nil) do |yielder, *args|
val = args.length >= 2 ? args : args.first

unless pattern === val
if block_given?
yielder.yield yield(val)
else
yielder.yield val
end
end
15 changes: 15 additions & 0 deletions kernel/common/file.rb
Original file line number Diff line number Diff line change
@@ -1195,6 +1195,21 @@ def self.sticky?(file_name)
return false
end

def self.mkfifo(file_name, mode = 0666)
raise NotImplementedError, "mkfifo is not implemented on this platform" unless Rubinius::HAVE_MKFIFO

file_name = file_name.to_path if file_name.respond_to?(:to_path)
file_name = StringValue(file_name)

ret = POSIX.mkfifo(file_name, mode)

if ret == 0
ret
else
Errno.handle(file_name)
end
end

class << self
alias_method :delete, :unlink
alias_method :exists?, :exist?
48 changes: 48 additions & 0 deletions kernel/common/hash.rb
Original file line number Diff line number Diff line change
@@ -252,6 +252,37 @@ def ==(other)
true
end

def <(other)
other = Rubinius::Type.coerce_to(other, Hash, :to_hash)
other > self
end

def <=(other)
other = Rubinius::Type.coerce_to(other, Hash, :to_hash)
other >= self
end

def >(other)
other = Rubinius::Type.coerce_to(other, Hash, :to_hash)

return false if size <= other.size

self >= other
end

def >=(other)
other = Rubinius::Type.coerce_to(other, Hash, :to_hash)

return false if size < other.size

other.each do |other_key, other_val|
val = fetch(other_key, undefined)
return false if undefined.equal?(val) || val != other_val
end

true
end

def assoc(key)
each_item { |e| return e.key, e.value if key == e.key }
end
@@ -322,6 +353,15 @@ def delete(key)
return yield(key) if block_given?
end

def dig(key, *remaining_keys)
item = self[key]
return item if remaining_keys.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*remaining_keys)
end

def each_item
return unless @state

@@ -358,6 +398,10 @@ def fetch(key, default=undefined)
raise KeyError, "key #{key} not found"
end

def fetch_values(*keys, &block)
keys.map { |key| fetch(key, &block) }
end

# Searches for an item matching +key+. Returns the item
# if found. Otherwise returns +nil+.
def find_item(key)
@@ -791,6 +835,10 @@ def to_hash
self
end

def to_proc
method(:[]).to_proc
end

def value?(value)
each_item do |item|
return true if item.value == value
49 changes: 37 additions & 12 deletions kernel/common/io.rb
Original file line number Diff line number Diff line change
@@ -1125,6 +1125,8 @@ def <<(obj)
# prog.rb:3:in `readlines': not opened for reading (IOError)
# from prog.rb:3
def close_read
return if closed?

if @mode == WRONLY || @mode == RDWR
raise IOError, 'closing non-duplex IO for reading'
end
@@ -1145,6 +1147,8 @@ def close_read
# from prog.rb:3:in `print'
# from prog.rb:3
def close_write
return if closed?

if @mode == RDONLY || @mode == RDWR
raise IOError, 'closing non-duplex IO for writing'
end
@@ -1394,6 +1398,7 @@ def each(sep_or_limit=$/, limit=nil, &block)
end
end

raise ArgumentError, "limit of 0 is invalid" if limit && limit.zero?
return if @ibuffer.exhausted?

EachReader.new(self, @ibuffer, sep, limit).each(&block)
@@ -1792,16 +1797,20 @@ def puts(*args)
args.each do |arg|
if arg.equal? nil
str = ""
elsif arg.kind_of? String
str = arg
elsif Thread.guarding? arg
str = "[...]"
elsif arg.kind_of?(Array)
else
Thread.recursion_guard arg do
arg.each do |a|
puts a
begin
arg.to_ary.each { |a| puts a }
rescue NoMethodError
unless (str = arg.to_s).kind_of? String
str = "#<#{arg.class}:0x#{arg.object_id.to_s(16)}>"
end
end
end
else
str = arg.to_s
end

if str
@@ -1886,21 +1895,34 @@ def read_all
#
# If the read buffer is not empty, read_nonblock reads from the
# buffer like readpartial. In this case, read(2) is not called.
def read_nonblock(size, buffer=nil)
def read_nonblock(size, buffer=nil, opts={})
raise ArgumentError, "illegal read size" if size < 0
ensure_open

if buffer.is_a?(Hash)
opts = buffer
buffer = nil
end

buffer = StringValue buffer if buffer

if @ibuffer.size > 0
return @ibuffer.shift(size)
end

if str = read_if_available(size)
begin
str = read_if_available(size)
rescue EAGAINWaitReadable => exc
raise exc unless opts[:exception] == false

return :wait_readable
end

if str
buffer.replace(str) if buffer
return str
else
raise EOFError, "stream closed"
raise EOFError, "stream closed" unless opts[:exception] == false
end
end

@@ -2429,7 +2451,7 @@ def write(data)
data.bytesize
end

def write_nonblock(data)
def write_nonblock(data, opts={})
ensure_open_and_writable

data = String data
@@ -2438,9 +2460,14 @@ def write_nonblock(data)
@ibuffer.unseek!(self) unless @sync

raw_write(data)
rescue EAGAINWaitWritable => exc
raise exc unless opts[:exception] == false

return :wait_writable
end

def close
return if closed?
begin
flush
ensure
@@ -2493,13 +2520,11 @@ def closed?
end

def close_read
raise IOError, 'closed stream' if closed?

close
end

def close_write
raise IOError, 'closed stream' if @write.closed?
return if @write.closed?

@write.close
end
3 changes: 2 additions & 1 deletion kernel/common/kernel.rb
Original file line number Diff line number Diff line change
@@ -510,7 +510,8 @@ def loop
while true
yield
end
rescue StopIteration
rescue StopIteration => e
e.result
end
end
module_function :loop
8 changes: 8 additions & 0 deletions kernel/common/numeric.rb
Original file line number Diff line number Diff line change
@@ -272,4 +272,12 @@ def denominator
def real?
true
end

def positive?
self > 0
end

def negative?
self < 0
end
end
4 changes: 2 additions & 2 deletions kernel/common/random.rb
Original file line number Diff line number Diff line change
@@ -66,9 +66,9 @@ def random_integer(limit)
end

def random_range(limit)
min, max = limit.max.coerce(limit.min)
min, max = limit.last.coerce(limit.first)
diff = max - min
diff += 1 if max.kind_of?(Integer)
diff += 1 if max.kind_of?(Integer) && !limit.exclude_end?
random(diff) + min
end

3 changes: 2 additions & 1 deletion kernel/common/string.rb
Original file line number Diff line number Diff line change
@@ -42,8 +42,9 @@ def clone
alias_method :dup, :clone
end

def initialize(arg = undefined)
def initialize(arg = undefined, encoding: nil)
replace arg unless undefined.equal?(arg)
self.force_encoding(encoding) if encoding
self
end

13 changes: 13 additions & 0 deletions kernel/common/struct.rb
Original file line number Diff line number Diff line change
@@ -181,6 +181,19 @@ def []=(var, obj)
return instance_variable_set(:"@#{var}", obj)
end

def dig(key, *remaining_keys)
item = begin
self[key]
rescue NameError
nil
end
return item if remaining_keys.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*remaining_keys)
end

def eql?(other)
return true if equal? other
return false if self.class != other.class
1 change: 1 addition & 0 deletions kernel/platform/posix.rb
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ module FFI::Platform::POSIX
attach_function :readlink, [:string, :pointer, :size_t], :ssize_t
attach_function :rename, [:string, :string], :int
attach_function :utimes, [:string, :pointer], :int
attach_function :mkfifo, [:string, :mode_t], :int

# directories
attach_function :chdir, [:string], :int
11 changes: 8 additions & 3 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -254,21 +254,26 @@ function rbx_deploy_docker_release {
echo "Deploying Docker release $(rbx_revision_version)..."

local version release file url response sha
local -a paths=("15.10" "14.04")
local -a paths=("12.04")

version=$(rbx_revision_version)
release=$(rbx_release_name)
file="Dockerfile"

for path in "${paths[@]}"; do
url="https://api.github.com/repos/rubinius/rubinius/contents/dockerfiles/ubuntu/$path/$file"
url="https://api.github.com/repos/rubinius/docker/contents/ubuntu/$path/$file"
response=$(curl "$url?access_token=$GITHUB_OAUTH_TOKEN")

cat > "$file" <<EOF
FROM ubuntu:$path
RUN apt-get update && apt-get install -y \
bzip2 \
libyaml-0-2 \
libssl1.0.0
ADD https://rubinius-binaries-rubinius-com.s3-us-west-2.amazonaws.com/ubuntu/$path/x86_64/$release /tmp/rubinius.tar.bz2
RUN apt-get -y install bzip2 && cd /opt && tar xvjf /tmp/rubinius.tar.bz2
RUN cd /opt && tar xvjf /tmp/rubinius.tar.bz2
ENV PATH /opt/rubinius/$version/bin:/opt/rubinius/$version/gems/bin:\$PATH
7 changes: 1 addition & 6 deletions scripts/llvm.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/bin/bash

LLVM_TAR=llvm-3.4.2-x86_64-unknown-linux-gnu-4.7.tar.bz2

curl -o $LLVM_TAR https://s3.amazonaws.com/asset.rubini.us/prebuilt/$LLVM_TAR \
&& mkdir -p vendor/llvm \
&& tar -C vendor/llvm -xjf $LLVM_TAR \
&& mv vendor/llvm/include vendor/llvm/Release/
sudo apt-get update && sudo apt-get install -y libedit-dev llvm-3.6; fi
4 changes: 4 additions & 0 deletions scripts/tag.sh
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@ __dir__="$(cd "$(dirname "$0")" && pwd)"
source "$__dir__/configuration.sh"

function rbx_tag_release {
git fetch --all -p

IFS="." read -r -a array <<< "$(rbx_revision_version)"

let major=${array[0]}
@@ -31,6 +33,8 @@ EOM
rbx_tag_usage
fi

git fetch --all -p

IFS="." read -r -a array <<< "$(rbx_revision_version)"

let major=${array[0]}
11 changes: 4 additions & 7 deletions spec/ruby/core/argf/close_spec.rb
Original file line number Diff line number Diff line change
@@ -24,13 +24,10 @@
end
end

# This passes on 1.9 and 1.8 HEAD, but fails on 1.8.7 and 1.8.6
ruby_bug "#1633", "1.8.7.174" do
it "raises an IOError if called on a closed stream" do
argv [@file1_name] do
lambda { ARGF.close }.should_not raise_error
lambda { ARGF.close }.should raise_error(IOError)
end
it "returns self if called on a closed stream" do
argv [@file1_name] do
ARGF.close
ARGF.close.should == ARGF
end
end

44 changes: 3 additions & 41 deletions spec/ruby/core/argf/read_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/read', __FILE__)

describe "ARGF.read" do
it_behaves_like :argf_read, :read

before :each do

@file1_name = fixture __FILE__, "file1.txt"
@@ -28,34 +31,6 @@
end
end

it "treats second nil argument as no output buffer" do
argv [@file1_name] do
ARGF.read(nil, nil).should == @file1
end
end

it "treats second argument as an output buffer" do
argv [@file1_name] do
buffer = ""
ARGF.read(nil, buffer)
buffer.should == @file1
end
end

it "reads a number of bytes from the first file" do
argv [@file1_name] do
ARGF.read(5).should == @file1[0,5]
end
end

it "reads from a single file consecutively" do
argv [@file1_name] do
ARGF.read(1).should == @file1[0,1]
ARGF.read(2).should == @file1[1,2]
ARGF.read(3).should == @file1[3,3]
end
end

it "reads the contents of two files" do
argv [@file1_name, @file2_name] do
ARGF.read.should == @file1 + @file2
@@ -81,11 +56,6 @@
stdin.should == @stdin
end

it "reads a number of bytes from stdin" do
stdin = ruby_exe("print ARGF.read(10)", :args => "< #{@stdin_name}")
stdin.should == @stdin[0,10]
end

it "reads the contents of one file and stdin" do
stdin = ruby_exe("print ARGF.read", :args => "#{@file1_name} - < #{@stdin_name}")
stdin.should == @file1 + @stdin
@@ -97,14 +67,6 @@
end
end

platform_is_not :windows do
it "reads the contents of a special device file" do
argv ['/dev/zero'] do
ARGF.read(100).should == "\000" * 100
end
end
end

with_feature :encoding do

before :each do
75 changes: 75 additions & 0 deletions spec/ruby/core/argf/readpartial_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/read', __FILE__)

describe "ARGF.readpartial" do
it_behaves_like :argf_read, :readpartial

before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@stdin_name = fixture __FILE__, "stdin.txt"

@file1 = File.read @file1_name
@file2 = File.read @file2_name
@stdin = File.read @stdin_name
end

it "raises an ArgumentError if called without a maximum read length" do
argv [@file1_name] do
lambda { ARGF.readpartial }.should raise_error(ArgumentError)
end
end

it "reads maximum number of bytes from one file at a time" do
argv [@file1_name, @file2_name] do
len = @file1.size + @file2.size
ARGF.readpartial(len).should == @file1
end
end

it "clears output buffer even if EOFError is raised because ARGF is at end" do
begin
output = "to be cleared"

argv [@file1_name] do
ARGF.read
ARGF.readpartial(1, output)
end
rescue EOFError
output.should == ""
end
end

it "reads maximum number of bytes from one file at a time" do
argv [@file1_name, @file2_name] do
len = @file1.size + @file2.size
ARGF.readpartial(len).should == @file1
end
end

it "returns an empty string if EOFError is raised while reading any but the last file" do
argv [@file1_name, @file2_name] do
ARGF.readpartial(@file1.size)
ARGF.readpartial(1).should == ""
end
end

it "raises an EOFError if the exception was raised while reading the last file" do
argv [@file1_name, @file2_name] do
ARGF.readpartial(@file1.size)
ARGF.readpartial(1)
ARGF.readpartial(@file2.size)
lambda { ARGF.readpartial(1) }.should raise_error(EOFError)
lambda { ARGF.readpartial(1) }.should raise_error(EOFError)
end
end

it "raises an EOFError if the exception was raised while reading STDIN" do
ruby_str = <<-STR
print ARGF.readpartial(#{@stdin.size})
ARGF.readpartial(1) rescue print $!.class
STR
stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true)
stdin.should == @stdin + "EOFError"
end
end
62 changes: 62 additions & 0 deletions spec/ruby/core/argf/shared/read.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
describe :argf_read, shared: true do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@stdin_name = fixture __FILE__, "stdin.txt"

@file1 = File.read @file1_name
@stdin = File.read @stdin_name
end

after :each do
ARGF.close unless ARGF.closed?
end

it "treats second nil argument as no output buffer" do
argv [@file1_name] do
ARGF.send(@method, @file1.size, nil).should == @file1
end
end

it "treats second argument as an output buffer" do
argv [@file1_name] do
buffer = ""
ARGF.send(@method, @file1.size, buffer)
buffer.should == @file1
end
end

it "clears output buffer before appending to it" do
argv [@file1_name] do
buffer = "to be cleared"
ARGF.send(@method, @file1.size, buffer)
buffer.should == @file1
end
end

it "reads a number of bytes from the first file" do
argv [@file1_name] do
ARGF.send(@method, 5).should == @file1[0, 5]
end
end

it "reads from a single file consecutively" do
argv [@file1_name] do
ARGF.send(@method, 1).should == @file1[0, 1]
ARGF.send(@method, 2).should == @file1[1, 2]
ARGF.send(@method, 3).should == @file1[3, 3]
end
end

it "reads a number of bytes from stdin" do
stdin = ruby_exe("print ARGF.#{@method}(10)", :args => "< #{@stdin_name}")
stdin.should == @stdin[0, 10]
end

platform_is_not :windows do
it "reads the contents of a special device file" do
argv ['/dev/zero'] do
ARGF.send(@method, 100).should == "\000" * 100
end
end
end
end
66 changes: 66 additions & 0 deletions spec/ruby/core/array/bsearch_index_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)

describe "Array#bsearch_index" do
it "returns an Enumerator when not passed a block" do
[1].bsearch_index.should be_an_instance_of(enumerator_class)
end

it_behaves_like :enumeratorized_with_unknown_size, :bsearch_index, [1, 2, 3]

it "raises a TypeError if the block returns an Object" do
lambda { [1].bsearch_index { Object.new } }.should raise_error(TypeError)
end

it "raises a TypeError if the block returns a String" do
lambda { [1].bsearch_index { "1" } }.should raise_error(TypeError)
end

context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
[0, 1, 2, 3].bsearch_index { |x| x > 3 }.should be_nil
end

it "returns nil if the block returns nil for every element" do
[0, 1, 2, 3].bsearch_index { |x| nil }.should be_nil
end

it "returns zero if the block returns true for every element" do
[0, 1, 2, 3].bsearch_index { |x| x < 4 }.should == 0
end

it "returns the smallest index for which block returns true" do
[0, 1, 3, 4].bsearch_index { |x| x >= 2 }.should == 2
[0, 1, 3, 4].bsearch_index { |x| x >= 1 }.should == 1
end
end

context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
[0, 1, 2, 3].bsearch_index { |x| x <=> 5 }.should be_nil
end

it "returns nil if the block returns greater than zero for every element" do
[0, 1, 2, 3].bsearch_index { |x| x <=> -1 }.should be_nil
end

it "returns nil if the block never returns zero" do
[0, 1, 3, 4].bsearch_index { |x| x <=> 2 }.should be_nil
end

it "accepts (+/-)Float::INFINITY from the block" do
[0, 1, 3, 4].bsearch_index { |x| Float::INFINITY }.should be_nil
[0, 1, 3, 4].bsearch_index { |x| -Float::INFINITY }.should be_nil
end

it "returns the index for which block returns 0.0" do
result = [0, 1, 2, 3, 4].bsearch_index { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
result.should == 2
end

it "returns the index for which block returns 0" do
result = [0, 1, 2, 3, 4].bsearch_index { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
result.should == 2
end
end
end
44 changes: 44 additions & 0 deletions spec/ruby/core/array/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Array#dig" do
it "returns the nested value specified by the sequence of indexes" do
a = [[1, [2, 3]]]

a.dig(0, 1, 1).should == 3
end

it "returns the nested value specified if the sequence includes a key" do
a = [42, new_hash(foo: :bar)]

a.dig(1, :foo).should == :bar
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]

lambda { a.dig(0, 1) }.should raise_error(TypeError)
end

it "raises an ArgumentError if no arguments provided" do
a = []

lambda { a.dig }.should raise_error(ArgumentError)
end

it "returns nil if any intermediate step is nil" do
a = [[1, [2, 3]]]

a.dig(1, 2, 3).should == nil
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
o = Object.new
a = [1, [2, o]]

def o.dig(*args)
{dug: args}
end

a.dig(1, 1, :bar, :baz).should == {dug: [:bar, :baz]}
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/bignum/negative_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Bignum#negative?" do
it "returns true if self is less than 0" do
bignum_value.coerce(-1).first.negative?.should == true
end

it "return false if self is 0" do
bignum_value.coerce(0).first.negative?.should == false
end

it "return false if self is greater than 0" do
bignum_value.coerce(1).first.negative?.should == false
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/bignum/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Bignum#positive?" do
it "returns true if self is greater than 0" do
bignum_value.coerce(1).first.positive?.should == true
end

it "returns false if self is 0" do
bignum_value.coerce(0).first.positive?.should == false
end

it "returns false if self is less than 0" do
bignum_value.coerce(-1).first.positive?.should == false
end
end
28 changes: 2 additions & 26 deletions spec/ruby/core/comparable/equal_value_spec.rb
Original file line number Diff line number Diff line change
@@ -37,33 +37,9 @@
(@a == @b).should be_false
end

it "returns false if calling #<=> on self returns a non-Integer" do
it "raises an ArgumentError if calling #<=> on self returns a non-Integer" do
@a.should_receive(:<=>).any_number_of_times.and_return("abc")
(@a == @b).should be_false
end

describe "when calling #<=> on self raises an Exception" do
before(:all) do
@raise_standard_error = @a.dup
def @raise_standard_error.<=>(b) raise StandardError, "test"; end

@raise_sub_standard_error = @a.dup
def @raise_sub_standard_error.<=>(b) raise TypeError, "test"; end

@not_standard_error = SyntaxError
@raise_not_standard_error = @a.dup
def @raise_not_standard_error.<=>(b) raise SyntaxError, "test"; end
end

it "raises the error if #<=> raises an Exception that excluding StandardError" do
lambda { @raise_not_standard_error == @b }.should raise_error(@not_standard_error)
end

# Behaviour confirmed by MRI test suite
it "returns false if #<=> raises a StandardError" do
(@raise_standard_error == @b).should be_false
(@raise_sub_standard_error == @b).should be_false
end
lambda { @a == @b }.should raise_error(ArgumentError)
end

context "when #<=> is not defined" do
6 changes: 5 additions & 1 deletion spec/ruby/core/dir/close_spec.rb
Original file line number Diff line number Diff line change
@@ -37,5 +37,9 @@
DirSpecs.delete_mock_dirs
end

it_behaves_like :dir_closed, :close
it "returns nil when called on a closed Dir instance" do
dir = Dir.open DirSpecs.mock_dir
dir.close
dir.close.should == nil
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/dir/shared/open.rb
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@

it "closes the Dir instance when the block exits if given a block" do
closed_dir = Dir.send(@method, DirSpecs.mock_dir) { |dir| dir }
lambda { closed_dir.close }.should raise_error(IOError)
closed_dir.close.should == nil
end

it "closes the Dir instance when the block exits the block even due to an exception" do
@@ -34,7 +34,7 @@
end
end.should raise_error

lambda { @closed_dir.close }.should raise_error(IOError)
@closed_dir.close.should == nil
end

it "calls #to_path on non-String arguments" do
24 changes: 5 additions & 19 deletions spec/ruby/core/enumerable/chunk_spec.rb
Original file line number Diff line number Diff line change
@@ -12,6 +12,11 @@
end.should raise_error(ArgumentError)
end

it 'raises an ArgumentError if called with an argument' do
e = EnumerableSpecs::Numerous.new(1, 2, 3, 2, 1)
lambda { e.chunk(42) { |x| x == 2 }.to_a }.should raise_error(ArgumentError)
end

it "returns an Enumerator if given a block" do
EnumerableSpecs::Numerous.new.chunk {}.should be_an_instance_of(enumerator_class)
end
@@ -51,25 +56,6 @@
lambda { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError)
end

describe "with [initial_state]" do
it "yields an element and an object value-equal but not identical to the object passed to #chunk" do
e = EnumerableSpecs::Numerous.new(1)
value = "value"

e.chunk(value) do |x, v|
x.should == 1
v.should == value
v.should_not equal(value)
end.to_a
end

it "does not yield the object passed to #chunk if it is nil" do
e = EnumerableSpecs::Numerous.new(1)
e.chunk(nil) { |*x| ScratchPad << x }.to_a
ScratchPad.recorded.should == [[1]]
end
end

it 'returned Enumerator size returns nil' do
e = EnumerableSpecs::NumerousWithSize.new(1, 2, 3, 2, 1)
enum = e.chunk { |x| true }
36 changes: 36 additions & 0 deletions spec/ruby/core/enumerable/chunk_while_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Enumerable#chunk_while" do
before :each do
ary = [10, 9, 7, 6, 4, 3, 2, 1]
@enum = EnumerableSpecs::Numerous.new *ary
@result = @enum.chunk_while { |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 false" 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.chunk_while 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.chunk_while }.should raise_error(ArgumentError)
end
end
end
5 changes: 5 additions & 0 deletions spec/ruby/core/enumerable/first_spec.rb
Original file line number Diff line number Diff line change
@@ -12,6 +12,11 @@
EnumerableSpecs::Empty.new.first.should == nil
end

it 'returns a gathered array from yield parameters' do
EnumerableSpecs::YieldsMulti.new.to_enum.first.should == [1, 2]
EnumerableSpecs::YieldsMixed2.new.to_enum.first.should == nil
end

it "raises a RangeError when passed a Bignum" do
enum = EnumerableSpecs::Empty.new
lambda { enum.first(bignum_value) }.should raise_error(RangeError)
34 changes: 34 additions & 0 deletions spec/ruby/core/enumerable/grep_v_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Enumerable#grep_v" do
it "returns an array of all elements not equal to the pattern when called without a block" do
pattern_cls = Class.new do
def ===(obj)
obj == '2'
end
end
enum = EnumerableSpecs::Numerous.new('2', 'a', 'nil', '3', false)

enum.grep_v(pattern_cls.new).should == ['a', 'nil', '3', false]
end

it "returns an array of all elements not equal to the pattern passed through the block" do
pattern_cls = Class.new do
def ===(obj)
/^ca/ =~ obj
end
end
enum = EnumerableSpecs::Numerous.new("cat", "coat", "car", "cadr", "cost")

enum.grep_v(pattern_cls.new) { |i| i.upcase }.should == ["COAT", "COST"]
end

it "calls the block with an array when yielded with multiple arguments" do
yields = []
EnumerableSpecs::YieldsMixed.new.grep_v(nil) { |v| yields << v }

yields.should == [1, [2], [3, 4], [5, 6, 7], [8, 9], []]
EnumerableSpecs::YieldsMixed.new.grep_v(nil).should == yields
end
end
28 changes: 2 additions & 26 deletions spec/ruby/core/enumerable/slice_before_spec.rb
Original file line number Diff line number Diff line change
@@ -41,32 +41,8 @@
end

describe "and an argument" do
it "calls the block with a copy of that argument" do
arg = [:foo]
first = nil
e = @enum.slice_before(arg) do |i, init|
init.should == arg
init.should_not equal(arg)
first = init
i == 6 || i == 2
end
e.should be_an_instance_of(enumerator_class)
e.to_a.should == [[7], [6, 5, 4, 3], [2, 1]]
e = @enum.slice_before(arg) do |i, init|
init.should_not equal(first)
end
e.to_a
end

quarantine! do # need to double-check with ruby-core. Might be wrong or too specific
it "duplicates the argument directly without calling dup" do
arg = EnumerableSpecs::Undupable.new
e = @enum.slice_before(arg) do |i, init|
init.initialize_dup_called.should be_true
false
end
e.to_a.should == [[7, 6, 5, 4, 3, 2, 1]]
end
it "raises an ArgumentError" do
lambda { @enum.slice_before("one") { |i| i == 6 } }.should raise_error(ArgumentError)
end
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/drop_while_spec.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.drop_while { |v| v }.size.should == nil
end

@@ -44,7 +44,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take(20).drop_while { |v| v }.size.should == nil
end

4 changes: 4 additions & 0 deletions spec/ruby/core/enumerator/lazy/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@ def self.gathered_yields
[nil, 0, [0, 1], [0, 1, 2], [0, 1, 2], nil, :default_arg, [], [], [0], [0, 1], [0, 1, 2]]
end

def self.gathered_non_array_yields
[nil, 0, nil, :default_arg]
end

def self.gathered_yields_with_args(arg, *args)
[nil, 0, [0, 1], [0, 1, 2], [0, 1, 2], nil, arg, args, [], [0], [0, 1], [0, 1, 2]]
end
4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/grep_spec.rb
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.grep(Object) {}.size.should == nil
enumerator_class::Lazy.new(Object.new, 100) {}.grep(Object).size.should == nil
end
@@ -58,7 +58,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.grep(Object) {}.size.should == nil
enumerator_class::Lazy.new(Object.new, 100) {}.grep(Object).size.should == nil
end
84 changes: 84 additions & 0 deletions spec/ruby/core/enumerator/lazy/grep_v_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Enumerator::Lazy#grep_v" do
before(:each) do
@yieldsmixed = EnumeratorLazySpecs::YieldsMixed.new.to_enum.lazy
@eventsmixed = EnumeratorLazySpecs::EventsMixed.new.to_enum.lazy
ScratchPad.record []
end

after(:each) do
ScratchPad.clear
end

it "requires an argument" do
enumerator_class::Lazy.instance_method(:grep_v).arity.should == 1
end

it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.grep_v(Object) {}
ret.should be_an_instance_of(enumerator_class::Lazy)
ret.should_not equal(@yieldsmixed)

ret = @yieldsmixed.grep_v(Object)
ret.should be_an_instance_of(enumerator_class::Lazy)
ret.should_not equal(@yieldsmixed)
end

it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.grep_v(Object) {}.size.should == nil
enumerator_class::Lazy.new(Object.new, 100) {}.grep_v(Object).size.should == nil
end

describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
it "stops after specified times when not given a block" do
(0..Float::INFINITY).lazy.grep_v(3..5).first(3).should == [0, 1, 2]

@eventsmixed.grep_v(Symbol).first(1)
ScratchPad.recorded.should == [:before_yield]
end

it "stops after specified times when given a block" do
(0..Float::INFINITY).lazy.grep_v(4..8, &:succ).first(3).should == [1, 2, 3]

@eventsmixed.grep_v(Symbol) {}.first(1)
ScratchPad.recorded.should == [:before_yield]
end
end

it "calls the block with a gathered array when yield with multiple arguments" do
yields = []
@yieldsmixed.grep_v(Array) { |v| yields << v }.force
yields.should == EnumeratorLazySpecs::YieldsMixed.gathered_non_array_yields

@yieldsmixed.grep_v(Array).force.should == yields
end

describe "on a nested Lazy" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object) {}.size.should == nil
enumerator_class::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object).size.should == nil
end

describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
it "stops after specified times when not given a block" do
(0..Float::INFINITY).lazy.grep_v(3..5).grep_v(6..10).first(3).should == [0, 1, 2]

@eventsmixed.grep_v(Symbol).grep_v(String).first(1)
ScratchPad.recorded.should == [:before_yield]
end

it "stops after specified times when given a block" do
(0..Float::INFINITY).lazy
.grep_v(1..2) { |n| n > 3 ? n : false }
.grep_v(false) { |n| n.even? ? n : false }
.first(3)
.should == [4, false, 6]

@eventsmixed.grep_v(Symbol) {}.grep_v(String) {}.first(1)
ScratchPad.recorded.should == [:before_yield]
end
end
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/initialize_spec.rb
Original file line number Diff line number Diff line change
@@ -31,11 +31,11 @@ def receiver.each
end
end

it "sets nil to size if not given a size" do
it "sets #size to nil if not given a size" do
@uninitialized.send(:initialize, @receiver) {}.size.should be_nil
end

it "sets nil to size if given size is nil" do
it "sets #size to nil if given size is nil" do
@uninitialized.send(:initialize, @receiver, nil) {}.size.should be_nil
end

4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/reject_spec.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.reject {}.size.should == nil
end

@@ -44,7 +44,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take(20).reject {}.size.should == nil
end

4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/shared/collect_concat.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.send(@method) { true }.size.should == nil
end

@@ -50,7 +50,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take(50) {}.send(@method) {}.size.should == nil
end

4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/shared/select.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.send(@method) { true }.size.should == nil
end

@@ -44,7 +44,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take(50) {}.send(@method) { true }.size.should == nil
end

2 changes: 1 addition & 1 deletion spec/ruby/core/enumerator/lazy/shared/to_enum.rb
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
ret.should_not equal(@infinite)
end

it "sets nil to size when not given a block" do
it "sets #size to nil when not given a block" do
enumerator_class::Lazy.new(Object.new, 100) {}.send(@method).size.should == nil
end

4 changes: 2 additions & 2 deletions spec/ruby/core/enumerator/lazy/take_while_spec.rb
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
ret.should_not equal(@yieldsmixed)
end

it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take_while { true }.size.should == nil
end

@@ -44,7 +44,7 @@
end

describe "on a nested Lazy" do
it "sets nil to size" do
it "sets #size to nil" do
enumerator_class::Lazy.new(Object.new, 100) {}.take(20).take_while { true }.size.should == nil
end

10 changes: 10 additions & 0 deletions spec/ruby/core/exception/receiver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "NameError#receiver" do
it "returns the receiver of the method call where the error occurred" do
receiver = 'receiver'
exception = receiver.doesnt_exist rescue $!

exception.receiver.should equal(receiver)
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/exception/system_call_error_spec.rb
Original file line number Diff line number Diff line change
@@ -62,12 +62,12 @@ def initialize
end

it "returns the errno given as optional argument to new" do
SystemCallError.new("message", -2**30).errno.should == -2**30
SystemCallError.new("message", -2**20).errno.should == -2**20
SystemCallError.new("message", -1).errno.should == -1
SystemCallError.new("message", 0).errno.should == 0
SystemCallError.new("message", 1).errno.should == 1
SystemCallError.new("message", 42).errno.should == 42
SystemCallError.new("message", 2**30).errno.should == 2**30
SystemCallError.new("message", 2**20).errno.should == 2**20
end
end

51 changes: 51 additions & 0 deletions spec/ruby/core/file/mkfifo_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "File.mkfifo" do
platform_is_not os: [:windows] do
before do
@path = tmp('fifo')
end

after do
rm_r(@path)
end

context "when path passed responds to :to_path" do
it "creates a FIFO file at the path specified" do
File.mkfifo(@path)
File.ftype(@path).should == "fifo"
end
end

context "when path passed is not a String value" do
it "raises a TypeError" do
lambda { File.mkfifo(:"/tmp/fifo") }.should raise_error(TypeError)
end
end

context "when path does not exist" do
it "raises an Errno::ENOENT exception" do
lambda { File.mkfifo("/bogus/path") }.should raise_error(Errno::ENOENT)
end
end

it "creates a FIFO file at the passed path" do
File.mkfifo(@path.to_s)
File.ftype(@path).should == "fifo"
end

it "creates a FIFO file with passed mode & ~umask" do
File.mkfifo(@path, 0755)
File.stat(@path).mode.should == 010755 & ~File.umask
end

it "creates a FIFO file with a default mode of 0666 & ~umask" do
File.mkfifo(@path)
File.stat(@path).mode.should == 010666 & ~File.umask
end

it "returns 0 after creating the FIFO file" do
File.mkfifo(@path).should == 0
end
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/fixnum/negative_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Fixnum#negative?" do
it "returns true if self is less than 0" do
-1.negative?.should == true
end

it "returns false if self is 0" do
0.negative?.should == false
end

it "returns false if self is greater than 0" do
1.negative?.should == false
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/fixnum/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Fixnum#positive?" do
it "returns true if self is greater than 0" do
1.positive?.should == true
end

it "returns false if self is 0" do
0.positive?.should == false
end

it "returns false if self is less than 0" do
-1.positive?.should == false
end
end
30 changes: 30 additions & 0 deletions spec/ruby/core/float/negative_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Float#negative?" do
it "returns true if self is less than 0.0" do
numbers = [
-1.0,
-(0.0.next_float),
-Float::INFINITY
]

numbers.each do |number|
number.negative?.should == true
end
end

it "returns false if self is greater than or equal to 0.0" do
numbers = [
+1.0,
+0.0,
-0.0,
+(0.0.next_float),
+Float::INFINITY,
Float::NAN
]

numbers.each do |number|
number.negative?.should == false
end
end
end
30 changes: 30 additions & 0 deletions spec/ruby/core/float/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Float#positive?" do
it "returns true if self is greater than 0.0" do
numbers = [
+1.0,
+(0.0.next_float),
+Float::INFINITY
]

numbers.each do |number|
number.positive?.should == true
end
end

it "returns false if self is less than or equal to 0.0" do
numbers = [
+0.0,
-0.0,
-1.0,
-(0.0.next_float),
-Float::INFINITY,
Float::NAN
]

numbers.each do |number|
number.positive?.should == false
end
end
end
44 changes: 44 additions & 0 deletions spec/ruby/core/hash/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Hash#dig" do
it "returns the nested value specified by the sequence of keys" do
h = new_hash(foo: new_hash(bar: new_hash(baz: 1)))

h.dig(:foo, :bar, :baz).should == 1
end

it "returns the nested value specified if the sequence includes an index" do
h = new_hash(foo: [1, 2, 3])

h.dig(:foo, 2).should == 3
end

it "returns nil if any intermediate step is nil" do
h = new_hash(foo: new_hash(bar: new_hash(baz: 1)))

h.dig(:foo, :zot, :xyz).should == nil
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
h = new_hash(foo: 1)

lambda { h.dig(:foo, 3) }.should raise_error(TypeError)
end

it "raises an ArgumentError if no arguments provided" do
h = {}

lambda { h.dig }.should raise_error(ArgumentError)
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
o = Object.new
h = new_hash(foo: o)

def o.dig(*args)
{dug: args}
end

h.dig(:foo, :bar, :baz).should == {dug: [:bar, :baz]}
end
end
31 changes: 31 additions & 0 deletions spec/ruby/core/hash/fetch_values_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Hash#fetch_values" do
before do
@h = new_hash(foo: 1, bar: 2, baz: 3)
end

it "returns an array containing the values associated with the given keys" do
@h.fetch_values(:foo, :baz).should == [1, 3]
end

context "when one of the given keys does not exist" do
context "when no block is given" do
it "raises a KeyError" do
lambda { @h.fetch_values(:foo, :foobar) }.should raise_error(KeyError)
end
end

context "when a block is given" do
it "returns the value of the block for the missing key" do
@h.fetch_values(:foo, :foobar) { |k| k.length }.should == [1, 6]
end
end
end

context "when called with no arguments" do
it "returns an empty array" do
@h.fetch_values.should == []
end
end
end
13 changes: 13 additions & 0 deletions spec/ruby/core/hash/greater_than_or_equal_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('../shared/comparison', __FILE__)
require File.expand_path('../shared/greater_than', __FILE__)

describe "Hash#>=" do
it_behaves_like :hash_comparison, :>=
it_behaves_like :hash_greater_than, :>=

it "returns true if both hashes are identical" do
h = new_hash(a: 1, b: 2)
(h >= h).should be_true
end
end
13 changes: 13 additions & 0 deletions spec/ruby/core/hash/greater_than_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('../shared/comparison', __FILE__)
require File.expand_path('../shared/greater_than', __FILE__)

describe "Hash#>" do
it_behaves_like :hash_comparison, :>
it_behaves_like :hash_greater_than, :>

it "returns false if both hashes are identical" do
h = new_hash(a: 1, b: 2)
(h > h).should be_false
end
end
13 changes: 13 additions & 0 deletions spec/ruby/core/hash/less_than_or_equal_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('../shared/comparison', __FILE__)
require File.expand_path('../shared/less_than', __FILE__)

describe "Hash#<=" do
it_behaves_like :hash_comparison, :<=
it_behaves_like :hash_less_than, :<=

it "returns true if both hashes are identical" do
h = new_hash(a: 1, b: 2)
(h <= h).should be_true
end
end
13 changes: 13 additions & 0 deletions spec/ruby/core/hash/less_than_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('../shared/comparison', __FILE__)
require File.expand_path('../shared/less_than', __FILE__)

describe "Hash#<" do
it_behaves_like :hash_comparison, :<
it_behaves_like :hash_less_than, :<

it "returns false if both hashes are identical" do
h = new_hash(a: 1, b: 2)
(h < h).should be_false
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/hash/shared/comparison.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
describe :hash_comparison, shared: true do
it "raises a TypeError if the right operand is not a hash" do
lambda { new_hash(a: 1).send(@method, 1) }.should raise_error(TypeError)
lambda { new_hash(a: 1).send(@method, nil) }.should raise_error(TypeError)
lambda { new_hash(a: 1).send(@method, []) }.should raise_error(TypeError)
end

it "returns false if both hashes have the same keys but different values" do
h1 = new_hash(a: 1)
h2 = new_hash(a: 2)

h1.send(@method, h2).should be_false
h2.send(@method, h1).should be_false
end
end
23 changes: 23 additions & 0 deletions spec/ruby/core/hash/shared/greater_than.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
describe :hash_greater_than, shared: true do
before do
@h1 = new_hash(a: 1, b: 2, c: 3)
@h2 = new_hash(a: 1, b: 2)
end

it "returns true if the other hash is a subset of self" do
@h1.send(@method, @h2).should be_true
end

it "returns false if the other hash is not a subset of self" do
@h2.send(@method, @h1).should be_false
end

it "converts the right operand to a hash before comparing" do
o = Object.new
def o.to_hash
new_hash(a: 1, b: 2)
end

@h1.send(@method, o).should be_true
end
end
23 changes: 23 additions & 0 deletions spec/ruby/core/hash/shared/less_than.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
describe :hash_less_than, shared: true do
before do
@h1 = new_hash(a: 1, b: 2)
@h2 = new_hash(a: 1, b: 2, c: 3)
end

it "returns true if self is a subset of the other hash" do
@h1.send(@method, @h2).should be_true
end

it "returns false if self is not a subset of the other hash" do
@h2.send(@method, @h1).should be_false
end

it "converts the right operand to a hash before comparing" do
o = Object.new
def o.to_hash
new_hash(a: 1, b: 2, c: 3)
end

@h1.send(@method, o).should be_true
end
end
20 changes: 20 additions & 0 deletions spec/ruby/core/hash/to_proc_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Hash#to_proc" do
before(:all) do
@hash = new_hash(foo: :bar)
end

it "returns a new Proc" do
proc = @hash.to_proc
proc.should be_kind_of(Proc)
end

it "sends :[] with argument passed to the Hash when calling #call on the Proc" do
@hash.to_proc.call(:foo).should == :bar
end

it "raises an ArgumentError when calling #call on the Proc without receiver" do
lambda { @hash.to_proc.call }.should raise_error(ArgumentError)
end
end
12 changes: 4 additions & 8 deletions spec/ruby/core/io/close_read_spec.rb
Original file line number Diff line number Diff line change
@@ -19,10 +19,8 @@
lambda { @io.read }.should raise_error(IOError)
end

it "raises an IOError on subsequent invocations" do
@io.close_read

lambda { @io.close_read }.should raise_error(IOError)
it "does nothing on subsequent invocations" do
@io.close_read.should be_nil
end

it "allows subsequent invocation of close" do
@@ -52,10 +50,8 @@
io.closed?.should == true
end

it "raises IOError on closed stream" do
@io.close

lambda { @io.close_read }.should raise_error(IOError)
it "does nothing on closed stream" do
@io.close.should be_nil
end

end
4 changes: 2 additions & 2 deletions spec/ruby/core/io/close_spec.rb
Original file line number Diff line number Diff line change
@@ -31,9 +31,9 @@
lambda { @io.write "data" }.should raise_error(IOError)
end

it "raises an IOError if closed" do
it "does nothing if closed" do
@io.close
lambda { @io.close }.should raise_error(IOError)
@io.close.should == nil
end
end

12 changes: 4 additions & 8 deletions spec/ruby/core/io/close_write_spec.rb
Original file line number Diff line number Diff line change
@@ -18,10 +18,8 @@
lambda { @io.write "attempt to write" }.should raise_error(IOError)
end

it "raises an IOError on subsequent invocations" do
@io.close_write

lambda { @io.close_write }.should raise_error(IOError)
it "does nothing on subsequent invocations" do
@io.close_write.should be_nil
end

it "allows subsequent invocation of close" do
@@ -56,9 +54,7 @@
@io.read.should == "12345\n"
end

it "raises IOError on closed stream" do
@io.close

lambda { @io.close_write }.should raise_error(IOError)
it "does nothing on closed stream" do
@io.close.should be_nil
end
end
30 changes: 29 additions & 1 deletion spec/ruby/core/io/puts_spec.rb
Original file line number Diff line number Diff line change
@@ -37,7 +37,26 @@
@io.puts(nil, nil).should == nil
end

it "calls to_s before writing non-string objects" do
it "calls :to_ary before writing non-string objects, regardless of it being implemented in the receiver" do
object = mock('hola')
object.should_receive(:method_missing).with(:to_ary)
object.should_receive(:to_s).and_return("#<Object:0x...>")

@io.should_receive(:write).with("#<Object:0x...>")
@io.should_receive(:write).with("\n")
@io.puts(object).should == nil
end

it "calls :to_ary before writing non-string objects" do
object = mock('hola')
object.should_receive(:to_ary).and_return(["hola"])

@io.should_receive(:write).with("hola")
@io.should_receive(:write).with("\n")
@io.puts(object).should == nil
end

it "calls :to_s before writing non-string objects that don't respond to :to_ary" do
object = mock('hola')
object.should_receive(:to_s).and_return("hola")

@@ -46,6 +65,15 @@
@io.puts(object).should == nil
end

it "returns general object info if :to_s does not return a string" do
object = mock('hola')
object.should_receive(:to_s).and_return(false)

@io.should_receive(:write).with(object.inspect.split(" ")[0] + ">")
@io.should_receive(:write).with("\n")
@io.puts(object).should == nil
end

it "writes each arg if given several" do
@io.should_receive(:write).with("1")
@io.should_receive(:write).with("two")
54 changes: 43 additions & 11 deletions spec/ruby/core/io/read_nonblock_spec.rb
Original file line number Diff line number Diff line change
@@ -11,8 +11,42 @@
@write.close rescue nil
end

it "raises IO::EAGAINWaitReadable when there is no data" do
lambda { @read.read_nonblock(5) }.should raise_error(IO::EAGAINWaitReadable)
context "when exception option is not passed" do
context "when there is no data" do
it "raises IO::EAGAINWaitReadable" do
lambda { @read.read_nonblock(5) }.should raise_error(IO::EAGAINWaitReadable)
end
end

context "when the end is reached" do
it "raises EOFError" do
@write << "hello"
@write.close

@read.read_nonblock(5)

lambda { @read.read_nonblock(5) }.should raise_error(EOFError)
end
end
end

context "when exception option is set to false" do
context "when there is no data" do
it "returns :wait_readable" do
@read.read_nonblock(5, exception: false).should == :wait_readable
end
end

context "when the end is reached" do
it "returns nil" do
@write << "hello"
@write.close

@read.read_nonblock(5)

@read.read_nonblock(5, exception: false).should be_nil
end
end
end

it "returns at most the number of bytes requested" do
@@ -35,6 +69,13 @@
@read.read_nonblock(1).should == "1"
end

it "reads into the passed buffer" do
buffer = ""
@write.write("1")
@read.read_nonblock(1, buffer)
buffer.should == "1"
end

not_compliant_on :rubinius, :jruby do
# TODO: Fix this.
#
@@ -46,13 +87,4 @@
it "raises IOError on closed stream" do
lambda { IOSpecs.closed_io.read_nonblock(5) }.should raise_error(IOError)
end

it "raises EOFError when the end is reached" do
@write << "hello"
@write.close

@read.read_nonblock(5)

lambda { @read.read_nonblock(5) }.should raise_error(EOFError)
end
end
9 changes: 9 additions & 0 deletions spec/ruby/core/io/shared/each.rb
Original file line number Diff line number Diff line change
@@ -73,6 +73,15 @@
end
end

describe "with limit" do
describe "when limit is 0" do
it "raises an ArgumentError" do
# must pass block so Enumerator is evaluated and raises
lambda { @io.send(@method, 0){} }.should raise_error(ArgumentError)
end
end
end

describe "when passed a String containing one space as a separator" do
it "uses the passed argument as the line separator" do
@io.send(@method, " ") { |s| ScratchPad << s }
16 changes: 13 additions & 3 deletions spec/ruby/core/io/write_nonblock_spec.rb
Original file line number Diff line number Diff line change
@@ -44,9 +44,19 @@
@write.close
end

it 'raises IO::EAGAINWaitWritable when the operation would block' do
proc { loop { @write.write_nonblock('a' * 10_000) } }
.should raise_error(IO::EAGAINWaitWritable)
context "when the operation would block" do
context "when exception option is not passed" do
it "raises IO::EAGAINWaitWritable" do
lambda { loop { @write.write_nonblock("a" * 10_000) } }.should raise_error(IO::EAGAINWaitWritable)
end
end

context "when exception option is set to false" do
it "returns :wait_writable" do
loop { break if @write.write_nonblock("a" * 10_000, exception: false) == :wait_writable }
1.should == 1
end
end
end
end

5 changes: 5 additions & 0 deletions spec/ruby/core/kernel/loop_spec.rb
Original file line number Diff line number Diff line change
@@ -60,6 +60,11 @@
lambda{ loop do raise StandardError end }.should raise_error( StandardError )
end

it "returns StopIteration#result when stopped by the exception" do
enum = Enumerator.new { |y| :ok }
loop { enum.next }.should == :ok
end

describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
68 changes: 66 additions & 2 deletions spec/ruby/core/kernel/rand_spec.rb
Original file line number Diff line number Diff line change
@@ -49,8 +49,72 @@
rand l
end

it "returns a float for an range argument where max is < 1" do
rand(0.25..0.75).should be_kind_of(Float)
context "given an exclusive range" do
it "returns an Integer between the two Integers" do
1000.times do
x = rand(4...6)
x.should be_kind_of(Integer)
(4...6).should include(x)
end
end

it "returns a Float between the given Integer and Float" do
1000.times do
x = rand(4...6.5)
x.should be_kind_of(Float)
(4...6.5).should include(x)
end
end

it "returns a Float between the given Float and Integer" do
1000.times do
x = rand(3.5...6)
x.should be_kind_of(Float)
(3.5...6).should include(x)
end
end

it "returns a Float between the two given Floats" do
1000.times do
x = rand(3.5...6.5)
x.should be_kind_of(Float)
(3.5...6.5).should include(x)
end
end
end

context "given an inclusive range" do
it "returns an Integer between the two Integers" do
1000.times do
x = rand(4..6)
x.should be_kind_of(Integer)
(4..6).should include(x)
end
end

it "returns a Float between the given Integer and Float" do
1000.times do
x = rand(4..6.5)
x.should be_kind_of(Float)
(4..6.5).should include(x)
end
end

it "returns a Float between the given Float and Integer" do
1000.times do
x = rand(3.5..6)
x.should be_kind_of(Float)
(3.5..6).should include(x)
end
end

it "returns a Float between the two given Floats" do
1000.times do
x = rand(3.5..6.5)
x.should be_kind_of(Float)
(3.5..6.5).should include(x)
end
end
end
end

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

describe "Numeric#negative?" do
before(:each) do
@obj = NumericSpecs::Subclass.new
end

it "returns true if self is less than 0" do
@obj.should_receive(:<).with(0).and_return(true)
@obj.negative?.should == true
end

it "returns false if self is greater than 0" do
@obj.should_receive(:<).with(0).and_return(false)
@obj.negative?.should == false
end
end
18 changes: 18 additions & 0 deletions spec/ruby/core/numeric/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Numeric#positive?" do
before(:each) do
@obj = NumericSpecs::Subclass.new
end

it "returns true if self is greater than 0" do
@obj.should_receive(:>).with(0).and_return(true)
@obj.positive?.should == true
end

it "returns false if self is less than 0" do
@obj.should_receive(:>).with(0).and_return(false)
@obj.positive?.should == false
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/rational/negative_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Rational#negative?" do
it "returns true if self is less than 0" do
Rational(-3, 4).negative?.should == true
end

it "returns false if self is 0" do
Rational(0).negative?.should == false
end

it "returns false if self is greater than 0" do
Rational(1, 2).negative?.should == false
end
end
15 changes: 15 additions & 0 deletions spec/ruby/core/rational/positive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Rational#positive?" do
it "returns true if self is greater than 0" do
Rational(1, 2).positive?.should == true
end

it "returns false if self is 0" do
Rational(0).positive?.should == false
end

it "returns false if self is less than 0" do
Rational(-3, 4).positive?.should == false
end
end
6 changes: 6 additions & 0 deletions spec/ruby/core/string/new_spec.rb
Original file line number Diff line number Diff line change
@@ -7,6 +7,12 @@
str.should be_an_instance_of(String)
end

it "accepts an encoding argument" do
str = String.new("\xA4\xA2", encoding: 'euc-jp')

str.encoding.should == Encoding::EUC_JP
end

it "returns a fully-formed String" do
str = String.new
str.size.should == 0
41 changes: 41 additions & 0 deletions spec/ruby/core/struct/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Struct#dig" do
before(:each) do
@klass = Struct.new(:a)
@instance = @klass.new(@klass.new(b: [1, 2, 3]))
end

it "returns the nested value specified by the sequence of keys" do
@instance.dig(:a, :a).should == {b: [1, 2, 3]}
end

it "returns the nested value specified if the sequence includes an index" do
@instance.dig(:a, :a, :b, 0).should == 1
end

it "returns nil if any intermediate step is nil" do
@instance.dig(:b, 0).should == nil
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
instance = @klass.new(1)

lambda { instance.dig(:a, 3) }.should raise_error(TypeError)
end

it "raises an ArgumentError if no arguments provided" do
lambda { @instance.dig }.should raise_error(ArgumentError)
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
obj = Object.new
instance = @klass.new(obj)

def obj.dig(*args)
{dug: args}
end

instance.dig(:a, :bar, :baz).should == {dug: [:bar, :baz]}
end
end
14 changes: 14 additions & 0 deletions spec/ruby/language/fixtures/super.rb
Original file line number Diff line number Diff line change
@@ -327,4 +327,18 @@ class AnonymousModuleIncludedTwice < AnonymousModuleIncludedTwiceBase
whatever
whatever
end

module KeywordArguments
class A
def foo(**args)
args
end
end

class B < A
def foo(**)
super
end
end
end
end
14 changes: 14 additions & 0 deletions spec/ruby/language/super_spec.rb
Original file line number Diff line number Diff line change
@@ -158,4 +158,18 @@ def a(arg)
it "invokes methods from a chain of anonymous modules" do
Super::AnonymousModuleIncludedTwice.new.a([]).should == ["anon", "anon", "non-anon"]
end

describe 'when using keyword arguments' do
it 'passes any given keyword arguments to the parent' do
b = Super::KeywordArguments::B.new

b.foo(:number => 10).should == {:number => 10}
end

it 'does not pass any keyword arguments to the parent when none are given' do
b = Super::KeywordArguments::B.new

b.foo.should == {}
end
end
end
8 changes: 8 additions & 0 deletions spec/ruby/optional/capi/kernel_spec.rb
Original file line number Diff line number Diff line change
@@ -265,6 +265,14 @@
@s.rb_rescue(@std_error_proc, nil, lambda { |*_| $! }, nil).class.should == StandardError
$!.should == nil
end

it "returns the break value if the passed function yields to a block with a break" do
def proc_caller
@s.rb_rescue(lambda { |*_| yield }, nil, @proc, nil)
end

proc_caller { break :value }.should == :value
end
end

describe "rb_rescue2" do
10 changes: 4 additions & 6 deletions spec/ruby/optional/capi/numeric_spec.rb
Original file line number Diff line number Diff line change
@@ -156,18 +156,16 @@
@s.rb_int2num(4.2).should == 4
end

it "converts a Bignum" do
@s.rb_int2num(0x7fff_ffff).should == 0x7fff_ffff
it "raises a RangeError when passed a BigNum" do
lambda { @s.rb_int2num(bignum_value) }.should raise_error(RangeError)
end

it "converts a Fixnum" do
@s.rb_int2num(5).should == 5
end

# INT2NUM used to use `long` prior to MRI 1.9. With 1.9 it has been changed
# to use `int` instead.
it "converts 0xFFFFFFFF to -1" do
@s.rb_int2num(0xFFFFFFFF).should == -1
it "converts a negative Fixnum" do
@s.rb_int2num(-11).should == -11
end
end

5 changes: 5 additions & 0 deletions spec/ruby/optional/capi/thread_spec.rb
Original file line number Diff line number Diff line change
@@ -84,5 +84,10 @@ def call_capi_rb_thread_wakeup

lambda { thr.join }.should raise_error(NotImplementedError)
end

it "sets the thread's group" do
thread_group = @t.rb_thread_create(lambda {}, nil).group
thread_group.should be_an_instance_of(ThreadGroup)
end
end
end
1 change: 1 addition & 0 deletions spec/tags/ruby/core/exception/receiver_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:NameError#receiver returns the receiver of the method call where the error occurred
1 change: 1 addition & 0 deletions spec/tags/ruby/language/super_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
fails:The super keyword raises a RuntimeError when called with implicit arguments from a method defined with define_method
fails:The super keyword invokes methods from a chain of anonymous modules
fails:The super keyword when using keyword arguments does not pass any keyword arguments to the parent when none are given
2 changes: 0 additions & 2 deletions vm/builtin/dir.cpp
Original file line number Diff line number Diff line change
@@ -78,8 +78,6 @@ namespace rubinius {
}

Object* Dir::close(STATE) {
guard(state);

if(os_) {
closedir(os_);
os_ = 0;
34 changes: 0 additions & 34 deletions vm/builtin/io.cpp
Original file line number Diff line number Diff line change
@@ -1230,40 +1230,6 @@ namespace rubinius {


/** Socket methods */
Object* IO::accept(STATE, CallFrame* calling_environment) {
int fd = descriptor()->to_native();
int new_fd = -1;

struct sockaddr_storage socka;
socklen_t sock_len = sizeof(socka);

retry:
state->vm()->interrupt_with_signal();
state->vm()->thread->sleep(state, cTrue);

{
GCIndependent guard(state, calling_environment);
new_fd = ::accept(fd, (struct sockaddr*)&socka, &sock_len);
}

state->vm()->thread->sleep(state, cFalse);
state->vm()->clear_waiter();

if(new_fd == -1) {
if(errno == EAGAIN || errno == EINTR) {
if(!state->check_async(calling_environment)) return NULL;
ensure_open(state);
goto retry;
} else {
Exception::errno_error(state, "accept(2) failed");
}

return NULL;
}

return Fixnum::from(new_fd);
}

static const int cmsg_space = CMSG_SPACE(sizeof(int));

Object* IO::send_io(STATE, IO* io) {
3 changes: 0 additions & 3 deletions vm/builtin/io.hpp
Original file line number Diff line number Diff line change
@@ -121,9 +121,6 @@ namespace rubinius {
// Rubinius.primitive :io_close
Object* close(STATE);

// Rubinius.primitive :io_accept
Object* accept(STATE, CallFrame* calling_environment);

// Rubinius.primitive :io_send_io
Object* send_io(STATE, IO* io);

8 changes: 8 additions & 0 deletions vm/capi/bignum.cpp
Original file line number Diff line number Diff line change
@@ -133,6 +133,14 @@ extern "C" {
VALUE rb_dbl2big(double num) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

// We have to handle exceptional cases here so that a C++ exception is not
// thrown when we call into C++ code.
if(isinf(num)) {
rb_raise(rb_eFloatDomainError, num < 0 ? "-Infinity" : "Infinity");
} else if(isnan(num)) {
rb_raise(rb_eFloatDomainError, "NaN");
}

Integer* bignum = Bignum::from_double(env->state(), num);

return env->get_handle(bignum);
3 changes: 1 addition & 2 deletions vm/capi/kernel.cpp
Original file line number Diff line number Diff line change
@@ -60,8 +60,7 @@ extern "C" {
ep.pop(env);

if(env->state()->thread_state()->raise_reason() != cException) {
//Something bad happened, we shouldn't be here.
return Qnil;
env->current_ep()->return_to(env);
}

VALUE exc_handle = env->get_handle(env->state()->thread_state()->current_exception());
2 changes: 2 additions & 0 deletions vm/capi/thread.cpp
Original file line number Diff line number Diff line change
@@ -335,6 +335,8 @@ extern "C" {
thr->locals_store(state, state->symbol("function"), nm);
thr->locals_store(state, state->symbol("argument"), ptr);

thr->group(state, state->vm()->thread.get()->group());

VALUE thr_handle = env->get_handle(thr);
thr->fork(state);
GCTokenImpl gct;
1 change: 1 addition & 0 deletions vm/ontology.cpp
Original file line number Diff line number Diff line change
@@ -515,6 +515,7 @@ namespace rubinius {

G(rubinius)->set_const(state, "HAVE_LCHMOD", RBX_HAVE_LCHMOD ? cTrue : cFalse);
G(rubinius)->set_const(state, "HAVE_LCHOWN", RBX_HAVE_LCHOWN ? cTrue : cFalse);
G(rubinius)->set_const(state, "HAVE_MKFIFO", RBX_HAVE_MKFIFO ? cTrue : cFalse);

#ifdef RBX_LITTLE_ENDIAN
G(rubinius)->set_const(state, "ENDIAN", state->symbol("little"));

0 comments on commit 0699fba

Please sign in to comment.