From 4d7b0b9112f2adf9e87ef75056f930bf7c1f3dc4 Mon Sep 17 00:00:00 2001 From: eregon Date: Fri, 1 Dec 2017 15:41:50 +0000 Subject: Update to ruby/spec@bacedc5 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60973 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- spec/ruby/.rubocop.yml | 4 + spec/ruby/.rubocop_todo.yml | 10 +- spec/ruby/command_line/rubyopt_spec.rb | 5 + spec/ruby/core/array/append_spec.rb | 7 + spec/ruby/core/array/prepend_spec.rb | 9 + spec/ruby/core/array/push_spec.rb | 33 +- spec/ruby/core/array/shared/push.rb | 33 + spec/ruby/core/array/shared/unshift.rb | 46 ++ spec/ruby/core/array/sort_spec.rb | 4 +- spec/ruby/core/array/unshift_spec.rb | 47 +- spec/ruby/core/bignum/exponent_spec.rb | 6 +- spec/ruby/core/dir/chroot_spec.rb | 2 +- spec/ruby/core/dir/shared/open.rb | 4 +- spec/ruby/core/file/printf_spec.rb | 18 + spec/ruby/core/file/stat/blocks_spec.rb | 4 +- spec/ruby/core/file/stat/new_spec.rb | 4 +- spec/ruby/core/file/utime_spec.rb | 11 + spec/ruby/core/io/read_nonblock_spec.rb | 10 + spec/ruby/core/io/shared/each.rb | 41 + spec/ruby/core/io/sysread_spec.rb | 16 + spec/ruby/core/io/write_nonblock_spec.rb | 12 +- spec/ruby/core/kernel/open_spec.rb | 5 +- spec/ruby/core/kernel/printf_spec.rb | 27 + spec/ruby/core/kernel/shared/sprintf.rb | 871 +++++++++++++++++++++ spec/ruby/core/kernel/shared/sprintf_encoding.rb | 28 + spec/ruby/core/kernel/sprintf_spec.rb | 316 +------- spec/ruby/core/main/using_spec.rb | 3 +- spec/ruby/core/module/fixtures/using.rb | 10 - spec/ruby/core/module/refine_spec.rb | 24 +- spec/ruby/core/module/using_spec.rb | 21 +- spec/ruby/core/mutex/sleep_spec.rb | 25 +- spec/ruby/core/process/groups_spec.rb | 34 +- spec/ruby/core/string/index_spec.rb | 1 + spec/ruby/core/string/percent_spec.rb | 14 + spec/ruby/core/thread/thread_variables_spec.rb | 9 +- spec/ruby/core/time/round_spec.rb | 6 +- spec/ruby/core/time/shared/gm.rb | 7 + spec/ruby/core/tracepoint/binding_spec.rb | 19 + spec/ruby/core/tracepoint/defined_class_spec.rb | 26 + spec/ruby/core/tracepoint/disable_spec.rb | 64 ++ spec/ruby/core/tracepoint/enable_spec.rb | 92 +++ spec/ruby/core/tracepoint/enabled_spec.rb | 14 + spec/ruby/core/tracepoint/event_spec.rb | 21 + spec/ruby/core/tracepoint/fixtures/classes.rb | 28 +- spec/ruby/core/tracepoint/inspect_spec.rb | 8 + spec/ruby/core/tracepoint/lineno_spec.rb | 10 + spec/ruby/core/tracepoint/method_id_spec.rb | 13 + spec/ruby/core/tracepoint/new_spec.rb | 68 ++ spec/ruby/core/tracepoint/path_spec.rb | 18 + spec/ruby/core/tracepoint/raised_exception_spec.rb | 16 + spec/ruby/core/tracepoint/return_value_spec.rb | 13 + spec/ruby/core/tracepoint/self_spec.rb | 10 + spec/ruby/core/tracepoint/trace_spec.rb | 9 + spec/ruby/language/BEGIN_spec.rb | 4 + spec/ruby/language/break_spec.rb | 18 + spec/ruby/language/constants_spec.rb | 22 + spec/ruby/language/defined_spec.rb | 4 +- spec/ruby/language/fixtures/begin_file.rb | 3 + spec/ruby/language/fixtures/break.rb | 28 + spec/ruby/language/rescue_spec.rb | 10 + spec/ruby/language/return_spec.rb | 33 + spec/ruby/library/bigdecimal/limit_spec.rb | 17 +- spec/ruby/library/date/constants_spec.rb | 8 +- spec/ruby/library/date/minus_month_spec.rb | 9 - spec/ruby/library/datetime/now_spec.rb | 2 +- spec/ruby/library/datetime/to_time_spec.rb | 12 + spec/ruby/library/erb/new_spec.rb | 6 +- spec/ruby/library/etc/nprocessors_spec.rb | 10 +- spec/ruby/library/openssl/config/freeze_spec.rb | 8 +- spec/ruby/library/socket/ipsocket/peeraddr_spec.rb | 4 +- .../library/socket/unixsocket/peeraddr_spec.rb | 4 +- spec/ruby/library/stringio/printf_spec.rb | 10 + spec/ruby/library/syslog/alert_spec.rb | 3 +- spec/ruby/library/syslog/close_spec.rb | 3 +- spec/ruby/library/syslog/constants_spec.rb | 3 +- spec/ruby/library/syslog/crit_spec.rb | 3 +- spec/ruby/library/syslog/debug_spec.rb | 3 +- spec/ruby/library/syslog/emerg_spec.rb | 3 +- spec/ruby/library/syslog/err_spec.rb | 3 +- spec/ruby/library/syslog/facility_spec.rb | 3 +- spec/ruby/library/syslog/ident_spec.rb | 3 +- spec/ruby/library/syslog/info_spec.rb | 3 +- spec/ruby/library/syslog/inspect_spec.rb | 3 +- spec/ruby/library/syslog/instance_spec.rb | 3 +- spec/ruby/library/syslog/log_spec.rb | 3 +- spec/ruby/library/syslog/mask_spec.rb | 3 +- spec/ruby/library/syslog/notice_spec.rb | 3 +- spec/ruby/library/syslog/open_spec.rb | 12 +- spec/ruby/library/syslog/opened_spec.rb | 3 +- spec/ruby/library/syslog/options_spec.rb | 3 +- spec/ruby/library/syslog/reopen_spec.rb | 3 +- spec/ruby/library/syslog/warning_spec.rb | 3 +- spec/ruby/library/time/to_datetime_spec.rb | 27 + spec/ruby/library/uri/join_spec.rb | 4 +- spec/ruby/library/uri/shared/join.rb | 4 +- spec/ruby/library/yaml/load_spec.rb | 21 + spec/ruby/optional/capi/ext/numeric_spec.c | 10 + spec/ruby/optional/capi/ext/object_spec.c | 40 +- spec/ruby/optional/capi/ext/rubyspec.h | 3 + spec/ruby/optional/capi/numeric_spec.rb | 15 + spec/ruby/optional/capi/object_spec.rb | 25 + spec/ruby/optional/capi/util_spec.rb | 10 + spec/ruby/shared/file/zero.rb | 14 +- spec/ruby/spec_helper.rb | 5 +- 104 files changed, 2105 insertions(+), 510 deletions(-) create mode 100644 spec/ruby/core/array/prepend_spec.rb create mode 100644 spec/ruby/core/array/shared/push.rb create mode 100644 spec/ruby/core/array/shared/unshift.rb create mode 100644 spec/ruby/core/file/printf_spec.rb create mode 100644 spec/ruby/core/kernel/shared/sprintf.rb create mode 100644 spec/ruby/core/kernel/shared/sprintf_encoding.rb delete mode 100644 spec/ruby/core/module/fixtures/using.rb create mode 100644 spec/ruby/core/string/percent_spec.rb create mode 100644 spec/ruby/core/tracepoint/binding_spec.rb create mode 100644 spec/ruby/core/tracepoint/defined_class_spec.rb create mode 100644 spec/ruby/core/tracepoint/disable_spec.rb create mode 100644 spec/ruby/core/tracepoint/enable_spec.rb create mode 100644 spec/ruby/core/tracepoint/enabled_spec.rb create mode 100644 spec/ruby/core/tracepoint/event_spec.rb create mode 100644 spec/ruby/core/tracepoint/inspect_spec.rb create mode 100644 spec/ruby/core/tracepoint/lineno_spec.rb create mode 100644 spec/ruby/core/tracepoint/method_id_spec.rb create mode 100644 spec/ruby/core/tracepoint/new_spec.rb create mode 100644 spec/ruby/core/tracepoint/path_spec.rb create mode 100644 spec/ruby/core/tracepoint/raised_exception_spec.rb create mode 100644 spec/ruby/core/tracepoint/return_value_spec.rb create mode 100644 spec/ruby/core/tracepoint/self_spec.rb create mode 100644 spec/ruby/core/tracepoint/trace_spec.rb create mode 100644 spec/ruby/language/fixtures/begin_file.rb create mode 100644 spec/ruby/library/time/to_datetime_spec.rb diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml index d8b9aa7f8a..fff542a222 100644 --- a/spec/ruby/.rubocop.yml +++ b/spec/ruby/.rubocop.yml @@ -13,6 +13,10 @@ Layout/TrailingWhitespace: Lint: Enabled: true +# {...} has higher precedence than do ... end, on purpose +Lint/AmbiguousBlockAssociation: + Enabled: false + Lint/AssignmentInCondition: Enabled: false diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml index 1d68068121..05ce1e9af8 100644 --- a/spec/ruby/.rubocop_todo.yml +++ b/spec/ruby/.rubocop_todo.yml @@ -6,14 +6,6 @@ # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 6 -Lint/AmbiguousBlockAssociation: - Exclude: - - 'core/kernel/trace_var_spec.rb' - - 'language/fixtures/argv_encoding.rb' - - 'language/fixtures/break.rb' - - 'shared/process/abort.rb' - # Offense count: 3 Lint/CircularArgumentReference: Exclude: @@ -57,6 +49,8 @@ Lint/FormatParameterMismatch: Exclude: - 'core/kernel/sprintf_spec.rb' - 'core/string/modulo_spec.rb' + - 'core/kernel/shared/sprintf.rb' + - 'core/kernel/shared/sprintf_encoding.rb' # Offense count: 25 Lint/HandleExceptions: diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb index a80cb51a94..a662b026bf 100644 --- a/spec/ruby/command_line/rubyopt_spec.rb +++ b/spec/ruby/command_line/rubyopt_spec.rb @@ -27,6 +27,11 @@ describe "Processing RUBYOPT" do ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION end + it "ignores whitespace around the option" do + ENV["RUBYOPT"] = ' -v ' + ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION + end + it "sets $VERBOSE to true for '-w'" do ENV["RUBYOPT"] = '-w' ruby_exe("p $VERBOSE", escape: true).chomp.should == "true" diff --git a/spec/ruby/core/array/append_spec.rb b/spec/ruby/core/array/append_spec.rb index 4c65004c58..90e1688c5a 100644 --- a/spec/ruby/core/array/append_spec.rb +++ b/spec/ruby/core/array/append_spec.rb @@ -1,5 +1,6 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/push', __FILE__) describe "Array#<<" do it "pushes the object onto the end of the array" do @@ -33,3 +34,9 @@ describe "Array#<<" do lambda { ArraySpecs.frozen_array << 5 }.should raise_error(RuntimeError) end end + +ruby_version_is "2.5" do + describe "Array#append" do + it_behaves_like(:array_push, :append) + end +end diff --git a/spec/ruby/core/array/prepend_spec.rb b/spec/ruby/core/array/prepend_spec.rb new file mode 100644 index 0000000000..d8c6bad1a8 --- /dev/null +++ b/spec/ruby/core/array/prepend_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/unshift', __FILE__) + +ruby_version_is "2.5" do + describe "Array#prepend" do + it_behaves_like(:array_unshift, :prepend) + end +end diff --git a/spec/ruby/core/array/push_spec.rb b/spec/ruby/core/array/push_spec.rb index 562a6888dd..0207474579 100644 --- a/spec/ruby/core/array/push_spec.rb +++ b/spec/ruby/core/array/push_spec.rb @@ -1,36 +1,7 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/push', __FILE__) describe "Array#push" do - it "appends the arguments to the array" do - a = [ "a", "b", "c" ] - a.push("d", "e", "f").should equal(a) - a.push().should == ["a", "b", "c", "d", "e", "f"] - a.push(5) - a.should == ["a", "b", "c", "d", "e", "f", 5] - - a = [0, 1] - a.push(2) - a.should == [0, 1, 2] - end - - it "isn't confused by previous shift" do - a = [ "a", "b", "c" ] - a.shift - a.push("foo") - a.should == ["b", "c", "foo"] - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - empty.push(:last).should == [empty, :last] - - array = ArraySpecs.recursive_array - array.push(:last).should == [1, 'two', 3.0, array, array, array, array, array, :last] - end - - it "raises a RuntimeError on a frozen array" do - lambda { ArraySpecs.frozen_array.push(1) }.should raise_error(RuntimeError) - lambda { ArraySpecs.frozen_array.push }.should raise_error(RuntimeError) - end + it_behaves_like(:array_push, :push) end diff --git a/spec/ruby/core/array/shared/push.rb b/spec/ruby/core/array/shared/push.rb new file mode 100644 index 0000000000..5951b71a19 --- /dev/null +++ b/spec/ruby/core/array/shared/push.rb @@ -0,0 +1,33 @@ +describe :array_push, shared: true do + it "appends the arguments to the array" do + a = [ "a", "b", "c" ] + a.send(@method, "d", "e", "f").should equal(a) + a.send(@method).should == ["a", "b", "c", "d", "e", "f"] + a.send(@method, 5) + a.should == ["a", "b", "c", "d", "e", "f", 5] + + a = [0, 1] + a.send(@method, 2) + a.should == [0, 1, 2] + end + + it "isn't confused by previous shift" do + a = [ "a", "b", "c" ] + a.shift + a.send(@method, "foo") + a.should == ["b", "c", "foo"] + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.send(@method, :last).should == [empty, :last] + + array = ArraySpecs.recursive_array + array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last] + end + + it "raises a RuntimeError on a frozen array" do + lambda { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(RuntimeError) + lambda { ArraySpecs.frozen_array.send(@method) }.should raise_error(RuntimeError) + end +end diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb new file mode 100644 index 0000000000..367bab4166 --- /dev/null +++ b/spec/ruby/core/array/shared/unshift.rb @@ -0,0 +1,46 @@ +describe :array_unshift, shared: true do + it "prepends object to the original array" do + a = [1, 2, 3] + a.send(@method, "a").should equal(a) + a.should == ['a', 1, 2, 3] + a.send(@method).should equal(a) + a.should == ['a', 1, 2, 3] + a.send(@method, 5, 4, 3) + a.should == [5, 4, 3, 'a', 1, 2, 3] + + # shift all but one element + a = [1, 2] + a.shift + a.send(@method, 3, 4) + a.should == [3, 4, 2] + + # now shift all elements + a.shift + a.shift + a.shift + a.send(@method, 3, 4) + a.should == [3, 4] + end + + it "quietly ignores unshifting nothing" do + [].send(@method).should == [] + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.send(@method, :new).should == [:new, empty] + + array = ArraySpecs.recursive_array + array.send(@method, :new) + array[0..5].should == [:new, 1, 'two', 3.0, array, array] + end + + it "raises a RuntimeError on a frozen array when the array is modified" do + lambda { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(RuntimeError) + end + + # see [ruby-core:23666] + it "raises a RuntimeError on a frozen array when the array would not be modified" do + lambda { ArraySpecs.frozen_array.send(@method) }.should raise_error(RuntimeError) + end +end diff --git a/spec/ruby/core/array/sort_spec.rb b/spec/ruby/core/array/sort_spec.rb index 584b818caf..0578742175 100644 --- a/spec/ruby/core/array/sort_spec.rb +++ b/spec/ruby/core/array/sort_spec.rb @@ -66,7 +66,9 @@ describe "Array#sort" do it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do o = Object.new - lambda { [o, 1].sort }.should raise_error + lambda { + [o, 1].sort + }.should raise_error(ArgumentError) end it "may take a block which is used to determine the order of objects a and b described as -1, 0 or +1" do diff --git a/spec/ruby/core/array/unshift_spec.rb b/spec/ruby/core/array/unshift_spec.rb index 9467a1a6df..eb224acfe8 100644 --- a/spec/ruby/core/array/unshift_spec.rb +++ b/spec/ruby/core/array/unshift_spec.rb @@ -1,50 +1,7 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/unshift', __FILE__) describe "Array#unshift" do - it "prepends object to the original array" do - a = [1, 2, 3] - a.unshift("a").should equal(a) - a.should == ['a', 1, 2, 3] - a.unshift().should equal(a) - a.should == ['a', 1, 2, 3] - a.unshift(5, 4, 3) - a.should == [5, 4, 3, 'a', 1, 2, 3] - - # shift all but one element - a = [1, 2] - a.shift - a.unshift(3, 4) - a.should == [3, 4, 2] - - # now shift all elements - a.shift - a.shift - a.shift - a.unshift(3, 4) - a.should == [3, 4] - end - - it "quietly ignores unshifting nothing" do - [].unshift().should == [] - [].unshift(*[]).should == [] - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - empty.unshift(:new).should == [:new, empty] - - array = ArraySpecs.recursive_array - array.unshift(:new) - array[0..5].should == [:new, 1, 'two', 3.0, array, array] - end - - it "raises a RuntimeError on a frozen array when the array is modified" do - lambda { ArraySpecs.frozen_array.unshift(1) }.should raise_error(RuntimeError) - end - - # see [ruby-core:23666] - it "raises a RuntimeError on a frozen array when the array would not be modified" do - lambda { ArraySpecs.frozen_array.unshift }.should raise_error(RuntimeError) - end + it_behaves_like(:array_unshift, :unshift) end diff --git a/spec/ruby/core/bignum/exponent_spec.rb b/spec/ruby/core/bignum/exponent_spec.rb index f69da833fd..9026c1ff3b 100644 --- a/spec/ruby/core/bignum/exponent_spec.rb +++ b/spec/ruby/core/bignum/exponent_spec.rb @@ -11,9 +11,9 @@ describe "Bignum#**" do end it "raises a TypeError when given a non-Integer" do - lambda { @bignum ** mock('10') }.should raise_error - lambda { @bignum ** "10" }.should raise_error - lambda { @bignum ** :symbol }.should raise_error + lambda { @bignum ** mock('10') }.should raise_error(TypeError) + lambda { @bignum ** "10" }.should raise_error(TypeError) + lambda { @bignum ** :symbol }.should raise_error(TypeError) end it "switch to a Float when the values is too big" do diff --git a/spec/ruby/core/dir/chroot_spec.rb b/spec/ruby/core/dir/chroot_spec.rb index 1afe254957..23d790c83b 100644 --- a/spec/ruby/core/dir/chroot_spec.rb +++ b/spec/ruby/core/dir/chroot_spec.rb @@ -31,7 +31,7 @@ platform_is_not :windows do it "calls #to_path on non-String argument" do p = mock('path') p.should_receive(:to_path).and_return('.') - lambda { Dir.chroot(p) }.should raise_error + lambda { Dir.chroot(p) }.should raise_error(Errno::EPERM) end end end diff --git a/spec/ruby/core/dir/shared/open.rb b/spec/ruby/core/dir/shared/open.rb index 3c2b63b6fa..7f4fe5c2a6 100644 --- a/spec/ruby/core/dir/shared/open.rb +++ b/spec/ruby/core/dir/shared/open.rb @@ -30,9 +30,9 @@ describe :dir_open, shared: true do lambda do Dir.send(@method, DirSpecs.mock_dir) do |dir| closed_dir = dir - raise + raise "dir specs" end - end.should raise_error + end.should raise_error(RuntimeError, "dir specs") lambda { closed_dir.read }.should raise_error(IOError) end diff --git a/spec/ruby/core/file/printf_spec.rb b/spec/ruby/core/file/printf_spec.rb new file mode 100644 index 0000000000..8423c010ab --- /dev/null +++ b/spec/ruby/core/file/printf_spec.rb @@ -0,0 +1,18 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../../kernel/shared/sprintf', __FILE__) + +describe "File#printf" do + it_behaves_like :kernel_sprintf, -> (format, *args) { + begin + @filename = tmp("printf.txt") + + File.open(@filename, "w", encoding: "utf-8") do |f| + f.printf(format, *args) + end + + File.read(@filename, encoding: "utf-8") + ensure + rm_r @filename + end + } +end diff --git a/spec/ruby/core/file/stat/blocks_spec.rb b/spec/ruby/core/file/stat/blocks_spec.rb index ca0fd2c8a6..e84e822a27 100644 --- a/spec/ruby/core/file/stat/blocks_spec.rb +++ b/spec/ruby/core/file/stat/blocks_spec.rb @@ -11,10 +11,10 @@ describe "File::Stat#blocks" do end platform_is_not :windows do - it "returns the blocks of a File::Stat object" do + it "returns a non-negative integer" do st = File.stat(@file) st.blocks.is_a?(Integer).should == true - st.blocks.should > 0 + st.blocks.should >= 0 end end diff --git a/spec/ruby/core/file/stat/new_spec.rb b/spec/ruby/core/file/stat/new_spec.rb index ec7d81362f..4579c4a807 100644 --- a/spec/ruby/core/file/stat/new_spec.rb +++ b/spec/ruby/core/file/stat/new_spec.rb @@ -13,7 +13,9 @@ describe "File::Stat#initialize" do end it "raises an exception if the file doesn't exist" do - lambda { File::Stat.new(tmp("i_am_a_dummy_file_that_doesnt_exist")) }.should raise_error + lambda { + File::Stat.new(tmp("i_am_a_dummy_file_that_doesnt_exist")) + }.should raise_error(Errno::ENOENT) end it "creates a File::Stat object for the given file" do diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb index 73112420d1..e586029715 100644 --- a/spec/ruby/core/file/utime_spec.rb +++ b/spec/ruby/core/file/utime_spec.rb @@ -33,4 +33,15 @@ describe "File.utime" do it "accepts an object that has a #to_path method" do File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) end + + platform_is :linux do + platform_is wordsize: 64 do + it "allows Time instances in the far future to set mtime and atime" do + time = Time.at(1<<44) + File.utime(time, time, @file1) + File.atime(@file1).year.should == 559444 + File.mtime(@file1).year.should == 559444 + end + end + end end diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb index 2b314987bc..69ddc3848d 100644 --- a/spec/ruby/core/io/read_nonblock_spec.rb +++ b/spec/ruby/core/io/read_nonblock_spec.rb @@ -43,6 +43,16 @@ describe "IO#read_nonblock" do end end + platform_is_not :windows do + it 'sets the IO in nonblock mode' do + require 'io/nonblock' + @read.nonblock?.should == false + @write.write "abc" + @read.read_nonblock(1).should == "a" + @read.nonblock?.should == true + end + end + it "returns at most the number of bytes requested" do @write << "hello" @read.read_nonblock(4).should == "hell" diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb index d87303b54a..4ef8a54147 100644 --- a/spec/ruby/core/io/shared/each.rb +++ b/spec/ruby/core/io/shared/each.rb @@ -115,6 +115,47 @@ describe :io_each, shared: true do end end + describe "with both separator and limit" do + describe "when no block is given" do + it "returns an Enumerator" do + enum = @io.send(@method, nil, 1024) + enum.should be_an_instance_of(Enumerator) + + enum.each { |l| ScratchPad << l } + ScratchPad.recorded.should == [IOSpecs.lines.join] + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + @io.send(@method, nil, 1024).size.should == nil + end + end + end + end + + describe "when a block is given" do + it "accepts an empty block" do + @io.send(@method, nil, 1024) {}.should equal(@io) + end + + describe "when passed nil as a separator" do + it "yields self's content starting from the current position when the passed separator is nil" do + @io.pos = 100 + @io.send(@method, nil, 1024) { |s| ScratchPad << s } + ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"] + end + end + + describe "when passed an empty String as a separator" do + it "yields each paragraph" do + @io.send(@method, "", 1024) { |s| ScratchPad << s } + ScratchPad.recorded.should == IOSpecs.paragraphs + end + end + end + end + ruby_version_is "2.4" do describe "when passed chomp" do it "yields each line without trailing newline characters to the passed block" do diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb index 1993653df9..bedcc31169 100644 --- a/spec/ruby/core/io/sysread_spec.rb +++ b/spec/ruby/core/io/sysread_spec.rb @@ -80,3 +80,19 @@ describe "IO#sysread on a file" do lambda { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError) end end + +describe "IO#sysread" do + before do + @read, @write = IO.pipe + end + + after do + @read.close + @write.close + end + + it "returns a smaller string if less than size bytes are available" do + @write.syswrite "ab" + @read.sysread(3).should == "ab" + end +end diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb index a6a263e931..751a36aade 100644 --- a/spec/ruby/core/io/write_nonblock_spec.rb +++ b/spec/ruby/core/io/write_nonblock_spec.rb @@ -32,7 +32,9 @@ platform_is_not :windows do end it "checks if the file is writable if writing zero bytes" do - lambda { @readonly_file.write_nonblock("") }.should raise_error + lambda { + @readonly_file.write_nonblock("") + }.should raise_error(IOError) end end @@ -73,4 +75,12 @@ describe 'IO#write_nonblock' do end end + platform_is_not :windows do + it 'sets the IO in nonblock mode' do + require 'io/nonblock' + @write.nonblock?.should == false + @write.write_nonblock('a') + @write.nonblock?.should == true + end + end end diff --git a/spec/ruby/core/kernel/open_spec.rb b/spec/ruby/core/kernel/open_spec.rb index 4e99061219..ff56dfa03b 100644 --- a/spec/ruby/core/kernel/open_spec.rb +++ b/spec/ruby/core/kernel/open_spec.rb @@ -33,13 +33,14 @@ describe "Kernel#open" do @io = open("|date") begin @io.should be_kind_of(IO) + @io.read ensure @io.close end end it "opens an io when called with a block" do - @output = open("|date") { |f| f.gets } + @output = open("|date") { |f| f.read } @output.should_not == '' end @@ -61,7 +62,7 @@ describe "Kernel#open" do end it "opens an io when called with a block" do - @output = open("|date /t") { |f| f.gets } + @output = open("|date /t") { |f| f.read } @output.should_not == '' end end diff --git a/spec/ruby/core/kernel/printf_spec.rb b/spec/ruby/core/kernel/printf_spec.rb index b4c68fa449..ed134027c0 100644 --- a/spec/ruby/core/kernel/printf_spec.rb +++ b/spec/ruby/core/kernel/printf_spec.rb @@ -1,5 +1,7 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/sprintf', __FILE__) +require "stringio" describe "Kernel#printf" do it "is a private method" do @@ -31,4 +33,29 @@ describe "Kernel.printf" do object.should_receive(:write).with("string") Kernel.printf(object, "%s", "string") end + + describe "formatting" do + context "io is specified" do + it_behaves_like :kernel_sprintf, -> (format, *args) { + io = StringIO.new + printf(io, format, *args) + io.string + } + end + + context "io is not specified" do + it_behaves_like :kernel_sprintf, -> (format, *args) { + stdout = $stdout + + begin + $stdout = io = StringIO.new + printf(format, *args) + io.string + ensure + $stdout = stdout + end + } + end + end end + diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb new file mode 100644 index 0000000000..e595a06640 --- /dev/null +++ b/spec/ruby/core/kernel/shared/sprintf.rb @@ -0,0 +1,871 @@ +describe :kernel_sprintf, shared: true do + def format(*args) + @method.call(*args) + end + + describe "integer formats" do + it "converts argument into Integer with to_int" do + obj = Object.new + def obj.to_i; 10; end + def obj.to_int; 10; end + + obj.should_receive(:to_int).and_return(10) + format("%b", obj).should == "1010" + end + + it "converts argument into Integer with to_i if to_int isn't available" do + obj = Object.new + def obj.to_i; 10; end + + obj.should_receive(:to_i).and_return(10) + format("%b", obj).should == "1010" + end + + it "converts String argument with Kernel#Integer" do + format("%d", "0b1010").should == "10" + format("%d", "112").should == "112" + format("%d", "0127").should == "87" + format("%d", "0xc4").should == "196" + end + + it "raises TypeError exception if cannot convert to Integer" do + -> () { + format("%b", Object.new) + }.should raise_error(TypeError) + end + + ["b", "B"].each do |f| + describe f do + it "converts argument as a binary number" do + format("%#{f}", 10).should == "1010" + end + + it "displays negative number as a two's complement prefixed with '..1'" do + format("%#{f}", -10).should == "..1" + "0110" + end + + it "collapse negative number representation if it equals 1" do + format("%#{f}", -1).should_not == "..11" + format("%#{f}", -1).should == "..1" + end + end + end + + ["d", "i", "u"].each do |f| + describe f do + it "converts argument as a decimal number" do + format("%#{f}", 112).should == "112" + format("%#{f}", -112).should == "-112" + end + + it "works well with large numbers" do + format("%#{f}", 1234567890987654321).should == "1234567890987654321" + end + end + end + + describe "o" do + it "converts argument as an octal number" do + format("%o", 87).should == "127" + end + + it "displays negative number as a two's complement prefixed with '..7'" do + format("%o", -87).should == "..7" + "651" + end + + it "collapse negative number representation if it equals 7" do + format("%o", -1).should_not == "..77" + format("%o", -1).should == "..7" + end + end + + describe "x" do + it "converts argument as a hexadecimal number" do + format("%x", 196).should == "c4" + end + + it "displays negative number as a two's complement prefixed with '..f'" do + format("%x", -196).should == "..f" + "3c" + end + + it "collapse negative number representation if it equals f" do + format("%x", -1).should_not == "..ff" + format("%x", -1).should == "..f" + end + end + + describe "X" do + it "converts argument as a hexadecimal number with uppercase letters" do + format("%X", 196).should == "C4" + end + + it "displays negative number as a two's complement prefixed with '..f'" do + format("%X", -196).should == "..F" + "3C" + end + + it "collapse negative number representation if it equals F" do + format("%X", -1).should_not == "..FF" + format("%X", -1).should == "..F" + end + end + end + + describe "float formats" do + it "converts argument into Float" do + obj = mock("float") + obj.should_receive(:to_f).and_return(9.6) + format("%f", obj).should == "9.600000" + end + + it "raises TypeError exception if cannot convert to Float" do + -> () { + format("%f", Object.new) + }.should raise_error(TypeError) + end + + {"e" => "e", "E" => "E"}.each_pair do |f, exp| + describe f do + it "converts argument into exponential notation [-]d.dddddde[+-]dd" do + format("%#{f}", 109.52).should == "1.095200#{exp}+02" + format("%#{f}", -109.52).should == "-1.095200#{exp}+02" + format("%#{f}", 0.10952).should == "1.095200#{exp}-01" + format("%#{f}", -0.10952).should == "-1.095200#{exp}-01" + end + + it "cuts excessive digits and keeps only 6 ones" do + format("%#{f}", 1.123456789).should == "1.123457#{exp}+00" + end + + it "rounds the last significant digit to the closest one" do + format("%#{f}", 1.555555555).should == "1.555556#{exp}+00" + format("%#{f}", -1.555555555).should == "-1.555556#{exp}+00" + format("%#{f}", 1.444444444).should == "1.444444#{exp}+00" + end + + it "displays Float::INFINITY as Inf" do + format("%#{f}", Float::INFINITY).should == "Inf" + format("%#{f}", -Float::INFINITY).should == "-Inf" + end + + it "displays Float::NAN as NaN" do + format("%#{f}", Float::NAN).should == "NaN" + format("%#{f}", -Float::NAN).should == "NaN" + end + end + end + + describe "f" do + it "converts floating point argument as [-]ddd.dddddd" do + format("%f", 10.952).should == "10.952000" + format("%f", -10.952).should == "-10.952000" + end + + it "cuts excessive digits and keeps only 6 ones" do + format("%f", 1.123456789).should == "1.123457" + end + + it "rounds the last significant digit to the closest one" do + format("%f", 1.555555555).should == "1.555556" + format("%f", -1.555555555).should == "-1.555556" + format("%f", 1.444444444).should == "1.444444" + end + + it "displays Float::INFINITY as Inf" do + format("%f", Float::INFINITY).should == "Inf" + format("%f", -Float::INFINITY).should == "-Inf" + end + + it "displays Float::NAN as NaN" do + format("%f", Float::NAN).should == "NaN" + format("%f", -Float::NAN).should == "NaN" + end + end + + {"g" => "e", "G" => "E"}.each_pair do |f, exp| + describe f do + context "the exponent is less than -4" do + it "converts a floating point number using exponential form" do + format("%#{f}", 0.0000123456).should == "1.23456#{exp}-05" + format("%#{f}", -0.0000123456).should == "-1.23456#{exp}-05" + + format("%#{f}", 0.000000000123456).should == "1.23456#{exp}-10" + format("%#{f}", -0.000000000123456).should == "-1.23456#{exp}-10" + end + end + + context "the exponent is greater than or equal to the precision (6 by default)" do + it "converts a floating point number using exponential form" do + format("%#{f}", 1234567).should == "1.23457#{exp}+06" + format("%#{f}", 1234567890123).should == "1.23457#{exp}+12" + format("%#{f}", -1234567).should == "-1.23457#{exp}+06" + end + end + + context "otherwise" do + it "converts a floating point number in dd.dddd form" do + format("%#{f}", 0.0001).should == "0.0001" + format("%#{f}", -0.0001).should == "-0.0001" + format("%#{f}", 123456).should == "123456" + format("%#{f}", -123456).should == "-123456" + end + + it "cuts excessive digits in fractional part and keeps only 4 ones" do + format("%#{f}", 12.12341111).should == "12.1234" + format("%#{f}", -12.12341111).should == "-12.1234" + end + + it "rounds the last significant digit to the closest one in fractional part" do + format("%#{f}", 1.555555555).should == "1.55556" + format("%#{f}", -1.555555555).should == "-1.55556" + format("%#{f}", 1.444444444).should == "1.44444" + end + + it "cuts fraction part to have only 6 digits at all" do + format("%#{f}", 1.1234567).should == "1.12346" + format("%#{f}", 12.1234567).should == "12.1235" + format("%#{f}", 123.1234567).should == "123.123" + format("%#{f}", 1234.1234567).should == "1234.12" + format("%#{f}", 12345.1234567).should == "12345.1" + format("%#{f}", 123456.1234567).should == "123456" + end + end + + it "displays Float::INFINITY as Inf" do + format("%#{f}", Float::INFINITY).should == "Inf" + format("%#{f}", -Float::INFINITY).should == "-Inf" + end + + it "displays Float::NAN as NaN" do + format("%#{f}", Float::NAN).should == "NaN" + format("%#{f}", -Float::NAN).should == "NaN" + end + end + end + + describe "a" do + it "converts floating point argument as [-]0xh.hhhhp[+-]dd" do + format("%a", 196).should == "0x1.88p+7" + format("%a", -196).should == "-0x1.88p+7" + format("%a", 196.1).should == "0x1.8833333333333p+7" + format("%a", 0.01).should == "0x1.47ae147ae147bp-7" + format("%a", -0.01).should == "-0x1.47ae147ae147bp-7" + end + + it "displays Float::INFINITY as Inf" do + format("%a", Float::INFINITY).should == "Inf" + format("%a", -Float::INFINITY).should == "-Inf" + end + + it "displays Float::NAN as NaN" do + format("%a", Float::NAN).should == "NaN" + format("%a", -Float::NAN).should == "NaN" + end + end + + describe "A" do + it "converts floating point argument as [-]0xh.hhhhp[+-]dd and use uppercase X and P" do + format("%A", 196).should == "0X1.88P+7" + format("%A", -196).should == "-0X1.88P+7" + format("%A", 196.1).should == "0X1.8833333333333P+7" + format("%A", 0.01).should == "0X1.47AE147AE147BP-7" + format("%A", -0.01).should == "-0X1.47AE147AE147BP-7" + end + + it "displays Float::INFINITY as Inf" do + format("%A", Float::INFINITY).should == "Inf" + format("%A", -Float::INFINITY).should == "-Inf" + end + + it "displays Float::NAN as NaN" do + format("%A", Float::NAN).should == "NaN" + format("%A", -Float::NAN).should == "NaN" + end + end + end + + describe "other formats" do + describe "c" do + it "displays character if argument is a numeric code of character" do + format("%c", 97).should == "a" + end + + it "displays character if argument is a single character string" do + format("%c", "a").should == "a" + end + + it "raises ArgumentError if argument is a string of several characters" do + -> () { + format("%c", "abc") + }.should raise_error(ArgumentError) + end + + it "raises ArgumentError if argument is an empty string" do + -> () { + format("%c", "") + }.should raise_error(ArgumentError) + end + + it "supports Unicode characters" do + format("%c", 1286).should == "Ԇ" + format("%c", "ش").should == "ش" + end + end + + describe "p" do + it "displays argument.inspect value" do + obj = mock("object") + obj.should_receive(:inspect).and_return("") + format("%p", obj).should == "" + end + end + + describe "s" do + it "substitute argument passes as a string" do + format("%s", "abc").should == "abc" + end + + it "converts argument to string with to_s" do + obj = mock("string") + obj.should_receive(:to_s).and_return("abc") + format("%s", obj).should == "abc" + end + + it "does not try to convert with to_str" do + obj = BasicObject.new + def obj.to_str + "abc" + end + + -> () { + format("%s", obj) + }.should raise_error(NoMethodError) + end + end + + describe "%" do + ruby_version_is ""..."2.5" do + it "alone displays the percent sign" do + format("%").should == "%" + end + end + + ruby_version_is "2.5" do + it "alone raises an ArgumentError" do + -> { + format("%") + }.should raise_error(ArgumentError) + end + end + + it "is escaped by %" do + format("%%").should == "%" + format("%%d", 10).should == "%d" + end + end + end + + describe "flags" do + describe "space" do + context "applies to numeric formats bBdiouxXeEfgGaA" do + it "leaves a space at the start of non-negative numbers" do + format("% b", 10).should == " 1010" + format("% B", 10).should == " 1010" + format("% d", 112).should == " 112" + format("% i", 112).should == " 112" + format("% o", 87).should == " 127" + format("% u", 112).should == " 112" + format("% x", 196).should == " c4" + format("% X", 196).should == " C4" + + format("% e", 109.52).should == " 1.095200e+02" + format("% E", 109.52).should == " 1.095200E+02" + format("% f", 10.952).should == " 10.952000" + format("% g", 12.1234).should == " 12.1234" + format("% G", 12.1234).should == " 12.1234" + format("% a", 196).should == " 0x1.88p+7" + format("% A", 196).should == " 0X1.88P+7" + end + + it "does not leave a space at the start of negative numbers" do + format("% b", -10).should == "-1010" + format("% B", -10).should == "-1010" + format("% d", -112).should == "-112" + format("% i", -112).should == "-112" + format("% o", -87).should == "-127" + format("% u", -112).should == "-112" + format("% x", -196).should == "-c4" + format("% X", -196).should == "-C4" + + format("% e", -109.52).should == "-1.095200e+02" + format("% E", -109.52).should == "-1.095200E+02" + format("% f", -10.952).should == "-10.952000" + format("% g", -12.1234).should == "-12.1234" + format("% G", -12.1234).should == "-12.1234" + format("% a", -196).should == "-0x1.88p+7" + format("% A", -196).should == "-0X1.88P+7" + end + + it "prevents converting negative argument to two's complement form" do + format("% b", -10).should == "-1010" + format("% B", -10).should == "-1010" + format("% o", -87).should == "-127" + format("% x", -196).should == "-c4" + format("% X", -196).should == "-C4" + end + + it "treats several white spaces as one" do + format("% b", 10).should == " 1010" + format("% B", 10).should == " 1010" + format("% d", 112).should == " 112" + format("% i", 112).should == " 112" + format("% o", 87).should == " 127" + format("% u", 112).should == " 112" + format("% x", 196).should == " c4" + format("% X", 196).should == " C4" + + format("% e", 109.52).should == " 1.095200e+02" + format("% E", 109.52).should == " 1.095200E+02" + format("% f", 10.952).should == " 10.952000" + format("% g", 12.1234).should == " 12.1234" + format("% G", 12.1234).should == " 12.1234" + format("% a", 196).should == " 0x1.88p+7" + format("% A", 196).should == " 0X1.88P+7" + end + end + end + + describe "(digit)$" do + it "specifies the absolute argument number for this field" do + format("%2$b", 0, 10).should == "1010" + format("%2$B", 0, 10).should == "1010" + format("%2$d", 0, 112).should == "112" + format("%2$i", 0, 112).should == "112" + format("%2$o", 0, 87).should == "127" + format("%2$u", 0, 112).should == "112" + format("%2$x", 0, 196).should == "c4" + format("%2$X", 0, 196).should == "C4" + + format("%2$e", 0, 109.52).should == "1.095200e+02" + format("%2$E", 0, 109.52).should == "1.095200E+02" + format("%2$f", 0, 10.952).should == "10.952000" + format("%2$g", 0, 12.1234).should == "12.1234" + format("%2$G", 0, 12.1234).should == "12.1234" + format("%2$a", 0, 196).should == "0x1.88p+7" + format("%2$A", 0, 196).should == "0X1.88P+7" + + format("%2$c", 1, 97).should == "a" + format("%2$p", "a", []).should == "[]" + format("%2$s", "-", "abc").should == "abc" + end + + it "raises exception if argument number is bigger than actual arguments list" do + -> () { + format("%4$d", 1, 2, 3) + }.should raise_error(ArgumentError) + end + + it "ignores '-' sign" do + format("%2$d", 1, 2, 3).should == "2" + format("%-2$d", 1, 2, 3).should == "2" + end + + it "raises ArgumentError exception when absolute and relative argument numbers are mixed" do + -> () { + format("%1$d %d", 1, 2) + }.should raise_error(ArgumentError) + end + end + + describe "#" do + context "applies to format o" do + it "increases the precision until the first digit will be `0' if it is not formatted as complements" do + format("%#o", 87).should == "0127" + end + + it "does nothing for negative argument" do + format("%#o", -87).should == "..7651" + end + end + + context "applies to formats bBxX" do + it "prefixes the result with 0x, 0X, 0b and 0B respectively for non-zero argument" do + format("%#b", 10).should == "0b1010" + format("%#b", -10).should == "0b..10110" + format("%#B", 10).should == "0B1010" + format("%#B", -10).should == "0B..10110" + + format("%#x", 196).should == "0xc4" + format("%#x", -196).should == "0x..f3c" + format("%#X", 196).should == "0XC4" + format("%#X", -196).should == "0X..F3C" + end + + it "does nothing for zero argument" do + format("%#b", 0).should == "0" + format("%#B", 0).should == "0" + + format("%#o", 0).should == "0" + + format("%#x", 0).should == "0" + format("%#X", 0).should == "0" + end + end + + context "applies to formats aAeEfgG" do + it "forces a decimal point to be added, even if no digits follow" do + format("%#.0a", 16.25).should == "0x1.p+4" + format("%#.0A", 16.25).should == "0X1.P+4" + + format("%#.0e", 100).should == "1.e+02" + format("%#.0E", 100).should == "1.E+02" + + format("%#.0f", 123.4).should == "123." + + format("%#g", 123456).should == "123456." + format("%#G", 123456).should == "123456." + end + + it "changes format from dd.dddd to exponential form for gG" do + format("%#.0g", 123.4).should_not == "123." + format("%#.0g", 123.4).should == "1.e+02" + end + end + + context "applies to gG" do + it "does not remove trailing zeros" do + format("%#g", 123.4).should == "123.400" + format("%#g", 123.4).should == "123.400" + end + end + end + + describe "+" do + context "applies to numeric formats bBdiouxXaAeEfgG" do + it "adds a leading plus sign to non-negative numbers" do + format("%+b", 10).should == "+1010" + format("%+B", 10).should == "+1010" + format("%+d", 112).should == "+112" + format("%+i", 112).should == "+112" + format("%+o", 87).should == "+127" + format("%+u", 112).should == "+112" + format("%+x", 196).should == "+c4" + format("%+X", 196).should == "+C4" + + format("%+e", 109.52).should == "+1.095200e+02" + format("%+E", 109.52).should == "+1.095200E+02" + format("%+f", 10.952).should == "+10.952000" + format("%+g", 12.1234).should == "+12.1234" + format("%+G", 12.1234).should == "+12.1234" + format("%+a", 196).should == "+0x1.88p+7" + format("%+A", 196).should == "+0X1.88P+7" + end + + it "does not use two's complement form for negative numbers for formats bBoxX" do + format("%+b", -10).should == "-1010" + format("%+B", -10).should == "-1010" + format("%+o", -87).should == "-127" + format("%+x", -196).should == "-c4" + format("%+X", -196).should == "-C4" + end + end + end + + describe "-" do + it "left-justifies the result of conversion if width is specified" do + format("%-10b", 10).should == "1010 " + format("%-10B", 10).should == "1010 " + format("%-10d", 112).should == "112 " + format("%-10i", 112).should == "112 " + format("%-10o", 87).should == "127 " + format("%-10u", 112).should == "112 " + format("%-10x", 196).should == "c4 " + format("%-10X", 196).should == "C4 " + + format("%-20e", 109.52).should == "1.095200e+02 " + format("%-20E", 109.52).should == "1.095200E+02 " + format("%-20f", 10.952).should == "10.952000 " + format("%-20g", 12.1234).should == "12.1234 " + format("%-20G", 12.1234).should == "12.1234 " + format("%-20a", 196).should == "0x1.88p+7 " + format("%-20A", 196).should == "0X1.88P+7 " + + format("%-10c", 97).should == "a " + format("%-10p", []).should == "[] " + format("%-10s", "abc").should == "abc " + end + end + + describe "0 (zero)" do + context "applies to numeric formats bBdiouxXaAeEfgG and width is specified" do + it "pads with zeros, not spaces" do + format("%010b", 10).should == "0000001010" + format("%010B", 10).should == "0000001010" + format("%010d", 112).should == "0000000112" + format("%010i", 112).should == "0000000112" + format("%010o", 87).should == "0000000127" + format("%010u", 112).should == "0000000112" + format("%010x", 196).should == "00000000c4" + format("%010X", 196).should == "00000000C4" + + format("%020e", 109.52).should == "000000001.095200e+02" + format("%020E", 109.52).should == "000000001.095200E+02" + format("%020f", 10.952).should == "0000000000010.952000" + format("%020g", 12.1234).should == "000000000000012.1234" + format("%020G", 12.1234).should == "000000000000012.1234" + format("%020a", 196).should == "0x000000000001.88p+7" + format("%020A", 196).should == "0X000000000001.88P+7" + end + + it "uses radix-1 when displays negative argument as a two's complement" do + format("%010b", -10).should == "..11110110" + format("%010B", -10).should == "..11110110" + format("%010o", -87).should == "..77777651" + format("%010x", -196).should == "..ffffff3c" + format("%010X", -196).should == "..FFFFFF3C" + end + end + end + + describe "*" do + it "uses the previous argument as the field width" do + format("%*b", 10, 10).should == " 1010" + format("%*B", 10, 10).should == " 1010" + format("%*d", 10, 112).should == " 112" + format("%*i", 10, 112).should == " 112" + format("%*o", 10, 87).should == " 127" + format("%*u", 10, 112).should == " 112" + format("%*x", 10, 196).should == " c4" + format("%*X", 10, 196).should == " C4" + + format("%*e", 20, 109.52).should == " 1.095200e+02" + format("%*E", 20, 109.52).should == " 1.095200E+02" + format("%*f", 20, 10.952).should == " 10.952000" + format("%*g", 20, 12.1234).should == " 12.1234" + format("%*G", 20, 12.1234).should == " 12.1234" + format("%*a", 20, 196).should == " 0x1.88p+7" + format("%*A", 20, 196).should == " 0X1.88P+7" + + format("%*c", 10, 97).should == " a" + format("%*p", 10, []).should == " []" + format("%*s", 10, "abc").should == " abc" + end + + it "left-justifies the result if width is negative" do + format("%*b", -10, 10).should == "1010 " + format("%*B", -10, 10).should == "1010 " + format("%*d", -10, 112).should == "112 " + format("%*i", -10, 112).should == "112 " + format("%*o", -10, 87).should == "127 " + format("%*u", -10, 112).should == "112 " + format("%*x", -10, 196).should == "c4 " + format("%*X", -10, 196).should == "C4 " + + format("%*e", -20, 109.52).should == "1.095200e+02 " + format("%*E", -20, 109.52).should == "1.095200E+02 " + format("%*f", -20, 10.952).should == "10.952000 " + format("%*g", -20, 12.1234).should == "12.1234 " + format("%*G", -20, 12.1234).should == "12.1234 " + format("%*a", -20, 196).should == "0x1.88p+7 " + format("%*A", -20, 196).should == "0X1.88P+7 " + + format("%*c", -10, 97).should == "a " + format("%*p", -10, []).should == "[] " + format("%*s", -10, "abc").should == "abc " + end + + it "uses the specified argument as the width if * is followed by a number and $" do + format("%1$*2$b", 10, 10).should == " 1010" + format("%1$*2$B", 10, 10).should == " 1010" + format("%1$*2$d", 112, 10).should == " 112" + format("%1$*2$i", 112, 10).should == " 112" + format("%1$*2$o", 87, 10).should == " 127" + format("%1$*2$u", 112, 10).should == " 112" + format("%1$*2$x", 196, 10).should == " c4" + format("%1$*2$X", 196, 10).should == " C4" + + format("%1$*2$e", 109.52, 20).should == " 1.095200e+02" + format("%1$*2$E", 109.52, 20).should == " 1.095200E+02" + format("%1$*2$f", 10.952, 20).should == " 10.952000" + format("%1$*2$g", 12.1234, 20).should == " 12.1234" + format("%1$*2$G", 12.1234, 20).should == " 12.1234" + format("%1$*2$a", 196, 20).should == " 0x1.88p+7" + format("%1$*2$A", 196, 20).should == " 0X1.88P+7" + + format("%1$*2$c", 97, 10).should == " a" + format("%1$*2$p", [], 10).should == " []" + format("%1$*2$s", "abc", 10).should == " abc" + end + + it "left-justifies the result if specified with $ argument is negative" do + format("%1$*2$b", 10, -10).should == "1010 " + format("%1$*2$B", 10, -10).should == "1010 " + format("%1$*2$d", 112, -10).should == "112 " + format("%1$*2$i", 112, -10).should == "112 " + format("%1$*2$o", 87, -10).should == "127 " + format("%1$*2$u", 112, -10).should == "112 " + format("%1$*2$x", 196, -10).should == "c4 " + format("%1$*2$X", 196, -10).should == "C4 " + + format("%1$*2$e", 109.52, -20).should == "1.095200e+02 " + format("%1$*2$E", 109.52, -20).should == "1.095200E+02 " + format("%1$*2$f", 10.952, -20).should == "10.952000 " + format("%1$*2$g", 12.1234, -20).should == "12.1234 " + format("%1$*2$G", 12.1234, -20).should == "12.1234 " + format("%1$*2$a", 196, -20).should == "0x1.88p+7 " + format("%1$*2$A", 196, -20).should == "0X1.88P+7 " + + format("%1$*2$c", 97, -10).should == "a " + format("%1$*2$p", [], -10).should == "[] " + format("%1$*2$s", "abc", -10).should == "abc " + end + + it "raises ArgumentError when is mixed with width" do + -> () { + format("%*10d", 10, 112) + }.should raise_error(ArgumentError) + end + end + end + + describe "width" do + it "specifies the minimum number of characters that will be written to the result" do + format("%10b", 10).should == " 1010" + format("%10B", 10).should == " 1010" + format("%10d", 112).should == " 112" + format("%10i", 112).should == " 112" + format("%10o", 87).should == " 127" + format("%10u", 112).should == " 112" + format("%10x", 196).should == " c4" + format("%10X", 196).should == " C4" + + format("%20e", 109.52).should == " 1.095200e+02" + format("%20E", 109.52).should == " 1.095200E+02" + format("%20f", 10.952).should == " 10.952000" + format("%20g", 12.1234).should == " 12.1234" + format("%20G", 12.1234).should == " 12.1234" + format("%20a", 196).should == " 0x1.88p+7" + format("%20A", 196).should == " 0X1.88P+7" + + format("%10c", 97).should == " a" + format("%10p", []).should == " []" + format("%10s", "abc").should == " abc" + end + + it "is ignored if argument's actual length is greater" do + format("%5d", 1234567890).should == "1234567890" + end + end + + describe "precision" do + context "integer types" do + it "controls the number of decimal places displayed" do + format("%.6b", 10).should == "001010" + format("%.6B", 10).should == "001010" + format("%.5d", 112).should == "00112" + format("%.5i", 112).should == "00112" + format("%.5o", 87).should == "00127" + format("%.5u", 112).should == "00112" + + format("%.5x", 196).should == "000c4" + format("%.5X", 196).should == "000C4" + end + end + + context "float types" do + it "controls the number of decimal places displayed in fraction part" do + format("%.10e", 109.52).should == "1.0952000000e+02" + format("%.10E", 109.52).should == "1.0952000000E+02" + format("%.10f", 10.952).should == "10.9520000000" + format("%.10a", 196).should == "0x1.8800000000p+7" + format("%.10A", 196).should == "0X1.8800000000P+7" + end + + it "does not affect G format" do + format("%.10g", 12.1234).should == "12.1234" + format("%.10g", 123456789).should == "123456789" + end + end + + context "string formats" do + it "determines the maximum number of characters to be copied from the string" do + format("%.1p", [1]).should == "[" + format("%.2p", [1]).should == "[1" + format("%.10p", [1]).should == "[1]" + format("%.0p", [1]).should == "" + + format("%.1s", "abc").should == "a" + format("%.2s", "abc").should == "ab" + format("%.10s", "abc").should == "abc" + format("%.0s", "abc").should == "" + end + end + end + + describe "reference by name" do + describe "%s style" do + it "uses value passed in a hash argument" do + format("%d", foo: 123).should == "123" + end + + it "supports flags, width, precision and type" do + format("%+20.10f", foo: 10.952).should == " +10.9520000000" + end + + it "allows to place name in any position" do + format("%+15.5f", foo: 10.952).should == " +10.95200" + format("%+15.5f", foo: 10.952).should == " +10.95200" + format("%+15.5f", foo: 10.952).should == " +10.95200" + format("%+15.5f", foo: 10.952).should == " +10.95200" + end + + it "cannot be mixed with unnamed style" do + -> () { + format("%d %d", 1, foo: "123") + }.should raise_error(ArgumentError) + end + + it "raises KeyError when there is no matching key" do + -> () { + format("%s", {}) + }.should raise_error(KeyError) + end + end + + describe "%{name} style" do + it "uses value passed in a hash argument" do + format("%{foo}", foo: 123).should == "123" + end + + it "does not support type style" do + format("%{foo}d", foo: 123).should == "123d" + end + + it "supports flags, width and precision" do + format("%-20.5{foo}", foo: "123456789").should == "12345 " + end + + it "cannot be mixed with unnamed style" do + -> () { + format("%d %{foo}", 1, foo: "123") + }.should raise_error(ArgumentError) + end + + it "raises KeyError when there is no matching key" do + -> () { + format("%{foo}", {}) + }.should raise_error(KeyError) + end + + it "converts value to String with to_s" do + obj = Object.new + def obj.to_s; end + def obj.to_str; end + + obj.should_receive(:to_s).and_return("42") + obj.should_not_receive(:to_str) + + format("%{foo}", foo: obj).should == "42" + end + end + end +end diff --git a/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/spec/ruby/core/kernel/shared/sprintf_encoding.rb new file mode 100644 index 0000000000..a92f3c10cd --- /dev/null +++ b/spec/ruby/core/kernel/shared/sprintf_encoding.rb @@ -0,0 +1,28 @@ +describe :kernel_sprintf_encoding, shared: true do + def format(*args) + @method.call(*args) + end + + it "returns a String in the same encoding as the format String if compatible" do + string = "%s".force_encoding(Encoding::KOI8_U) + result = format(string, "dogs") + result.encoding.should equal(Encoding::KOI8_U) + end + + it "returns a String in the argument's encoding if format encoding is more restrictive" do + string = "foo %s".force_encoding(Encoding::US_ASCII) + argument = "b\303\274r".force_encoding(Encoding::UTF_8) + + result = format(string, argument) + result.encoding.should equal(Encoding::UTF_8) + end + + it "raises Encoding::CompatibilityError if both encodings are ASCII compatible and there ano not ASCII characters" do + string = "Ä %s".encode('windows-1252') + argument = "Ђ".encode('windows-1251') + + -> () { + format(string, argument) + }.should raise_error(Encoding::CompatibilityError) + end +end diff --git a/spec/ruby/core/kernel/sprintf_spec.rb b/spec/ruby/core/kernel/sprintf_spec.rb index 984f31dc7f..a89b253803 100644 --- a/spec/ruby/core/kernel/sprintf_spec.rb +++ b/spec/ruby/core/kernel/sprintf_spec.rb @@ -1,310 +1,24 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/sprintf', __FILE__) +require File.expand_path('../shared/sprintf_encoding', __FILE__) describe "Kernel#sprintf" do - it "is a private method" do - Kernel.should have_private_instance_method(:sprintf) - end + it_behaves_like :kernel_sprintf, -> (format, *args) { + sprintf(format, *args) + } - it "treats nil arguments as zero-width strings in %s slots" do - sprintf("%s%d%s%s", nil, 4, 'a', 'b').should == '4ab' - end - - it "passes some tests for positive %x" do - sprintf("%x", 123).should == "7b" - sprintf("%0x", 123).should == "7b" - sprintf("% x", 123).should == " 7b" - sprintf("%+x", 123).should == "+7b" - sprintf("%+0x", 123).should == "+7b" - sprintf("%+ x", 123).should == "+7b" - sprintf("% 0x", 123).should == " 7b" - - sprintf("%#x", 123).should == "0x7b" - sprintf("%#0x", 123).should == "0x7b" - sprintf("%# x", 123).should == " 0x7b" - sprintf("%#+x", 123).should == "+0x7b" - sprintf("%#+0x", 123).should == "+0x7b" - sprintf("%#+ x", 123).should == "+0x7b" - sprintf("%# 0x", 123).should == " 0x7b" - - sprintf("%8x", 123).should == " 7b" - sprintf("%08x", 123).should == "0000007b" - sprintf("% 8x", 123).should == " 7b" - sprintf("%+8x", 123).should == " +7b" - sprintf("%+08x", 123).should == "+000007b" - sprintf("%+ 8x", 123).should == " +7b" - sprintf("% 08x", 123).should == " 000007b" - - sprintf("%#8x", 123).should == " 0x7b" - sprintf("%#08x", 123).should == "0x00007b" - sprintf("%# 8x", 123).should == " 0x7b" - sprintf("%#+8x", 123).should == " +0x7b" - sprintf("%#+08x", 123).should == "+0x0007b" - sprintf("%#+ 8x", 123).should == " +0x7b" - sprintf("%# 08x", 123).should == " 0x0007b" - - sprintf("%8.10x", 123).should == "000000007b" - sprintf("%08.10x", 123).should == "000000007b" - sprintf("% 8.10x", 123).should == " 000000007b" - sprintf("%+8.10x", 123).should == "+000000007b" - sprintf("%+08.10x", 123).should == "+000000007b" - sprintf("%+ 8.10x", 123).should == "+000000007b" - sprintf("% 08.10x", 123).should == " 000000007b" - - sprintf("%10.8x", 123).should == " 0000007b" - sprintf("%010.8x", 123).should == " 0000007b" - sprintf("% 10.8x", 123).should == " 0000007b" - sprintf("%+10.8x", 123).should == " +0000007b" - sprintf("%+010.8x", 123).should == " +0000007b" - sprintf("%+ 10.8x", 123).should == " +0000007b" - sprintf("% 010.8x", 123).should == " 0000007b" - end - - describe "with format string that contains %{} sections" do - it "substitutes values for named references" do - sprintf("%{foo}f", {foo: 1}).should == "1f" - end - - it "raises KeyError when no matching key is in second argument" do - lambda { sprintf("%{foo}f", {}) }.should raise_error(KeyError) - end - end - - describe "with format string that contains %<> sections" do - it "formats values for named references" do - sprintf("%f", {foo: 1}).should == "1.000000" - end - - it "raises KeyError when no matching key is in second argument" do - lambda { sprintf("%f", {}) }.should raise_error(KeyError) - end - - it "raises ArgumentError if missing second named argument" do - lambda { sprintf("%d", {key: 1}) }.should raise_error(ArgumentError) - end - end - - describe "with negative values" do - describe "with format %x" do - it "precedes the number with '..'" do - sprintf("%0x", -123).should == "..f85" - sprintf("%#0x", -123).should == "0x..f85" - sprintf("%08x", -123).should == "..ffff85" - sprintf("%#08x", -123).should == "0x..ff85" - sprintf("%8.10x", -123).should == "..ffffff85" - sprintf("%08.10x", -123).should == "..ffffff85" - sprintf("%10.8x", -123).should == " ..ffff85" - sprintf("%010.8x", -123).should == " ..ffff85" - end - end - - describe "with format %b or %B" do - it "precedes the number with '..'" do - sprintf("%.7b", -5).should == "..11011" - sprintf("%.7B", -5).should == "..11011" - sprintf("%0b", -5).should == "..1011" - end - end - end - - it "passes some tests for negative %x" do - sprintf("%x", -123).should == "..f85" - sprintf("% x", -123).should == "-7b" - sprintf("%+x", -123).should == "-7b" - sprintf("%+0x", -123).should == "-7b" - sprintf("%+ x", -123).should == "-7b" - sprintf("% 0x", -123).should == "-7b" - - sprintf("%#x", -123).should == "0x..f85" - sprintf("%# x", -123).should == "-0x7b" - sprintf("%#+x", -123).should == "-0x7b" - sprintf("%#+0x", -123).should == "-0x7b" - sprintf("%#+ x", -123).should == "-0x7b" - sprintf("%# 0x", -123).should == "-0x7b" - - sprintf("%8x", -123).should == " ..f85" - sprintf("% 8x", -123).should == " -7b" - sprintf("%+8x", -123).should == " -7b" - sprintf("%+08x", -123).should == "-000007b" - sprintf("%+ 8x", -123).should == " -7b" - sprintf("% 08x", -123).should == "-000007b" - - sprintf("%#8x", -123).should == " 0x..f85" - sprintf("%# 8x", -123).should == " -0x7b" - sprintf("%#+8x", -123).should == " -0x7b" - sprintf("%#+08x", -123).should == "-0x0007b" - sprintf("%#+ 8x", -123).should == " -0x7b" - sprintf("%# 08x", -123).should == "-0x0007b" - - sprintf("% 8.10x", -123).should == "-000000007b" - sprintf("%+8.10x", -123).should == "-000000007b" - sprintf("%+08.10x", -123).should == "-000000007b" - sprintf("%+ 8.10x", -123).should == "-000000007b" - sprintf("% 08.10x", -123).should == "-000000007b" - - sprintf("% 10.8x", -123).should == " -0000007b" - sprintf("%+10.8x", -123).should == " -0000007b" - sprintf("%+010.8x", -123).should == " -0000007b" - sprintf("%+ 10.8x", -123).should == " -0000007b" - sprintf("% 010.8x", -123).should == " -0000007b" - end - - it "passes some tests for negative %u" do - sprintf("%u", -123).should == "-123" - sprintf("%0u", -123).should == "-123" - sprintf("%#u", -123).should == "-123" - sprintf("%#0u", -123).should == "-123" - sprintf("%8u", -123).should == " -123" - sprintf("%08u", -123).should == "-0000123" - sprintf("%#8u", -123).should == " -123" - sprintf("%#08u", -123).should == "-0000123" - - sprintf("%30u", -123).should == " -123" - sprintf("%030u", -123).should == "-00000000000000000000000000123" - - sprintf("%#30u", -123).should == " -123" - sprintf("%#030u", -123).should == "-00000000000000000000000000123" - - sprintf("%24.30u", -123).should == "-000000000000000000000000000123" - sprintf("%024.30u", -123).should == "-000000000000000000000000000123" - - sprintf("%#24.30u", -123).should == "-000000000000000000000000000123" - sprintf("%#024.30u", -123).should == "-000000000000000000000000000123" - - - sprintf("%30.24u", -123).should == " -000000000000000000000123" - sprintf("%030.24u", -123).should == " -000000000000000000000123" - - sprintf("%#30.24u", -123).should == " -000000000000000000000123" - sprintf("%#030.24u", -123).should == " -000000000000000000000123" - end - - it "passes some tests for positive %u" do - sprintf("%30u", 123).should == " 123" - sprintf("%030u", 123).should == "000000000000000000000000000123" - - sprintf("%#30u", 123).should == " 123" - sprintf("%#030u", 123).should == "000000000000000000000000000123" - - sprintf("%24.30u", 123).should == "000000000000000000000000000123" - sprintf("%024.30u", 123).should == "000000000000000000000000000123" - - sprintf("%#24.30u", 123).should == "000000000000000000000000000123" - sprintf("%#024.30u", 123).should == "000000000000000000000000000123" - - sprintf("%30.24u", 123).should == " 000000000000000000000123" - sprintf("%030.24u", 123).should == " 000000000000000000000123" - - sprintf("%#30.24u", 123).should == " 000000000000000000000123" - sprintf("%#030.24u", 123).should == " 000000000000000000000123" - end - - it "passes some tests for positive %d" do - sprintf("%30d", 123).should == " 123" - sprintf("%030d", 123).should == "000000000000000000000000000123" - - sprintf("%#30d", 123).should == " 123" - sprintf("%#030d", 123).should == "000000000000000000000000000123" - - sprintf("%24.30d", 123).should == "000000000000000000000000000123" - sprintf("%024.30d", 123).should == "000000000000000000000000000123" - - sprintf("%#24.30d", 123).should == "000000000000000000000000000123" - sprintf("%#024.30d", 123).should == "000000000000000000000000000123" - - sprintf("%30.24d", 123).should == " 000000000000000000000123" - sprintf("%030.24d", 123).should == " 000000000000000000000123" - - sprintf("%#30.24d", 123).should == " 000000000000000000000123" - sprintf("%#030.24d", 123).should == " 000000000000000000000123" - end - - it "passes some tests for positive %f" do - sprintf("%30f", 123.1).should == " 123.100000" - sprintf("%030f", 123.1).should == "00000000000000000000123.100000" - - sprintf("%#30f", 123.1).should == " 123.100000" - sprintf("%#030f", 123.1).should == "00000000000000000000123.100000" - - sprintf("%10.4f", 123.1).should == " 123.1000" - sprintf("%010.4f", 123.1).should == "00123.1000" - - sprintf("%10.0f", 123.1).should == " 123" - sprintf("%010.0f", 123.1).should == "0000000123" - end - - it "passes some tests for negative %f" do - sprintf("%30f", -123.5).should == " -123.500000" - sprintf("%030f", -123.5).should == "-0000000000000000000123.500000" - - sprintf("%#30f", -123.5).should == " -123.500000" - sprintf("%#030f", -123.5).should == "-0000000000000000000123.500000" - - sprintf("%10.4f", -123.5).should == " -123.5000" - sprintf("%010.4f", -123.5).should == "-0123.5000" - - sprintf("%10.0f", -123.5).should == " -124" - sprintf("%010.0f", -123.5).should == "-000000124" - end - - it "passes some tests for infinite and nan" do - sprintf("%f", Float::INFINITY).should == "Inf" - sprintf("%f", -Float::INFINITY).should == "-Inf" - sprintf("%f", Float::NAN).should == "NaN" - - sprintf("%10f", Float::INFINITY).should == " Inf" - sprintf("%10f", -Float::INFINITY).should == " -Inf" - sprintf("%10f", Float::NAN).should == " NaN" - end - - it "passes kstephens's tests" do - sprintf("%*1$.*2$3$d", 10, 5, 1).should == " 00001" - sprintf("%b", 0).should == "0" - sprintf("%B", 0).should == "0" - sprintf("%b", -5).should == "..1011" - sprintf("%B", -5).should == "..1011" - sprintf("%+b", -5).should == "-101" - sprintf("%+b", 10).should == "+1010" - sprintf("%+b", 0).should == "+0" - sprintf("%+o", -5).should == "-5" - sprintf("%+o", 10).should == "+12" - sprintf("%+o", 0).should == "+0" - sprintf("%+d", -5).should == "-5" - sprintf("%+d", 10).should == "+10" - sprintf("%+d", 0).should == "+0" - sprintf("%+x", -15).should == "-f" - sprintf("%+x", 100).should == "+64" - sprintf("%+x", 0).should == "+0" - sprintf("%+X", -15).should == "-F" - sprintf("%+X", 100).should == "+64" - sprintf("%+X", 0).should == "+0" - sprintf("=%02X", 1).should == "=01" - sprintf("%+03d", 0).should == "+00" - sprintf("%+03d", 5).should == "+05" - sprintf("%+03d", -5).should == "-05" - sprintf("%+03d", 12).should == "+12" - sprintf("%+03d", -12).should == "-12" - sprintf("%+03d", 123).should == "+123" - sprintf("%+03d", -123).should == "-123" - end - - with_feature :encoding do - it "returns a String in the same encoding as the format String if compatible" do - format = "%.2f %4s".force_encoding(Encoding::KOI8_U) - result = sprintf(format, 1.2, "dogs") - result.encoding.should equal(Encoding::KOI8_U) - end - - it "returns a String in the argument encoding if format encoding is more restrictive" do - format = "foo %s".force_encoding(Encoding::US_ASCII) - arg = "b\303\274r".force_encoding(Encoding::UTF_8) - - result = sprintf(format, arg) - result.encoding.should equal(Encoding::UTF_8) - end - end + it_behaves_like :kernel_sprintf_encoding, -> (format, *args) { + sprintf(format, *args) + } end describe "Kernel.sprintf" do - it "needs to be reviewed for spec completeness" + it_behaves_like :kernel_sprintf, -> (format, *args) { + Kernel.sprintf(format, *args) + } + + it_behaves_like :kernel_sprintf_encoding, -> (format, *args) { + Kernel.sprintf(format, *args) + } end diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb index ed18cdca39..108cc50dad 100644 --- a/spec/ruby/core/main/using_spec.rb +++ b/spec/ruby/core/main/using_spec.rb @@ -2,7 +2,6 @@ require File.expand_path('../../../spec_helper', __FILE__) ruby_version_is "2.0.0" do require File.expand_path('../fixtures/classes', __FILE__) - require File.expand_path('../fixtures/string_refinement', __FILE__) describe "main.using" do it "requires one Module argument" do @@ -16,6 +15,7 @@ ruby_version_is "2.0.0" do end it "uses refinements from the given module only in the target file" do + require File.expand_path('../fixtures/string_refinement', __FILE__) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__) MainSpecs::DATA[:in_module].should == 'foo' MainSpecs::DATA[:toplevel].should == 'foo' @@ -25,6 +25,7 @@ ruby_version_is "2.0.0" do end it "uses refinements from the given module for method calls in the target file" do + require File.expand_path('../fixtures/string_refinement', __FILE__) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__) lambda do 'hello'.foo diff --git a/spec/ruby/core/module/fixtures/using.rb b/spec/ruby/core/module/fixtures/using.rb deleted file mode 100644 index 0ed9355af1..0000000000 --- a/spec/ruby/core/module/fixtures/using.rb +++ /dev/null @@ -1,10 +0,0 @@ -module ModuleSpecs - module EmptyRefinement - end - - module RefinementForStringToS - refine String do - def to_s; "hello from refinement"; end - end - end -end diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb index 67832ff676..b54d83075f 100644 --- a/spec/ruby/core/module/refine_spec.rb +++ b/spec/ruby/core/module/refine_spec.rb @@ -1,6 +1,3 @@ - -return ## this code causes double free and now we are debugging. - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/refine', __FILE__) @@ -87,18 +84,20 @@ describe "Module#refine" do end end - ruby_version_is "2.4" do - it "accepts a module as argument" do - inner_self = nil - Module.new do - refine(Enumerable) do - def blah + quarantine! do # https://bugs.ruby-lang.org/issues/14070 + ruby_version_is "2.4" do + it "accepts a module as argument" do + inner_self = nil + Module.new do + refine(Enumerable) do + def blah + end + inner_self = self end - inner_self = self end - end - inner_self.public_instance_methods.should include(:blah) + inner_self.public_instance_methods.should include(:blah) + end end end @@ -616,4 +615,3 @@ describe "Module#refine" do end end end - diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb index 32e8f8f96b..2e7e15b748 100644 --- a/spec/ruby/core/module/using_spec.rb +++ b/spec/ruby/core/module/using_spec.rb @@ -1,5 +1,4 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/using', __FILE__) describe "Module#using" do it "imports class refinements from module into the current class/module" do @@ -90,7 +89,7 @@ describe "Module#using" do it "raises error in method scope" do mod = Module.new do def self.foo - using ModuleSpecs::EmptyRefinement + using Module.new {} end end @@ -156,7 +155,11 @@ describe "Module#using" do Module.new do Class.new do - using ModuleSpecs::RefinementForStringToS + using Module.new { + refine String do + def to_s; "hello from refinement"; end + end + } ScratchPad << "1".to_s end @@ -175,7 +178,11 @@ describe "Module#using" do Module.new do Class.new do ScratchPad << "1".to_s - using ModuleSpecs::RefinementForStringToS + using Module.new { + refine String do + def to_s; "hello from refinement"; end + end + } ScratchPad << "1".to_s end end @@ -241,7 +248,11 @@ describe "Module#using" do Module.new do if false - using ModuleSpecs::RefinementForStringToS + using Module.new { + refine String do + def to_s; "hello from refinement"; end + end + } end result = "1".to_s end diff --git a/spec/ruby/core/mutex/sleep_spec.rb b/spec/ruby/core/mutex/sleep_spec.rb index a3fb86fba7..ab49ccfd7d 100644 --- a/spec/ruby/core/mutex/sleep_spec.rb +++ b/spec/ruby/core/mutex/sleep_spec.rb @@ -25,9 +25,11 @@ describe "Mutex#sleep" do m = Mutex.new m.lock duration = 0.1 - start = Time.now + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) m.sleep duration - (Time.now - start).should be_close(duration, 0.2) + now = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (now - start).should > 0 + (now - start).should < 2.0 end it "unlocks the mutex while sleeping" do @@ -71,4 +73,23 @@ describe "Mutex#sleep" do m.lock m.sleep(0.01).should be_kind_of(Integer) end + + it "wakes up when requesting sleep times near or equal to zero" do + times = [] + val = 1 + + # power of two divisor so we eventually get near zero + loop do + val = val / 16.0 + times << val + break if val == 0.0 + end + + m = Mutex.new + m.lock + times.each do |time| + # just testing that sleep completes + m.sleep(time).should_not == nil + end + end end diff --git a/spec/ruby/core/process/groups_spec.rb b/spec/ruby/core/process/groups_spec.rb index 0669258bf3..2e12aa350c 100644 --- a/spec/ruby/core/process/groups_spec.rb +++ b/spec/ruby/core/process/groups_spec.rb @@ -10,17 +10,24 @@ describe "Process.groups" do actual = (Process.groups - [gid]).sort actual.should == expected end + end +end - # NOTE: This is kind of sketchy. - it "sets the list of gids of groups in the supplemental group access list" do - groups = Process.groups - if Process.uid == 0 +describe "Process.groups=" do + platform_is_not :windows do + as_superuser do + it "sets the list of gids of groups in the supplemental group access list" do + groups = Process.groups Process.groups = [] Process.groups.should == [] Process.groups = groups Process.groups.sort.should == groups.sort - else - platform_is :aix do + end + end + + as_user do + platform_is :aix do + it "sets the list of gids of groups in the supplemental group access list" do # setgroups() is not part of the POSIX standard, # so its behavior varies from OS to OS. AIX allows a non-root # process to set the supplementary group IDs, as long as @@ -30,6 +37,7 @@ describe "Process.groups" do # it should no longer be able to set any supplementary # group IDs, even if it originally belonged to them. # It should only be able to set its primary group ID. + groups = Process.groups Process.groups = groups Process.groups.sort.should == groups.sort Process.groups = [] @@ -41,14 +49,16 @@ describe "Process.groups" do lambda { Process.groups = supplementary }.should raise_error(Errno::EPERM) end end - platform_is_not :aix do - lambda { Process.groups = [] }.should raise_error(Errno::EPERM) + end + + platform_is_not :aix do + it "raises Errno::EPERM" do + groups = Process.groups + lambda { + Process.groups = groups + }.should raise_error(Errno::EPERM) end end end end end - -describe "Process.groups=" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb index 37d11a0fd7..7889f69c5d 100644 --- a/spec/ruby/core/string/index_spec.rb +++ b/spec/ruby/core/string/index_spec.rb @@ -137,6 +137,7 @@ describe "String#index with String" do "hello".index("he", 1).should == nil "hello".index("he", 2).should == nil + "I’ve got a multibyte character.\n".index("\n\n").should == nil end with_feature :encoding do diff --git a/spec/ruby/core/string/percent_spec.rb b/spec/ruby/core/string/percent_spec.rb new file mode 100644 index 0000000000..5eeb98c217 --- /dev/null +++ b/spec/ruby/core/string/percent_spec.rb @@ -0,0 +1,14 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../../kernel/shared/sprintf', __FILE__) +require File.expand_path('../../kernel/shared/sprintf_encoding', __FILE__) + +describe "String#%" do + it_behaves_like :kernel_sprintf, -> (format, *args) { + format % args + } + + it_behaves_like :kernel_sprintf_encoding, -> (format, *args) { + format % args + } +end + diff --git a/spec/ruby/core/thread/thread_variables_spec.rb b/spec/ruby/core/thread/thread_variables_spec.rb index 538c85c5e4..39299cf20e 100644 --- a/spec/ruby/core/thread/thread_variables_spec.rb +++ b/spec/ruby/core/thread/thread_variables_spec.rb @@ -17,8 +17,13 @@ describe "Thread#thread_variables" do end it "sets a value private to self" do - @t.thread_variable_set :thread_variables_spec_a, 82 - @t.thread_variable_set :thread_variables_spec_b, 82 + @t.thread_variable_set :a, 82 + @t.thread_variable_set :b, 82 + Thread.current.thread_variables.should_not include(:a, :b) + end + + it "only contains user thread variables and is empty initially" do Thread.current.thread_variables.should == [] + @t.thread_variables.should == [] end end diff --git a/spec/ruby/core/time/round_spec.rb b/spec/ruby/core/time/round_spec.rb index a9a793c156..97568802b9 100644 --- a/spec/ruby/core/time/round_spec.rb +++ b/spec/ruby/core/time/round_spec.rb @@ -3,7 +3,6 @@ require File.expand_path('../../../spec_helper', __FILE__) describe "Time#round" do before do @time = Time.utc(2010, 3, 30, 5, 43, "25.123456789".to_r) - @subclass = Class.new(Time).now end it "defaults to rounding to 0 places" do @@ -19,7 +18,10 @@ describe "Time#round" do end it "returns an instance of Time, even if #round is called on a subclass" do - @subclass.round.should be_an_instance_of(Time) + subclass = Class.new(Time) + instance = subclass.at(0) + instance.class.should equal subclass + instance.round.should be_an_instance_of(Time) end it "copies own timezone to the returning value" do diff --git a/spec/ruby/core/time/shared/gm.rb b/spec/ruby/core/time/shared/gm.rb index 805e35766c..72012caa66 100644 --- a/spec/ruby/core/time/shared/gm.rb +++ b/spec/ruby/core/time/shared/gm.rb @@ -19,4 +19,11 @@ describe :time_gm, shared: true do it "interprets post-Gregorian reform dates using Gregorian calendar" do Time.send(@method, 1582, 10, 15, 12).to_i.should == -12219249600 # 2299161j end + + it "handles fractional usec close to rounding limit" do + time = Time.send(@method, 2000, 1, 1, 12, 30, 0, 9999r/10000) + + time.usec.should == 0 + time.nsec.should == 999 + end end diff --git a/spec/ruby/core/tracepoint/binding_spec.rb b/spec/ruby/core/tracepoint/binding_spec.rb new file mode 100644 index 0000000000..6d327fb693 --- /dev/null +++ b/spec/ruby/core/tracepoint/binding_spec.rb @@ -0,0 +1,19 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#binding' do + def test + secret = 42 + end + + it 'return the generated binding object from event' do + bindings = [] + TracePoint.new(:return) { |tp| + bindings << tp.binding + }.enable { + test + } + bindings.size.should == 1 + bindings[0].should be_kind_of(Binding) + bindings[0].local_variables.should == [:secret] + end +end diff --git a/spec/ruby/core/tracepoint/defined_class_spec.rb b/spec/ruby/core/tracepoint/defined_class_spec.rb new file mode 100644 index 0000000000..c5a93c6e04 --- /dev/null +++ b/spec/ruby/core/tracepoint/defined_class_spec.rb @@ -0,0 +1,26 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) + +describe 'TracePoint#defined_class' do + it 'returns class or module of the method being called' do + last_class_name = nil + TracePoint.new(:call) do |tp| + last_class_name = tp.defined_class + end.enable do + TracePointSpec::B.new.foo + last_class_name.should equal(TracePointSpec::B) + + TracePointSpec::B.new.bar + last_class_name.should equal(TracePointSpec::A) + + c = TracePointSpec::C.new + last_class_name.should equal(TracePointSpec::C) + + c.foo + last_class_name.should equal(TracePointSpec::B) + + c.bar + last_class_name.should equal(TracePointSpec::A) + end + end +end diff --git a/spec/ruby/core/tracepoint/disable_spec.rb b/spec/ruby/core/tracepoint/disable_spec.rb new file mode 100644 index 0000000000..7da644621b --- /dev/null +++ b/spec/ruby/core/tracepoint/disable_spec.rb @@ -0,0 +1,64 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#disable' do + def test; end + it 'returns true if trace was enabled' do + event_name, method_name = nil + trace = TracePoint.new(:call) do |tp| + event_name = tp.event + method_name = tp.method_id + end + + trace.enable + trace.disable.should be_true + event_name, method_name = nil + test + method_name.equal?(:test).should be_false + event_name.should equal(nil) + end + + it 'returns false if trace was disabled' do + event_name, method_name = nil + trace = TracePoint.new(:call) do |tp| + event_name = tp.event + method_name = tp.method_id + end + + trace.disable.should be_false + event_name, method_name = nil + test + method_name.equal?(:test).should be_false + event_name.should equal(nil) + end + + it 'is disabled within a block & is enabled outside the block' do + enabled = nil + trace = TracePoint.new(:line) {} + trace.enable + trace.disable { enabled = trace.enabled? } + enabled.should be_false + trace.enabled?.should be_true + trace.disable + end + + it 'is disabled within a block & also returns false when its called with a block' do + trace = TracePoint.new(:line) {} + trace.enable + trace.disable { trace.enabled? }.should == false + trace.enabled?.should equal(true) + trace.disable + end + + ruby_bug "#14057", "2.0"..."2.5" do + it 'can accept param within a block but it should not yield arguments' do + event_name = nil + trace = TracePoint.new(:line) {} + trace.enable + trace.disable do |*args| + args.should == [] + end + trace.enabled?.should be_true + trace.disable + end + end +end diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb new file mode 100644 index 0000000000..675f9939c1 --- /dev/null +++ b/spec/ruby/core/tracepoint/enable_spec.rb @@ -0,0 +1,92 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#enable' do + def test; end + + describe 'without a block' do + it 'returns true if trace was enabled' do + event_name, method_name = nil, nil + method_name = [] + trace = TracePoint.new(:call) do |tp| + event_name = tp.event + method_name << tp.method_id + end + + test + event_name.should == nil + + trace.enable + test + event_name.should equal(:call) + trace.disable + end + + it 'returns false if trace was disabled' do + event_name, method_name = nil, nil + trace = TracePoint.new(:call) do |tp| + event_name = tp.event + method_name = tp.method_id + end + + trace.enable.should be_false + event_name.should equal(:call) + test + method_name.equal?(:test).should be_true + + trace.disable + event_name, method_name = nil + test + method_name.equal?(:test).should be_false + event_name.should equal(nil) + + trace.enable.should be_false + event_name.should equal(:call) + test + method_name.equal?(:test).should be_true + trace.disable + end + end + + describe 'with a block' do + it 'enables the trace object within a block' do + event_name = nil + TracePoint.new(:line) do |tp| + event_name = tp.event + end.enable { event_name.should equal(:line) } + end + + ruby_bug "#14057", "2.0"..."2.5" do + it 'can accept arguments within a block but it should not yield arguments' do + event_name = nil + trace = TracePoint.new(:line) { |tp| event_name = tp.event } + trace.enable do |*args| + event_name.should equal(:line) + args.should == [] + end + trace.enabled?.should be_false + end + end + + it 'enables trace object on calling with a block if it was already enabled' do + enabled = nil + trace = TracePoint.new(:line) {} + trace.enable + trace.enable { enabled = trace.enabled? } + enabled.should == true + trace.disable + end + + it 'returns value returned by the block' do + trace = TracePoint.new(:line) {} + trace.enable { true; 'test' }.should == 'test' + end + + it 'disables the trace object outside the block' do + event_name = nil + trace = TracePoint.new(:line) { |tp|event_name = tp.event } + trace.enable { '2 + 2' } + event_name.should equal(:line) + trace.enabled?.should be_false + end + end +end diff --git a/spec/ruby/core/tracepoint/enabled_spec.rb b/spec/ruby/core/tracepoint/enabled_spec.rb new file mode 100644 index 0000000000..0b5130979f --- /dev/null +++ b/spec/ruby/core/tracepoint/enabled_spec.rb @@ -0,0 +1,14 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#enabled?' do + it 'returns true when current status of the trace is enable' do + trace = TracePoint.new(:call) {} + trace.enable do + trace.enabled?.should be_true + end + end + + it 'returns false when current status of the trace is disabled' do + TracePoint.new(:call) {}.enabled?.should be_false + end +end diff --git a/spec/ruby/core/tracepoint/event_spec.rb b/spec/ruby/core/tracepoint/event_spec.rb new file mode 100644 index 0000000000..46bc7a0d50 --- /dev/null +++ b/spec/ruby/core/tracepoint/event_spec.rb @@ -0,0 +1,21 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) + +describe 'TracePoint#event' do + it 'returns the type of event' do + event_name = nil + TracePoint.new(:end, :call) do |tp| + event_name = tp.event + end.enable do + TracePointSpec.test + event_name.should equal(:call) + + TracePointSpec::B.new.foo + event_name.should equal(:call) + + class TracePointSpec::B; end + event_name.should equal(:end) + end + + end +end diff --git a/spec/ruby/core/tracepoint/fixtures/classes.rb b/spec/ruby/core/tracepoint/fixtures/classes.rb index fd22ac319d..49c70e1915 100644 --- a/spec/ruby/core/tracepoint/fixtures/classes.rb +++ b/spec/ruby/core/tracepoint/fixtures/classes.rb @@ -4,5 +4,31 @@ module TracePointSpec end alias_method :m_alias, :m end -end + module A + def bar; end + end + + class B + include A + + def foo; end; + end + + class C < B + def initialize + end + + def foo + super + end + + def bar + super + end + end + + def self.test + 'test' + end +end diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb new file mode 100644 index 0000000000..3902872ab5 --- /dev/null +++ b/spec/ruby/core/tracepoint/inspect_spec.rb @@ -0,0 +1,8 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#inspect' do + it 'returns a string containing a human-readable TracePoint status' do + TracePoint.new(:call) {}.inspect.should == + '#' + end +end diff --git a/spec/ruby/core/tracepoint/lineno_spec.rb b/spec/ruby/core/tracepoint/lineno_spec.rb new file mode 100644 index 0000000000..49be6f8116 --- /dev/null +++ b/spec/ruby/core/tracepoint/lineno_spec.rb @@ -0,0 +1,10 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#lineno' do + it 'returns the line number of the event' do + lineno = nil + TracePoint.new(:line) { |tp| lineno = tp.lineno }.enable do + lineno.should == 7 + end + end +end diff --git a/spec/ruby/core/tracepoint/method_id_spec.rb b/spec/ruby/core/tracepoint/method_id_spec.rb new file mode 100644 index 0000000000..4b18ba696d --- /dev/null +++ b/spec/ruby/core/tracepoint/method_id_spec.rb @@ -0,0 +1,13 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#method_id' do + def test; end + + it 'returns the name at the definition of the method being called' do + method_name = nil + TracePoint.new(:call) { |tp| method_name = tp.method_id}.enable do + test + method_name.should equal(:test) + end + end +end diff --git a/spec/ruby/core/tracepoint/new_spec.rb b/spec/ruby/core/tracepoint/new_spec.rb new file mode 100644 index 0000000000..c3f6d60f5c --- /dev/null +++ b/spec/ruby/core/tracepoint/new_spec.rb @@ -0,0 +1,68 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) + +describe 'TracePoint.new' do + it 'returns a new TracePoint object, not enabled by default' do + TracePoint.new(:call) {}.enabled?.should be_false + end + + it 'includes :line event when event is not specified' do + event_name = nil + TracePoint.new() { |tp| event_name = tp.event }.enable do + event_name.should equal(:line) + + event_name = nil + TracePointSpec.test + event_name.should equal(:line) + + event_name = nil + TracePointSpec::B.new.foo + event_name.should equal(:line) + end + end + + it 'converts given event name as string into symbol using to_sym' do + event_name = nil + (o = mock('return')).should_receive(:to_sym).and_return(:return) + + TracePoint.new(o) { |tp| event_name = tp.event}.enable do + event_name.should equal(nil) + TracePointSpec.test + event_name.should equal(:return) + end + end + + it 'includes multiple events when multiple event names are passed as params' do + event_name = nil + TracePoint.new(:end, :call) do |tp| + event_name = tp.event + end.enable do + TracePointSpec.test + event_name.should equal(:call) + + TracePointSpec::B.new.foo + event_name.should equal(:call) + + class TracePointSpec::B; end + event_name.should equal(:end) + end + end + + it 'raises a TypeError when the given object is not a string/symbol' do + o = mock('123') + -> { TracePoint.new(o) {}}.should raise_error(TypeError) + + o.should_receive(:to_sym).and_return(123) + -> { TracePoint.new(o) {}}.should raise_error(TypeError) + end + + ruby_bug "#140740", "2.0"..."2.5" do + it 'expects to be called with a block' do + -> { TracePoint.new(:line) }.should raise_error(ArgumentError) + end + end + + it "raises a Argument error when the give argument doesn't match an event name" do + -> { TracePoint.new(:test) }.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/core/tracepoint/path_spec.rb b/spec/ruby/core/tracepoint/path_spec.rb new file mode 100644 index 0000000000..61592f5106 --- /dev/null +++ b/spec/ruby/core/tracepoint/path_spec.rb @@ -0,0 +1,18 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#path' do + it 'returns the path of the file being run' do + path = nil + TracePoint.new(:line) { |tp| path = tp.path }.enable do + path.should == "#{__FILE__}" + end + end + + it 'equals (eval) inside an eval for :end event' do + path = nil + TracePoint.new(:end) { |tp| path = tp.path }.enable do + eval("class A; end") + path.should == '(eval)' + end + end +end diff --git a/spec/ruby/core/tracepoint/raised_exception_spec.rb b/spec/ruby/core/tracepoint/raised_exception_spec.rb new file mode 100644 index 0000000000..6c81431b25 --- /dev/null +++ b/spec/ruby/core/tracepoint/raised_exception_spec.rb @@ -0,0 +1,16 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#raised_exception' do + it 'returns value from exception raised on the :raise event' do + raised_exception, error_result = nil + trace = TracePoint.new(:raise) { |tp| raised_exception = tp.raised_exception } + trace.enable do + begin + raise StandardError + rescue => e + error_result = e + end + raised_exception.should equal(error_result) + end + end +end diff --git a/spec/ruby/core/tracepoint/return_value_spec.rb b/spec/ruby/core/tracepoint/return_value_spec.rb new file mode 100644 index 0000000000..c9cfe091cd --- /dev/null +++ b/spec/ruby/core/tracepoint/return_value_spec.rb @@ -0,0 +1,13 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#return_value' do + def test; 'test' end + + it 'returns value from :return event' do + trace_value = nil + TracePoint.new(:return) { |tp| trace_value = tp.return_value}.enable do + test + trace_value.should == 'test' + end + end +end diff --git a/spec/ruby/core/tracepoint/self_spec.rb b/spec/ruby/core/tracepoint/self_spec.rb new file mode 100644 index 0000000000..9d33aa7477 --- /dev/null +++ b/spec/ruby/core/tracepoint/self_spec.rb @@ -0,0 +1,10 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint#self' do + it 'return the trace object from event' do + trace = nil + TracePoint.new(:line) { |tp| trace = tp.self }.enable do + trace.equal?(self).should be_true + end + end +end diff --git a/spec/ruby/core/tracepoint/trace_spec.rb b/spec/ruby/core/tracepoint/trace_spec.rb new file mode 100644 index 0000000000..9279348026 --- /dev/null +++ b/spec/ruby/core/tracepoint/trace_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe 'TracePoint.trace' do + it 'activates the trace automatically' do + trace = TracePoint.trace(:call) {} + trace.enabled?.should be_true + trace.disable + end +end diff --git a/spec/ruby/language/BEGIN_spec.rb b/spec/ruby/language/BEGIN_spec.rb index 826d5f0c89..c0784971b0 100644 --- a/spec/ruby/language/BEGIN_spec.rb +++ b/spec/ruby/language/BEGIN_spec.rb @@ -29,4 +29,8 @@ describe "The BEGIN keyword" do ScratchPad.recorded.should == ['foo', 'bar'] end + + it "returns the top-level script's filename for __FILE__" do + ruby_exe(fixture(__FILE__, "begin_file.rb")).chomp.should =~ /begin_file\.rb$/ + end end diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb index da3c3bd272..09e8ff3d93 100644 --- a/spec/ruby/language/break_spec.rb +++ b/spec/ruby/language/break_spec.rb @@ -24,6 +24,24 @@ describe "The break statement in a block" do value.should == :value end end + + describe "captured and delegated to another method repeatedly" do + it "breaks out of the block" do + @program.looped_break_in_captured_block + ScratchPad.recorded.should == [:begin, + :preloop, + :predele, + :preyield, + :prebreak, + :postbreak, + :postyield, + :postdele, + :predele, + :preyield, + :prebreak, + :end] + end + end end describe "The break statement in a captured block" do diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb index 1d3cecd9c6..45d87ce52f 100644 --- a/spec/ruby/language/constants_spec.rb +++ b/spec/ruby/language/constants_spec.rb @@ -375,6 +375,28 @@ describe "Constant resolution within methods" do end end + + describe "with &&=" do + it "re-assigns a scoped constant if already true" do + module ConstantSpecs + OpAssignTrue = true + end + suppress_warning do + ConstantSpecs::OpAssignTrue &&= 1 + end + ConstantSpecs::OpAssignTrue.should == 1 + ConstantSpecs.send :remove_const, :OpAssignTrue + end + + it "leaves scoped constant if not true" do + module ConstantSpecs + OpAssignFalse = false + end + ConstantSpecs::OpAssignFalse &&= 1 + ConstantSpecs::OpAssignFalse.should == false + ConstantSpecs.send :remove_const, :OpAssignFalse + end + end end describe "Constant resolution within a singleton class (class << obj)" do diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb index 1247658381..0c8e657786 100644 --- a/spec/ruby/language/defined_spec.rb +++ b/spec/ruby/language/defined_spec.rb @@ -750,7 +750,7 @@ describe "The defined? keyword for a scoped constant" do end it "returns nil when an undefined constant is scoped to a defined constant" do - defined?(DefinedSpecs::Child::B).should be_nil + defined?(DefinedSpecs::Child::Undefined).should be_nil end it "returns nil when a constant is scoped to an undefined constant" do @@ -785,7 +785,7 @@ describe "The defined? keyword for a top-level scoped constant" do end it "returns nil when an undefined constant is scoped to a defined constant" do - defined?(::DefinedSpecs::Child::B).should be_nil + defined?(::DefinedSpecs::Child::Undefined).should be_nil end it "returns nil when the undefined constant is scoped to an undefined constant" do diff --git a/spec/ruby/language/fixtures/begin_file.rb b/spec/ruby/language/fixtures/begin_file.rb new file mode 100644 index 0000000000..cd3930b681 --- /dev/null +++ b/spec/ruby/language/fixtures/begin_file.rb @@ -0,0 +1,3 @@ +BEGIN { + puts __FILE__ +} \ No newline at end of file diff --git a/spec/ruby/language/fixtures/break.rb b/spec/ruby/language/fixtures/break.rb index 50e7fcf5d9..2d07cc3d48 100644 --- a/spec/ruby/language/fixtures/break.rb +++ b/spec/ruby/language/fixtures/break.rb @@ -106,6 +106,34 @@ module BreakSpecs note :d end + def looped_break_in_captured_block + note :begin + looped_delegate_block do |i| + note :prebreak + break if i == 1 + note :postbreak + end + note :end + end + + def looped_delegate_block(&block) + note :preloop + 2.times do |i| + note :predele + yield_value(i, &block) + note :postdele + end + note :postloop + end + private :looped_delegate_block + + def yield_value(value) + note :preyield + yield value + note :postyield + end + private :yield_value + def method(v) yield v end diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb index 281bb8fde8..d7042b7973 100644 --- a/spec/ruby/language/rescue_spec.rb +++ b/spec/ruby/language/rescue_spec.rb @@ -291,10 +291,20 @@ describe "The rescue keyword" do end.should == :expected end + ruby_version_is ""..."2.4" do + it "fails when using 'rescue' in method arguments" do + lambda { eval '1.+ (1 rescue 1)' }.should raise_error(SyntaxError) + end + end + ruby_version_is "2.4" do it "allows 'rescue' in method arguments" do two = eval '1.+ (raise("Error") rescue 1)' two.should == 2 end + + it "requires the 'rescue' in method arguments to be wrapped in parens" do + lambda { eval '1.+(1 rescue 1)' }.should raise_error(SyntaxError) + end end end diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb index a203b79078..ba4bbfb5f3 100644 --- a/spec/ruby/language/return_spec.rb +++ b/spec/ruby/language/return_spec.rb @@ -409,6 +409,39 @@ describe "The return keyword" do end end + describe "within a class" do + ruby_version_is ""..."2.5" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + class A + ScratchPad << "before return" + return + + ScratchPad << "after return" + end + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before return"] + end + end + + ruby_version_is "2.5" do + it "raises a SyntaxError" do + File.write(@filename, <<-END_OF_CODE) + class A + ScratchPad << "before return" + return + + ScratchPad << "after return" + end + END_OF_CODE + + -> { load @filename }.should raise_error(SyntaxError) + end + end + end + describe "file loading" do it "stops file loading and execution" do File.write(@filename, <<-END_OF_CODE) diff --git a/spec/ruby/library/bigdecimal/limit_spec.rb b/spec/ruby/library/bigdecimal/limit_spec.rb index 41308abcd8..0c90415aec 100644 --- a/spec/ruby/library/bigdecimal/limit_spec.rb +++ b/spec/ruby/library/bigdecimal/limit_spec.rb @@ -11,20 +11,35 @@ describe "BigDecimal.limit" do BigDecimal.limit(old) end - it "use the global limit if no precision is specified" do + it "uses the global limit if no precision is specified" do BigDecimalSpecs.with_limit(0) do (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.888') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.888') (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.296') end BigDecimalSpecs.with_limit(1) do (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.9') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.9') (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.3') end BigDecimalSpecs.with_limit(2) do (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.89') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.89') (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.7') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.30') + end + end + + it "picks the specified precision over global limit" do + BigDecimalSpecs.with_limit(3) do + BigDecimal('0.888').add(BigDecimal('0'), 2).should == BigDecimal('0.89') + BigDecimal('0.888').sub(BigDecimal('0'), 2).should == BigDecimal('0.89') + BigDecimal('0.888').mult(BigDecimal('3'), 2).should == BigDecimal('2.7') + BigDecimal('0.888').div(BigDecimal('3'), 2).should == BigDecimal('0.30') end end end diff --git a/spec/ruby/library/date/constants_spec.rb b/spec/ruby/library/date/constants_spec.rb index 8e564fe665..ae343f07ec 100644 --- a/spec/ruby/library/date/constants_spec.rb +++ b/spec/ruby/library/date/constants_spec.rb @@ -34,9 +34,13 @@ describe "Date constants" do it "freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES" do [Date::MONTHNAMES, Date::DAYNAMES, Date::ABBR_MONTHNAMES, Date::ABBR_DAYNAMES].each do |ary| - lambda { ary << "Unknown" }.should raise_error + lambda { + ary << "Unknown" + }.should raise_error(RuntimeError, /frozen/) ary.compact.each do |name| - lambda { name << "modified" }.should raise_error + lambda { + name << "modified" + }.should raise_error(RuntimeError, /frozen/) end end end diff --git a/spec/ruby/library/date/minus_month_spec.rb b/spec/ruby/library/date/minus_month_spec.rb index fbe5cb8593..51befcc6d4 100644 --- a/spec/ruby/library/date/minus_month_spec.rb +++ b/spec/ruby/library/date/minus_month_spec.rb @@ -13,15 +13,6 @@ describe "Date#<<" do d.should == Date.civil(2008, 2, 29) end - ruby_version_is ""..."2.3" do - it "raises an error on non numeric parameters" do - lambda { Date.civil(2007,2,27) << :hello }.should raise_error - lambda { Date.civil(2007,2,27) << "hello" }.should raise_error - lambda { Date.civil(2007,2,27) << Date.new }.should raise_error - lambda { Date.civil(2007,2,27) << Object.new }.should raise_error - end - end - ruby_version_is "2.3" do it "raises an error on non numeric parameters" do lambda { Date.civil(2007,2,27) << :hello }.should raise_error(TypeError) diff --git a/spec/ruby/library/datetime/now_spec.rb b/spec/ruby/library/datetime/now_spec.rb index a5bf590aff..9118163533 100644 --- a/spec/ruby/library/datetime/now_spec.rb +++ b/spec/ruby/library/datetime/now_spec.rb @@ -7,7 +7,7 @@ describe "DateTime.now" do end it "sets the current date" do - (DateTime.now - Date.today).to_f.should be_close(0.0, 1.0) + (DateTime.now - Date.today).to_f.should be_close(0.0, 2.0) end it "sets the current time" do diff --git a/spec/ruby/library/datetime/to_time_spec.rb b/spec/ruby/library/datetime/to_time_spec.rb index f5b7cb8a23..2a016d1528 100644 --- a/spec/ruby/library/datetime/to_time_spec.rb +++ b/spec/ruby/library/datetime/to_time_spec.rb @@ -6,6 +6,18 @@ describe "DateTime#to_time" do DateTime.now.to_time.should be_kind_of(Time) end + it "returns a Time representing the same instant" do + datetime = DateTime.civil(3, 12, 31, 23, 58, 59) + time = datetime.to_time.utc + + time.year.should == 3 + time.month.should == 12 + time.day.should == 31 + time.hour.should == 23 + time.min.should == 58 + time.sec.should == 59 + end + ruby_version_is "2.4" do it "preserves the same time regardless of local time or zone" do date = DateTime.new(2012, 12, 24, 12, 23, 00, '+03:00') diff --git a/spec/ruby/library/erb/new_spec.rb b/spec/ruby/library/erb/new_spec.rb index 917fd470b7..f141f1c00e 100644 --- a/spec/ruby/library/erb/new_spec.rb +++ b/spec/ruby/library/erb/new_spec.rb @@ -65,7 +65,7 @@ END end - it "not support '<%-= expr %> even when trim_mode is '-'" do + it "does not support '<%-= expr %> even when trim_mode is '-'" do input = <<'END'

