Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git@github.com:evanphx/rubinius

  • Loading branch information...
commit b5c32eb42357ab9e2729b07f3c7fa847ccb94f5c 2 parents b9af12a + e15f927
Konstantin Haase rkh authored
Showing with 791 additions and 490 deletions.
  1. +5 −0 kernel/bootstrap/array.rb
  2. +0 −16 kernel/bootstrap/task.rb
  3. +35 −80 kernel/common/array.rb
  4. +16 −0 kernel/common/method_context.rb
  5. +3 −1 lib/debugger/standard_commands.rb
  6. +25 −4 mspec/lib/mspec/utils/script.rb
  7. +28 −0 mspec/spec/utils/script_spec.rb
  8. +12 −0 spec/core/context/fixtures/classes.rb
  9. +21 −0 spec/core/context/stack_at_spec.rb
  10. +8 −0 spec/core/context/stack_depth_spec.rb
  11. +0 −10 spec/core/task/get_stack_value_spec.rb
  12. +3 −3 spec/frozen/core/array/delete_if_spec.rb
  13. +3 −3 spec/frozen/core/array/each_index_spec.rb
  14. +6 −6 spec/frozen/core/array/each_spec.rb
  15. +11 −11 spec/frozen/core/array/fill_spec.rb
  16. +27 −7 spec/frozen/core/array/fixtures/classes.rb
  17. +108 −96 spec/frozen/core/array/initialize_spec.rb
  18. +105 −91 spec/frozen/core/array/new_spec.rb
  19. +8 −8 spec/frozen/core/array/pack_spec.rb
  20. +3 −3 spec/frozen/core/array/pop_spec.rb
  21. +1 −1  spec/frozen/core/array/shared/collect.rb
  22. +5 −5 spec/frozen/core/array/shared/join.rb
  23. +3 −3 spec/frozen/core/bignum/div_spec.rb
  24. +5 −5 spec/frozen/core/bignum/divmod_spec.rb
  25. +5 −5 spec/frozen/core/class/new_spec.rb
  26. +11 −5 spec/frozen/core/dir/shared/open.rb
  27. +3 −3 spec/frozen/core/enumerable/all_spec.rb
  28. +3 −3 spec/frozen/core/enumerable/any_spec.rb
  29. +1 −1  spec/frozen/core/file/open_spec.rb
  30. +1 −1  spec/frozen/core/io/close_spec.rb
  31. +1 −1  spec/frozen/core/io/open_spec.rb
  32. +4 −4 spec/frozen/core/io/readpartial_spec.rb
  33. +5 −3 spec/frozen/core/io/shared/tty_shared.rb
  34. +5 −0 spec/frozen/core/kernel/raise_spec.rb
  35. +1 −1  spec/frozen/core/kernel/throw_spec.rb
  36. +24 −0 spec/frozen/core/thread/fixtures/classes.rb
  37. +121 −1 spec/frozen/core/thread/raise_spec.rb
  38. +11 −29 spec/frozen/core/thread/wakeup_spec.rb
  39. +6 −5 spec/frozen/language/encoding_spec.rb
  40. +4 −0 spec/frozen/language/fixtures/private.rb
  41. +4 −14 spec/frozen/language/private_spec.rb
  42. +0 −41 spec/frozen/language/raise_spec.rb
  43. +11 −4 spec/frozen/ruby.1.8.mspec
  44. +11 −4 spec/frozen/ruby.1.9.mspec
  45. +43 −0 spec/frozen/shared/kernel/raise.rb
  46. +0 −1  spec/tags/core/task/get_stack_value_tags.txt
  47. +0 −1  spec/tags/frozen/core/array/initialize_tags.txt
  48. +0 −1  spec/tags/frozen/core/array/new_tags.txt
  49. +12 −0 spec/tags/frozen/core/array/pack_tags.txt
  50. +7 −0 spec/tags/frozen/core/thread/raise_tags.txt
  51. +10 −0 vm/builtin/array.cpp
  52. +3 −0  vm/builtin/array.hpp
  53. +13 −0 vm/builtin/contexts.hpp
  54. +13 −9 vm/ontology.cpp
  55. +16 −0 vm/test/test_array.hpp
  56. +1 −0  vm/vm.hpp
