diff options
Diffstat (limited to 'spec')
102 files changed, 770 insertions, 425 deletions
diff --git a/spec/ruby/README.md b/spec/ruby/README.md index f2e18d5800..eef4e9ca0b 100644 --- a/spec/ruby/README.md +++ b/spec/ruby/README.md @@ -88,9 +88,9 @@ In similar fashion, the following commands run the respective specs: $ ../mspec/bin/mspec :library $ ../mspec/bin/mspec :capi -### Contributing +### Contributing and Writing Specs -See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md). +See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) for documentation about contributing and writing specs (guards, matchers, etc). ### Socket specs from rubysl-socket diff --git a/spec/ruby/appveyor.yml b/spec/ruby/appveyor.yml index 88dd753070..588172ee3d 100644 --- a/spec/ruby/appveyor.yml +++ b/spec/ruby/appveyor.yml @@ -1,6 +1,6 @@ --- version: "{build}" -clone_depth: 5 +clone_depth: 100 init: # To avoid duplicated executables in PATH, see https://github.com/ruby/spec/pull/468 - set PATH=C:\Ruby%ruby_version%\bin;C:\Program Files\7-Zip;C:\Program Files\AppVeyor\BuildAgent;C:\Program Files\Git\cmd;C:\Windows\system32;C:\Program Files;C:\Windows diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb index b57e16ec94..8180ce38be 100644 --- a/spec/ruby/core/dir/home_spec.rb +++ b/spec/ruby/core/dir/home_spec.rb @@ -15,8 +15,8 @@ describe "Dir.home" do end platform_is_not :windows do - it "returns the named user's home directory as a string if called with an argument" do - Dir.home(ENV['USER']).should == ENV['HOME'] + it "returns the named user's home directory, from the user database, as a string if called with an argument" do + Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp end end diff --git a/spec/ruby/core/file/expand_path_spec.rb b/spec/ruby/core/file/expand_path_spec.rb index 99279aec85..b7363fefa9 100644 --- a/spec/ruby/core/file/expand_path_spec.rb +++ b/spec/ruby/core/file/expand_path_spec.rb @@ -88,7 +88,8 @@ describe "File.expand_path" do platform_is_not :windows do before do - @home = ENV['HOME'].chomp('/') + @var_home = ENV['HOME'].chomp('/') + @db_home = `echo ~#{ENV['USER']}`.chomp end # FIXME: these are insane! @@ -107,9 +108,9 @@ describe "File.expand_path" do File.expand_path('./////').should == Dir.pwd File.expand_path('.').should == Dir.pwd File.expand_path(Dir.pwd).should == Dir.pwd - File.expand_path('~/').should == @home - File.expand_path('~/..badfilename').should == "#{@home}/..badfilename" - File.expand_path('~/a','~/b').should == "#{@home}/a" + File.expand_path('~/').should == @var_home + File.expand_path('~/..badfilename').should == "#{@var_home}/..badfilename" + File.expand_path('~/a','~/b').should == "#{@var_home}/a" File.expand_path('..').should == File.dirname(Dir.pwd) end @@ -126,8 +127,11 @@ describe "File.expand_path" do end it "expands ~ENV['USER'] to the user's home directory" do - File.expand_path("~#{ENV['USER']}").should == @home - File.expand_path("~#{ENV['USER']}/a").should == "#{@home}/a" + File.expand_path("~#{ENV['USER']}").should == @db_home + end + + it "expands ~ENV['USER']/a to a in the user's home directory" do + File.expand_path("~#{ENV['USER']}/a").should == "#{@db_home}/a" end it "does not expand ~ENV['USER'] when it's not at the start" do @@ -135,7 +139,7 @@ describe "File.expand_path" do end it "expands ../foo with ~/dir as base dir to /path/to/user/home/foo" do - File.expand_path('../foo', '~/dir').should == "#{@home}/foo" + File.expand_path('../foo', '~/dir').should == "#{@var_home}/foo" end end @@ -239,4 +243,19 @@ platform_is_not :windows do lambda { File.expand_path("~") }.should raise_error(ArgumentError) end end + + describe "File.expand_path with a non-absolute HOME" do + before :each do + @home = ENV["HOME"] + end + + after :each do + ENV["HOME"] = @home + end + + it "raises an ArgumentError" do + ENV["HOME"] = "non-absolute" + lambda { File.expand_path("~") }.should raise_error(ArgumentError, 'non-absolute home') + end + end end diff --git a/spec/ruby/core/gc/count_spec.rb b/spec/ruby/core/gc/count_spec.rb index 11648ac9be..af2fbbe713 100644 --- a/spec/ruby/core/gc/count_spec.rb +++ b/spec/ruby/core/gc/count_spec.rb @@ -4,4 +4,14 @@ describe "GC.count" do it "returns an integer" do GC.count.should be_kind_of(Integer) end + + it "increases as collections are run" do + count_before = GC.count + i = 0 + while GC.count <= count_before and i < 10 + GC.start + i += 1 + end + GC.count.should > count_before + end end diff --git a/spec/ruby/core/hash/shift_spec.rb b/spec/ruby/core/hash/shift_spec.rb index 9421a77537..8cf3f4025a 100644 --- a/spec/ruby/core/hash/shift_spec.rb +++ b/spec/ruby/core/hash/shift_spec.rb @@ -61,4 +61,19 @@ describe "Hash#shift" do lambda { HashSpecs.frozen_hash.shift }.should raise_error(frozen_error_class) lambda { HashSpecs.empty_frozen_hash.shift }.should raise_error(frozen_error_class) end + + it "works when the hash is at capacity" do + # We try a wide range of sizes in hopes that this will cover all implementationss base Hash size. + results = [] + 1.upto(100) do |n| + h = {} + n.times do |i| + h[i] = i + end + h.shift + results << h.size + end + + results.should == 0.upto(99).to_a + end end diff --git a/spec/ruby/core/integer/gcd_spec.rb b/spec/ruby/core/integer/gcd_spec.rb index 69f711d4c5..238bf66cc0 100644 --- a/spec/ruby/core/integer/gcd_spec.rb +++ b/spec/ruby/core/integer/gcd_spec.rb @@ -43,6 +43,17 @@ describe "Integer#gcd" do bignum.gcd(99).should == 99 end + it "doesn't cause an integer overflow" do + [2 ** (1.size * 8 - 2), 0x8000000000000000].each do |max| + [max - 1, max, max + 1].each do |num| + num.gcd(num).should == num + (-num).gcd(num).should == num + (-num).gcd(-num).should == num + num.gcd(-num).should == num + end + end + end + it "raises an ArgumentError if not given an argument" do lambda { 12.gcd }.should raise_error(ArgumentError) end diff --git a/spec/ruby/core/io/syswrite_spec.rb b/spec/ruby/core/io/syswrite_spec.rb index 1b1477bc6e..a4dc8328aa 100644 --- a/spec/ruby/core/io/syswrite_spec.rb +++ b/spec/ruby/core/io/syswrite_spec.rb @@ -55,7 +55,7 @@ describe "IO#syswrite on a pipe" do r, w = IO.pipe begin w.nonblock = true - larger_than_pipe_capacity = 100 * 1024 + larger_than_pipe_capacity = 2 * 1024 * 1024 written = w.syswrite("a"*larger_than_pipe_capacity) written.should > 0 written.should < larger_than_pipe_capacity diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb index b7de1b7a6d..2639d24c45 100644 --- a/spec/ruby/core/io/ungetbyte_spec.rb +++ b/spec/ruby/core/io/ungetbyte_spec.rb @@ -50,7 +50,7 @@ describe "IO#ungetbyte" do end ruby_version_is '2.6' do - it "is an RangeError if the integr is not in 8bit" do + it "is an RangeError if the integer is not in 8bit" do for i in [4095, 0x4f7574206f6620636861722072616e6765] do lambda { @io.ungetbyte(i) }.should raise_error(RangeError) end diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb index 922ce58cbd..1fb812f5cc 100644 --- a/spec/ruby/core/main/using_spec.rb +++ b/spec/ruby/core/main/using_spec.rb @@ -6,6 +6,7 @@ describe "main.using" do lambda do eval('using', TOPLEVEL_BINDING) end.should raise_error(ArgumentError) + lambda do eval('using "foo"', TOPLEVEL_BINDING) end.should raise_error(TypeError) diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb index 3fa493b1da..97ea0a706d 100644 --- a/spec/ruby/core/module/refine_spec.rb +++ b/spec/ruby/core/module/refine_spec.rb @@ -717,4 +717,19 @@ describe "Module#refine" do result.should == "hello from refinement" end end + + it 'does not list methods defined only in refinement' do + refine_object = Module.new do + refine Object do + def refinement_only_method + end + end + end + spec = self + klass = Class.new { instance_methods.should_not spec.send(:include, :refinement_only_method) } + instance = klass.new + instance.methods.should_not include :refinement_only_method + instance.respond_to?(:refinement_only_method).should == false + -> { instance.method :refinement_only_method }.should raise_error(NameError) + end end diff --git a/spec/ruby/core/mutex/lock_spec.rb b/spec/ruby/core/mutex/lock_spec.rb index a272b16a32..a1a2972d8c 100644 --- a/spec/ruby/core/mutex/lock_spec.rb +++ b/spec/ruby/core/mutex/lock_spec.rb @@ -11,22 +11,15 @@ describe "Mutex#lock" do m.unlock end - it "waits if the lock is not available" do + it "blocks the caller if already locked" do m = Mutex.new - m.lock + lambda { m.lock }.should block_caller + end - th = Thread.new do - m.lock - ScratchPad.record :after_lock - end - - Thread.pass while th.status and th.status != "sleep" - - ScratchPad.recorded.should be_nil - m.unlock - th.join - ScratchPad.recorded.should == :after_lock + it "does not block the caller if not locked" do + m = Mutex.new + lambda { m.lock }.should_not block_caller end # Unable to find a specific ticket but behavior change may be diff --git a/spec/ruby/core/mutex/synchronize_spec.rb b/spec/ruby/core/mutex/synchronize_spec.rb index 206b14e828..e3dad508b8 100644 --- a/spec/ruby/core/mutex/synchronize_spec.rb +++ b/spec/ruby/core/mutex/synchronize_spec.rb @@ -24,4 +24,43 @@ describe "Mutex#synchronize" do th.join m1.locked?.should be_false end + + it "blocks the caller if already locked" do + m = Mutex.new + m.lock + lambda { m.synchronize { } }.should block_caller + end + + it "does not block the caller if not locked" do + m = Mutex.new + lambda { m.synchronize { } }.should_not block_caller + end + + it "blocks the caller if another thread is also in the synchronize block" do + m = Mutex.new + q1 = Queue.new + q2 = Queue.new + + t = Thread.new { + m.synchronize { + q1.push :ready + q2.pop + } + } + + q1.pop.should == :ready + + lambda { m.synchronize { } }.should block_caller + + q2.push :done + t.join + end + + it "is not recursive" do + m = Mutex.new + + m.synchronize do + lambda { m.synchronize { } }.should raise_error(ThreadError) + end + end end diff --git a/spec/ruby/core/process/clock_gettime_spec.rb b/spec/ruby/core/process/clock_gettime_spec.rb new file mode 100644 index 0000000000..165f0db730 --- /dev/null +++ b/spec/ruby/core/process/clock_gettime_spec.rb @@ -0,0 +1,35 @@ +require_relative '../../spec_helper' + +describe "Process.clock_gettime" do + describe 'time units' do + it 'handles a fixed set of time units' do + [:nanosecond, :microsecond, :millisecond, :second].each do |unit| + Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should be_kind_of(Integer) + end + + [:float_microsecond, :float_millisecond, :float_second].each do |unit| + Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should be_an_instance_of(Float) + end + end + + it 'raises an ArgumentError for an invalid time unit' do + lambda { Process.clock_gettime(Process::CLOCK_MONOTONIC, :bad) }.should raise_error(ArgumentError) + end + + it 'defaults to :float_second' do + t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC) + t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) + + t1.should be_an_instance_of(Float) + t2.should be_close(t1, 2.0) # 2.0 is chosen arbitrarily to allow for time skew without admitting failure cases, which would be off by an order of magnitude. + end + + it 'uses the default time unit (:float_second) when passed nil' do + t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, nil) + t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) + + t1.should be_an_instance_of(Float) + t2.should be_close(t1, 2.0) # 2.0 is chosen arbitrarily to allow for time skew without admitting failure cases, which would be off by an order of magnitude. + end + end +end diff --git a/spec/ruby/core/queue/append_spec.rb b/spec/ruby/core/queue/append_spec.rb new file mode 100644 index 0000000000..34165a7506 --- /dev/null +++ b/spec/ruby/core/queue/append_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' + +describe "Queue#<<" do + it_behaves_like :queue_enq, :<<, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/clear_spec.rb b/spec/ruby/core/queue/clear_spec.rb new file mode 100644 index 0000000000..3245e4cb83 --- /dev/null +++ b/spec/ruby/core/queue/clear_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/clear' + +describe "Queue#clear" do + it_behaves_like :queue_clear, :clear, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/close_spec.rb b/spec/ruby/core/queue/close_spec.rb new file mode 100644 index 0000000000..c0d774cd74 --- /dev/null +++ b/spec/ruby/core/queue/close_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/close' + +describe "Queue#close" do + it_behaves_like :queue_close, :close, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/closed_spec.rb b/spec/ruby/core/queue/closed_spec.rb new file mode 100644 index 0000000000..10d552996d --- /dev/null +++ b/spec/ruby/core/queue/closed_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/closed' + +describe "Queue#closed?" do + it_behaves_like :queue_closed?, :closed?, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/deq_spec.rb b/spec/ruby/core/queue/deq_spec.rb new file mode 100644 index 0000000000..9510978eac --- /dev/null +++ b/spec/ruby/core/queue/deq_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "Queue#deq" do + it_behaves_like :queue_deq, :deq, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/empty_spec.rb b/spec/ruby/core/queue/empty_spec.rb new file mode 100644 index 0000000000..55ca777466 --- /dev/null +++ b/spec/ruby/core/queue/empty_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/empty' + +describe "Queue#empty?" do + it_behaves_like :queue_empty?, :empty?, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/enq_spec.rb b/spec/ruby/core/queue/enq_spec.rb new file mode 100644 index 0000000000..c69c496fbc --- /dev/null +++ b/spec/ruby/core/queue/enq_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' + +describe "Queue#enq" do + it_behaves_like :queue_enq, :enq, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/length_spec.rb b/spec/ruby/core/queue/length_spec.rb new file mode 100644 index 0000000000..25399b2b76 --- /dev/null +++ b/spec/ruby/core/queue/length_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/length' + +describe "Queue#length" do + it_behaves_like :queue_length, :length, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/num_waiting_spec.rb b/spec/ruby/core/queue/num_waiting_spec.rb new file mode 100644 index 0000000000..edc0c37a82 --- /dev/null +++ b/spec/ruby/core/queue/num_waiting_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/num_waiting' + +describe "Queue#num_waiting" do + it_behaves_like :queue_num_waiting, :num_waiting, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/pop_spec.rb b/spec/ruby/core/queue/pop_spec.rb new file mode 100644 index 0000000000..1ce9231685 --- /dev/null +++ b/spec/ruby/core/queue/pop_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "Queue#pop" do + it_behaves_like :queue_deq, :pop, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/push_spec.rb b/spec/ruby/core/queue/push_spec.rb new file mode 100644 index 0000000000..e936f9d282 --- /dev/null +++ b/spec/ruby/core/queue/push_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' + +describe "Queue#push" do + it_behaves_like :queue_enq, :push, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/shift_spec.rb b/spec/ruby/core/queue/shift_spec.rb new file mode 100644 index 0000000000..f84058e1df --- /dev/null +++ b/spec/ruby/core/queue/shift_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "Queue#shift" do + it_behaves_like :queue_deq, :shift, -> { Queue.new } +end diff --git a/spec/ruby/core/queue/size_spec.rb b/spec/ruby/core/queue/size_spec.rb new file mode 100644 index 0000000000..f528dfe797 --- /dev/null +++ b/spec/ruby/core/queue/size_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/length' + +describe "Queue#size" do + it_behaves_like :queue_length, :size, -> { Queue.new } +end diff --git a/spec/ruby/core/signal/list_spec.rb b/spec/ruby/core/signal/list_spec.rb index 2af9c50597..56ad6828fe 100644 --- a/spec/ruby/core/signal/list_spec.rb +++ b/spec/ruby/core/signal/list_spec.rb @@ -61,4 +61,8 @@ describe "Signal.list" do it "includes the EXIT key with a value of zero" do Signal.list["EXIT"].should == 0 end + + it "includes the KILL key with a value of nine" do + Signal.list["KILL"].should == 9 + end end diff --git a/spec/ruby/core/sizedqueue/append_spec.rb b/spec/ruby/core/sizedqueue/append_spec.rb new file mode 100644 index 0000000000..ff96b46d2c --- /dev/null +++ b/spec/ruby/core/sizedqueue/append_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' +require_relative '../../shared/sizedqueue/enque' + +describe "SizedQueue#<<" do + it_behaves_like :queue_enq, :<<, -> { SizedQueue.new(10) } +end + +describe "SizedQueue#<<" do + it_behaves_like :sizedqueue_enq, :<<, ->(n) { SizedQueue.new(n) } +end diff --git a/spec/ruby/core/sizedqueue/clear_spec.rb b/spec/ruby/core/sizedqueue/clear_spec.rb new file mode 100644 index 0000000000..abae01c6c0 --- /dev/null +++ b/spec/ruby/core/sizedqueue/clear_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/clear' + +describe "SizedQueue#clear" do + it_behaves_like :queue_clear, :clear, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/library/thread/sizedqueue/close_spec.rb b/spec/ruby/core/sizedqueue/close_spec.rb index 3222772f61..0e0af851cb 100644 --- a/spec/ruby/library/thread/sizedqueue/close_spec.rb +++ b/spec/ruby/core/sizedqueue/close_spec.rb @@ -1,6 +1,5 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/close' +require_relative '../../spec_helper' +require_relative '../../shared/queue/close' describe "SizedQueue#close" do it_behaves_like :queue_close, :close, -> { SizedQueue.new(10) } diff --git a/spec/ruby/library/thread/sizedqueue/closed_spec.rb b/spec/ruby/core/sizedqueue/closed_spec.rb index 9e41b89640..4b90da1faa 100644 --- a/spec/ruby/library/thread/sizedqueue/closed_spec.rb +++ b/spec/ruby/core/sizedqueue/closed_spec.rb @@ -1,6 +1,5 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/closed' +require_relative '../../spec_helper' +require_relative '../../shared/queue/closed' describe "SizedQueue#closed?" do it_behaves_like :queue_closed?, :closed?, -> { SizedQueue.new(10) } diff --git a/spec/ruby/core/sizedqueue/deq_spec.rb b/spec/ruby/core/sizedqueue/deq_spec.rb new file mode 100644 index 0000000000..5e1bd9f746 --- /dev/null +++ b/spec/ruby/core/sizedqueue/deq_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "SizedQueue#deq" do + it_behaves_like :queue_deq, :deq, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/sizedqueue/empty_spec.rb b/spec/ruby/core/sizedqueue/empty_spec.rb new file mode 100644 index 0000000000..9b0d4ff013 --- /dev/null +++ b/spec/ruby/core/sizedqueue/empty_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/empty' + +describe "SizedQueue#empty?" do + it_behaves_like :queue_empty?, :empty?, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/sizedqueue/enq_spec.rb b/spec/ruby/core/sizedqueue/enq_spec.rb new file mode 100644 index 0000000000..11c65ec14d --- /dev/null +++ b/spec/ruby/core/sizedqueue/enq_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' +require_relative '../../shared/sizedqueue/enque' + +describe "SizedQueue#enq" do + it_behaves_like :queue_enq, :enq, -> { SizedQueue.new(10) } +end + +describe "SizedQueue#enq" do + it_behaves_like :sizedqueue_enq, :enq, ->(n) { SizedQueue.new(n) } +end diff --git a/spec/ruby/core/sizedqueue/length_spec.rb b/spec/ruby/core/sizedqueue/length_spec.rb new file mode 100644 index 0000000000..b93e7f8997 --- /dev/null +++ b/spec/ruby/core/sizedqueue/length_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/length' + +describe "SizedQueue#length" do + it_behaves_like :queue_length, :length, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/sizedqueue/max_spec.rb b/spec/ruby/core/sizedqueue/max_spec.rb new file mode 100644 index 0000000000..b65a67eeb0 --- /dev/null +++ b/spec/ruby/core/sizedqueue/max_spec.rb @@ -0,0 +1,10 @@ +require_relative '../../spec_helper' +require_relative '../../shared/sizedqueue/max' + +describe "SizedQueue#max" do + it_behaves_like :sizedqueue_max, :max, ->(n) { SizedQueue.new(n) } +end + +describe "SizedQueue#max=" do + it_behaves_like :sizedqueue_max=, :max=, ->(n) { SizedQueue.new(n) } +end diff --git a/spec/ruby/core/sizedqueue/new_spec.rb b/spec/ruby/core/sizedqueue/new_spec.rb new file mode 100644 index 0000000000..8febbfa63b --- /dev/null +++ b/spec/ruby/core/sizedqueue/new_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/sizedqueue/new' + +describe "SizedQueue.new" do + it_behaves_like :sizedqueue_new, :new, ->(*n) { SizedQueue.new(*n) } +end diff --git a/spec/ruby/core/sizedqueue/num_waiting_spec.rb b/spec/ruby/core/sizedqueue/num_waiting_spec.rb new file mode 100644 index 0000000000..cbbbb2d062 --- /dev/null +++ b/spec/ruby/core/sizedqueue/num_waiting_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/sizedqueue/num_waiting' + +describe "SizedQueue#num_waiting" do + it_behaves_like :sizedqueue_num_waiting, :new, ->(n) { SizedQueue.new(n) } +end diff --git a/spec/ruby/core/sizedqueue/pop_spec.rb b/spec/ruby/core/sizedqueue/pop_spec.rb new file mode 100644 index 0000000000..a0cf6f509c --- /dev/null +++ b/spec/ruby/core/sizedqueue/pop_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "SizedQueue#pop" do + it_behaves_like :queue_deq, :pop, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/sizedqueue/push_spec.rb b/spec/ruby/core/sizedqueue/push_spec.rb new file mode 100644 index 0000000000..5f92c5a2b7 --- /dev/null +++ b/spec/ruby/core/sizedqueue/push_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/enque' +require_relative '../../shared/sizedqueue/enque' + +describe "SizedQueue#push" do + it_behaves_like :queue_enq, :push, -> { SizedQueue.new(10) } +end + +describe "SizedQueue#push" do + it_behaves_like :sizedqueue_enq, :push, ->(n) { SizedQueue.new(n) } +end diff --git a/spec/ruby/core/sizedqueue/shift_spec.rb b/spec/ruby/core/sizedqueue/shift_spec.rb new file mode 100644 index 0000000000..5138e68258 --- /dev/null +++ b/spec/ruby/core/sizedqueue/shift_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/deque' + +describe "SizedQueue#shift" do + it_behaves_like :queue_deq, :shift, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/sizedqueue/size_spec.rb b/spec/ruby/core/sizedqueue/size_spec.rb new file mode 100644 index 0000000000..dfa76faabe --- /dev/null +++ b/spec/ruby/core/sizedqueue/size_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../spec_helper' +require_relative '../../shared/queue/length' + +describe "SizedQueue#size" do + it_behaves_like :queue_length, :size, -> { SizedQueue.new(10) } +end diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb index 7c33489779..01231e85fb 100644 --- a/spec/ruby/core/struct/new_spec.rb +++ b/spec/ruby/core/struct/new_spec.rb @@ -130,6 +130,17 @@ describe "Struct.new" do it "fails with too many arguments" do lambda { StructClasses::Ruby.new('2.0', 'i686', true) }.should raise_error(ArgumentError) end + + it "passes a hash as a normal argument" do + type = Struct.new(:args) + + obj = type.new(keyword: :arg) + obj2 = type.new(*[{keyword: :arg}]) + + obj.should == obj2 + obj.args.should == {keyword: :arg} + obj2.args.should == {keyword: :arg} + end end ruby_version_is "2.5" do @@ -163,6 +174,12 @@ describe "Struct.new" do @struct_with_kwa.new("elefant", 4) }.should raise_error(ArgumentError, /wrong number of arguments/) end + + it "raises ArgumentError when passed a single non-hash argument" do + -> { + @struct_with_kwa.new("elefant") + }.should raise_error(ArgumentError, /wrong number of arguments/) + end end end diff --git a/spec/ruby/core/thread/exclusive_spec.rb b/spec/ruby/core/thread/exclusive_spec.rb index 522a43cac5..9de427fb52 100644 --- a/spec/ruby/core/thread/exclusive_spec.rb +++ b/spec/ruby/core/thread/exclusive_spec.rb @@ -14,5 +14,29 @@ describe "Thread.exclusive" do Thread.exclusive { :result }.should == :result end - it "needs to be reviewed for spec completeness" + it "blocks the caller if another thread is also in an exclusive block" do + m = Mutex.new + q1 = Queue.new + q2 = Queue.new + + t = Thread.new { + Thread.exclusive { + q1.push :ready + q2.pop + } + } + + q1.pop.should == :ready + + lambda { Thread.exclusive { } }.should block_caller + + q2.push :done + t.join + end + + it "is not recursive" do + Thread.exclusive do + lambda { Thread.exclusive { } }.should raise_error(ThreadError) + end + end end diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb index 0b18369cb9..38571854ef 100644 --- a/spec/ruby/core/thread/raise_spec.rb +++ b/spec/ruby/core/thread/raise_spec.rb @@ -78,6 +78,30 @@ describe "Thread#raise on a sleeping thread" do end -> { t.value }.should raise_error(RuntimeError) end + + it "re-raises a previously rescued exception without overwriting the backtrace" do + t = Thread.new do + -> { # To make sure there is at least one entry in the call stack + begin + sleep + rescue => e + e + end + }.call + end + + ThreadSpecs.spin_until_sleeping(t) + + begin + initial_raise_line = __LINE__; raise 'raised' + rescue => raised + raise_again_line = __LINE__; t.raise raised + raised_again = t.value + + raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:") + raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:") + end + end end describe "Thread#raise on a running thread" do diff --git a/spec/ruby/core/time/nsec_spec.rb b/spec/ruby/core/time/nsec_spec.rb index fb3df6394c..9338eb435a 100644 --- a/spec/ruby/core/time/nsec_spec.rb +++ b/spec/ruby/core/time/nsec_spec.rb @@ -24,4 +24,8 @@ describe "Time#nsec" do it "returns the nanoseconds part of a Time constructed with an Rational number of microseconds" do Time.at(0, Rational(99, 10)).nsec.should == 9900 end + + it "returns a positive value for dates before the epoch" do + Time.utc(1969, 11, 12, 13, 18, 57, 404240).nsec.should == 404240000 + end end diff --git a/spec/ruby/core/time/shared/time_params.rb b/spec/ruby/core/time/shared/time_params.rb index 120d8d3af1..39245116b0 100644 --- a/spec/ruby/core/time/shared/time_params.rb +++ b/spec/ruby/core/time/shared/time_params.rb @@ -230,6 +230,10 @@ describe :time_params_microseconds, shared: true do t.usec.should == 123 end + it "raises an ArgumentError for out of range microsecond" do + lambda { Time.send(@method, 2000, 1, 1, 20, 15, 1, 1000000) }.should raise_error(ArgumentError) + end + it "handles fractional microseconds as a Float" do t = Time.send(@method, 2000, 1, 1, 20, 15, 1, 1.75) t.usec.should == 1 diff --git a/spec/ruby/core/time/usec_spec.rb b/spec/ruby/core/time/usec_spec.rb index 44cd2047e7..6ea52f5e79 100644 --- a/spec/ruby/core/time/usec_spec.rb +++ b/spec/ruby/core/time/usec_spec.rb @@ -36,4 +36,8 @@ describe "Time#usec" do it "returns the microseconds for time created by Time#local" do Time.local(1,2,3,4,5,Rational(6.78)).usec.should == 780000 end + + it "returns a positive value for dates before the epoch" do + Time.utc(1969, 11, 12, 13, 18, 57, 404240).usec.should == 404240 + end end diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb index 9ebe018d8f..2844d97e76 100644 --- a/spec/ruby/core/warning/warn_spec.rb +++ b/spec/ruby/core/warning/warn_spec.rb @@ -8,6 +8,14 @@ describe "Warning.warn" do }.should complain("Chunky bacon!") end + it "does not add a newline" do + ruby_exe("Warning.warn('test')", args: "2>&1").should == "test" + end + + it "returns nil" do + ruby_exe("p Warning.warn('test')", args: "2>&1").should == "testnil\n" + end + it "extends itself" do Warning.singleton_class.ancestors.should include(Warning) end diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb index 95469546c7..dee60c9adf 100644 --- a/spec/ruby/language/def_spec.rb +++ b/spec/ruby/language/def_spec.rb @@ -79,6 +79,18 @@ describe "Defining a method" do end end +describe "An instance method" do + it "raises an error with too few arguments" do + def foo(a, b); end + lambda { foo 1 }.should raise_error(ArgumentError, 'wrong number of arguments (given 1, expected 2)') + end + + it "raises an error with too many arguments" do + def foo(a); end + lambda { foo 1, 2 }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)') + end +end + describe "An instance method definition with a splat" do it "accepts an unnamed '*' argument" do def foo(*); end; @@ -106,7 +118,7 @@ describe "An instance method definition with a splat" do it "requires the presence of any arguments that precede the *" do def foo(a, b, *c); end - lambda { foo 1 }.should raise_error(ArgumentError) + lambda { foo 1 }.should raise_error(ArgumentError, 'wrong number of arguments (given 1, expected 2+)') end end @@ -139,7 +151,7 @@ describe "An instance method with a default argument" do def foo(a, b = 2) [a,b] end - lambda { foo }.should raise_error(ArgumentError) + lambda { foo }.should raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1..2)') foo(1).should == [1, 2] end @@ -147,7 +159,7 @@ describe "An instance method with a default argument" do def foo(a, b = 2, *c) [a,b,c] end - lambda { foo }.should raise_error(ArgumentError) + lambda { foo }.should raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1+)') foo(1).should == [1,2,[]] end @@ -717,7 +729,7 @@ describe "a method definition that sets more than one default parameter all to t end it "only allows overriding the default value of the first such parameter in each set" do - lambda { foo(1,2) }.should raise_error(ArgumentError) + lambda { foo(1,2) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 0..1)') end def bar(a=b=c=1,d=2) @@ -728,7 +740,7 @@ describe "a method definition that sets more than one default parameter all to t bar.should == [1,1,1,2] bar(3).should == [3,nil,nil,2] bar(3,4).should == [3,nil,nil,4] - lambda { bar(3,4,5) }.should raise_error(ArgumentError) + lambda { bar(3,4,5) }.should raise_error(ArgumentError, 'wrong number of arguments (given 3, expected 0..2)') end end diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb index 54f0c6ccf8..c5612ed19f 100644 --- a/spec/ruby/language/method_spec.rb +++ b/spec/ruby/language/method_spec.rb @@ -1269,7 +1269,7 @@ describe "A method" do def m(a, b = nil, c = nil, d, e: nil, **f) [a, b, c, d, e, f] end - ruby + ruby result = m(1, 2) result.should == [1, nil, nil, 2, nil, {}] @@ -1281,6 +1281,19 @@ describe "A method" do result.should == [1, nil, nil, {foo: :bar}, nil, {}] end end + + context "assigns keyword arguments from a passed Hash without modifying it" do + evaluate <<-ruby do + def m(a: nil); a; end + ruby + + options = {a: 1}.freeze + lambda do + m(options).should == 1 + end.should_not raise_error + options.should == {a: 1} + end + end end describe "A method call with a space between method name and parentheses" do diff --git a/spec/ruby/library/erb/new_spec.rb b/spec/ruby/library/erb/new_spec.rb index 3f6ae93f9f..f1e5cd299e 100644 --- a/spec/ruby/library/erb/new_spec.rb +++ b/spec/ruby/library/erb/new_spec.rb @@ -38,14 +38,9 @@ END ruby_version_is "2.6" do it "warns invalid trim_mode" do - begin - $VERBOSE, verbose = false, $VERBOSE # Some other specs make $VERBOSE `nil`. - lambda do - ERBSpecs.new_erb(@eruby_str, trim_mode: '') - end.should output(nil, /Invalid ERB trim mode/) - ensure - $VERBOSE = verbose - end + lambda do + ERBSpecs.new_erb(@eruby_str, trim_mode: '') + end.should complain(/Invalid ERB trim mode/) end end diff --git a/spec/ruby/library/set/initialize_spec.rb b/spec/ruby/library/set/initialize_spec.rb index 11a1095fd7..887cae45fc 100644 --- a/spec/ruby/library/set/initialize_spec.rb +++ b/spec/ruby/library/set/initialize_spec.rb @@ -14,6 +14,14 @@ describe "Set#initialize" do s.should include(3) end + it "should initialize with empty array and set" do + s = Set.new([]) + s.size.should eql(0) + + s = Set.new({}) + s.size.should eql(0) + end + it "preprocesses all elements by a passed block before adding to self" do s = Set.new([1, 2, 3]) { |x| x * x } s.size.should eql(3) @@ -21,4 +29,20 @@ describe "Set#initialize" do s.should include(4) s.should include(9) end + + it "should initialize with empty array and block" do + s = Set.new([]) { |x| x * x } + s.size.should eql(0) + end + + it "should initialize with empty set and block" do + s = Set.new(Set.new) { |x| x * x } + s.size.should eql(0) + end + + it "should initialize with just block" do + s = Set.new { |x| x * x } + s.size.should eql(0) + s.should eql(Set.new) + end end diff --git a/spec/ruby/library/socket/socket/connect_nonblock_spec.rb b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb index 0012b5ada7..c56bebee62 100644 --- a/spec/ruby/library/socket/socket/connect_nonblock_spec.rb +++ b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb @@ -99,19 +99,43 @@ describe 'Socket#connect_nonblock' do end end - platform_is_not :freebsd, :solaris do - describe 'using a STREAM socket' do - before do - @server = Socket.new(family, :STREAM) - @client = Socket.new(family, :STREAM) - @sockaddr = Socket.sockaddr_in(0, ip_address) + describe 'using a STREAM socket' do + before do + @server = Socket.new(family, :STREAM) + @client = Socket.new(family, :STREAM) + @sockaddr = Socket.sockaddr_in(0, ip_address) + end + + after do + @client.close + @server.close + end + + platform_is_not :windows do + it 'raises Errno::EISCONN when already connected' do + @server.listen(1) + @client.connect(@server.getsockname).should == 0 + + lambda { + @client.connect_nonblock(@server.getsockname) + + # A second call needed if non-blocking sockets become default + # XXX honestly I don't expect any real code to care about this spec + # as it's too implementation-dependent and checking for connect() + # errors is futile anyways because of TOCTOU + @client.connect_nonblock(@server.getsockname) + }.should raise_error(Errno::EISCONN) end - after do - @client.close - @server.close + it 'returns 0 when already connected in exceptionless mode' do + @server.listen(1) + @client.connect(@server.getsockname).should == 0 + + @client.connect_nonblock(@server.getsockname, exception: false).should == 0 end + end + platform_is_not :freebsd, :solaris do it 'raises IO:EINPROGRESSWaitWritable when the connection would block' do @server.bind(@sockaddr) diff --git a/spec/ruby/library/tempfile/open_spec.rb b/spec/ruby/library/tempfile/open_spec.rb index 062d1a3fc2..c4c3d91051 100644 --- a/spec/ruby/library/tempfile/open_spec.rb +++ b/spec/ruby/library/tempfile/open_spec.rb @@ -41,6 +41,14 @@ describe "Tempfile.open" do Tempfile.open(["specs", ".tt"]) { |tempfile| @tempfile = tempfile } @tempfile.path.should =~ /specs.*\.tt$/ end + + it "passes the third argument (options) to open" do + Tempfile.open("specs", Dir.tmpdir, encoding: "IBM037:IBM037", binmode: true) do |tempfile| + @tempfile = tempfile + tempfile.external_encoding.should == Encoding.find("IBM037") + tempfile.binmode?.should be_true + end + end end describe "Tempfile.open when passed a block" do diff --git a/spec/ruby/library/thread/exclusive_spec.rb b/spec/ruby/library/thread/exclusive_spec.rb deleted file mode 100644 index 2be2346761..0000000000 --- a/spec/ruby/library/thread/exclusive_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' -require 'thread' - -describe "Thread.exclusive" do - before :each do - ScratchPad.clear - end - - it "returns the result of yielding" do - Thread.exclusive { :result }.should == :result - end -end diff --git a/spec/ruby/library/thread/queue/append_spec.rb b/spec/ruby/library/thread/queue/append_spec.rb deleted file mode 100644 index 09b9fc0cfa..0000000000 --- a/spec/ruby/library/thread/queue/append_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' - -describe "Thread::Queue#<<" do - it_behaves_like :queue_enq, :<<, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/clear_spec.rb b/spec/ruby/library/thread/queue/clear_spec.rb deleted file mode 100644 index f4ec45add6..0000000000 --- a/spec/ruby/library/thread/queue/clear_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/clear' - -describe "Thread::Queue#clear" do - it_behaves_like :queue_clear, :clear, -> { Queue.new } - - # TODO: test for atomicity of Queue#clear -end diff --git a/spec/ruby/library/thread/queue/close_spec.rb b/spec/ruby/library/thread/queue/close_spec.rb deleted file mode 100644 index 32bc0a32d7..0000000000 --- a/spec/ruby/library/thread/queue/close_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/close' - -describe "Queue#close" do - it_behaves_like :queue_close, :close, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/closed_spec.rb b/spec/ruby/library/thread/queue/closed_spec.rb deleted file mode 100644 index df3596b14b..0000000000 --- a/spec/ruby/library/thread/queue/closed_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/closed' - -describe "Queue#closed?" do - it_behaves_like :queue_closed?, :closed?, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/deq_spec.rb b/spec/ruby/library/thread/queue/deq_spec.rb deleted file mode 100644 index 176dc3620e..0000000000 --- a/spec/ruby/library/thread/queue/deq_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::Queue#deq" do - it_behaves_like :queue_deq, :deq, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/empty_spec.rb b/spec/ruby/library/thread/queue/empty_spec.rb deleted file mode 100644 index 6854d31155..0000000000 --- a/spec/ruby/library/thread/queue/empty_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/empty' - -describe "Thread::Queue#empty?" do - it_behaves_like :queue_empty?, :empty?, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/enq_spec.rb b/spec/ruby/library/thread/queue/enq_spec.rb deleted file mode 100644 index 01d3a48738..0000000000 --- a/spec/ruby/library/thread/queue/enq_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' - -describe "Thread::Queue#enq" do - it_behaves_like :queue_enq, :enq, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/length_spec.rb b/spec/ruby/library/thread/queue/length_spec.rb deleted file mode 100644 index 7b0a3ccccd..0000000000 --- a/spec/ruby/library/thread/queue/length_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/length' - -describe "Thread::Queue#length" do - it_behaves_like :queue_length, :length, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/num_waiting_spec.rb b/spec/ruby/library/thread/queue/num_waiting_spec.rb deleted file mode 100644 index dcb6d6fb72..0000000000 --- a/spec/ruby/library/thread/queue/num_waiting_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/num_waiting' - -describe "Thread::Queue#num_waiting" do - it_behaves_like :queue_num_waiting, :num_waiting, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/pop_spec.rb b/spec/ruby/library/thread/queue/pop_spec.rb deleted file mode 100644 index ab4f44d6d4..0000000000 --- a/spec/ruby/library/thread/queue/pop_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::Queue#pop" do - it_behaves_like :queue_deq, :pop, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/push_spec.rb b/spec/ruby/library/thread/queue/push_spec.rb deleted file mode 100644 index 670a2095e3..0000000000 --- a/spec/ruby/library/thread/queue/push_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' - -describe "Thread::Queue#push" do - it_behaves_like :queue_enq, :push, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/shift_spec.rb b/spec/ruby/library/thread/queue/shift_spec.rb deleted file mode 100644 index fc3f6e9b0c..0000000000 --- a/spec/ruby/library/thread/queue/shift_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::Queue#shift" do - it_behaves_like :queue_deq, :shift, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue/size_spec.rb b/spec/ruby/library/thread/queue/size_spec.rb deleted file mode 100644 index 00c3d19f32..0000000000 --- a/spec/ruby/library/thread/queue/size_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/length' - -describe "Thread::Queue#size" do - it_behaves_like :queue_length, :size, -> { Queue.new } -end diff --git a/spec/ruby/library/thread/queue_spec.rb b/spec/ruby/library/thread/queue_spec.rb new file mode 100644 index 0000000000..c7e2bb1b50 --- /dev/null +++ b/spec/ruby/library/thread/queue_spec.rb @@ -0,0 +1,8 @@ +require_relative '../../spec_helper' + +describe "Thread::Queue" do + it "is the same class as ::Queue" do + Thread.should have_constant(:Queue) + Thread::Queue.should equal ::Queue + end +end diff --git a/spec/ruby/library/thread/shared/queue/close.rb b/spec/ruby/library/thread/shared/queue/close.rb deleted file mode 100644 index 4457f3ae8b..0000000000 --- a/spec/ruby/library/thread/shared/queue/close.rb +++ /dev/null @@ -1,26 +0,0 @@ -describe :queue_close, shared: true do - it "closes the queue and returns nil for further #pop" do - q = @object.call - q << 1 - q.close - q.pop.should == 1 - q.pop.should == nil - q.pop.should == nil - end - - it "prevents further #push" do - q = @object.call - q.close - lambda { - q << 1 - }.should raise_error(ClosedQueueError) - end - - it "may be called multiple times" do - q = @object.call - q.close - q.closed?.should be_true - q.close # no effect - q.closed?.should be_true - end -end diff --git a/spec/ruby/library/thread/shared/queue/deque.rb b/spec/ruby/library/thread/shared/queue/deque.rb deleted file mode 100644 index 1b06dffa2c..0000000000 --- a/spec/ruby/library/thread/shared/queue/deque.rb +++ /dev/null @@ -1,37 +0,0 @@ -describe :queue_deq, shared: true do - it "removes an item from the Queue" do - q = @object.call - q << Object.new - q.size.should == 1 - q.send(@method) - q.size.should == 0 - end - - it "returns items in the order they were added" do - q = @object.call - q << 1 - q << 2 - q.send(@method).should == 1 - q.send(@method).should == 2 - end - - it "blocks the thread until there are items in the queue" do - q = @object.call - v = 0 - - th = Thread.new do - q.send(@method) - v = 1 - end - - v.should == 0 - q << Object.new - th.join - v.should == 1 - end - - it "raises a ThreadError if Queue is empty" do - q = @object.call - lambda { q.send(@method,true) }.should raise_error(ThreadError) - end -end diff --git a/spec/ruby/library/thread/shared/queue/enque.rb b/spec/ruby/library/thread/shared/queue/enque.rb deleted file mode 100644 index 36b98d3a07..0000000000 --- a/spec/ruby/library/thread/shared/queue/enque.rb +++ /dev/null @@ -1,10 +0,0 @@ -describe :queue_enq, shared: true do - it "adds an element to the Queue" do - q = @object.call - q.size.should == 0 - q.send(@method, Object.new) - q.size.should == 1 - q.send(@method, Object.new) - q.size.should == 2 - end -end diff --git a/spec/ruby/library/thread/sizedqueue/append_spec.rb b/spec/ruby/library/thread/sizedqueue/append_spec.rb deleted file mode 100644 index daf65178de..0000000000 --- a/spec/ruby/library/thread/sizedqueue/append_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' -require_relative 'shared/enque' - -describe "Thread::SizedQueue#<<" do - it_behaves_like :queue_enq, :<<, -> { SizedQueue.new(10) } -end - -describe "Thread::SizedQueue#<<" do - it_behaves_like :sizedqueue_enq, :<< -end diff --git a/spec/ruby/library/thread/sizedqueue/clear_spec.rb b/spec/ruby/library/thread/sizedqueue/clear_spec.rb deleted file mode 100644 index 86e16f275e..0000000000 --- a/spec/ruby/library/thread/sizedqueue/clear_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/clear' - -describe "Thread::SizedQueue#clear" do - it_behaves_like :queue_clear, :clear, -> { SizedQueue.new(10) } - - # TODO: test for atomicity of Queue#clear -end diff --git a/spec/ruby/library/thread/sizedqueue/deq_spec.rb b/spec/ruby/library/thread/sizedqueue/deq_spec.rb deleted file mode 100644 index 0ed42cba91..0000000000 --- a/spec/ruby/library/thread/sizedqueue/deq_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::SizedQueue#deq" do - it_behaves_like :queue_deq, :deq, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue/empty_spec.rb b/spec/ruby/library/thread/sizedqueue/empty_spec.rb deleted file mode 100644 index d44ea405d5..0000000000 --- a/spec/ruby/library/thread/sizedqueue/empty_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/empty' - -describe "Thread::SizedQueue#empty?" do - it_behaves_like :queue_empty?, :empty?, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue/enq_spec.rb b/spec/ruby/library/thread/sizedqueue/enq_spec.rb deleted file mode 100644 index b81fd2b225..0000000000 --- a/spec/ruby/library/thread/sizedqueue/enq_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' -require_relative 'shared/enque' - -describe "Thread::SizedQueue#enq" do - it_behaves_like :queue_enq, :enq, -> { SizedQueue.new(10) } -end - -describe "Thread::SizedQueue#enq" do - it_behaves_like :sizedqueue_enq, :enq -end diff --git a/spec/ruby/library/thread/sizedqueue/length_spec.rb b/spec/ruby/library/thread/sizedqueue/length_spec.rb deleted file mode 100644 index e15db85f82..0000000000 --- a/spec/ruby/library/thread/sizedqueue/length_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/length' - -describe "Thread::SizedQueue#length" do - it_behaves_like :queue_length, :length, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue/max_spec.rb b/spec/ruby/library/thread/sizedqueue/max_spec.rb deleted file mode 100644 index 75b1957e86..0000000000 --- a/spec/ruby/library/thread/sizedqueue/max_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' - -describe "Thread::SizedQueue#max" do - before :each do - @sized_queue = SizedQueue.new(5) - end - - it "returns the size of the queue" do - @sized_queue.max.should == 5 - end -end - -describe "Thread::SizedQueue#max=" do - before :each do - @sized_queue = SizedQueue.new(5) - end - - it "sets the size of the queue" do - @sized_queue.max.should == 5 - @sized_queue.max = 10 - @sized_queue.max.should == 10 - end - - it "does not remove items already in the queue beyond the maximum" do - @sized_queue.enq 1 - @sized_queue.enq 2 - @sized_queue.enq 3 - @sized_queue.max = 2 - (@sized_queue.size > @sized_queue.max).should be_true - @sized_queue.deq.should == 1 - @sized_queue.deq.should == 2 - @sized_queue.deq.should == 3 - end - - it "raises a TypeError when given a non-numeric value" do - lambda { @sized_queue.max = "foo" }.should raise_error(TypeError) - lambda { @sized_queue.max = Object.new }.should raise_error(TypeError) - end - - it "raises an argument error when set to zero" do - @sized_queue.max.should == 5 - lambda { @sized_queue.max = 0 }.should raise_error(ArgumentError) - @sized_queue.max.should == 5 - end - - it "raises an argument error when set to a negative number" do - @sized_queue.max.should == 5 - lambda { @sized_queue.max = -1 }.should raise_error(ArgumentError) - @sized_queue.max.should == 5 - end -end diff --git a/spec/ruby/library/thread/sizedqueue/new_spec.rb b/spec/ruby/library/thread/sizedqueue/new_spec.rb deleted file mode 100644 index 364e10f694..0000000000 --- a/spec/ruby/library/thread/sizedqueue/new_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' - -describe "Thread::SizedQueue#new" do - it "returns a new SizedQueue" do - SizedQueue.new(1).should be_kind_of(SizedQueue) - end - - it "raises a TypeError when the given argument is not Numeric" do - lambda { SizedQueue.new("foo") }.should raise_error(TypeError) - lambda { SizedQueue.new(Object.new) }.should raise_error(TypeError) - end - - it "raises an argument error when no argument is given" do - lambda { SizedQueue.new }.should raise_error(ArgumentError) - end - - it "raises an argument error when the given argument is zero" do - lambda { SizedQueue.new(0) }.should raise_error(ArgumentError) - end - - it "raises an argument error when the given argument is negative" do - lambda { SizedQueue.new(-1) }.should raise_error(ArgumentError) - end -end diff --git a/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb b/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb deleted file mode 100644 index 7c5243250d..0000000000 --- a/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/num_waiting' - -describe "Thread::SizedQueue#num_waiting" do - it_behaves_like :queue_num_waiting, :num_waiting, -> { SizedQueue.new(10) } - - it "reports the number of threads waiting to push" do - q = SizedQueue.new(1) - q.push(1) - t = Thread.new { q.push(2) } - sleep 0.05 until t.stop? - q.num_waiting.should == 1 - - q.pop - t.join - end -end diff --git a/spec/ruby/library/thread/sizedqueue/pop_spec.rb b/spec/ruby/library/thread/sizedqueue/pop_spec.rb deleted file mode 100644 index 21508bd26b..0000000000 --- a/spec/ruby/library/thread/sizedqueue/pop_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::SizedQueue#pop" do - it_behaves_like :queue_deq, :pop, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue/push_spec.rb b/spec/ruby/library/thread/sizedqueue/push_spec.rb deleted file mode 100644 index aefe6eb28a..0000000000 --- a/spec/ruby/library/thread/sizedqueue/push_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/enque' -require_relative 'shared/enque' - -describe "Thread::SizedQueue#push" do - it_behaves_like :queue_enq, :push, -> { SizedQueue.new(10) } -end - -describe "Thread::SizedQueue#push" do - it_behaves_like :sizedqueue_enq, :push -end diff --git a/spec/ruby/library/thread/sizedqueue/shift_spec.rb b/spec/ruby/library/thread/sizedqueue/shift_spec.rb deleted file mode 100644 index 6c2adfce9d..0000000000 --- a/spec/ruby/library/thread/sizedqueue/shift_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/deque' - -describe "Thread::SizedQueue#shift" do - it_behaves_like :queue_deq, :shift, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue/size_spec.rb b/spec/ruby/library/thread/sizedqueue/size_spec.rb deleted file mode 100644 index 1bacef1eb1..0000000000 --- a/spec/ruby/library/thread/sizedqueue/size_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative '../../../spec_helper' -require 'thread' -require_relative '../shared/queue/length' - -describe "Thread::SizedQueue#size" do - it_behaves_like :queue_length, :size, -> { SizedQueue.new(10) } -end diff --git a/spec/ruby/library/thread/sizedqueue_spec.rb b/spec/ruby/library/thread/sizedqueue_spec.rb new file mode 100644 index 0000000000..6151ff437c --- /dev/null +++ b/spec/ruby/library/thread/sizedqueue_spec.rb @@ -0,0 +1,8 @@ +require_relative '../../spec_helper' + +describe "Thread::SizedQueue" do + it "is the same class as ::SizedQueue" do + Thread.should have_constant(:SizedQueue) + Thread::SizedQueue.should equal ::SizedQueue + end +end diff --git a/spec/ruby/library/win32ole/win32ole/new_spec.rb b/spec/ruby/library/win32ole/win32ole/new_spec.rb index cb45488288..d1c3e02593 100644 --- a/spec/ruby/library/win32ole/win32ole/new_spec.rb +++ b/spec/ruby/library/win32ole/win32ole/new_spec.rb @@ -17,7 +17,7 @@ platform_is :windows do end it "raises WIN32OLERuntimeError if invalid string is given" do - lambda { WIN32OLESpecs.new_ole('foo') }.should raise_error( WIN32OLERuntimeError ) + lambda { WIN32OLE.new('foo') }.should raise_error( WIN32OLERuntimeError ) end end diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb index 4128a636ad..3cff55ac6e 100644 --- a/spec/ruby/shared/kernel/raise.rb +++ b/spec/ruby/shared/kernel/raise.rb @@ -44,11 +44,11 @@ describe :kernel_raise, shared: true do it "re-raises the previously rescued exception if no exception is specified" do lambda do begin - raise Exception, "outer" + @object.raise Exception, "outer" ScratchPad.record :no_abort rescue begin - raise StandardError, "inner" + @object.raise StandardError, "inner" rescue end @@ -62,16 +62,17 @@ describe :kernel_raise, shared: true do it "re-raises a previously rescued exception without overwriting the backtrace" do begin - raise 'raised' + initial_raise_line = __LINE__; @object.raise 'raised' rescue => raised begin - raise_again_line = __LINE__; raise raised + raise_again_line = __LINE__; @object.raise raised rescue => raised_again # This spec is written using #backtrace and matching the line number # from the string, as backtrace_locations is a more advanced # method that is not always supported by implementations. - raised_again.backtrace.first.should_not include(":#{raise_again_line}:") + raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:") + raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:") end end end diff --git a/spec/ruby/library/thread/shared/queue/clear.rb b/spec/ruby/shared/queue/clear.rb index 59ea37d615..5db5a5b497 100644 --- a/spec/ruby/library/thread/shared/queue/clear.rb +++ b/spec/ruby/shared/queue/clear.rb @@ -7,4 +7,6 @@ describe :queue_clear, shared: true do queue.clear queue.empty?.should be_true end + + # TODO: test for atomicity of Queue#clear end diff --git a/spec/ruby/shared/queue/close.rb b/spec/ruby/shared/queue/close.rb new file mode 100644 index 0000000000..0e7c69acba --- /dev/null +++ b/spec/ruby/shared/queue/close.rb @@ -0,0 +1,14 @@ +describe :queue_close, shared: true do + it "may be called multiple times" do + q = @object.call + q.close + q.closed?.should be_true + q.close # no effect + q.closed?.should be_true + end + + it "returns self" do + q = @object.call + q.close.should == q + end +end diff --git a/spec/ruby/library/thread/shared/queue/closed.rb b/spec/ruby/shared/queue/closed.rb index b3cea0c524..b3cea0c524 100644 --- a/spec/ruby/library/thread/shared/queue/closed.rb +++ b/spec/ruby/shared/queue/closed.rb diff --git a/spec/ruby/shared/queue/deque.rb b/spec/ruby/shared/queue/deque.rb new file mode 100644 index 0000000000..3590f367ba --- /dev/null +++ b/spec/ruby/shared/queue/deque.rb @@ -0,0 +1,85 @@ +describe :queue_deq, shared: true do + it "removes an item from the queue" do + q = @object.call + q << Object.new + q.size.should == 1 + q.send @method + q.size.should == 0 + end + + it "returns items in the order they were added" do + q = @object.call + q << 1 + q << 2 + q.send(@method).should == 1 + q.send(@method).should == 2 + end + + it "blocks the thread until there are items in the queue" do + q = @object.call + v = 0 + + th = Thread.new do + q.send(@method) + v = 1 + end + + v.should == 0 + q << Object.new + th.join + v.should == 1 + end + + it "removes an item from a closed queue" do + q = @object.call + q << 1 + q.close + q.send(@method).should == 1 + end + + it "returns nil for a closed empty queue" do + q = @object.call + q.close + q.send(@method).should == nil + end + + it "returns nil for an empty queue that becomes closed" do + q = @object.call + + t = Thread.new { + q.send(@method).should == nil + } + + Thread.pass until t.status == "sleep" && q.num_waiting == 1 + q.close + t.join + end + + describe "in non-blocking mode" do + it "removes an item from the queue" do + q = @object.call + q << Object.new + q.size.should == 1 + q.send(@method, true) + q.size.should == 0 + end + + it "raises a ThreadError if the queue is empty" do + q = @object.call + lambda { q.send(@method, true) }.should raise_error(ThreadError) + end + + it "removes an item from a closed queue" do + q = @object.call + q << 1 + q.close + q.send(@method, true).should == 1 + end + + it "raises a ThreadError for a closed empty queue" do + q = @object.call + q.close + lambda { q.send(@method, true) }.should raise_error(ThreadError) + end + end +end diff --git a/spec/ruby/library/thread/shared/queue/empty.rb b/spec/ruby/shared/queue/empty.rb index 4acd831d48..4acd831d48 100644 --- a/spec/ruby/library/thread/shared/queue/empty.rb +++ b/spec/ruby/shared/queue/empty.rb diff --git a/spec/ruby/shared/queue/enque.rb b/spec/ruby/shared/queue/enque.rb new file mode 100644 index 0000000000..ad413e1f46 --- /dev/null +++ b/spec/ruby/shared/queue/enque.rb @@ -0,0 +1,18 @@ +describe :queue_enq, shared: true do + it "adds an element to the Queue" do + q = @object.call + q.size.should == 0 + q.send @method, Object.new + q.size.should == 1 + q.send @method, Object.new + q.size.should == 2 + end + + it "is an error for a closed queue" do + q = @object.call + q.close + lambda { + q.send @method, Object.new + }.should raise_error(ClosedQueueError) + end +end diff --git a/spec/ruby/library/thread/shared/queue/length.rb b/spec/ruby/shared/queue/length.rb index a0143a4e19..a0143a4e19 100644 --- a/spec/ruby/library/thread/shared/queue/length.rb +++ b/spec/ruby/shared/queue/length.rb diff --git a/spec/ruby/library/thread/shared/queue/num_waiting.rb b/spec/ruby/shared/queue/num_waiting.rb index b054951e45..b054951e45 100644 --- a/spec/ruby/library/thread/shared/queue/num_waiting.rb +++ b/spec/ruby/shared/queue/num_waiting.rb diff --git a/spec/ruby/library/thread/sizedqueue/shared/enque.rb b/spec/ruby/shared/sizedqueue/enque.rb index 627f8bd745..b724101269 100644 --- a/spec/ruby/library/thread/sizedqueue/shared/enque.rb +++ b/spec/ruby/shared/sizedqueue/enque.rb @@ -1,6 +1,6 @@ describe :sizedqueue_enq, shared: true do it "blocks if queued elements exceed size" do - q = SizedQueue.new(1) + q = @object.call(1) q.size.should == 0 q.send(@method, :first_element) @@ -19,7 +19,7 @@ describe :sizedqueue_enq, shared: true do end it "raises a ThreadError if queued elements exceed size when not blocking" do - q = SizedQueue.new(2) + q = @object.call(2) non_blocking = true add_to_queue = lambda { q.send(@method, Object.new, non_blocking) } @@ -31,4 +31,20 @@ describe :sizedqueue_enq, shared: true do q.size.should == 2 add_to_queue.should raise_error(ThreadError) end + + it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do + q = @object.call(1) + q << 1 + + t = Thread.new { + lambda { q.send(@method, 2) }.should raise_error(ClosedQueueError) + } + + Thread.pass until q.num_waiting == 1 + + q.close + + t.join + q.pop.should == 1 + end end diff --git a/spec/ruby/shared/sizedqueue/max.rb b/spec/ruby/shared/sizedqueue/max.rb new file mode 100644 index 0000000000..cd4b47f1c1 --- /dev/null +++ b/spec/ruby/shared/sizedqueue/max.rb @@ -0,0 +1,47 @@ +describe :sizedqueue_max, shared: true do + it "returns the size of the queue" do + q = @object.call(5) + q.max.should == 5 + end +end + +describe :sizedqueue_max=, shared: true do + it "sets the size of the queue" do + q = @object.call(5) + q.max.should == 5 + q.max = 10 + q.max.should == 10 + end + + it "does not remove items already in the queue beyond the maximum" do + q = @object.call(5) + q.enq 1 + q.enq 2 + q.enq 3 + q.max = 2 + (q.size > q.max).should be_true + q.deq.should == 1 + q.deq.should == 2 + q.deq.should == 3 + end + + it "raises a TypeError when given a non-numeric value" do + q = @object.call(5) + lambda { q.max = "foo" }.should raise_error(TypeError) + lambda { q.max = Object.new }.should raise_error(TypeError) + end + + it "raises an argument error when set to zero" do + q = @object.call(5) + q.max.should == 5 + lambda { q.max = 0 }.should raise_error(ArgumentError) + q.max.should == 5 + end + + it "raises an argument error when set to a negative number" do + q = @object.call(5) + q.max.should == 5 + lambda { q.max = -1 }.should raise_error(ArgumentError) + q.max.should == 5 + end +end diff --git a/spec/ruby/shared/sizedqueue/new.rb b/spec/ruby/shared/sizedqueue/new.rb new file mode 100644 index 0000000000..4439f2a9c6 --- /dev/null +++ b/spec/ruby/shared/sizedqueue/new.rb @@ -0,0 +1,18 @@ +describe :sizedqueue_new, shared: true do + it "raises a TypeError when the given argument is not Numeric" do + lambda { @object.call("foo") }.should raise_error(TypeError) + lambda { @object.call(Object.new) }.should raise_error(TypeError) + end + + it "raises an argument error when no argument is given" do + lambda { @object.call }.should raise_error(ArgumentError) + end + + it "raises an argument error when the given argument is zero" do + lambda { @object.call(0) }.should raise_error(ArgumentError) + end + + it "raises an argument error when the given argument is negative" do + lambda { @object.call(-1) }.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/shared/sizedqueue/num_waiting.rb b/spec/ruby/shared/sizedqueue/num_waiting.rb new file mode 100644 index 0000000000..8c31e48ca5 --- /dev/null +++ b/spec/ruby/shared/sizedqueue/num_waiting.rb @@ -0,0 +1,12 @@ +describe :sizedqueue_num_waiting, shared: true do + it "reports the number of threads waiting to push" do + q = @object.call(1) + q.push(1) + t = Thread.new { q.push(2) } + sleep 0.05 until t.stop? + q.num_waiting.should == 1 + + q.pop + t.join + end +end |