[前][次][番号順一覧][スレッド一覧]

ruby-changes:30765

From: drbrain <ko1@a...>
Date: Thu, 5 Sep 2013 14:02:25 +0900 (JST)
Subject: [ruby-changes:30765] drbrain:r42844 (trunk): * lib/optparse.rb: The Integer acceptable now allows binary and

drbrain	2013-09-05 14:02:17 +0900 (Thu, 05 Sep 2013)

  New Revision: 42844

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42844

  Log:
    * lib/optparse.rb:  The Integer acceptable now allows binary and
      hexadecimal numbers per the documentation.  [ruby-trunk - Bug #8865]
    
      DecimalInteger, OctalInteger, DecimalNumeric now validate their input
      before converting to a number.  [ruby-trunk - Bug #8865]
    
    * test/optparse/test_acceptable.rb:  Tests for the above, tests for all
      numeric acceptables for existing behavior.

  Added files:
    trunk/test/optparse/test_acceptable.rb
  Modified files:
    trunk/ChangeLog
    trunk/lib/optparse.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42843)
+++ ChangeLog	(revision 42844)
@@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Sep  5 14:01:22 2013  Eric Hodel  <drbrain@s...>
+
+	* lib/optparse.rb:  The Integer acceptable now allows binary and
+	  hexadecimal numbers per the documentation.  [ruby-trunk - Bug #8865]
+
+	  DecimalInteger, OctalInteger, DecimalNumeric now validate their input
+	  before converting to a number.  [ruby-trunk - Bug #8865]
+
+	* test/optparse/test_acceptable.rb:  Tests for the above, tests for all
+	  numeric acceptables for existing behavior.
+
 Thu Sep  5 13:49:00 2013  Charlie Somerville  <charliesome@r...>
 
 	* include/ruby/ruby.h: add RSTRING_FSTR flag
Index: lib/optparse.rb
===================================================================
--- lib/optparse.rb	(revision 42843)
+++ lib/optparse.rb	(revision 42844)
@@ -1637,15 +1637,22 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1637
   decimal = '\d+(?:_\d+)*'
   binary = 'b[01]+(?:_[01]+)*'
   hex = 'x[\da-f]+(?:_[\da-f]+)*'
-  octal = "0(?:[0-7]*(?:_[0-7]+)*|#{binary}|#{hex})"
+  octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?"
   integer = "#{octal}|#{decimal}"
-  accept(Integer, %r"\A[-+]?(?:#{integer})"io) {|s,| Integer(s) if s}
+
+  accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,|
+    begin
+      Integer(s)
+    rescue ArgumentError
+      raise OptionParser::InvalidArgument, s
+    end if s
+  }
 
   #
   # Float number format, and converts to Float.
   #
   float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
-  floatpat = %r"\A[-+]?#{float}"io
+  floatpat = %r"\A[-+]?#{float}\z"io
   accept(Float, floatpat) {|s,| s.to_f if s}
 
   #
@@ -1653,7 +1660,7 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1660
   # for float format, and Rational for rational format.
   #
   real = "[-+]?(?:#{octal}|#{float})"
-  accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n|
+  accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, n|
     if n
       Rational(d, n)
     elsif s
@@ -1664,22 +1671,40 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1671
   #
   # Decimal integer format, to be converted to Integer.
   #
-  DecimalInteger = /\A[-+]?#{decimal}/io
-  accept(DecimalInteger) {|s,| s.to_i if s}
+  DecimalInteger = /\A[-+]?#{decimal}\z/io
+  accept(DecimalInteger, DecimalInteger) {|s,|
+    begin
+      Integer(s)
+    rescue ArgumentError
+      raise OptionParser::InvalidArgument, s
+    end if s
+  }
 
   #
   # Ruby/C like octal/hexadecimal/binary integer format, to be converted to
   # Integer.
   #
-  OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io
-  accept(OctalInteger) {|s,| s.oct if s}
+  OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io
+  accept(OctalInteger, OctalInteger) {|s,|
+    begin
+      Integer(s, 8)
+    rescue ArgumentError
+      raise OptionParser::InvalidArgument, s
+    end if s
+  }
 
   #
   # Decimal integer/float number format, to be converted to Integer for
   # integer format, Float for float format.
   #
   DecimalNumeric = floatpat     # decimal integer is allowed as float also.
-  accept(DecimalNumeric) {|s,| eval(s) if s}
+  accept(DecimalNumeric, floatpat) {|s,|
+    begin
+      eval(s)
+    rescue SyntaxError
+      raise OptionParser::InvalidArgument, s
+    end if s
+  }
 
   #
   # Boolean switch, which means whether it is present or not, whether it is
Index: test/optparse/test_acceptable.rb
===================================================================
--- test/optparse/test_acceptable.rb	(revision 0)
+++ test/optparse/test_acceptable.rb	(revision 42844)
@@ -0,0 +1,195 @@ https://github.com/ruby/ruby/blob/trunk/test/optparse/test_acceptable.rb#L1
+require_relative 'test_optparse'
+
+class TestOptionParser::Acceptable < TestOptionParser
+
+  def setup
+    super
+    @opt.def_option("--integer VAL", Integer) { |v| @integer = v }
+    @opt.def_option("--float VAL",   Float)   { |v| @float   = v }
+    @opt.def_option("--numeric VAL", Numeric) { |v| @numeric = v }
+
+    @opt.def_option("--decimal-integer VAL",
+                    OptionParser::DecimalInteger) { |i| @decimal_integer = i }
+    @opt.def_option("--octal-integer VAL",
+                    OptionParser::OctalInteger)   { |i| @octal_integer   = i }
+    @opt.def_option("--decimal-numeric VAL",
+                    OptionParser::DecimalNumeric) { |i| @decimal_numeric = i }
+  end
+
+  def test_integer
+    assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0")})
+    assert_equal(0, @integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0b10")})
+    assert_equal(2, @integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--integer 077")})
+    assert_equal(63, @integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--integer 10")})
+    assert_equal(10, @integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0x3")})
+    assert_equal(3, @integer)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--integer 0b")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--integer 09")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--integer 0x")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--integer 1234xyz")
+    end
+  end
+
+  def test_float
+    assert_equal(%w"", no_error {@opt.parse!(%w"--float 0")})
+    assert_in_epsilon(0.0, @float)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--float 0.0")})
+    assert_in_epsilon(0.0, @float)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--float 1.2")})
+    assert_in_epsilon(1.2, @float)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E2")})
+    assert_in_epsilon(100, @float)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E-2")})
+    assert_in_epsilon(0.01, @float)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--float 0e")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--float 1.234xyz")
+    end
+  end
+
+  def test_numeric
+    assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0")})
+    assert_equal(0, @numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0/1")})
+    assert_equal(0, @numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1/2")})
+    assert_equal(Rational(1, 2), @numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1.2/2.3")})
+    assert_equal(Rational(12, 23), @numeric)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--numeric 1/")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--numeric 12/34xyz")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--numeric 12x/34yz")
+    end
+  end
+
+  def test_decimal_integer
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 0")})
+    assert_equal(0, @decimal_integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 10")})
+    assert_equal(10, @decimal_integer)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer 0b1")
+    end
+
+    e = assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer 09")
+    end
+
+    assert_equal("invalid argument: --decimal-integer 09", e.message)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer x")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer 1234xyz")
+    end
+  end
+
+  def test_octal_integer
+    assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 0")})
+    assert_equal(0, @octal_integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 6")})
+    assert_equal(6, @octal_integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 07")})
+    assert_equal(7, @octal_integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 10")})
+    assert_equal(8, @octal_integer)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 011")})
+    assert_equal(9, @octal_integer)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--octal-integer 09")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--octal-integer 0b1")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--octal-integer x")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--octal-integer 01234xyz")
+    end
+  end
+
+  def test_decimal_numeric
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 0")})
+    assert_equal(0, @decimal_numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 01")})
+    assert_equal(1, @decimal_numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1.2")})
+    assert_in_delta(1.2, @decimal_numeric)
+
+    assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1E2")})
+    assert_in_delta(100.0, @decimal_numeric)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-numeric 0b1")
+    end
+
+    e = assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-numeric 09")
+    end
+
+    assert_equal("invalid argument: --decimal-numeric 09", e.message)
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer 1234xyz")
+    end
+
+    assert_raises(OptionParser::InvalidArgument) do
+      @opt.parse!(%w"--decimal-integer 12.34xyz")
+    end
+  end
+
+end
+

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]