5 kernel/bootstrap/array.rb
View
@@ -5,6 +5,11 @@ def total ; @total ; end
def tuple ; @tuple ; end
def start ; @start ; end
+ def self.allocate
+ Ruby.primitive :array_allocate
+ raise PrimitiveFailure, "Array.allocate primitive failed"
+ end
+
def size
@total
end
16 kernel/bootstrap/task.rb
View
@@ -78,22 +78,6 @@ def raise(exc)
Kernel.raise PrimitiveFailure, "primitive failed"
end
- # Returns the current size of the stack for this task.
- def stack_size
- Ruby.primitive :task_stack_size
- Kernel.raise PrimitiveFailure, "primitive failed"
- end
-
- # Returns the value at the specified depth on the task stack, where depth is
- # a positive integer counting down from the top of the stack.
- def get_stack_value(depth)
- Ruby.primitive :task_get_stack_value
-
- # If we get here, the primitive failed
- # Kernel raise is used, since we don't want to use the raise primitive above
- Kernel.raise ArgumentError, "#{self.class} stack index out of range"
- end
-
def probe
@probe
end
115 kernel/common/array.rb
View
@@ -28,14 +28,6 @@ def self.[](*args)
new args
end
- def self.allocate
- ary = super()
- ary.start = 0
- ary.total = 0
- ary.tuple = Tuple.new 8
- ary
- end
-
# Creates a new Array. Without arguments, an empty
# Array is returned. If the only argument is an object
# that responds to +to_ary+, a copy of that Array is
@@ -47,38 +39,44 @@ def self.allocate
# will be run size times to fill the Array with its
# result. The block supercedes any object given. If
# neither is provided, the Array is filled with nil.
- def initialize(*args)
- raise ArgumentError, "Wrong number of arguments, #{args.size} for 2" if args.size > 2
+ def initialize(size_or_array=Undefined, obj=Undefined)
+ if size_or_array.equal? Undefined
+ unless @total == 0
+ @total = @start = 0
+ @tuple = Tuple.new 8
+ end
- if args.empty?
- @tuple = Tuple.new 8
- @start = 0
- @total = 0
- else
- if args.size == 1 and (args.first.__kind_of__ Array or args.first.respond_to? :to_ary)
- ary = Type.coerce_to args.first, Array, :to_ary
+ return self
+ end
+
+ if obj.equal? Undefined
+ obj = nil
+
+ if size_or_array.respond_to? :to_ary
+ ary = Type.coerce_to size_or_array, Array, :to_ary
@tuple = ary.tuple.dup
@start = ary.start
@total = ary.size
- else
- count = Type.check_and_coerce_to args.first, Integer, :to_int
- raise ArgumentError, "size must be positive" if count < 0
- raise ArgumentError, "size must be a Fixnum" unless count.is_a? Fixnum
- obj = args[1]
-
- @total = count
- if block_given?
- @tuple = Tuple.new(count)
- i = 0
- while i < count
- @tuple.put i, yield(i)
- i += 1
- end
- else
- @tuple = Tuple.pattern(count, obj)
- end
+
+ return self
+ end
+ end
+
+ size = Type.coerce_to size_or_array, Integer, :to_int
+ raise ArgumentError, "size must be positive" if size < 0
+ raise ArgumentError, "size must be <= #{MAX_SIZE}" if size > MAX_SIZE
+
+ if block_given?
+ @tuple = Tuple.new size
+ @total = i = 0
+ while i < size
+ @tuple.put i, yield(i)
+ @total = i += 1
end
+ else
+ @total = size
+ @tuple = Tuple.pattern size, obj
end
self
@@ -1165,9 +1163,9 @@ def pack schema
size.times do |i|
item = Type.coerce_to(self[arr_idx], Integer, :to_int)
- # MRI seems only only raise RangeError at 2**32 and above, even shorts
- raise RangeError, "bignum too big to convert into 'unsigned long'" if
- item.abs >= 2**32 # FIX: const
+ if item.abs >= 2**Rubinius::WORDSIZE
+ raise RangeError, "bignum too big to convert into 'unsigned long'"
+ end
ret << if little_endian then
item += 2 ** (8 * bytes) if item < 0
@@ -1261,49 +1259,6 @@ def pop()
elem
end
- # Rubinius-only, better inspect representation of the Array
- def indented_inspect(indent = 0)
- # Here there be dragons. In fact, there is one jusAAAAAAAARGH
- str = "["
-
- sub = false
- i = 0
- lst = size - 1
- while i < size
- element = self[i]
- if Array === element
- estr = element.indented_inspect(indent + 2)
- if str.size > 30 or estr.size > 30
- if estr[0] != ?\s
- estr = "#{' ' * (indent + 2)}#{estr}"
- end
-
- str << "\n#{estr}"
- sub = true
- else
- str << estr
- end
- else
- str << element.inspect
- end
-
- str << ", " unless i == lst
- i += 1
- end
-
- if sub
- str << "\n#{' ' * indent}]"
- else
- str << "]"
- end
-
- if sub
- return "#{' ' * indent}#{str}"
- end
-
- return str
- end
-
# Appends the given object(s) to the Array and returns
# the modified self.
def push(*args)
16 kernel/common/method_context.rb
View
@@ -384,6 +384,22 @@ def get_eval_local(name)
return @dynamic_locals[name]
end
+ # Returns the current depth of the stack for this context.
+ def stack_depth
+ Ruby.primitive :context_stack_depth
+ Kernel.raise PrimitiveFailure, "primitive failed"
+ end
+
+ # Returns the value at the specified depth on the task stack, where depth is
+ # a positive integer counting down from the top of the stack.
+ def stack_at(depth)
+ Ruby.primitive :context_stack_at
+
+ # If we get here, the primitive failed
+ # Kernel raise is used, since we don't want to use the raise primitive above
+ Kernel.raise ArgumentError, "#{self.class} stack index out of range"
+ end
+
end
#
4 lib/debugger/standard_commands.rb
View
@@ -1,3 +1,5 @@
+require 'pp'
+
# Defines standard debugger commands that are always available
class Debugger
@@ -358,7 +360,7 @@ def execute(dbg, interface, md)
end
output = Output.info("S-expression for source lines [#{first+1}-#{last+1}] in #{file}:")
- sexp = lines[first..last].join().to_sexp.indented_inspect
+ sexp = lines[first..last].join().to_sexp.pretty_inspect
output << sexp
output
end
29 mspec/lib/mspec/utils/script.rb
View
@@ -25,6 +25,18 @@ def self.set(key, value)
config[key] = value
end
+ # Gets the value of +key+ from the config object. Simplifies
+ # getting values in a config file:
+ #
+ # class MSpecScript
+ # set :a, 1
+ # set :b, 2
+ # set :c, get(:a) + get(:b)
+ # end
+ def self.get(key)
+ config[key]
+ end
+
def initialize
config[:formatter] = nil
config[:includes] = []
@@ -148,13 +160,22 @@ def entries(partial)
Dir[partial]
end
- # Resolves each entry in +list+ to a set of files. If the entry
- # has a leading '^' character, the list of files is subtracted
- # from the list of files accumulated to that point.
+ # Resolves each entry in +list+ to a set of files.
+ #
+ # If the entry has a leading '^' character, the list of files
+ # is subtracted from the list of files accumulated to that point.
+ #
+ # If the entry has a leading ':' character, the corresponding
+ # key is looked up in the config object and the entries in the
+ # value retrieved are processed through #entries.
def files(list)
list.inject([]) do |files, item|
- if item[0] == ?^
+ case item[0]
+ when ?^
files -= entries(item[1..-1])
+ when ?:
+ key = item[1..-1].to_sym
+ files += files(Array(config[key]))
else
files += entries(item)
end
28 mspec/spec/utils/script_spec.rb
View
@@ -19,6 +19,13 @@
end
end
+describe MSpecScript, ".get" do
+ it "gets the config hash value for a key" do
+ MSpecScript.set :a, 10
+ MSpecScript.get(:a).should == 10
+ end
+end
+
describe MSpecScript, "#config" do
it "returns the MSpecScript config hash" do
MSpecScript.set :b, 5
@@ -380,3 +387,24 @@ class MSSClass < MSpecScript; end
@script.files(["^a", "a", "b"]).should == ["file1", "file2"]
end
end
+
+describe MSpecScript, "#files" do
+ before :each do
+ MSpecScript.set :files, ["file1", "file2"]
+
+ @script = MSpecScript.new
+ end
+
+ after :each do
+ MSpecScript.config.delete :files
+ end
+
+ it "looks up items with leading ':' in the config object" do
+ @script.should_receive(:entries).and_return(["file1"], ["file2"])
+ @script.files(":files").should == ["file1", "file2"]
+ end
+
+ it "returns an empty list if the config key is not set" do
+ @script.files(":all_files").should == []
+ end
+end
12 spec/core/context/fixtures/classes.rb
View
@@ -66,6 +66,18 @@ def called_from_ret_7?
end
end
+ class B
+ def inspect_stack(depth)
+ ctx = Rubinius::Task.current.current_context
+ #puts ctx.method.decode
+ inspector 'First', :second, 3, [4, 5, 6], ctx.stack_at(depth)
+ end
+
+ def inspector(*args)
+ args.last
+ end
+ end
+
# Simple listener class to receive call-backs when yield_debugger is hit
class Listener
def initialize
21 spec/core/context/stack_at_spec.rb
View
@@ -0,0 +1,21 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/fixtures/classes.rb'
+
+describe "MethodContext#stack_at" do
+ before :each do
+ @b = ContextSpecs::B.new
+ end
+
+ it "returns the value on the context operand stack at the specified depth" do
+ @b.inspect_stack(3).should == 'First'
+ @b.inspect_stack(4).should == :second
+ @b.inspect_stack(5).should == 3
+ @b.inspect_stack(6).should == [4,5,6]
+ end
+
+ it "throws an ArgumentError if depth is out of range" do
+ lambda { @b.inspect_stack(0) }.should_not raise_error(ArgumentError)
+ lambda { @b.inspect_stack(-1) }.should raise_error(ArgumentError)
+ lambda { @b.inspect_stack(10) }.should raise_error(ArgumentError)
+ end
+end
8 spec/core/context/stack_depth_spec.rb
View
@@ -0,0 +1,8 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe "MethodContext#stack_depth" do
+ it "returns the depth of the bytecode operand stack" do
+ ctx = Rubinius::Task.current.current_context
+ ctx.stack_depth.should == 1
+ end
+end
10 spec/core/task/get_stack_value_spec.rb
View
@@ -1,10 +0,0 @@
-require File.dirname(__FILE__) + '/../../spec_helper'
-
-describe "Task#get_stack_value" do
- it "throws an ArgumentError if depth is out of range" do
- lambda { Task.current.get_stack_value(0) }.should_not raise_error(ArgumentError)
- lambda { Task.current.get_stack_value(-1) }.should raise_error(ArgumentError)
- lambda { Task.current.get_stack_value(Task.current.stack_size) }.should raise_error(ArgumentError)
- lambda { Task.current.get_stack_value(Task.current.stack_size-1) }.should_not raise_error(ArgumentError)
- end
-end
6 spec/frozen/core/array/delete_if_spec.rb
View
@@ -3,11 +3,11 @@
describe "Array#delete_if" do
before do
- @a = [ "a", "b", "c" ]
+ @a = [ "a", "b", "c" ]
end
it "removes each element for which block returns true" do
- @a = [ "a", "b", "c" ]
+ @a = [ "a", "b", "c" ]
@a.delete_if { |x| x >= "b" }
@a.should == ["a"]
end
@@ -18,7 +18,7 @@
ruby_version_is "" ... "1.8.7" do
it "raises a LocalJumpError if no block given" do
- lambda { @a.delete_if }.should raise_error(LocalJumpError, /no block given/)
+ lambda { @a.delete_if }.should raise_error(LocalJumpError)
end
end
ruby_version_is "1.8.7" ... "1.9" do
6 spec/frozen/core/array/each_index_spec.rb
View
@@ -8,14 +8,14 @@
x.each_index { |i| a << i }.should equal(x)
a.should == [0, 1, 2, 3]
end
-
+
it "passes the index of each element to the block even if the array is changed during iteration" do
a = []
x = [10, 11, 12, 13,]
x.each_index {|i| a << i; x << x[i]+5 if (x[i]%2).zero? }.should equal(x)
a.should == [0, 1, 2, 3, 4, 5]
end
-
+
it "passes the index from 0..size even if size changes" do
a = []
x = [10, 11, 12, 13, 14]
@@ -30,7 +30,7 @@
ruby_version_is '' ... '1.8.7' do
it 'raises a LocalJumpError if no block given' do
- lambda{ [1,2].each_index }.should raise_error(LocalJumpError, /no block given/)
+ lambda{ [1,2].each_index }.should raise_error(LocalJumpError)
end
end
ruby_version_is '1.8.7' ... '1.9' do
12 spec/frozen/core/array/each_spec.rb
View
@@ -8,32 +8,32 @@
x.each { |item| a << item }.should equal(x)
a.should == [1, 2, 3]
end
-
+
it "yields each element to the block even if the array is changed during iteration" do
a = [1, 2, 3, 4, 5]
b = []
a.each {|x| b << x; a << x+5 if (x%2).zero? }
b.should == [1, 2, 3, 4, 5, 7, 9]
end
-
+
it "yields only elements that are still in the array" do
a = [0, 1, 2, 3, 4]
b = []
a.each {|x| b << x; a.pop if (x%2).zero? }
b.should == [0, 1, 2]
- end
+ end
it "yields elements based on an internal index" do
a = [0, 1, 2, 3, 4]
b = []
a.each {|x| b << x; a.shift if (x%2).zero? }
b.should == [0, 2, 4]
- end
+ end
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []
-
+
a.each { |x, y| b << x }
b.should == [1, :a, 3]
@@ -44,7 +44,7 @@
ruby_version_is '' ... '1.8.7' do
it 'raises a LocalJumpError if no block given' do
- lambda{ [1,2].each }.should raise_error(LocalJumpError, /no block given/)
+ lambda{ [1,2].each }.should raise_error(LocalJumpError)
end
end
ruby_version_is '1.8.7' ... '1.9' do
22 spec/frozen/core/array/fill_spec.rb
View
@@ -137,7 +137,7 @@
a = [1, 2, 3]
a.size.should == 3
a.fill 'a', 0, 10
- a.size.should == 10
+ a.size.should == 10
end
it "pads between the last element and the index with nil if given an index which is greater than size of the array" do
@@ -209,7 +209,7 @@
filler.should_not_receive(:to_int)
[1, 2, 3, 4, 5].fill(filler, obj, obj).should == [1, 2, filler, filler, 5]
end
-
+
it "checks whether the passed arguments respond to #to_int" do
obj = mock('method_missing to_int')
obj.should_receive(:respond_to?).with(:to_int).any_number_of_times.and_return(true)
@@ -224,7 +224,7 @@
obj.should_receive(:respond_to?).with(:to_int).and_return(false)
lambda { [].fill('a', obj) }.should raise_error(TypeError)
end
-
+
platform_is :wordsize => 32 do
it "raises an ArgumentError or RangeError for too-large sizes" do
arr = [1, 2, 3]
@@ -256,7 +256,7 @@
[1, 2, 3, 4, 5, 6].fill('x', 0...0).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 1..1).should == [1, 'x', 3, 4, 5, 6]
end
-
+
it "replaces all elements in range with the value of block" do
[1, 1, 1, 1, 1, 1].fill(1..6) { |i| i + 1 }.should == [1, 2, 3, 4, 5, 6, 7]
end
@@ -319,13 +319,13 @@
end
it "raise an exception if some of the given range lies before the first of the array" do
- lambda { [1, 2, 3].fill('x', -5..-3) }.should raise_error(RangeError, /-5\.\.-3/)
- lambda { [1, 2, 3].fill('x', -5...-3) }.should raise_error(RangeError, /-5\.\.\.-3/)
- lambda { [1, 2, 3].fill('x', -5..-4) }.should raise_error(RangeError, /-5\.\.-4/)
+ lambda { [1, 2, 3].fill('x', -5..-3) }.should raise_error(RangeError)
+ lambda { [1, 2, 3].fill('x', -5...-3) }.should raise_error(RangeError)
+ lambda { [1, 2, 3].fill('x', -5..-4) }.should raise_error(RangeError)
- lambda { [1, 2, 3].fill(-5..-3, &@never_passed) }.should raise_error(RangeError, /-5\.\.-3/)
- lambda { [1, 2, 3].fill(-5...-3, &@never_passed) }.should raise_error(RangeError, /-5\.\.\.-3/)
- lambda { [1, 2, 3].fill(-5..-4, &@never_passed) }.should raise_error(RangeError, /-5\.\.-4/)
+ lambda { [1, 2, 3].fill(-5..-3, &@never_passed) }.should raise_error(RangeError)
+ lambda { [1, 2, 3].fill(-5...-3, &@never_passed) }.should raise_error(RangeError)
+ lambda { [1, 2, 3].fill(-5..-4, &@never_passed) }.should raise_error(RangeError)
end
it "tries to convert the start and end of the passed range to Integers using #to_int" do
@@ -336,7 +336,7 @@ def obj.<=>(rhs); rhs == self ? 0 : nil end
filler.should_not_receive(:to_int)
[1, 2, 3, 4, 5].fill(filler, obj..obj).should == [1, 2, filler, 4, 5]
end
-
+
it "checks whether the start and end of the passed range respond to #to_int" do
obj = mock('method_missing to_int')
def obj.<=>(rhs); rhs == self ? 0 : nil end
34 spec/frozen/core/array/fixtures/classes.rb
View
@@ -1,4 +1,24 @@
module ArraySpecs
+ not_compliant_on :rubinius do
+ def self.max_32bit_size
+ 2**32/4
+ end
+
+ def self.max_64bit_size
+ 2**64/8
+ end
+ end
+
+ deviates_on :rubinius do
+ def self.max_32bit_size
+ 2**30-1
+ end
+
+ def self.max_64bit_size
+ 2**62-1
+ end
+ end
+
def self.frozen_array
@frozen_array ||= [1,2,3]
@frozen_array.freeze
@@ -32,6 +52,8 @@ def initialize(*args)
end
end
+ # TODO: replace specs that use this with #should_not_receive(:to_ary)
+ # expectations on regular objects (e.g. Array instances).
class ToAryArray < Array
def to_ary() ["to_ary", "was", "called!"] end
end
@@ -42,18 +64,16 @@ class AssocKey
def ==(other); other == 'it'; end
end
- class D
- def <=>(obj)
+ class D
+ def <=>(obj)
return 4 <=> obj unless obj.class == D
0
end
end
-
+
class SubArray < Array
- attr_reader :special
-
- def initialize(size=0)
- @special = size
+ def initialize(*args)
+ ScratchPad.record args
end
end
end
204 spec/frozen/core/array/initialize_spec.rb
View
@@ -2,51 +2,70 @@
require File.dirname(__FILE__) + '/fixtures/classes'
describe "Array#initialize" do
- it "is private" do
- [].private_methods.map{|name| name.to_s}.should include("initialize")
+ before :each do
+ ScratchPad.clear
end
- it "raise an ArgumentError if 3 or more arguments passed and no block given" do
- lambda { [1, 2].send(:initialize) }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1) }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1, 'x') }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1, 'x', true) }.should raise_error(ArgumentError)
+ ruby_version_is "" ... "1.9" do
+ it "is private" do
+ [].private_methods.should include("initialize")
+ end
end
- it "raise an ArgumentError if 3 or more arguments passed and a block given" do
- lambda { [1, 2].send(:initialize){} }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1){} }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1, 'x'){} }.should_not raise_error(ArgumentError)
- lambda { [1, 2].send(:initialize, 1, 'x', true){} }.should raise_error(ArgumentError)
+ ruby_version_is "1.9" do
+ it "is private" do
+ [].private_methods.should include(:initialize)
+ end
+ end
+
+ it "is called on subclasses" do
+ b = ArraySpecs::SubArray.new :size_or_array, :obj
+
+ b.should == []
+ ScratchPad.recorded.should == [:size_or_array, :obj]
+ end
+
+ it "preserves the object's identity even when changing its value" do
+ a = [1, 2, 3]
+ a.send(:initialize).should equal(a)
+ a.should_not == [1, 2, 3]
+ end
+
+ it "raise an ArgumentError if passed 3 or more arguments" do
+ lambda do
+ [1, 2].send :initialize, 1, 'x', true
+ end.should raise_error(ArgumentError)
+ lambda do
+ [1, 2].send(:initialize, 1, 'x', true) {}
+ end.should raise_error(ArgumentError)
end
-
- compliant_on :ruby, :jruby, :ir do
- ruby_version_is '' ... '1.9' do
- it "raises a TypeError on frozen arrays even if the array would not be 'modified'" do
- # This is true at least 1.8.6p111 onwards
- lambda { ArraySpecs.frozen_array.send(:initialize) }.should raise_error(TypeError)
- lambda { ArraySpecs.frozen_array.send(:initialize, 1) }.should raise_error(TypeError)
- lambda { ArraySpecs.frozen_array.send(:initialize, [1, 2, 3]) }.should raise_error(TypeError)
+ not_compliant_on :rubinius do
+ ruby_version_is '' ... '1.9' do
+ it "raises a TypeError on frozen arrays even if the array would not be modified" do
+ lambda do
+ ArraySpecs.frozen_array.send :initialize
+ end.should raise_error(TypeError)
+ lambda do
+ ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
+ end.should raise_error(TypeError)
end
end
- ruby_version_is '1.9' do
- it "raises a RuntimeError on frozen arrays even if the array would not be 'modified'" do
- lambda { ArraySpecs.frozen_array.send(:initialize) }.should raise_error(RuntimeError)
- lambda { ArraySpecs.frozen_array.send(:initialize, 1) }.should raise_error(RuntimeError)
- lambda { ArraySpecs.frozen_array.send(:initialize, [1, 2, 3]) }.should raise_error(RuntimeError)
+ ruby_version_is '1.9' do
+ it "raises a RuntimeError on frozen arrays even if the array would not be modified" do
+ lambda do
+ ArraySpecs.frozen_array.send :initialize
+ end.should raise_error(RuntimeError)
+ lambda do
+ ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
+ end.should raise_error(RuntimeError)
end
end
end
end
describe "Array#initialize with no arguments" do
- it "returns self" do
- a = [1, 2, 3]
- a.send(:initialize).should equal(a)
- end
-
it "makes the array empty" do
[1, 2, 3].send(:initialize).should be_empty
end
@@ -56,110 +75,103 @@
end
end
-describe "Array#initialize with (size, object)" do
- it "is called on subclasses" do
- a = ArraySpecs::SubArray.new 10
- a.special.should == 10
- a.should == []
+describe "Array#initialize with (array)" do
+ it "replaces self with the other array" do
+ b = [4, 5, 6]
+ [1, 2, 3].send(:initialize, b).should == b
end
+ it "does not use the given block" do
+ lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ end
+
+ it "calls #to_ary to convert the value to an array" do
+ a = mock("array")
+ a.should_receive(:to_ary).and_return([1, 2])
+ a.should_not_receive(:to_int)
+ [].send(:initialize, a).should == [1, 2]
+ end
+
+ it "does not call #to_ary on instances of Array or subclasses of Array" do
+ a = [1, 2]
+ a.should_not_receive(:to_ary)
+ [].send(:initialize, a).should == a
+ end
+
+ it "raises a TypeError if an Array type argument and a default object" do
+ lambda { [].send(:initialize, [1, 2], 1) }.should raise_error(TypeError)
+ end
+end
+
+describe "Array#initialize with (size, object=nil)" do
it "sets the array to size and fills with the object" do
a = []
- a.send(:initialize, 2, [3])
- a.should == [[3], [3]]
- a[0].should equal(a[1])
+ obj = [3]
+ a.send(:initialize, 2, obj).should == [obj, obj]
+ a[0].should equal(obj)
+ a[1].should equal(obj)
end
it "sets the array to size and fills with nil when object is omitted" do
[].send(:initialize, 3).should == [nil, nil, nil]
end
-
+
it "raises an ArgumentError if size is negative" do
lambda { [].send(:initialize, -1, :a) }.should raise_error(ArgumentError)
- lambda { [1, 2, 3].send(:initialize, -1) }.should raise_error(ArgumentError)
+ lambda { [].send(:initialize, -1) }.should raise_error(ArgumentError)
end
platform_is :wordsize => 32 do
it "raises an ArgumentError if size is too large" do
- lambda { [].send(:initialize, 2**32/4+1) }.should raise_error(ArgumentError, /size/)
+ max_size = ArraySpecs.max_32bit_size
+ lambda { [].send(:initialize, max_size + 1) }.should raise_error(ArgumentError)
end
end
+
platform_is :wordsize => 64 do
it "raises an ArgumentError if size is too large" do
- lambda { [].send(:initialize, 2**64/8+1) }.should raise_error(ArgumentError, /size/)
+ max_size = ArraySpecs.max_64bit_size
+ lambda { [].send(:initialize, max_size + 1) }.should raise_error(ArgumentError)
end
end
- it "tries to convert the passed size argument to an Integer using #to_int" do
+ it "calls #to_int to convert the size argument to an Integer when object is given" do
obj = mock('1')
obj.should_receive(:to_int).and_return(1)
- [1, 2].send(:initialize, obj, :a).should == [:a]
+ [].send(:initialize, obj, :a).should == [:a]
end
- it "checks whether the passed size argument responds to #to_int" do
+ it "calls #to_int to convert the size argument to an Integer when object is not given" do
obj = mock('1')
- obj.should_receive(:respond_to?).with(:to_int).any_number_of_times.and_return(true)
- obj.should_receive(:method_missing).with(:to_int).and_return(1)
- [1, 2].send(:initialize, obj, :a).should == [:a]
+ obj.should_receive(:to_int).and_return(1)
+ [].send(:initialize, obj).should == [nil]
end
- it "raises a TypeError if the passed size is no numeric" do
+ it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
- obj.should_receive(:respond_to?).with(:to_int).and_return(false)
- lambda{ [1, 2].send(:initialize, obj) }.should raise_error(TypeError)
+ obj.stub!(:to_ary).and_return([1, 2])
+ lambda{ [].send(:initialize, obj, :a) }.should raise_error(TypeError)
end
- it "yields the given block size times passing an index and fills self with values of the block" do
- [1, 2].send(:initialize, 5){|i| "#{i}"}.should == ['0', '1', '2', '3', '4']
+ it "yields the index of the element and sets the element to the value of the block" do
+ [].send(:initialize, 3) { |i| i.to_s }.should == ['0', '1', '2']
end
- it "yields the given block size times passing an index and fills self with values of the block even if a filler value passed" do
- [1, 2].send(:initialize, 5, 'filler'){|i| "#{i}"}.should == ['0', '1', '2', '3', '4']
+ it "uses the block value instead of using the default value" do
+ [].send(:initialize, 3, :obj) { |i| i.to_s }.should == ['0', '1', '2']
end
- it "returns the specified value if it would break in the given block" do
- [1, 2].send(:initialize, 5){ break :a }.should == :a
+ it "returns the value passed to break" do
+ [].send(:initialize, 3) { break :a }.should == :a
end
- it "makes the array contain values the given block would yield even if it would break in the block" do
- ary = [1, 2, 3, 4, 5]
- ary.send(:initialize, 7) {|i|
- break :a if i == 2
- "#{i}"
- }
- ary.should == ['0', '1']
- end
-end
-
-describe "Array#initialize with (array)" do
- it "replaces self with the other array" do
- o = [2]
- def o.special() size end
- a = [1, o, 3]
- ary = Array.new a
- ary[1].special.should == 1
-
- b = [1, [2], 3]
- ary.send :initialize, b
-
- b.==(ary).should == true
- lambda { b[1].special }.should raise_error(NoMethodError)
- lambda { ary[1].special }.should raise_error(NoMethodError)
- end
-
- it "is called on subclasses" do
- b = ArraySpecs::SubArray.new [1,2,3]
- b.special.should == [1,2,3]
- b.should == []
- end
-
- it "does nothing when passed self" do
- ary = [1, 2, 3]
- ary.send(:initialize, ary)
- ary.should == [1, 2, 3]
- end
+ it "sets the array to the values returned by the block before break is executed" do
+ a = [1, 2, 3]
+ a.send(:initialize, 3) do |i|
+ break if i == 2
+ i.to_s
+ end
- it "does not use the given block" do
- lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ a.should == ['0', '1']
end
end
196 spec/frozen/core/array/new_spec.rb
View
@@ -2,112 +2,126 @@
require File.dirname(__FILE__) + '/fixtures/classes'
describe "Array.new" do
- it "returns a new array when not passed arguments" do
- a = Array.new
- a.class.should == Array
+ it "returns an instance of Array" do
+ Array.new.class.should == Array
end
- it "returns an instance of the subclass when called for a subclass of Array" do
- b = ArraySpecs::MyArray.new
- b.class.should == ArraySpecs::MyArray
+ it "returns an instance of a subclass" do
+ ArraySpecs::MyArray.new.class.should == ArraySpecs::MyArray
end
-
- it "raises an ArgumentError when passed a negative size" do
+
+ it "raise an ArgumentError if passed 3 or more arguments" do
+ lambda do
+ [1, 2].send :initialize, 1, 'x', true
+ end.should raise_error(ArgumentError)
+ lambda do
+ [1, 2].send(:initialize, 1, 'x', true) {}
+ end.should raise_error(ArgumentError)
+ end
+end
+
+describe "Array.new with no arguments" do
+ it "returns an empty array" do
+ Array.new.should be_empty
+ end
+
+ it "does not use the given block" do
+ lambda{ Array.new { raise } }.should_not raise_error
+ end
+end
+
+describe "Array.new with (array)" do
+ it "returns an array initialized to the other array" do
+ b = [4, 5, 6]
+ Array.new(b).should == b
+ end
+
+ it "does not use the given block" do
+ lambda{ Array.new([1, 2]) { raise } }.should_not raise_error
+ end
+
+ it "calls #to_ary to convert the value to an array" do
+ a = mock("array")
+ a.should_receive(:to_ary).and_return([1, 2])
+ a.should_not_receive(:to_int)
+ Array.new(a).should == [1, 2]
+ end
+
+ it "does not call #to_ary on instances of Array or subclasses of Array" do
+ a = [1, 2]
+ a.should_not_receive(:to_ary)
+ Array.new(a)
+ end
+
+ it "raises a TypeError if an Array type argument and a default object" do
+ lambda { Array.new([1, 2], 1) }.should raise_error(TypeError)
+ end
+end
+
+describe "Array.new with (size, object=nil)" do
+ it "returns an array of size filled with object" do
+ obj = [3]
+ a = Array.new(2, obj)
+ a.should == [obj, obj]
+ a[0].should equal(obj)
+ a[1].should equal(obj)
+ end
+
+ it "returns an array of size filled with nil when object is omitted" do
+ Array.new(3).should == [nil, nil, nil]
+ end
+
+ it "raises an ArgumentError if size is negative" do
+ lambda { Array.new(-1, :a) }.should raise_error(ArgumentError)
lambda { Array.new(-1) }.should raise_error(ArgumentError)
end
platform_is :wordsize => 32 do
- it "raises an ArgumentError when passed a too large size" do
- enough_large_size = 2**32/4 + 1
- lambda { Array.new(enough_large_size) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError if size is too large" do
+ max_size = ArraySpecs.max_32bit_size
+ lambda { Array.new(max_size + 1) }.should raise_error(ArgumentError)
end
end
+
platform_is :wordsize => 64 do
- it "raises an ArgumentError when passed a too large size" do
- enough_large_size = 2**64/8 + 1
- lambda { Array.new(enough_large_size) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError if size is too large" do
+ max_size = ArraySpecs.max_64bit_size
+ lambda { Array.new(max_size + 1) }.should raise_error(ArgumentError)
end
end
- it "returns a new array of size with nil elements" do
- Array.new(5).should == [nil, nil, nil, nil, nil]
+ it "calls #to_int to convert the size argument to an Integer when object is given" do
+ obj = mock('1')
+ obj.should_receive(:to_int).and_return(1)
+ Array.new(obj, :a).should == [:a]
+ end
- a = ArraySpecs::MyArray.new(5)
- a.class.should == ArraySpecs::MyArray
- (1...5).each do |i|
- a[0].should == nil
- end
+ it "calls #to_int to convert the size argument to an Integer when object is not given" do
+ obj = mock('1')
+ obj.should_receive(:to_int).and_return(1)
+ Array.new(obj).should == [nil]
end
- it "tries to convert the passed arguments to Arrays using #to_ary" do
- obj = mock('[:foo]')
- obj.should_receive(:to_ary).and_return([:foo])
- Array.new(obj).should == [:foo]
- end
-
- it "checks whether the passed argument responds to #to_ary" do
- obj = mock('[:foo]')
- obj.should_receive(:respond_to?).with(:to_ary).any_number_of_times.and_return(true)
- obj.should_receive(:method_missing).with(:to_ary).any_number_of_times.and_return([:foo])
- Array.new(obj).should == [:foo]
- end
-
- it "tries to convert the passed arguments to Integers using #to_int when they don't respond to #to_ary" do
- obj = mock('3')
- obj.should_receive(:to_int).and_return(3)
- Array.new(obj).should == [nil, nil, nil]
- end
-
- it "checks whether the passed argument responds to #to_int if they don't respond to #to_ary" do
- obj = mock('3')
- obj.should_receive(:respond_to?).with(:to_ary).and_return(false)
- obj.should_receive(:respond_to?).with(:to_int).any_number_of_times.and_return(true)
- obj.should_receive(:method_missing).with(:to_int).and_return(3)
- Array.new(obj).should == [nil, nil, nil]
- end
-
- it "returns a new array of size default objects" do
- Array.new(4, true).should == [true, true, true, true]
-
- a = ArraySpecs::MyArray.new(4, true)
- a.class.should == ArraySpecs::MyArray
- a.inspect.should == [true, true, true, true].inspect
- end
-
- it "does not copy the object given as default" do
- str = "x"
- ary = Array.new(4, str)
- ary[0].object_id.should == str.object_id
- ary[1].object_id.should == str.object_id
- ary[2].object_id.should == str.object_id
- ary[3].object_id.should == str.object_id
- end
-
- it "does not call to_ary on Array subclasses when passed an array-like argument" do
- Array.new(ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
- end
-
- it "calls to_ary on an argument before to_int" do
- obj = mock('[1,2,3]')
- def obj.to_ary() [1, 2, 3] end
- def obj.to_int() 3 end
-
- Array.new(obj).should == [1, 2, 3]
- end
-
- it "returns an array of size elements from the result of passing each index to block" do
- Array.new(5) { |i| i + 1 }.should == [1, 2, 3, 4, 5]
-
- a = ArraySpecs::MyArray.new(5) { |i| i + 1 }
- a.class.should == ArraySpecs::MyArray
- a[0].should == 1
- a[1].should == 2
- a[2].should == 3
- a[3].should == 4
- a[4].should == 5
- end
-
- it "will fail if a to_ary is supplied as the first argument and a second argument is given" do
- lambda { Array.new([1, 2], 1) }.should raise_error(TypeError)
+ it "raises a TypeError if the size argument is not an Integer type" do
+ obj = mock('nonnumeric')
+ obj.stub!(:to_ary).and_return([1, 2])
+ lambda{ Array.new(obj, :a) }.should raise_error(TypeError)
+ end
+
+ it "yields the index of the element and sets the element to the value of the block" do
+ Array.new(3) { |i| i.to_s }.should == ['0', '1', '2']
+ end
+
+ it "uses the block value instead of using the default value" do
+ Array.new(3, :obj) { |i| i.to_s }.should == ['0', '1', '2']
+ end
+
+ it "returns the value passed to break" do
+ a = Array.new(3) do |i|
+ break if i == 2
+ i.to_s
+ end
+
+ a.should == nil
end
end
16 spec/frozen/core/array/pack_spec.rb
View
@@ -2324,8 +2324,8 @@ def self.format(count = nil)
end
it "raises an ArgumentError if the count is greater than the number of remaining array elements" do
- lambda { [1].pack('w2') }.should raise_error(ArgumentError, /few/)
- lambda { [1, 2, 3, 4, 5].pack('w10') }.should raise_error(ArgumentError, /few/)
+ lambda { [1].pack('w2') }.should raise_error(ArgumentError)
+ lambda { [1, 2, 3, 4, 5].pack('w10') }.should raise_error(ArgumentError)
end
it "calls to_int on non-integer values before packing" do
@@ -2343,10 +2343,10 @@ def self.format(count = nil)
it "raises TypeError on nil and non-numeric arguments" do
- lambda { [nil].pack('w') }.should raise_error(TypeError, /nil/)
- lambda { [()].pack('w') }.should raise_error(TypeError, /nil/)
- lambda { ['a'].pack('w') }.should raise_error(TypeError, /String/)
- lambda { [Object.new].pack('w') }.should raise_error(TypeError, /Object/)
+ lambda { [nil].pack('w') }.should raise_error(TypeError)
+ lambda { [()].pack('w') }.should raise_error(TypeError)
+ lambda { ['a'].pack('w') }.should raise_error(TypeError)
+ lambda { [Object.new].pack('w') }.should raise_error(TypeError)
end
ruby_version_is '1.9' do
@@ -2641,8 +2641,8 @@ def self.cbyte(byte)
end
it "raises an ArgumentError if count is greater than the corresponding string in array" do
- lambda { ["abc", "def"].pack("P3") }.should_not raise_error(ArgumentError, /short buffer/)
- lambda { ["ab", "def"].pack("P3") }.should raise_error(ArgumentError, /short buffer/)
+ lambda { ["abc", "def"].pack("P3") }.should_not raise_error(ArgumentError)
+ lambda { ["ab", "def"].pack("P3") }.should raise_error(ArgumentError)
end
ruby_version_is '1.9' do
6 spec/frozen/core/array/pop_spec.rb
View
@@ -4,7 +4,7 @@
describe "Array#pop" do
it "removes and returns the last element of the array" do
a = ["a", 1, nil, true]
-
+
a.pop.should == true
a.should == ["a", 1, nil]
@@ -17,7 +17,7 @@
a.pop.should == "a"
a.should == []
end
-
+
it "returns nil if there are no more elements" do
[].pop.should == nil
end
@@ -111,7 +111,7 @@
end
it "raises an ArgumentError if n is negative" do
- lambda{ [1, 2, 3].pop(-1) }.should raise_error(ArgumentError, /negative/)
+ lambda{ [1, 2, 3].pop(-1) }.should raise_error(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
2  spec/frozen/core/array/shared/collect.rb
View
@@ -88,7 +88,7 @@
ruby_version_is '' ... '1.8.7' do
it 'raises LocalJumpError if no block given' do
a = [1, 2, 3]
- lambda { a.send(@method) }.should raise_error(LocalJumpError, /no block given/)
+ lambda { a.send(@method) }.should raise_error(LocalJumpError)
end
end
ruby_version_is '1.8.7' ... '1.9' do
10 spec/frozen/core/array/shared/join.rb
View
@@ -18,9 +18,9 @@ class << obj; undef :to_s; end
it "raises a NoMethodError if an element does not respond to #to_s" do
obj = mock('o')
class << obj; undef :to_s; end
- lambda{ [1,obj].send(@method, ':') }.should raise_error(NoMethodError, /to_s/)
+ lambda{ [1,obj].send(@method, ':') }.should raise_error(NoMethodError)
end
-
+
it "uses the same separator with nested arrays" do
[1, [2, [3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
[1, [2, ArraySpecs::MyArray[3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
@@ -31,7 +31,7 @@ class << obj; undef :to_s; end
obj.should_receive(:to_str).and_return("::")
[1, 2, 3, 4].send(@method, obj).should == '1::2::3::4'
end
-
+
it "checks whether the passed seperator responds to #to_str" do
obj = mock('.')
obj.should_receive(:respond_to?).with(:to_str).any_number_of_times.and_return(true)
@@ -62,7 +62,7 @@ class << obj; undef :to_s; end
str = x.send(@method, '/')
str.should include("one/two")
str.should include("three/four")
-
+
x = []
y = []
y << 9 << x << 8 << y << 7
@@ -102,7 +102,7 @@ class << obj; undef :to_s; end
end
ruby_version_is '1.9' do
- it "does not consider untrustworthiness of either the array or the separator when the array is empty" do
+ it "does not consider untrustworthiness of either the array or the separator when the array is empty" do
[].send(@method, ":").untrusted?.should == false
[].untrust.send(@method, ":").untrusted?.should == false
[].send(@method, ":".untrust).untrusted?.should == false
6 spec/frozen/core/bignum/div_spec.rb
View
@@ -11,10 +11,10 @@
bignum_value(88).div(bignum_value(88).to_f).should eql(1)
bignum_value(88).div(-bignum_value(88).to_f).should eql(-1)
end
-
+
it "raises FloatDomainError if the argument is a float zero" do
- lambda { bignum_value(88).div(0.0) }.should raise_error(FloatDomainError, "Infinity")
- lambda { bignum_value(88).div(-0.0) }.should raise_error(FloatDomainError, "-Infinity")
+ lambda { bignum_value(88).div(0.0) }.should raise_error(FloatDomainError)
+ lambda { bignum_value(88).div(-0.0) }.should raise_error(FloatDomainError)
end
end
end
10 spec/frozen/core/bignum/divmod_spec.rb
View
@@ -4,7 +4,7 @@
before(:each) do
@bignum = bignum_value(55)
end
-
+
# Based on MRI's test/test_integer.rb (test_divmod),
# MRI maintains the following property:
# if q, r = a.divmod(b) ==>
@@ -26,15 +26,15 @@
(-10**50).divmod(10**40 + 1).should == [-10000000000, 10000000000]
(10**50).divmod(-(10**40 + 1)).should == [-10000000000, -10000000000]
end
-
+
it "raises a ZeroDivisionError when the given argument is 0" do
lambda { @bignum.divmod(0) }.should raise_error(ZeroDivisionError)
lambda { (-@bignum).divmod(0) }.should raise_error(ZeroDivisionError)
end
-
+
it "raises a FloatDomainError when the given argument is 0 and a Float" do
- lambda { @bignum.divmod(0.0) }.should raise_error(FloatDomainError, "NaN")
- lambda { (-@bignum).divmod(0.0) }.should raise_error(FloatDomainError, "NaN")
+ lambda { @bignum.divmod(0.0) }.should raise_error(FloatDomainError)
+ lambda { (-@bignum).divmod(0.0) }.should raise_error(FloatDomainError)
end
it "raises a TypeError when the given argument is not an Integer" do
10 spec/frozen/core/class/new_spec.rb
View
@@ -73,10 +73,10 @@ def message2; "hello"; end
it "raises a TypeError when given a non-Class" do
error_msg = /superclass must be a Class/
- lambda { Class.new("") }.should raise_error(TypeError, error_msg)
- lambda { Class.new(1) }.should raise_error(TypeError, error_msg)
- lambda { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
- lambda { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
- lambda { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
+ lambda { Class.new("") }.should raise_error(TypeError)
+ lambda { Class.new(1) }.should raise_error(TypeError)
+ lambda { Class.new(:symbol) }.should raise_error(TypeError)
+ lambda { Class.new(mock('o')) }.should raise_error(TypeError)
+ lambda { Class.new(Module.new) }.should raise_error(TypeError)
end
end
16 spec/frozen/core/dir/shared/open.rb
View
@@ -6,7 +6,9 @@
end
it "raises a SystemCallError if the directory does not exist" do
- lambda { Dir.send @method, DirSpecs.nonexistent }.should raise_error(SystemCallError)
+ lambda do
+ Dir.send @method, DirSpecs.nonexistent
+ end.should raise_error(SystemCallError)
end
it "may take a block which is yielded to with the Dir instance" do
@@ -19,15 +21,19 @@
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 directory")
+ lambda { closed_dir.close }.should raise_error(IOError)
end
it "closes the Dir instance when the block exits the block even due to an exception" do
@closed_dir = nil
- l = lambda { Dir.send(@method, DirSpecs.mock_dir) { |dir| @closed_dir = dir; raise } }
- l.should raise_error
+ lambda do
+ Dir.send(@method, DirSpecs.mock_dir) do |dir|
+ @closed_dir = dir
+ raise
+ end
+ end.should raise_error
- lambda { @closed_dir.close }.should raise_error(IOError, "closed directory")
+ lambda { @closed_dir.close }.should raise_error(IOError)
end
end
6 spec/frozen/core/enumerable/all_spec.rb
View
@@ -37,11 +37,11 @@
it "does not hide exceptions out of #each" do
lambda {
EnumerableSpecs::ThrowingEach.new.all?
- }.should raise_error(RuntimeError, "from each")
+ }.should raise_error(RuntimeError)
lambda {
EnumerableSpecs::ThrowingEach.new.all? { false }
- }.should raise_error(RuntimeError, "from each")
+ }.should raise_error(RuntimeError)
end
describe "with no block" do
@@ -109,7 +109,7 @@
it "does not hide exceptions out of the block" do
lambda {
@enum.all? { raise "from block" }
- }.should raise_error(RuntimeError, "from block")
+ }.should raise_error(RuntimeError)
end
end
end
6 spec/frozen/core/enumerable/any_spec.rb
View
@@ -36,11 +36,11 @@
it "does not hide exceptions out of #each" do
lambda {
EnumerableSpecs::ThrowingEach.new.any?
- }.should raise_error(RuntimeError, "from each")
+ }.should raise_error(RuntimeError)
lambda {
EnumerableSpecs::ThrowingEach.new.any? { false }
- }.should raise_error(RuntimeError, "from each")
+ }.should raise_error(RuntimeError)
end
describe "with no block" do
@@ -122,7 +122,7 @@
it "does not hide exceptions out of the block" do
lambda {
@enum.any? { raise "from block" }
- }.should raise_error(RuntimeError, "from block")
+ }.should raise_error(RuntimeError)
end
end
end
2  spec/frozen/core/file/open_spec.rb
View
@@ -50,7 +50,7 @@ def close
end
end
end
- }.should raise_error(Exception, "exception out of close")
+ }.should raise_error(Exception)
end
it "with a block swallows StandardErrors produced by close" do
2  spec/frozen/core/io/close_spec.rb
View
@@ -51,7 +51,7 @@
io.close
- lambda { io.pid }.should raise_error(IOError, 'closed stream')
+ lambda { io.pid }.should raise_error(IOError)
end
it "sets $?" do
2  spec/frozen/core/io/open_spec.rb
View
@@ -39,7 +39,7 @@ def io.close
end
end
end # IO object is closed here
- }.should raise_error(Exception, "exception out of close")
+ }.should raise_error(Exception)
end
it "with a block swallows StandardErrors produced by close" do
8 spec/frozen/core/io/readpartial_spec.rb
View
@@ -46,7 +46,7 @@
@wr.write("b")
@rd.readpartial(2).should == "b"
end
-
+
it "discards the existing buffer content upon successful read" do
buffer = "existing"
@wr.write("hello world")
@@ -54,21 +54,21 @@
@rd.readpartial(11, buffer)
buffer.should == "hello world"
end
-
+
it "discards the existing buffer content upon error" do
buffer = 'hello'
@wr.close
lambda { @rd.readpartial(1, buffer) }.should raise_error(EOFError)
buffer.should be_empty
end
-
+
it "raises IOError if the stream is closed" do
@wr.close
lambda { @rd.readpartial(1) }.should raise_error(IOError)
end
it "raises ArgumentError if the negative argument is provided" do
- lambda { @rd.readpartial(-1) }.should raise_error(ArgumentError, /negative/)
+ lambda { @rd.readpartial(-1) }.should raise_error(ArgumentError)
end
it "immediately returns an empty string if the length argument is 0" do
8 spec/frozen/core/io/shared/tty_shared.rb
View
@@ -1,9 +1,11 @@
require File.dirname(__FILE__) + '/../fixtures/classes'
describe :io_tty, :shared => true do
- # Yeah, this will probably break.
- it "returns true if this stream is a terminal device (TTY)" do
- File.open('/dev/tty') {|f| f.send @method }.should == true
+ with_tty do
+ # Yeah, this will probably break.
+ it "returns true if this stream is a terminal device (TTY)" do
+ File.open('/dev/tty') {|f| f.send @method }.should == true
+ end
end
it "returns false if this stream is not a terminal device (TTY)" do
5 spec/frozen/core/kernel/raise_spec.rb
View
@@ -1,5 +1,6 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require File.dirname(__FILE__) + '/fixtures/classes'
+require File.dirname(__FILE__) + '/../../shared/kernel/raise'
describe "Kernel#raise" do
it "is a private method" do
@@ -7,6 +8,10 @@
end
end
+describe "Kernel#raise" do
+ it_behaves_like :kernel_raise, :raise, Kernel
+end
+
describe "Kernel.raise" do
it "needs to be reviewed for spec completeness"
end
2  spec/frozen/core/kernel/throw_spec.rb
View
@@ -44,7 +44,7 @@
it "raises NameError if there is no catch block for the symbol" do
proc {
throw :blah
- }.should raise_error(NameError, "uncaught throw `blah'") { |error|
+ }.should raise_error(NameError) { |error|
# TODO:
# See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17629
#
24 spec/frozen/core/thread/fixtures/classes.rb
View
@@ -4,3 +4,27 @@ class Channel < Queue
alias receive shift
end
end
+
+module ThreadSpecs
+ def self.sleeping_thread
+ Thread.new do
+ begin
+ sleep
+ ScratchPad.record :woken
+ rescue Object => e
+ ScratchPad.record e
+ end
+ end
+ end
+
+ def self.running_thread
+ Thread.new do
+ begin
+ loop {}
+ ScratchPad.record :woken
+ rescue Object => e
+ ScratchPad.record e
+ end
+ end
+ end
+end
122 spec/frozen/core/thread/raise_spec.rb
View
@@ -1,2 +1,122 @@
require File.dirname(__FILE__) + '/../../spec_helper'
-require File.dirname(__FILE__) + '/fixtures/classes'
+require File.dirname(__FILE__) + '/fixtures/classes'
+require File.dirname(__FILE__) + '/../../shared/kernel/raise'
+
+describe "Thread#raise" do
+ it "ignores dead threads" do
+ t = Thread.new { :dead }
+ Thread.pass while t.alive?
+ lambda {t.raise("Kill the thread")}.should_not raise_error
+ lambda {t.value}.should_not raise_error
+ end
+end
+
+describe "Thread#raise on a sleeping thread" do
+ before :each do
+ ScratchPad.clear
+ @thr = ThreadSpecs.sleeping_thread
+ Thread.pass while (@thr.alive? && @thr.status != "sleep")
+ end
+
+ after :each do
+ @thr.kill
+ end
+
+ it "raises a RuntimeError if no exception class is given" do
+ @thr.raise
+ Thread.pass while @thr.status
+ ScratchPad.recorded.should be_kind_of(RuntimeError)
+ end
+
+ it "raises the given exception" do
+ @thr.raise Exception
+ Thread.pass while @thr.status
+ ScratchPad.recorded.class.should == Exception
+ end
+
+ it "raises the given exception with the given message" do
+ @thr.raise Exception, "get to work"
+ Thread.pass while @thr.status
+ ScratchPad.recorded.class.should == Exception
+ ScratchPad.recorded.message.should == "get to work"
+ end
+
+ it "can go unhandled" do
+ t = Thread.new do
+ sleep
+ end
+
+ t.raise
+ lambda {t.value}.should raise_error(RuntimeError)
+ end
+
+ it "re-raises active exception" do
+ t = Thread.new do
+ begin
+ 1/0
+ rescue ZeroDivisionError
+ sleep
+ end
+ end
+
+ Thread.pass while t.status != "sleep"
+ t.raise
+ lambda {t.value}.should raise_error(ZeroDivisionError)
+ end
+end
+
+describe "Thread#raise on a running thread" do
+ before :each do
+ ScratchPad.clear
+ @thr = ThreadSpecs.running_thread
+ Thread.pass while (@thr.alive? && @thr.status != "run")
+ end
+
+ it "raises a RuntimeError if no exception class is given" do
+ @thr.raise
+ Thread.pass while @thr.status
+ ScratchPad.recorded.should be_kind_of(RuntimeError)
+ end
+
+ it "raises the given exception" do
+ @thr.raise Exception
+ Thread.pass while @thr.status
+ ScratchPad.recorded.class.should == Exception
+ end
+
+ it "raises the given exception with the given message" do
+ @thr.raise Exception, "get to work"
+ Thread.pass while @thr.status
+ ScratchPad.recorded.class.should == Exception
+ ScratchPad.recorded.message.should == "get to work"
+ end
+
+ it "can go unhandled" do
+ t = Thread.new do
+ loop {}
+ end
+
+ t.raise
+ lambda {t.value}.should raise_error(RuntimeError)
+ end
+
+ it "re-raises active exception" do
+ raised = false
+ t = Thread.new do
+ begin
+ 1/0
+ rescue ZeroDivisionError
+ raised = true
+ loop {}
+ end
+ end
+
+ Thread.pass until raised || !t.alive?
+ t.raise
+ lambda {t.value}.should raise_error(ZeroDivisionError)
+ end
+end
+
+describe "Thread#raise on same thread" do
+ it_behaves_like :kernel_raise, :raise, Thread.current
+end
40 spec/frozen/core/thread/wakeup_spec.rb
View
@@ -2,37 +2,19 @@
require File.dirname(__FILE__) + '/fixtures/classes'
describe "Thread#wakeup" do
- it "does not result in a deadlock" do
- c = Channel.new
- t1 = Thread.new do
- loop do
- c << t1
- c << t1
- Thread.stop
- end
- end
- t2 = Thread.new do
- loop do
- c << t2
- Thread.stop
- end
+ it "wakes up a sleeping thread" do
+ a = 0
+ t = Thread.new do
+ a = 1
+ Thread.stop
+ a = 2
end
- count1 = 0
- count2 = 0
- while(count1 < 10) do
- if c.size > 0
- case c.receive
- when t1; count1+=1
- when t2; count2+=1
- end
- end
- t1.wakeup
- t2.wakeup
- end
- count1.should > count2
+ Thread.pass until t.status == "sleep" || !t.alive?
+ a.should == 1
- t1.kill
- t2.kill
+ t.wakeup
+ t.join
+ a.should == 2
end
end
11 spec/frozen/language/encoding_spec.rb
View
@@ -16,14 +16,15 @@
end
it "is equal to the specified encoding when a magic comment exists" do
- eval("# coding: ASCII-8BIT\n__ENCODING__".force_encoding("US-ASCII")).should == Encoding::ASCII_8BIT
- eval("# coding: US-ASCII\n__ENCODING__".force_encoding("ASCII-8BIT")).should == Encoding::US_ASCII
+ code = "# coding: ASCII-8BIT\n__ENCODING__".force_encoding("US-ASCII")
+ eval(code).should == Encoding::ASCII_8BIT
+
+ code = "# coding: US-ASCII\n__ENCODING__".force_encoding("ASCII-8BIT")
+ eval(code).should == Encoding::US_ASCII
end
it "is not assignable" do
- lambda {
- eval("__ENCODING__ = nil")
- }.should raise_error(SyntaxError, /Can't assign to __ENCODING__/)
+ lambda { eval("__ENCODING__ = nil") }.should raise_error(SyntaxError)
end
end
end
4 spec/frozen/language/fixtures/private.rb
View
@@ -56,4 +56,8 @@ def foo
"foo"
end
end
+
+ class H < A
+ private :foo
+ end
end
18 spec/frozen/language/private_spec.rb
View
@@ -52,19 +52,9 @@ class G
}.should raise_error(NoMethodError)
end
- it "defines a new method rather than changing visibility of an existing one" do
- Module.new do
- class A
- def foo
- end
- end
-
- class B < A
- private :foo
- end
-
- A.new.foo
- lambda { B.new.foo }.should raise_error(NoMethodError)
- end
+ it "changes the visibility of the existing method in the subclass" do
+ Private::A.new.foo.should == 'foo'
+ lambda {Private::H.new.foo}.should raise_error(NoMethodError)
+ Private::H.new.send(:foo).should == 'foo'
end
end
41 spec/frozen/language/raise_spec.rb
View
@@ -1,41 +0,0 @@
-require File.dirname(__FILE__) + '/../spec_helper'
-
-describe "Kernel#raise" do
- it "aborts the execution" do
- some_var = "This should not change"
-
- lambda {
- raise "Stops the execution"
- some_var = "Ha, it was changed!"
- }.should raise_error(RuntimeError)
-
- some_var.should == "This should not change"
- end
-end
-
-describe "Kernel#raise inside a rescue block" do
- it "re-raises the exception that was rescued" do
- lambda {
- begin
- raise "This exception is re-raised"
- rescue
- raise
- end
- }.should raise_error(RuntimeError, "This exception is re-raised")
- end
-
- it "ignores inner exceptions" do
- lambda {
- begin
- raise "This exception is re-raised"
- rescue
- begin
- raise "This is another error"
- rescue
- end
-
- raise
- end
- }.should raise_error(RuntimeError, "This exception is re-raised")
- end
-end
15 spec/frozen/ruby.1.8.mspec
View
@@ -1,8 +1,12 @@
class MSpecScript
- # An ordered list of the directories containing specs to run
- set :files, [
- 'language',
- 'core',
+ # Language features specs
+ set :language, [ 'language' ]
+
+ # Core library specs
+ set :core, [ 'core' ]
+
+ # Standard library specs
+ set :library, [
'library',
# 1.9 feature
@@ -18,6 +22,9 @@ class MSpecScript
'^library/rubygems',
]
+ # An ordered list of the directories containing specs to run
+ set :files, get(:language) + get(:core) + get(:library)
+
# The default implementation to run the specs.
set :target, 'ruby'
end
15 spec/frozen/ruby.1.9.mspec
View
@@ -1,8 +1,12 @@
class MSpecScript
- # An ordered list of the directories containing specs to run
- set :files, [
- 'language',
- 'core',
+ # Language features specs
+ set :language, [ 'language' ]
+
+ # Core library specs
+ set :core, [ 'core' ]
+
+ # Standard library specs
+ set :library, [
'library',
# obsolete libraries
@@ -34,6 +38,9 @@ class MSpecScript
'^library/dl', # reimplemented and API changed
]
+ # An ordered list of the directories containing specs to run
+ set :files, get(:language) + get(:core) + get(:library)
+
# The default implementation to run the specs.
# TODO: this needs to be more sophisticated since the
# executable is not consistently named.
43 spec/frozen/shared/kernel/raise.rb
View
@@ -0,0 +1,43 @@
+describe :kernel_raise, :shared => true do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "aborts execution" do
+ lambda do
+ @object.raise Exception, "abort"
+ ScratchPad.record :no_abort
+ end.should raise_error(Exception, "abort")
+
+ ScratchPad.recorded.should be_nil
+ end
+
+ it "raises RuntimeError if no exception class is given" do
+ lambda { @object.raise }.should raise_error(RuntimeError)
+ end
+
+ it "re-raises the rescued exception" do
+ lambda do
+ begin
+ raise Exception, "outer"
+ ScratchPad.record :no_abort
+ rescue
+ begin
+ raise StandardError, "inner"
+ rescue
+ end
+
+ @object.raise
+ ScratchPad.record :no_reraise
+ end
+ end.should raise_error(Exception, "outer")
+
+ ScratchPad.recorded.should be_nil
+ end
+
+ it "allows Exception, message, and backtrace parameters" do
+ lambda do
+ @object.raise(ArgumentError, "message", caller)
+ end.should raise_error(ArgumentError, "message")
+ end
+end
1  spec/tags/core/task/get_stack_value_tags.txt
View
@@ -1 +0,0 @@
-fails:Task#get_stack_value throws an ArgumentError if depth is out of range
1  spec/tags/frozen/core/array/initialize_tags.txt
View
@@ -1 +0,0 @@
-fails:Array#initialize with (size, object) makes the array contain values the given block would yield even if it would break in the block
1  spec/tags/frozen/core/array/new_tags.txt
View
@@ -1 +0,0 @@
-fails:Array.new raises an ArgumentError when passed a too large size
12 spec/tags/frozen/core/array/pack_tags.txt
View
@@ -249,3 +249,15 @@ fails:Array#pack with format 'P' consumes one array item per a format
fails:Array#pack with format 'P' ignores '*' parameter
fails:Array#pack with format 'P' returns a pointer to zero-length byte sequence if count = 0 with
fails:Array#pack with format 'P' raises an ArgumentError if count is greater than the corresponding string in array
+fails(on 64bit):Array#pack with format 'i!' drops higher bytes when a pack argument is >= 2**32
+fails(on 64bit):Array#pack with format 'i!' drops higher bytes when a pack argument is < -2**32
+fails(on 64bit):Array#pack with format 'i_' drops higher bytes when a pack argument is >= 2**32
+fails(on 64bit):Array#pack with format 'i_' drops higher bytes when a pack argument is < -2**32
+fails(on 64bit):Array#pack with format 'I!' drops higher bytes when a pack argument is >= 2**32
+fails(on 64bit):Array#pack with format 'I!' drops higher bytes when a pack argument is < -2**32
+fails(on 64bit):Array#pack with format 'I_' drops higher bytes when a pack argument is >= 2**32
+fails(on 64bit):Array#pack with format 'I_' drops higher bytes when a pack argument is < -2**32
+fails(on 64bit):Array#pack with format 'l!' returns a string containing 8 bytes for an integer
+fails(on 64bit):Array#pack with format 'l_' returns a string containing 8 bytes for an integer
+fails(on 64bit):Array#pack with format 'L!' returns a string containing 8 bytes for an integer
+fails(on 64bit):Array#pack with format 'L_' returns a string containing 8 bytes for an integer
7 spec/tags/frozen/core/thread/raise_tags.txt
View
@@ -0,0 +1,7 @@
+fails:Thread#raise on a sleeping thread can go unhandled
+fails:Thread#raise on a running thread raises a RuntimeError if no exception class is given
+fails:Thread#raise on a running thread raises the given exception
+fails:Thread#raise on a running thread raises the given exception with the given message
+fails:Thread#raise on a running thread can go unhandled
+fails:Thread#raise on a running thread re-raises active exception
+fails:Thread#raise on a sleeping thread re-raises active exception
10 vm/builtin/array.cpp
View
@@ -9,6 +9,7 @@
#include "primitives.hpp"
#include <iostream>
+#include <cmath>
/* Implementation certain Array methods. These methods are just
* the ones the VM requires, not the entire set of all Array methods.
@@ -20,6 +21,8 @@ namespace rubinius {
void Array::init(STATE) {
GO(array).set(state->new_class("Array", G(object)));
G(array)->set_object_type(state, ArrayType);
+
+ G(array)->set_const(state, "MAX_SIZE", Fixnum::from(FIXNUM_MAX));
}
size_t Array::size() {
@@ -35,6 +38,13 @@ namespace rubinius {
return ary;
}
+ // 'self' is passed in automatically by the primitive glue
+ Array* Array::allocate(STATE, Object* self) {
+ Array* ary = Array::create(state, 0U);
+ ary->klass(state, (Class*)self);
+ return ary;
+ }
+
Array* Array::from_tuple(STATE, Tuple* tup) {
size_t length = tup->num_fields();
Array* ary = Array::create(state, length);
3  vm/builtin/array.hpp
View
@@ -34,6 +34,9 @@ namespace rubinius {
static Array* from_tuple(STATE, Tuple* tup);
void setup(STATE, size_t size);
+ // Ruby.primitive :array_allocate
+ static Array* allocate(STATE, Object* self);
+
// Ruby.primitive :array_aref
Object* aref(STATE, Fixnum* idx);
13 vm/builtin/contexts.hpp
View
@@ -182,6 +182,19 @@ namespace rubinius {
return js.stack - stk;
}
+
+ // Ruby.primitive :context_stack_depth
+ Fixnum* stack_depth() {
+ return Fixnum::from(calculate_sp());
+ }
+
+ // Ruby.primitive :context_stack_at
+ Object* stack_at_prim(STATE, Fixnum *depth) {
+ int d = depth->to_native();
+ if(d < 0 || d >= calculate_sp()) return Primitives::failure();
+ return stack_at(depth->to_native());
+ }
+
// Manage the dynamic Unwind stack for this context
void push_unwind(int target_ip) {
assert(current_unwind < kMaxUnwindInfos);
22 vm/ontology.cpp
View
@@ -244,7 +244,7 @@ namespace rubinius {
* Create our Rubinius module that we hang stuff off
*/
- GO(rubinius).set(new_module("Rubinius"));
+ initialize_fundamental_constants();
bootstrap_symbol();
initialize_builtin_classes();
@@ -269,6 +269,18 @@ namespace rubinius {
initialize_platform_data();
}
+ void VM::initialize_fundamental_constants() {
+ GO(rubinius).set(new_module("Rubinius"));
+
+ if(sizeof(int) == sizeof(long)) {
+ G(rubinius)->set_const(state, "L64", Qfalse);
+ } else {
+ G(rubinius)->set_const(state, "L64", Qtrue);
+ }
+
+ G(rubinius)->set_const(state, "WORDSIZE", Fixnum::from(sizeof(void*) * 8));
+ }
+
void VM::initialize_platform_data() {
// HACK test hooking up IO
IO* in_io = IO::create(state, fileno(stdin));
@@ -286,14 +298,6 @@ namespace rubinius {
G(object)->set_const(state, "STDOUT", out_io);
G(object)->set_const(state, "STDERR", err_io);
- if(sizeof(int) == sizeof(long)) {
- G(rubinius)->set_const(state, "L64", Qfalse);
- } else {
- G(rubinius)->set_const(state, "L64", Qtrue);
- }
-
- G(rubinius)->set_const(state, "WORDSIZE", Fixnum::from(sizeof(void*) * 8));
-
#if defined(__ppc__) || defined(__POWERPC__) || defined(_POWER)
G(rubinius)->set_const(state, "PLATFORM", symbol("ppc"));
#elif defined(__amd64__)
16 vm/test/test_array.hpp
View
@@ -24,6 +24,22 @@ class TestArray : public CxxTest::TestSuite {
delete state;
}
+ void test_init() {
+#if __WORDSIZE == 64
+ size_t max_size = 4611686018427387903U;
+#else
+ size_t max_size = 1073741823U;
+#endif
+ TS_ASSERT_EQUALS(Fixnum::from(max_size), G(array)->get_const(state, "MAX_SIZE"));
+ }
+
+ void test_allocate() {
+ Class* sub = state->new_class("ArraySub", G(array), 0);