@@ -74,7 +74,9 @@ END

END - lambda { ERB.new(input, nil, '-').result }.should raise_error + lambda { + ERB.new(input, nil, '-').result + }.should raise_error(SyntaxError) end it "regards lines starting with '%' as '<% ... %>' when trim_mode is '%'" do diff --git a/spec/ruby/library/etc/nprocessors_spec.rb b/spec/ruby/library/etc/nprocessors_spec.rb index bce11d06c5..2a22aaafdf 100644 --- a/spec/ruby/library/etc/nprocessors_spec.rb +++ b/spec/ruby/library/etc/nprocessors_spec.rb @@ -1,11 +1,9 @@ require File.expand_path('../../../spec_helper', __FILE__) require 'etc' -ruby_version_is "2.2" do - describe "Etc.nprocessors" do - it "returns the number of online processors" do - Etc.nprocessors.should be_kind_of(Integer) - Etc.nprocessors.should >= 1 - end +describe "Etc.nprocessors" do + it "returns the number of online processors" do + Etc.nprocessors.should be_kind_of(Integer) + Etc.nprocessors.should >= 1 end end diff --git a/spec/ruby/library/openssl/config/freeze_spec.rb b/spec/ruby/library/openssl/config/freeze_spec.rb index 2ed48ae629..b764df4f45 100644 --- a/spec/ruby/library/openssl/config/freeze_spec.rb +++ b/spec/ruby/library/openssl/config/freeze_spec.rb @@ -8,9 +8,13 @@ describe "OpenSSL::Config#freeze" do it "freezes" do c = OpenSSL::Config.new - lambda{c['foo'] = [ ['key', 'value'] ]}.should_not raise_error + lambda { + c['foo'] = [ ['key', 'value'] ] + }.should_not raise_error c.freeze c.frozen?.should be_true - lambda{c['foo'] = [ ['key', 'value'] ]}.should raise_error + lambda { + c['foo'] = [ ['key', 'value'] ] + }.should raise_error(TypeError) end end diff --git a/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb b/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb index dfd4e050ce..27529c3d1c 100644 --- a/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb +++ b/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb @@ -16,7 +16,9 @@ describe "Socket::IPSocket#peeraddr" do end it "raises error if socket is not connected" do - lambda { @server.peeraddr }.should raise_error + lambda { + @server.peeraddr + }.should raise_error(Errno::ENOTCONN) end it "returns an array of information on the peer" do diff --git a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb index 14dccf7917..dc5a319f4d 100644 --- a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb +++ b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb @@ -21,7 +21,9 @@ describe "UNIXSocket#peeraddr" do end it "raises an error in server sockets" do - lambda { @server.peeraddr }.should raise_error + lambda { + @server.peeraddr + }.should raise_error(Errno::ENOTCONN) end end diff --git a/spec/ruby/library/stringio/printf_spec.rb b/spec/ruby/library/stringio/printf_spec.rb index 5f811547bc..a2094bf52d 100644 --- a/spec/ruby/library/stringio/printf_spec.rb +++ b/spec/ruby/library/stringio/printf_spec.rb @@ -1,5 +1,6 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../../../core/kernel/shared/sprintf', __FILE__) describe "StringIO#printf" do before :each do @@ -28,6 +29,14 @@ describe "StringIO#printf" do @io.printf("%d %04x", 123, 123) @io.pos.should eql(16) end + + describe "formatting" do + it_behaves_like :kernel_sprintf, -> (format, *args) { + io = StringIO.new + io.printf(format, *args) + io.string + } + end end describe "StringIO#printf when in append mode" do @@ -59,3 +68,4 @@ describe "StringIO#printf when self is not writable" do lambda { io.printf("test") }.should raise_error(IOError) end end + diff --git a/spec/ruby/library/syslog/alert_spec.rb b/spec/ruby/library/syslog/alert_spec.rb index 4653fa8636..e61b3d6ef3 100644 --- a/spec/ruby/library/syslog/alert_spec.rb +++ b/spec/ruby/library/syslog/alert_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/close_spec.rb b/spec/ruby/library/syslog/close_spec.rb index f7bc4ac6e9..d7aadb2198 100644 --- a/spec/ruby/library/syslog/close_spec.rb +++ b/spec/ruby/library/syslog/close_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.close" do diff --git a/spec/ruby/library/syslog/constants_spec.rb b/spec/ruby/library/syslog/constants_spec.rb index c335ff46e6..1ce82be883 100644 --- a/spec/ruby/library/syslog/constants_spec.rb +++ b/spec/ruby/library/syslog/constants_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog::Constants" do diff --git a/spec/ruby/library/syslog/crit_spec.rb b/spec/ruby/library/syslog/crit_spec.rb index 28e3af67cc..cf2cc71abc 100644 --- a/spec/ruby/library/syslog/crit_spec.rb +++ b/spec/ruby/library/syslog/crit_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/debug_spec.rb b/spec/ruby/library/syslog/debug_spec.rb index ff9fc5d97e..09ba9997a2 100644 --- a/spec/ruby/library/syslog/debug_spec.rb +++ b/spec/ruby/library/syslog/debug_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/emerg_spec.rb b/spec/ruby/library/syslog/emerg_spec.rb index 15cc49be32..d416ee57c6 100644 --- a/spec/ruby/library/syslog/emerg_spec.rb +++ b/spec/ruby/library/syslog/emerg_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/err_spec.rb b/spec/ruby/library/syslog/err_spec.rb index fdadd49e09..ad65f6c276 100644 --- a/spec/ruby/library/syslog/err_spec.rb +++ b/spec/ruby/library/syslog/err_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/facility_spec.rb b/spec/ruby/library/syslog/facility_spec.rb index 02ea754b6b..fdcabfa0dd 100644 --- a/spec/ruby/library/syslog/facility_spec.rb +++ b/spec/ruby/library/syslog/facility_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.facility" do diff --git a/spec/ruby/library/syslog/ident_spec.rb b/spec/ruby/library/syslog/ident_spec.rb index a685dfa927..ef1144f12e 100644 --- a/spec/ruby/library/syslog/ident_spec.rb +++ b/spec/ruby/library/syslog/ident_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.ident" do diff --git a/spec/ruby/library/syslog/info_spec.rb b/spec/ruby/library/syslog/info_spec.rb index 88ff81994d..b2abe7c04a 100644 --- a/spec/ruby/library/syslog/info_spec.rb +++ b/spec/ruby/library/syslog/info_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/inspect_spec.rb b/spec/ruby/library/syslog/inspect_spec.rb index 5fd7793c22..c22a053286 100644 --- a/spec/ruby/library/syslog/inspect_spec.rb +++ b/spec/ruby/library/syslog/inspect_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.inspect" do diff --git a/spec/ruby/library/syslog/instance_spec.rb b/spec/ruby/library/syslog/instance_spec.rb index 60f43dbdea..65d97a5d50 100644 --- a/spec/ruby/library/syslog/instance_spec.rb +++ b/spec/ruby/library/syslog/instance_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.instance" do diff --git a/spec/ruby/library/syslog/log_spec.rb b/spec/ruby/library/syslog/log_spec.rb index 2403943cfc..eac6be8b01 100644 --- a/spec/ruby/library/syslog/log_spec.rb +++ b/spec/ruby/library/syslog/log_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.log" do diff --git a/spec/ruby/library/syslog/mask_spec.rb b/spec/ruby/library/syslog/mask_spec.rb index 49be56d304..7a11d1e88c 100644 --- a/spec/ruby/library/syslog/mask_spec.rb +++ b/spec/ruby/library/syslog/mask_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.mask" do diff --git a/spec/ruby/library/syslog/notice_spec.rb b/spec/ruby/library/syslog/notice_spec.rb index 7a27e23729..f31074f3f6 100644 --- a/spec/ruby/library/syslog/notice_spec.rb +++ b/spec/ruby/library/syslog/notice_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/open_spec.rb b/spec/ruby/library/syslog/open_spec.rb index 18e7f0c80e..424b48d831 100644 --- a/spec/ruby/library/syslog/open_spec.rb +++ b/spec/ruby/library/syslog/open_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/reopen', __FILE__) require 'syslog' @@ -73,8 +74,13 @@ platform_is_not :windows do it "raises an error if the log is opened" do Syslog.open - lambda { Syslog.open}.should raise_error - lambda { Syslog.close; Syslog.open }.should_not raise_error + lambda { + Syslog.open + }.should raise_error(RuntimeError, /syslog already open/) + lambda { + Syslog.close + Syslog.open + }.should_not raise_error Syslog.close end end diff --git a/spec/ruby/library/syslog/opened_spec.rb b/spec/ruby/library/syslog/opened_spec.rb index 82b8ba45f7..1db388fa61 100644 --- a/spec/ruby/library/syslog/opened_spec.rb +++ b/spec/ruby/library/syslog/opened_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.opened?" do diff --git a/spec/ruby/library/syslog/options_spec.rb b/spec/ruby/library/syslog/options_spec.rb index 4a3914531a..145d11a2fb 100644 --- a/spec/ruby/library/syslog/options_spec.rb +++ b/spec/ruby/library/syslog/options_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require 'syslog' describe "Syslog.options" do diff --git a/spec/ruby/library/syslog/reopen_spec.rb b/spec/ruby/library/syslog/reopen_spec.rb index de1ce2c255..49704784e5 100644 --- a/spec/ruby/library/syslog/reopen_spec.rb +++ b/spec/ruby/library/syslog/reopen_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/reopen', __FILE__) require 'syslog' diff --git a/spec/ruby/library/syslog/warning_spec.rb b/spec/ruby/library/syslog/warning_spec.rb index 85fcb3a355..31fa9524f7 100644 --- a/spec/ruby/library/syslog/warning_spec.rb +++ b/spec/ruby/library/syslog/warning_spec.rb @@ -1,5 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) + platform_is_not :windows do - require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/log', __FILE__) require 'syslog' diff --git a/spec/ruby/library/time/to_datetime_spec.rb b/spec/ruby/library/time/to_datetime_spec.rb new file mode 100644 index 0000000000..54655963c6 --- /dev/null +++ b/spec/ruby/library/time/to_datetime_spec.rb @@ -0,0 +1,27 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require 'time' + +describe "Time#to_datetime" do + it "returns a DateTime representing the same instant" do + time = Time.utc(3, 12, 31, 23, 58, 59) + datetime = time.to_datetime + datetime.year.should == 3 + datetime.month.should == 12 + datetime.day.should == 31 + datetime.hour.should == 23 + datetime.min.should == 58 + datetime.sec.should == 59 + end + + it "roundtrips" do + time = Time.utc(3, 12, 31, 23, 58, 59) + datetime = time.to_datetime + datetime.to_time.utc.should == time + end + + it "yields a DateTime with the default Calendar reform day" do + Time.utc(1582, 10, 4, 1, 2, 3).to_datetime.start.should == Date::ITALY + Time.utc(1582, 10, 14, 1, 2, 3).to_datetime.start.should == Date::ITALY + Time.utc(1582, 10, 15, 1, 2, 3).to_datetime.start.should == Date::ITALY + end +end diff --git a/spec/ruby/library/uri/join_spec.rb b/spec/ruby/library/uri/join_spec.rb index 681ba45cc7..3e0dbe7f2b 100644 --- a/spec/ruby/library/uri/join_spec.rb +++ b/spec/ruby/library/uri/join_spec.rb @@ -21,7 +21,9 @@ describe "URI.join" do end it "raises an error if given no argument" do - lambda{ URI.join }.should raise_error + lambda { + URI.join + }.should raise_error(ArgumentError) end it "doesn't create redundant '/'s" do diff --git a/spec/ruby/library/uri/shared/join.rb b/spec/ruby/library/uri/shared/join.rb index dfe44e9be2..ff85b57a80 100644 --- a/spec/ruby/library/uri/shared/join.rb +++ b/spec/ruby/library/uri/shared/join.rb @@ -18,7 +18,9 @@ describe :uri_join, shared: true do end it "raises an error if given no argument" do - lambda{ @object.join }.should raise_error + lambda { + @object.join + }.should raise_error(ArgumentError) end it "doesn't create redundant '/'s" do diff --git a/spec/ruby/library/yaml/load_spec.rb b/spec/ruby/library/yaml/load_spec.rb index 7c5a33d52f..6a2ab65b65 100644 --- a/spec/ruby/library/yaml/load_spec.rb +++ b/spec/ruby/library/yaml/load_spec.rb @@ -34,6 +34,27 @@ describe "YAML.load" do end end + it "loads strings with chars from non-base Unicode plane" do + # We add these strings as bytes and force the encoding for safety + # as bugs in parsing unicode characters can obscure bugs in this + # area. + + yaml_and_strings = { + # "--- 🌵" => "🌵" + [45, 45, 45, 32, 240, 159, 140, 181] => + [240, 159, 140, 181], + # "--- 🌵 and some text" => "🌵 and some text" + [45, 45, 45, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => + [240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116], + # "--- Some text 🌵 and some text" => "Some text 🌵 and some text" + [45, 45, 45, 32, 83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] => + [83, 111, 109, 101, 32, 116, 101, 120, 116, 32, 240, 159, 140, 181, 32, 97, 110, 100, 32, 115, 111, 109, 101, 32, 116, 101, 120, 116] + } + yaml_and_strings.each do |yaml, str| + YAML.load(yaml.pack("C*").force_encoding("UTF-8")).should == str.pack("C*").force_encoding("UTF-8") + end + end + it "fails on invalid keys" do if YAML.to_s == "Psych" error = Psych::SyntaxError diff --git a/spec/ruby/optional/capi/ext/numeric_spec.c b/spec/ruby/optional/capi/ext/numeric_spec.c index cd643cc66f..2f0f504549 100644 --- a/spec/ruby/optional/capi/ext/numeric_spec.c +++ b/spec/ruby/optional/capi/ext/numeric_spec.c @@ -96,6 +96,12 @@ static VALUE numeric_spec_rb_num_coerce_relop(VALUE self, VALUE x, VALUE y, VALU } #endif +#ifdef HAVE_RB_ABSINT_SINGLEBIT_P +static VALUE numeric_spec_rb_absint_singlebit_p(VALUE self, VALUE num) { + return INT2FIX(rb_absint_singlebit_p(num)); +} +#endif + void Init_numeric_spec(void) { VALUE cls; cls = rb_define_class("CApiNumericSpecs", rb_cObject); @@ -159,6 +165,10 @@ void Init_numeric_spec(void) { #ifdef HAVE_RB_NUM_COERCE_RELOP rb_define_method(cls, "rb_num_coerce_relop", numeric_spec_rb_num_coerce_relop, 3); #endif + +#ifdef HAVE_RB_ABSINT_SINGLEBIT_P +rb_define_method(cls, "rb_absint_singlebit_p", numeric_spec_rb_absint_singlebit_p, 1); +#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/object_spec.c b/spec/ruby/optional/capi/ext/object_spec.c index ad1ebecc78..45a28169ef 100644 --- a/spec/ruby/optional/capi/ext/object_spec.c +++ b/spec/ruby/optional/capi/ext/object_spec.c @@ -5,6 +5,32 @@ extern "C" { #endif +#ifdef HAVE_FL_ABLE +static VALUE object_spec_FL_ABLE(VALUE self, VALUE obj) { + if (FL_ABLE(obj)) { + return Qtrue; + } else { + return Qfalse; + } +} +#endif + +#ifdef HAVE_FL_TEST +static int object_spec_FL_TEST_flag(VALUE flag_string) { + char *flag_cstr = StringValueCStr(flag_string); + if (strcmp(flag_cstr, "FL_TAINT") == 0) { + return FL_TAINT; + } else if (strcmp(flag_cstr, "FL_FREEZE") == 0) { + return FL_FREEZE; + } + return 0; +} + +static VALUE object_spec_FL_TEST(VALUE self, VALUE obj, VALUE flag) { + return INT2FIX(FL_TEST(obj, object_spec_FL_TEST_flag(flag))); +} +#endif + #ifdef HAVE_OBJ_TAINT static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) { OBJ_TAINT(obj); @@ -204,7 +230,11 @@ static VALUE object_spec_rb_method_boundp(VALUE self, VALUE obj, VALUE method, V #ifdef HAVE_RB_SPECIAL_CONST_P static VALUE object_spec_rb_special_const_p(VALUE self, VALUE value) { - return rb_special_const_p(value); + if (rb_special_const_p(value)) { + return Qtrue; + } else { + return Qfalse; + } } #endif @@ -404,6 +434,14 @@ void Init_object_spec(void) { VALUE cls; cls = rb_define_class("CApiObjectSpecs", rb_cObject); +#ifdef HAVE_FL_ABLE + rb_define_method(cls, "FL_ABLE", object_spec_FL_ABLE, 1); +#endif + +#ifdef HAVE_FL_TEST + rb_define_method(cls, "FL_TEST", object_spec_FL_TEST, 2); +#endif + #ifdef HAVE_OBJ_TAINT rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1); #endif diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h index aab74b88ae..341cff0428 100644 --- a/spec/ruby/optional/capi/ext/rubyspec.h +++ b/spec/ruby/optional/capi/ext/rubyspec.h @@ -422,6 +422,7 @@ #define HAVE_RB_NUM_COERCE_BIN 1 #define HAVE_RB_NUM_COERCE_CMP 1 #define HAVE_RB_NUM_COERCE_RELOP 1 +#define HAVE_RB_ABSINT_SINGLEBIT_P 1 #define HAVE_RB_NUM_ZERODIV 1 /* Fixnum */ @@ -431,6 +432,8 @@ #endif /* Object */ +#define HAVE_FL_ABLE 1 +#define HAVE_FL_TEST 1 #define HAVE_OBJ_TAINT 1 #define HAVE_OBJ_TAINTED 1 #define HAVE_OBJ_INFECT 1 diff --git a/spec/ruby/optional/capi/numeric_spec.rb b/spec/ruby/optional/capi/numeric_spec.rb index fdf794247d..1d4a44d7a2 100644 --- a/spec/ruby/optional/capi/numeric_spec.rb +++ b/spec/ruby/optional/capi/numeric_spec.rb @@ -429,4 +429,19 @@ describe "CApiNumericSpecs" do lambda { @s.rb_num_coerce_relop(2, obj, :<) }.should raise_error(ArgumentError) end end + + describe "rb_absint_singlebit_p" do + it "returns 1 if absolute value fits into a bit" do + @s.rb_absint_singlebit_p(1).should == 1 + @s.rb_absint_singlebit_p(2).should == 1 + @s.rb_absint_singlebit_p(3).should == 0 + @s.rb_absint_singlebit_p(-1).should == 1 + @s.rb_absint_singlebit_p(-2).should == 1 + @s.rb_absint_singlebit_p(-3).should == 0 + @s.rb_absint_singlebit_p(bignum_value).should == 1 + @s.rb_absint_singlebit_p(bignum_value(1)).should == 0 + @s.rb_absint_singlebit_p(-bignum_value).should == 1 + @s.rb_absint_singlebit_p(-bignum_value(1)).should == 0 + end + end end diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb index cf7ea2e8cf..97bff38ec0 100644 --- a/spec/ruby/optional/capi/object_spec.rb +++ b/spec/ruby/optional/capi/object_spec.rb @@ -404,6 +404,31 @@ describe "CApiObject" do end end + describe "FL_ABLE" do + it "returns correct boolean for type" do + @o.FL_ABLE(Object.new).should be_true + @o.FL_ABLE(true).should be_false + @o.FL_ABLE(nil).should be_false + @o.FL_ABLE(1).should be_false + end + end + + describe "FL_TEST" do + it "returns correct status for FL_TAINT" do + obj = Object.new + @o.FL_TEST(obj, "FL_TAINT").should == 0 + obj.taint + @o.FL_TEST(obj, "FL_TAINT").should_not == 0 + end + + it "returns correct status for FL_FREEZE" do + obj = Object.new + @o.FL_TEST(obj, "FL_FREEZE").should == 0 + obj.freeze + @o.FL_TEST(obj, "FL_FREEZE").should_not == 0 + end + end + describe "rb_inspect" do it "returns a string with the inspect representation" do @o.rb_inspect(nil).should == "nil" diff --git a/spec/ruby/optional/capi/util_spec.rb b/spec/ruby/optional/capi/util_spec.rb index c8d0401cbc..b2ef2ba92e 100644 --- a/spec/ruby/optional/capi/util_spec.rb +++ b/spec/ruby/optional/capi/util_spec.rb @@ -105,6 +105,16 @@ describe "C-API Util function" do ScratchPad.recorded.should == [1, h] end + it "assigns required and Hash arguments with optional Hash" do + @o.rb_scan_args([1], "1:", 2, @acc).should == 1 + ScratchPad.recorded.should == [1, nil] + end + + it "assigns required and Hash arguments with nil Hash" do + @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1 + ScratchPad.recorded.should == [1, nil] + end + it "assigns required, optional, splat, post-splat, Hash and block arguments" do h = {a: 1, b: 2} @o.rb_scan_args([1, 2, 3, 4, 5, h], "11*1:&", 6, @acc, &@prc).should == 5 diff --git a/spec/ruby/shared/file/zero.rb b/spec/ruby/shared/file/zero.rb index bb5eea57ad..cf014d4722 100644 --- a/spec/ruby/shared/file/zero.rb +++ b/spec/ruby/shared/file/zero.rb @@ -55,17 +55,9 @@ describe :file_zero, shared: true do end end - platform_is_not :windows do - it "returns false for a directory" do - @object.send(@method, @dir).should == false - end - end - - platform_is :windows do - # see http://redmine.ruby-lang.org/issues/show/449 for background - it "returns true for a directory" do - @object.send(@method, @dir).should == true - end + # See https://bugs.ruby-lang.org/issues/449 for background + it "returns true or false for a directory" do + @object.send(@method, @dir).should be_true_or_false end end diff --git a/spec/ruby/spec_helper.rb b/spec/ruby/spec_helper.rb index e7873ce594..c38965d3c5 100644 --- a/spec/ruby/spec_helper.rb +++ b/spec/ruby/spec_helper.rb @@ -16,11 +16,14 @@ end # Running directly with ruby some_spec.rb unless ENV['MSPEC_RUNNER'] + mspec_lib = File.expand_path("../../mspec/lib", __FILE__) + $LOAD_PATH << mspec_lib if File.directory?(mspec_lib) + begin require 'mspec' require 'mspec/commands/mspec-run' rescue LoadError - puts "Please add -Ipath/to/mspec/lib or install the MSpec gem to run the specs." + puts "Please add -Ipath/to/mspec/lib or clone mspec as a sibling to run the specs." exit 1 end -- cgit v1.2.3