1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60973 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-12-01 15:41:50 +00:00
parent 821d9a2d30
commit 4d7b0b9112
104 changed files with 2105 additions and 510 deletions

View file

@ -13,6 +13,10 @@ Layout/TrailingWhitespace:
Lint: Lint:
Enabled: true Enabled: true
# {...} has higher precedence than do ... end, on purpose
Lint/AmbiguousBlockAssociation:
Enabled: false
Lint/AssignmentInCondition: Lint/AssignmentInCondition:
Enabled: false Enabled: false

View file

@ -6,14 +6,6 @@
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # 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 # Offense count: 3
Lint/CircularArgumentReference: Lint/CircularArgumentReference:
Exclude: Exclude:
@ -57,6 +49,8 @@ Lint/FormatParameterMismatch:
Exclude: Exclude:
- 'core/kernel/sprintf_spec.rb' - 'core/kernel/sprintf_spec.rb'
- 'core/string/modulo_spec.rb' - 'core/string/modulo_spec.rb'
- 'core/kernel/shared/sprintf.rb'
- 'core/kernel/shared/sprintf_encoding.rb'
# Offense count: 25 # Offense count: 25
Lint/HandleExceptions: Lint/HandleExceptions:

View file

@ -27,6 +27,11 @@ describe "Processing RUBYOPT" do
ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION
end 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 it "sets $VERBOSE to true for '-w'" do
ENV["RUBYOPT"] = '-w' ENV["RUBYOPT"] = '-w'
ruby_exe("p $VERBOSE", escape: true).chomp.should == "true" ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"

View file

@ -1,5 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/push', __FILE__)
describe "Array#<<" do describe "Array#<<" do
it "pushes the object onto the end of the 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) lambda { ArraySpecs.frozen_array << 5 }.should raise_error(RuntimeError)
end end
end end
ruby_version_is "2.5" do
describe "Array#append" do
it_behaves_like(:array_push, :append)
end
end

View file

@ -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

View file

@ -1,36 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/push', __FILE__)
describe "Array#push" do describe "Array#push" do
it "appends the arguments to the array" do it_behaves_like(:array_push, :push)
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
end end

View file

@ -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

View file

@ -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

View file

@ -66,7 +66,9 @@ describe "Array#sort" do
it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do
o = Object.new o = Object.new
lambda { [o, 1].sort }.should raise_error lambda {
[o, 1].sort
}.should raise_error(ArgumentError)
end 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 it "may take a block which is used to determine the order of objects a and b described as -1, 0 or +1" do

View file

@ -1,50 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/unshift', __FILE__)
describe "Array#unshift" do describe "Array#unshift" do
it "prepends object to the original array" do it_behaves_like(:array_unshift, :unshift)
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
end end

View file

@ -11,9 +11,9 @@ describe "Bignum#**" do
end end
it "raises a TypeError when given a non-Integer" do it "raises a TypeError when given a non-Integer" do
lambda { @bignum ** mock('10') }.should raise_error lambda { @bignum ** mock('10') }.should raise_error(TypeError)
lambda { @bignum ** "10" }.should raise_error lambda { @bignum ** "10" }.should raise_error(TypeError)
lambda { @bignum ** :symbol }.should raise_error lambda { @bignum ** :symbol }.should raise_error(TypeError)
end end
it "switch to a Float when the values is too big" do it "switch to a Float when the values is too big" do

View file

@ -31,7 +31,7 @@ platform_is_not :windows do
it "calls #to_path on non-String argument" do it "calls #to_path on non-String argument" do
p = mock('path') p = mock('path')
p.should_receive(:to_path).and_return('.') 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 end
end end

View file

@ -30,9 +30,9 @@ describe :dir_open, shared: true do
lambda do lambda do
Dir.send(@method, DirSpecs.mock_dir) do |dir| Dir.send(@method, DirSpecs.mock_dir) do |dir|
closed_dir = dir closed_dir = dir
raise raise "dir specs"
end end
end.should raise_error end.should raise_error(RuntimeError, "dir specs")
lambda { closed_dir.read }.should raise_error(IOError) lambda { closed_dir.read }.should raise_error(IOError)
end end

