summaryrefslogtreecommitdiff
path: root/spec/ruby/core/kernel/Float_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/kernel/Float_spec.rb')
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb252
1 files changed, 162 insertions, 90 deletions
diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 43daefa6aa..9c436b05f7 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -22,7 +22,7 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for nil" do
- lambda { @object.send(:Float, nil) }.should raise_error(TypeError)
+ -> { @object.send(:Float, nil) }.should raise_error(TypeError)
end
it "returns the identical NaN for NaN" do
@@ -41,7 +41,7 @@ describe :kernel_float, shared: true do
end
it "converts Strings to floats without calling #to_f" do
- string = "10"
+ string = +"10"
string.should_not_receive(:to_f)
@object.send(:Float, string).should == 10.0
end
@@ -51,24 +51,30 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for a String of word characters" do
- lambda { @object.send(:Float, "float") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "float") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError for a String with string in error message" do
+ -> { @object.send(:Float, "foo") }.should raise_error(ArgumentError) { |e|
+ e.message.should == 'invalid value for Float(): "foo"'
+ }
end
it "raises an ArgumentError if there are two decimal points in the String" do
- lambda { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String of numbers followed by word characters" do
- lambda { @object.send(:Float, "10D") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10D") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String of word characters followed by numbers" do
- lambda { @object.send(:Float, "D10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "D10") }.should raise_error(ArgumentError)
end
it "is strict about the string form even across newlines" do
- lambda { @object.send(:Float, "not a number\n10") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "10\nnot a number") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "not a number\n10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10\nnot a number") }.should raise_error(ArgumentError)
end
it "converts String subclasses to floats without calling #to_f" do
@@ -90,17 +96,17 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError if a + or - is embedded in a String" do
- lambda { @object.send(:Float, "1+1") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "1-1") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1+1") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1-1") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if a String has a trailing + or -" do
- lambda { @object.send(:Float, "11+") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "11-") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "11+") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "11-") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String with a leading _" do
- lambda { @object.send(:Float, "_1") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "_1") }.should raise_error(ArgumentError)
end
it "returns a value for a String with an embedded _" do
@@ -108,31 +114,31 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for a String with a trailing _" do
- lambda { @object.send(:Float, "10_") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10_") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String of \\0" do
- lambda { @object.send(:Float, "\0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "\0") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String with a leading \\0" do
- lambda { @object.send(:Float, "\01") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "\01") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String with an embedded \\0" do
- lambda { @object.send(:Float, "1\01") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1\01") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String with a trailing \\0" do
- lambda { @object.send(:Float, "1\0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1\0") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String that is just an empty space" do
- lambda { @object.send(:Float, " ") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, " ") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for a String that with an embedded space" do
- lambda { @object.send(:Float, "1 2") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1 2") }.should raise_error(ArgumentError)
end
it "returns a value for a String with a leading space" do
@@ -151,13 +157,33 @@ describe :kernel_float, shared: true do
@object.send(:Float, "1\t\n").should == 1.0
end
+ ruby_version_is ""..."3.4" do
+ it "raises ArgumentError if a fractional part is missing" do
+ -> { @object.send(:Float, "1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "+1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "-1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1.e+0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1.e-2") }.should raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "allows String representation without a fractional part" do
+ @object.send(:Float, "1.").should == 1.0
+ @object.send(:Float, "+1.").should == 1.0
+ @object.send(:Float, "-1.").should == -1.0
+ @object.send(:Float, "1.e+0").should == 1.0
+ @object.send(:Float, "1.e-2").should be_close(0.01, TOLERANCE)
+ end
+ end
+
%w(e E).each do |e|
it "raises an ArgumentError if #{e} is the trailing character" do
- lambda { @object.send(:Float, "2#{e}") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "2#{e}") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if #{e} is the leading character" do
- lambda { @object.send(:Float, "#{e}2") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "#{e}2") }.should raise_error(ArgumentError)
end
it "returns Infinity for '2#{e}1000'" do
@@ -175,18 +201,18 @@ describe :kernel_float, shared: true do
end
it "raises an exception if a space is embedded on either side of the '#{e}'" do
- lambda { @object.send(:Float, "2 0#{e}100") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "20#{e}1 00") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "2 0#{e}100") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20#{e}1 00") }.should raise_error(ArgumentError)
end
it "raises an exception if there's a leading _ on either side of the '#{e}'" do
- lambda { @object.send(:Float, "_20#{e}100") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "20#{e}_100") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "_20#{e}100") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20#{e}_100") }.should raise_error(ArgumentError)
end
it "raises an exception if there's a trailing _ on either side of the '#{e}'" do
- lambda { @object.send(:Float, "20_#{e}100") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "20#{e}100_") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20_#{e}100") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20#{e}100_") }.should raise_error(ArgumentError)
end
it "allows decimal points on the left side of the '#{e}'" do
@@ -194,63 +220,111 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError if there's a decimal point on the right side of the '#{e}'" do
- lambda { @object.send(:Float, "20#{e}2.0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20#{e}2.0") }.should raise_error(ArgumentError)
end
end
- describe "for hexadecimal literals with binary exponent" do
- %w(p P).each do |p|
- it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
- @object.send(:Float, "0x10#{p}0").should == 16.0
- end
+ context "for hexadecimal literals" do
+ it "interprets the 0x prefix as hexadecimal" do
+ @object.send(:Float, "0x10").should == 16.0
+ @object.send(:Float, "0x0F").should == 15.0
+ @object.send(:Float, "0x0f").should == 15.0
+ end
- it "interprets the exponent (on the right of '#{p}') in decimal" do
- @object.send(:Float, "0x1#{p}10").should == 1024.0
- end
+ it "interprets negative hex value" do
+ @object.send(:Float, "-0x10").should == -16.0
+ end
- it "raises an ArgumentError if #{p} is the trailing character" do
- lambda { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
- end
+ it "accepts embedded _ if the number does not contain a-f" do
+ @object.send(:Float, "0x1_0").should == 16.0
+ end
- it "raises an ArgumentError if #{p} is the leading character" do
- lambda { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
+ ruby_version_is ""..."3.4.3" do
+ it "does not accept embedded _ if the number contains a-f" do
+ -> { @object.send(:Float, "0x1_0a") }.should raise_error(ArgumentError)
+ @object.send(:Float, "0x1_0a", exception: false).should be_nil
end
+ end
- it "returns Infinity for '0x1#{p}10000'" do
- @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
+ ruby_version_is "3.4.3" do
+ it "accepts embedded _ if the number contains a-f" do
+ @object.send(:Float, "0x1_0a").should == 0x10a.to_f
end
+ end
- it "returns 0 for '0x1#{p}-10000'" do
- @object.send(:Float, "0x1#{p}-10000").should == 0
- end
+ it "does not accept _ before, after or inside the 0x prefix" do
+ -> { @object.send(:Float, "_0x10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0_x10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x_10") }.should raise_error(ArgumentError)
+ @object.send(:Float, "_0x10", exception: false).should be_nil
+ @object.send(:Float, "0_x10", exception: false).should be_nil
+ @object.send(:Float, "0x_10", exception: false).should be_nil
+ end
- it "allows embedded _ in a number on either side of the #{p}" do
- @object.send(:Float, "0x1_0#{p}10").should == 16384.0
- @object.send(:Float, "0x10#{p}1_0").should == 16384.0
- @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
- end
+ it "parses negative hexadecimal string as negative float" do
+ @object.send(:Float, "-0x7b").should == -123.0
+ end
- it "raises an exception if a space is embedded on either side of the '#{p}'" do
- lambda { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ ruby_version_is "3.4" do
+ it "accepts a fractional part" do
+ @object.send(:Float, "0x0.8").should == 0.5
end
+ end
- it "raises an exception if there's a leading _ on either side of the '#{p}'" do
- lambda { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
- end
+ describe "with binary exponent" do
+ %w(p P).each do |p|
+ it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
+ @object.send(:Float, "0x10#{p}0").should == 16.0
+ end
- it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
- lambda { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
- lambda { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
- end
+ it "interprets the exponent (on the right of '#{p}') in decimal" do
+ @object.send(:Float, "0x1#{p}10").should == 1024.0
+ end
- it "allows hexadecimal points on the left side of the '#{p}'" do
- @object.send(:Float, "0x1.8#{p}0").should == 1.5
- end
+ it "raises an ArgumentError if #{p} is the trailing character" do
+ -> { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if #{p} is the leading character" do
+ -> { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
+ end
+
+ it "returns Infinity for '0x1#{p}10000'" do
+ @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
+ end
+
+ it "returns 0 for '0x1#{p}-10000'" do
+ @object.send(:Float, "0x1#{p}-10000").should == 0
+ end
+
+ it "allows embedded _ in a number on either side of the #{p}" do
+ @object.send(:Float, "0x1_0#{p}10").should == 16384.0
+ @object.send(:Float, "0x10#{p}1_0").should == 16384.0
+ @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ end
+
+ it "raises an exception if a space is embedded on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ end
- it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
- lambda { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ it "raises an exception if there's a leading _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
+ end
+
+ it "allows hexadecimal points on the left side of the '#{p}'" do
+ @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ end
+
+ it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ end
end
end
end
@@ -274,7 +348,7 @@ describe :kernel_float, shared: true do
nan2.should equal(nan)
end
- it "returns the identical Infinity if to_f is called and it returns Infinity" do
+ it "returns the identical Infinity if #to_f is called and it returns Infinity" do
infinity = infinity_value
(infinity_to_f = mock('Infinity')).should_receive(:to_f).once.and_return(infinity)
infinity2 = @object.send(:Float, infinity_to_f)
@@ -282,45 +356,43 @@ describe :kernel_float, shared: true do
end
it "raises a TypeError if #to_f is not provided" do
- lambda { @object.send(:Float, mock('x')) }.should raise_error(TypeError)
+ -> { @object.send(:Float, mock('x')) }.should raise_error(TypeError)
end
it "raises a TypeError if #to_f returns a String" do
(obj = mock('ha!')).should_receive(:to_f).once.and_return('ha!')
- lambda { @object.send(:Float, obj) }.should raise_error(TypeError)
+ -> { @object.send(:Float, obj) }.should raise_error(TypeError)
end
it "raises a TypeError if #to_f returns an Integer" do
(obj = mock('123')).should_receive(:to_f).once.and_return(123)
- lambda { @object.send(:Float, obj) }.should raise_error(TypeError)
+ -> { @object.send(:Float, obj) }.should raise_error(TypeError)
end
it "raises a RangeError when passed a Complex argument" do
c = Complex(2, 3)
- lambda { @object.send(:Float, c) }.should raise_error(RangeError)
+ -> { @object.send(:Float, c) }.should raise_error(RangeError)
end
- ruby_version_is "2.6" do
- describe "when passed exception: false" do
- describe "and valid input" do
- it "returns a Float number" do
- @object.send(:Float, 1, exception: false).should == 1.0
- @object.send(:Float, "1", exception: false).should == 1.0
- @object.send(:Float, "1.23", exception: false).should == 1.23
- end
+ describe "when passed exception: false" do
+ describe "and valid input" do
+ it "returns a Float number" do
+ @object.send(:Float, 1, exception: false).should == 1.0
+ @object.send(:Float, "1", exception: false).should == 1.0
+ @object.send(:Float, "1.23", exception: false).should == 1.23
end
+ end
- describe "and invalid input" do
- it "swallows an error" do
- @object.send(:Float, "abc", exception: false).should == nil
- @object.send(:Float, :sym, exception: false).should == nil
- end
+ describe "and invalid input" do
+ it "swallows an error" do
+ @object.send(:Float, "abc", exception: false).should == nil
+ @object.send(:Float, :sym, exception: false).should == nil
end
+ end
- describe "and nil" do
- it "swallows it" do
- @object.send(:Float, nil, exception: false).should == nil
- end
+ describe "and nil" do
+ it "swallows it" do
+ @object.send(:Float, nil, exception: false).should == nil
end
end
end