View file

@ -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

View file

@ -11,10 +11,10 @@ describe "File::Stat#blocks" do
end end
platform_is_not :windows do 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 = File.stat(@file)
st.blocks.is_a?(Integer).should == true st.blocks.is_a?(Integer).should == true
st.blocks.should > 0 st.blocks.should >= 0
end end
end end

View file

@ -13,7 +13,9 @@ describe "File::Stat#initialize" do
end end
it "raises an exception if the file doesn't exist" do 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 end
it "creates a File::Stat object for the given file" do it "creates a File::Stat object for the given file" do

View file

@ -33,4 +33,15 @@ describe "File.utime" do
it "accepts an object that has a #to_path method" do it "accepts an object that has a #to_path method" do
File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2))
end 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 end

View file

@ -43,6 +43,16 @@ describe "IO#read_nonblock" do
end end
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 it "returns at most the number of bytes requested" do
@write << "hello" @write << "hello"
@read.read_nonblock(4).should == "hell" @read.read_nonblock(4).should == "hell"

View file

@ -115,6 +115,47 @@ describe :io_each, shared: true do
end end
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 ruby_version_is "2.4" do
describe "when passed chomp" do describe "when passed chomp" do
it "yields each line without trailing newline characters to the passed block" do it "yields each line without trailing newline characters to the passed block" do

View file

@ -80,3 +80,19 @@ describe "IO#sysread on a file" do
lambda { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError) lambda { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError)
end end
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

View file

@ -32,7 +32,9 @@ platform_is_not :windows do
end end
it "checks if the file is writable if writing zero bytes" do 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
end end
@ -73,4 +75,12 @@ describe 'IO#write_nonblock' do
end end
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 end

View file

@ -33,13 +33,14 @@ describe "Kernel#open" do
@io = open("|date") @io = open("|date")
begin begin
@io.should be_kind_of(IO) @io.should be_kind_of(IO)
@io.read
ensure ensure
@io.close @io.close
end end
end end
it "opens an io when called with a block" do 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 == '' @output.should_not == ''
end end
@ -61,7 +62,7 @@ describe "Kernel#open" do
end end
it "opens an io when called with a block" do 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 == '' @output.should_not == ''
end end
end end

View file

@ -1,5 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/sprintf', __FILE__)
require "stringio"
describe "Kernel#printf" do describe "Kernel#printf" do
it "is a private method" do it "is a private method" do
@ -31,4 +33,29 @@ describe "Kernel.printf" do
object.should_receive(:write).with("string") object.should_receive(:write).with("string")
Kernel.printf(object, "%s", "string") Kernel.printf(object, "%s", "string")
end 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 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

View file

@ -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("<inspect-result>")
format("%p", obj).should == "<inspect-result>"
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 "%<name>s style" do
it "uses value passed in a hash argument" do
format("%<foo>d", foo: 123).should == "123"
end
it "supports flags, width, precision and type" do
format("%+20.10<foo>f", foo: 10.952).should == " +10.9520000000"
end
it "allows to place name in any position" do
format("%+15.5<foo>f", foo: 10.952).should == " +10.95200"
format("%+15<foo>.5f", foo: 10.952).should == " +10.95200"
format("%+<foo>15.5f", foo: 10.952).should == " +10.95200"
format("%<foo>+15.5f", foo: 10.952).should == " +10.95200"
end
it "cannot be mixed with unnamed style" do
-> () {
format("%d %<foo>d", 1, foo: "123")
}.should raise_error(ArgumentError)
end
it "raises KeyError when there is no matching key" do
-> () {
format("%<foo>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

View file

@ -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

View file

@ -1,310 +1,24 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __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 describe "Kernel#sprintf" do
it "is a private method" do it_behaves_like :kernel_sprintf, -> (format, *args) {
Kernel.should have_private_instance_method(:sprintf) sprintf(format, *args)
end }
it "treats nil arguments as zero-width strings in %s slots" do it_behaves_like :kernel_sprintf_encoding, -> (format, *args) {
sprintf("%s%d%s%s", nil, 4, 'a', 'b').should == '4ab' sprintf(format, *args)
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("%<foo>f", {foo: 1}).should == "1.000000"
end
it "raises KeyError when no matching key is in second argument" do
lambda { sprintf("%<foo>f", {}) }.should raise_error(KeyError)
end
it "raises ArgumentError if missing second named argument" do
lambda { sprintf("%<key><foo>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
end end
describe "Kernel.sprintf" do 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 end

View file

@ -2,7 +2,6 @@ require File.expand_path('../../../spec_helper', __FILE__)
ruby_version_is "2.0.0" do ruby_version_is "2.0.0" do
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../fixtures/string_refinement', __FILE__)
describe "main.using" do describe "main.using" do
it "requires one Module argument" do it "requires one Module argument" do
@ -16,6 +15,7 @@ ruby_version_is "2.0.0" do
end end
it "uses refinements from the given module only in the target file" do 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__) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
MainSpecs::DATA[:in_module].should == 'foo' MainSpecs::DATA[:in_module].should == 'foo'
MainSpecs::DATA[:toplevel].should == 'foo' MainSpecs::DATA[:toplevel].should == 'foo'
@ -25,6 +25,7 @@ ruby_version_is "2.0.0" do
end end
it "uses refinements from the given module for method calls in the target file" do 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__) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
lambda do lambda do
'hello'.foo 'hello'.foo

View file

@ -1,10 +0,0 @@
module ModuleSpecs
module EmptyRefinement
end
module RefinementForStringToS
refine String do
def to_s; "hello from refinement"; end
end
end
end

View file

@ -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('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/refine', __FILE__) require File.expand_path('../fixtures/refine', __FILE__)
@ -87,6 +84,7 @@ describe "Module#refine" do
end end
end end
quarantine! do # https://bugs.ruby-lang.org/issues/14070
ruby_version_is "2.4" do ruby_version_is "2.4" do
it "accepts a module as argument" do it "accepts a module as argument" do
inner_self = nil inner_self = nil
@ -101,6 +99,7 @@ describe "Module#refine" do
inner_self.public_instance_methods.should include(:blah) inner_self.public_instance_methods.should include(:blah)
end end
end end
end
it "raises ArgumentError if not given a block" do it "raises ArgumentError if not given a block" do
lambda do lambda do
@ -616,4 +615,3 @@ describe "Module#refine" do
end end
end end
end end

View file

@ -1,5 +1,4 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/using', __FILE__)
describe "Module#using" do describe "Module#using" do
it "imports class refinements from module into the current class/module" 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 it "raises error in method scope" do
mod = Module.new do mod = Module.new do
def self.foo def self.foo
using ModuleSpecs::EmptyRefinement using Module.new {}
end end
end end
@ -156,7 +155,11 @@ describe "Module#using" do
Module.new do Module.new do
Class.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 ScratchPad << "1".to_s
end end
@ -175,7 +178,11 @@ describe "Module#using" do
Module.new do Module.new do
Class.new do Class.new do
ScratchPad << "1".to_s 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 ScratchPad << "1".to_s
end end
end end
@ -241,7 +248,11 @@ describe "Module#using" do
Module.new do Module.new do
if false if false
using ModuleSpecs::RefinementForStringToS using Module.new {
refine String do
def to_s; "hello from refinement"; end
end
}
end end
result = "1".to_s result = "1".to_s
end end

View file

@ -25,9 +25,11 @@ describe "Mutex#sleep" do
m = Mutex.new m = Mutex.new
m.lock m.lock
duration = 0.1 duration = 0.1
start = Time.now start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
m.sleep duration 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 end
it "unlocks the mutex while sleeping" do it "unlocks the mutex while sleeping" do
@ -71,4 +73,23 @@ describe "Mutex#sleep" do
m.lock m.lock
m.sleep(0.01).should be_kind_of(Integer) m.sleep(0.01).should be_kind_of(Integer)
end 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 end

View file

@ -10,17 +10,24 @@ describe "Process.groups" do
actual = (Process.groups - [gid]).sort actual = (Process.groups - [gid]).sort
actual.should == expected actual.should == expected
end end
end
end
# NOTE: This is kind of sketchy. 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 it "sets the list of gids of groups in the supplemental group access list" do
groups = Process.groups groups = Process.groups
if Process.uid == 0
Process.groups = [] Process.groups = []
Process.groups.should == [] Process.groups.should == []
Process.groups = groups Process.groups = groups
Process.groups.sort.should == groups.sort Process.groups.sort.should == groups.sort
else end
end
as_user do
platform_is :aix 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, # setgroups() is not part of the POSIX standard,
# so its behavior varies from OS to OS. AIX allows a non-root # so its behavior varies from OS to OS. AIX allows a non-root
# process to set the supplementary group IDs, as long as # 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 # it should no longer be able to set any supplementary
# group IDs, even if it originally belonged to them. # group IDs, even if it originally belonged to them.
# It should only be able to set its primary group ID. # It should only be able to set its primary group ID.
groups = Process.groups
Process.groups = groups Process.groups = groups
Process.groups.sort.should == groups.sort Process.groups.sort.should == groups.sort
Process.groups = [] Process.groups = []
@ -41,14 +49,16 @@ describe "Process.groups" do
lambda { Process.groups = supplementary }.should raise_error(Errno::EPERM) lambda { Process.groups = supplementary }.should raise_error(Errno::EPERM)
end end
end end
platform_is_not :aix do
lambda { Process.groups = [] }.should raise_error(Errno::EPERM)
end
end
end
end
end end
describe "Process.groups=" do platform_is_not :aix do
it "needs to be reviewed for spec completeness" it "raises Errno::EPERM" do
groups = Process.groups
lambda {
Process.groups = groups
}.should raise_error(Errno::EPERM)
end
end
end
end
end end

View file

@ -137,6 +137,7 @@ describe "String#index with String" do
"hello".index("he", 1).should == nil "hello".index("he", 1).should == nil
"hello".index("he", 2).should == nil "hello".index("he", 2).should == nil
"Ive got a multibyte character.\n".index("\n\n").should == nil
end end
with_feature :encoding do with_feature :encoding do

View file

@ -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

View file

@ -17,8 +17,13 @@ describe "Thread#thread_variables" do
end end
it "sets a value private to self" do it "sets a value private to self" do
@t.thread_variable_set :thread_variables_spec_a, 82 @t.thread_variable_set :a, 82
@t.thread_variable_set :thread_variables_spec_b, 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 == [] Thread.current.thread_variables.should == []
@t.thread_variables.should == []
end end
end end

View file

@ -3,7 +3,6 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Time#round" do describe "Time#round" do
before do before do
@time = Time.utc(2010, 3, 30, 5, 43, "25.123456789".to_r) @time = Time.utc(2010, 3, 30, 5, 43, "25.123456789".to_r)
@subclass = Class.new(Time).now
end end
it "defaults to rounding to 0 places" do it "defaults to rounding to 0 places" do
@ -19,7 +18,10 @@ describe "Time#round" do
end end
it "returns an instance of Time, even if #round is called on a subclass" do 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 end
it "copies own timezone to the returning value" do it "copies own timezone to the returning value" do

View file

@ -19,4 +19,11 @@ describe :time_gm, shared: true do
it "interprets post-Gregorian reform dates using Gregorian calendar" do it "interprets post-Gregorian reform dates using Gregorian calendar" do
Time.send(@method, 1582, 10, 15, 12).to_i.should == -12219249600 # 2299161j Time.send(@method, 1582, 10, 15, 12).to_i.should == -12219249600 # 2299161j
end 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 end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -4,5 +4,31 @@ module TracePointSpec
end end
alias_method :m_alias, :m alias_method :m_alias, :m
end end
module A
def bar; end
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

View file

@ -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 ==
'#<TracePoint:disabled>'
end
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -29,4 +29,8 @@ describe "The BEGIN keyword" do
ScratchPad.recorded.should == ['foo', 'bar'] ScratchPad.recorded.should == ['foo', 'bar']
end 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 end

View file

@ -24,6 +24,24 @@ describe "The break statement in a block" do
value.should == :value value.should == :value
end end
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 end
describe "The break statement in a captured block" do describe "The break statement in a captured block" do

View file

@ -375,6 +375,28 @@ describe "Constant resolution within methods" do
end end
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 end
describe "Constant resolution within a singleton class (class << obj)" do describe "Constant resolution within a singleton class (class << obj)" do

View file

@ -750,7 +750,7 @@ describe "The defined? keyword for a scoped constant" do
end end
it "returns nil when an undefined constant is scoped to a defined constant" do 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 end
it "returns nil when a constant is scoped to an undefined constant" do 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 end
it "returns nil when an undefined constant is scoped to a defined constant" do 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 end
it "returns nil when the undefined constant is scoped to an undefined constant" do it "returns nil when the undefined constant is scoped to an undefined constant" do

View file

@ -0,0 +1,3 @@
BEGIN {
puts __FILE__
}

View file

@ -106,6 +106,34 @@ module BreakSpecs
note :d note :d
end 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) def method(v)
yield v yield v
end end

View file

@ -291,10 +291,20 @@ describe "The rescue keyword" do
end.should == :expected end.should == :expected
end 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 ruby_version_is "2.4" do
it "allows 'rescue' in method arguments" do it "allows 'rescue' in method arguments" do
two = eval '1.+ (raise("Error") rescue 1)' two = eval '1.+ (raise("Error") rescue 1)'
two.should == 2 two.should == 2
end 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
end end

View file

@ -409,6 +409,39 @@ describe "The return keyword" do
end end
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 describe "file loading" do
it "stops file loading and execution" do it "stops file loading and execution" do
File.write(@filename, <<-END_OF_CODE) File.write(@filename, <<-END_OF_CODE)

View file

@ -11,20 +11,35 @@ describe "BigDecimal.limit" do
BigDecimal.limit(old) BigDecimal.limit(old)
end 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 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('0')).should == BigDecimal('0.888')
(BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664') (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664')
(BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.296')
end end
BigDecimalSpecs.with_limit(1) do 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('0')).should == BigDecimal('0.9')
(BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3') (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3')
(BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.3')
end end
BigDecimalSpecs.with_limit(2) do 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('0')).should == BigDecimal('0.89')
(BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.7') (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 end
end end

View file

@ -34,9 +34,13 @@ describe "Date constants" do
it "freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES" do it "freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES" do
[Date::MONTHNAMES, Date::DAYNAMES, Date::ABBR_MONTHNAMES, Date::ABBR_DAYNAMES].each do |ary| [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| ary.compact.each do |name|
lambda { name << "modified" }.should raise_error lambda {
name << "modified"
}.should raise_error(RuntimeError, /frozen/)
end end
end end
end end

View file

@ -13,15 +13,6 @@ describe "Date#<<" do
d.should == Date.civil(2008, 2, 29) d.should == Date.civil(2008, 2, 29)
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
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 ruby_version_is "2.3" do
it "raises an error on non numeric parameters" do it "raises an error on non numeric parameters" do
lambda { Date.civil(2007,2,27) << :hello }.should raise_error(TypeError) lambda { Date.civil(2007,2,27) << :hello }.should raise_error(TypeError)

View file

@ -7,7 +7,7 @@ describe "DateTime.now" do
end end
it "sets the current date" do 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 end
it "sets the current time" do it "sets the current time" do

View file

@ -6,6 +6,18 @@ describe "DateTime#to_time" do
DateTime.now.to_time.should be_kind_of(Time) DateTime.now.to_time.should be_kind_of(Time)
end 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 ruby_version_is "2.4" do
it "preserves the same time regardless of local time or zone" do it "preserves the same time regardless of local time or zone" do
date = DateTime.new(2012, 12, 24, 12, 23, 00, '+03:00') date = DateTime.new(2012, 12, 24, 12, 23, 00, '+03:00')

View file

@ -65,7 +65,7 @@ END
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' input = <<'END'
<p> <p>
@ -74,7 +74,9 @@ END
</p> </p>
END END
lambda { ERB.new(input, nil, '-').result }.should raise_error lambda {
ERB.new(input, nil, '-').result
}.should raise_error(SyntaxError)
end end
it "regards lines starting with '%' as '<% ... %>' when trim_mode is '%'" do it "regards lines starting with '%' as '<% ... %>' when trim_mode is '%'" do

View file

@ -1,11 +1,9 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require 'etc' require 'etc'
ruby_version_is "2.2" do
describe "Etc.nprocessors" do describe "Etc.nprocessors" do
it "returns the number of online processors" do it "returns the number of online processors" do
Etc.nprocessors.should be_kind_of(Integer) Etc.nprocessors.should be_kind_of(Integer)
Etc.nprocessors.should >= 1 Etc.nprocessors.should >= 1
end end
end end
end

View file

@ -8,9 +8,13 @@ describe "OpenSSL::Config#freeze" do
it "freezes" do it "freezes" do
c = OpenSSL::Config.new 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.freeze
c.frozen?.should be_true c.frozen?.should be_true
lambda{c['foo'] = [ ['key', 'value'] ]}.should raise_error lambda {
c['foo'] = [ ['key', 'value'] ]
}.should raise_error(TypeError)
end end
end end

View file

@ -16,7 +16,9 @@ describe "Socket::IPSocket#peeraddr" do
end end
it "raises error if socket is not connected" do it "raises error if socket is not connected" do
lambda { @server.peeraddr }.should raise_error lambda {
@server.peeraddr
}.should raise_error(Errno::ENOTCONN)
end end
it "returns an array of information on the peer" do it "returns an array of information on the peer" do

View file

@ -21,7 +21,9 @@ describe "UNIXSocket#peeraddr" do
end end
it "raises an error in server sockets" do it "raises an error in server sockets" do
lambda { @server.peeraddr }.should raise_error lambda {
@server.peeraddr
}.should raise_error(Errno::ENOTCONN)
end end
end end

View file

@ -1,5 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__) require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../../../core/kernel/shared/sprintf', __FILE__)
describe "StringIO#printf" do describe "StringIO#printf" do
before :each do before :each do
@ -28,6 +29,14 @@ describe "StringIO#printf" do
@io.printf("%d %04x", 123, 123) @io.printf("%d %04x", 123, 123)
@io.pos.should eql(16) @io.pos.should eql(16)
end end
describe "formatting" do
it_behaves_like :kernel_sprintf, -> (format, *args) {
io = StringIO.new
io.printf(format, *args)
io.string
}
end
end end
describe "StringIO#printf when in append mode" do 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) lambda { io.printf("test") }.should raise_error(IOError)
end end
end end

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.close" do describe "Syslog.close" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog::Constants" do describe "Syslog::Constants" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.facility" do describe "Syslog.facility" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.ident" do describe "Syslog.ident" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.inspect" do describe "Syslog.inspect" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.instance" do describe "Syslog.instance" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.log" do describe "Syslog.log" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.mask" do describe "Syslog.mask" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/reopen', __FILE__) require File.expand_path('../shared/reopen', __FILE__)
require 'syslog' require 'syslog'
@ -73,8 +74,13 @@ platform_is_not :windows do
it "raises an error if the log is opened" do it "raises an error if the log is opened" do
Syslog.open Syslog.open
lambda { Syslog.open}.should raise_error lambda {
lambda { Syslog.close; Syslog.open }.should_not raise_error Syslog.open
}.should raise_error(RuntimeError, /syslog already open/)
lambda {
Syslog.close
Syslog.open
}.should_not raise_error
Syslog.close Syslog.close
end end
end end

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.opened?" do describe "Syslog.opened?" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require 'syslog' require 'syslog'
describe "Syslog.options" do describe "Syslog.options" do

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/reopen', __FILE__) require File.expand_path('../shared/reopen', __FILE__)
require 'syslog' require 'syslog'

View file

@ -1,5 +1,6 @@
platform_is_not :windows do
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
platform_is_not :windows do
require File.expand_path('../shared/log', __FILE__) require File.expand_path('../shared/log', __FILE__)
require 'syslog' require 'syslog'

View file

@ -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

View file

@ -21,7 +21,9 @@ describe "URI.join" do
end end
it "raises an error if given no argument" do it "raises an error if given no argument" do
lambda{ URI.join }.should raise_error lambda {
URI.join
}.should raise_error(ArgumentError)
end end
it "doesn't create redundant '/'s" do it "doesn't create redundant '/'s" do

View file

@ -18,7 +18,9 @@ describe :uri_join, shared: true do
end end
it "raises an error if given no argument" do it "raises an error if given no argument" do
lambda{ @object.join }.should raise_error lambda {
@object.join
}.should raise_error(ArgumentError)
end end
it "doesn't create redundant '/'s" do it "doesn't create redundant '/'s" do

View file

@ -34,6 +34,27 @@ describe "YAML.load" do
end end
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 it "fails on invalid keys" do
if YAML.to_s == "Psych" if YAML.to_s == "Psych"
error = Psych::SyntaxError error = Psych::SyntaxError

View file

@ -96,6 +96,12 @@ static VALUE numeric_spec_rb_num_coerce_relop(VALUE self, VALUE x, VALUE y, VALU
} }
#endif #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) { void Init_numeric_spec(void) {
VALUE cls; VALUE cls;
cls = rb_define_class("CApiNumericSpecs", rb_cObject); cls = rb_define_class("CApiNumericSpecs", rb_cObject);
@ -159,6 +165,10 @@ void Init_numeric_spec(void) {
#ifdef HAVE_RB_NUM_COERCE_RELOP #ifdef HAVE_RB_NUM_COERCE_RELOP
rb_define_method(cls, "rb_num_coerce_relop", numeric_spec_rb_num_coerce_relop, 3); rb_define_method(cls, "rb_num_coerce_relop", numeric_spec_rb_num_coerce_relop, 3);
#endif #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 #ifdef __cplusplus

View file

@ -5,6 +5,32 @@
extern "C" { extern "C" {
#endif #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 #ifdef HAVE_OBJ_TAINT
static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) { static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) {
OBJ_TAINT(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 #ifdef HAVE_RB_SPECIAL_CONST_P
static VALUE object_spec_rb_special_const_p(VALUE self, VALUE value) { 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 #endif
@ -404,6 +434,14 @@ void Init_object_spec(void) {
VALUE cls; VALUE cls;
cls = rb_define_class("CApiObjectSpecs", rb_cObject); 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 #ifdef HAVE_OBJ_TAINT
rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1); rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1);
#endif #endif

View file

@ -422,6 +422,7 @@
#define HAVE_RB_NUM_COERCE_BIN 1 #define HAVE_RB_NUM_COERCE_BIN 1
#define HAVE_RB_NUM_COERCE_CMP 1 #define HAVE_RB_NUM_COERCE_CMP 1
#define HAVE_RB_NUM_COERCE_RELOP 1 #define HAVE_RB_NUM_COERCE_RELOP 1
#define HAVE_RB_ABSINT_SINGLEBIT_P 1
#define HAVE_RB_NUM_ZERODIV 1 #define HAVE_RB_NUM_ZERODIV 1
/* Fixnum */ /* Fixnum */
@ -431,6 +432,8 @@
#endif #endif
/* Object */ /* Object */
#define HAVE_FL_ABLE 1
#define HAVE_FL_TEST 1
#define HAVE_OBJ_TAINT 1 #define HAVE_OBJ_TAINT 1
#define HAVE_OBJ_TAINTED 1 #define HAVE_OBJ_TAINTED 1
#define HAVE_OBJ_INFECT 1 #define HAVE_OBJ_INFECT 1

View file

@ -429,4 +429,19 @@ describe "CApiNumericSpecs" do
lambda { @s.rb_num_coerce_relop(2, obj, :<) }.should raise_error(ArgumentError) lambda { @s.rb_num_coerce_relop(2, obj, :<) }.should raise_error(ArgumentError)
end end
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 end

Some files were not shown because too many files have changed in this diff Show more