]> git.donarmstrong.com Git - biopieces.git/commitdiff
fixed unit tests for biopieces.rb
authormartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Mon, 14 Jun 2010 13:57:21 +0000 (13:57 +0000)
committermartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Mon, 14 Jun 2010 13:57:21 +0000 (13:57 +0000)
git-svn-id: http://biopieces.googlecode.com/svn/trunk@980 74ccb610-7750-0410-82ae-013aeee3265d

code_ruby/Maasha/lib/biopieces.rb
code_ruby/Maasha/test/test_biopieces.rb

index f1a448e02575b22d7ed83f051bd1c24a59a05b85..5f054f1bef8d8f256cc2e5d1a434d0463640cfc8 100644 (file)
@@ -12,73 +12,22 @@ require 'pp'
 # of lines with a key/value pair seperated by a colon and a white space ': '.
 # Each record is separated by a line with three dashes '---'.
 class Biopieces
-  REGEX_LIST   = /^(list|files|files!)$/
-  REGEX_INT    = /^(int|uint)$/
-  REGEX_STRING = /^(string|file|file!|dir|dir!|genome)$/
-
   # Initialize a Biopiece and write the status to file.
   # Options are for testing purposes only.
-  def initialize(no_status=nil,input=STDIN,output=STDOUT)
-    status_set unless no_status
+  def initialize(test=nil, input=STDIN, output=STDOUT)
+    @test   = test
     @input  = input
     @output = output
+    status_set unless @test
   end
 
   # Check the integrity of a list of casts, followed by parsion options from argv
-  # and finally checking the options according to the casts. Returns nil if
-  # argv is empty, otherwise an options hash.
-  def parse(argv,cast_list=[],script_path=$0)
-    casts = Casts.new(cast_list)
-    
-    pp casts
-
-    @script_path = script_path
-
-    @options = {}
-
-    options_template = OptionParser.new do |option|
-      casts.each do |cast|
-        if cast[:type] == 'flag'
-          option.on("-#{cast[:short]}", "--#{cast[:long]}") do |o|
-            @options[cast[:long]] = o
-          end
-        elsif cast[:type] =~ REGEX_LIST
-          option.on( "-#{cast[:short]}", "--#{cast[:long]} A", Array) do |a|
-            @options[cast[:long]] = a
-          end
-        elsif cast[:type] =~ REGEX_INT
-          option.on("-#{cast[:short]}", "--#{cast[:long]} I", Integer) do |i|
-            @options[cast[:long]] = i
-          end
-        elsif cast[:type] =~ REGEX_STRING
-          option.on("-#{cast[:short]}", "--#{cast[:long]} S", String) do |s|
-            @options[cast[:long]] = s
-          end
-        elsif cast[:type] == 'float'
-          option.on("-#{cast[:short]}", "--#{cast[:long]} F", Float) do |f|
-            @options[cast[:long]] = f
-          end
-        else
-          raise ArgumentError, "Unknown option type: '#{cast[:type]}'"
-        end
-      end
-    end
-
-    options_template.parse!(argv)
-
-    if print_usage_full?
-      print_usage_and_exit(true)
-      return # break for unit testing.
-    elsif print_usage_short?
-      print_usage_and_exit
-      return # break for unit testing.
-    end
-
-    options_default
-    options_glob
-    options_check
-
-    @options
+  # and finally checking the options according to the casts. Returns nil if argv
+  # is empty, otherwise an options hash.
+  def parse(argv, cast_list=[], script_path=$0)
+    casts          = Casts.new(cast_list)
+    option_handler = OptionHandler.new(argv, casts, script_path, @test)
+    @options       = option_handler.options_parse
   end
 
   # Open Biopiece input stream if not open and iterate over all Biopiece
@@ -129,198 +78,21 @@ class Biopieces
 
   private
 
-  # Given the script name determine the path of the wiki file with the usage info.
-  def wiki_path
-    path = ENV["BP_DIR"] + "/bp_usage/" + File.basename(@script_path, ".rb") + ".wiki"
-    raise "No such wiki file: #{path}" unless File.file? path
-
-    path
-  end
-
-  # Check if full "usage info" should be printed.
-  def print_usage_full?
-    @options["help"]
-  end
-
-  # Check if short "usage info" should be printed.
-  def print_usage_short?
-    if not $stdin.tty?
-      return false
-    elsif @options["stream_in"]
-      return false
-    elsif @options["data_in"]
-      return false
-    elsif wiki_path =~ /^(list_biopieces|list_genomes|list_mysql_databases|biostat)$/  # TODO get rid of this!
-      return false
-    else
-      return true
-    end
-  end
-
-  # Print usage info by Calling an external script 'print_wiki'
-  # using a system() call and exit. An optional 'full' flag
-  # outputs the full usage info.
-  def print_usage_and_exit(full=nil)
-    if full
-      system("print_wiki --data_in #{wiki_path} --help")
-    else
-      system("print_wiki --data_in #{wiki_path}")
-    end
-
-    raise "Failed printing wiki: #{wiki_path}" unless $?.success?
-
-    exit
-  end
-
-  # Set default options value from cast unless a value is set.
-  def options_default
-    casts.each do |cast|
-      if cast[:default]
-        @options[cast[:long]] = cast[:default] unless @options.has_key? cast[:long]
-      end
-    end
-  end
-
-  # Expands glob expressions to a full list of paths.
-  # Examples: "*.fna" or "foo.fna,*.fna" or "foo.fna,/bar/*.fna"
-  def options_glob
-    casts.each do |cast|
-      if cast[:type] == 'files' or cast[:type] == 'files!'
-        if @options.has_key? cast[:long]
-          files = []
-        
-          @options[cast[:long]].each do |path|
-            if path.include? "*"
-              Dir.glob(path).each do |file|
-                files << file if File.file? file
-              end
-            else
-              files << path
-            end
-          end
-
-          @options[cast[:long]] = files
-        end
-      end
-    end
-  end
-
-  # Check all options according to casts.
-  def options_check
-    casts.each do |cast|
-      options_check_mandatory(cast)
-      options_check_int(cast)
-      options_check_uint(cast)
-      options_check_file(cast)
-      options_check_files(cast)
-      options_check_dir(cast)
-      options_check_allowed(cast)
-      options_check_disallowed(cast)
-    end
-  end
-  
-  # Check if a mandatory option is set and raise if it isn't.
-  def options_check_mandatory(cast)
-    if cast[:mandatory]
-      raise ArgumentError, "Mandatory argument: --#{cast[:long]}" unless @options.has_key? cast[:long]
-    end
-  end
-
-  # Check int type option and raise if not an integer.
-  def options_check_int(cast)
-    if cast[:type] == 'int' and @options.has_key? cast[:long]
-      unless @options[cast[:long]].is_a? Integer
-        raise ArgumentError, "Argument to --#{cast[:long]} must be an integer, not '#{@options[cast[:long]]}'"
-      end
-    end
-  end
-  
-  # Check uint type option and raise if not an unsinged integer.
-  def options_check_uint(cast)
-    if cast[:type] == 'uint' and @options.has_key? cast[:long]
-      unless @options[cast[:long]].is_a? Integer and @options[cast[:long]] >= 0
-        raise ArgumentError, "Argument to --#{cast[:long]} must be an unsigned integer, not '#{@options[cast[:long]]}'"
-      end
-    end
-  end
-
-  # Check file! type argument and raise if file don't exists.
-  def options_check_file(cast)
-    if cast[:type] == 'file!' and @options.has_key? cast[:long]
-      raise ArgumentError, "No such file: '#{@options[cast[:long]]}'" unless File.file? @options[cast[:long]]
-    end
-  end
-
-  # Check files! type argument and raise if files don't exists.
-  def options_check_files(cast)
-    if cast[:type] == 'files!' and @options.has_key? cast[:long]
-      @options[cast[:long]].each do |path|
-        raise ArgumentError, "No such file: '#{path}'" unless File.file? path
-      end
-    end
-  end
-  
-  # Check dir! type argument and raise if directory don't exist.
-  def options_check_dir(cast)
-    if cast[:type] == 'dir!' and @options.has_key? cast[:long]
-      raise ArgumentError, "No such directory: '#{@options[cast[:long]]}'" unless File.directory? @options[cast[:long]]
-    end
-  end
-  
-  # Check options and raise unless allowed.
-  def options_check_allowed(cast)
-    if cast[:allowed] and @options.has_key? cast[:long]
-      allowed_hash = {}
-      cast[:allowed].split(',').each { |a| allowed_hash[a] = 1 }
-  
-      raise ArgumentError, "Argument '#{@options[cast[:long]]}' to --#{cast[:long]} not allowed" unless allowed_hash.has_key? @options[cast[:long]]
-    end
-  end
-  
-  # Check disallowed argument values and raise if disallowed.
-  def options_check_disallowed(cast)
-    if cast[:disallowed] and @options.has_key? cast[:long]
-      cast[:disallowed].split(',').each do |val|
-        raise ArgumentError, "Argument '#{@options[cast[:long]]}' to --#{cast[:long]} is disallowed" if val == @options[cast[:long]]
-      end
-    end
-  end
-
   # Open Biopieces input data stream for reading from either
   # stdin or from a list of files specified in options["stream_in"].
   def stream_in_open
-    if not $stdin.tty?
-      p "IN"
-      stream = @input
-    else
-      stream = read(@options["stream_in"])
-    end
-
-    stream
+    $stdin.tty? ? read(@options["stream_in"]) : @input
   end
 
   # Open Biopieces output data stream for writing to stdout
   # or a file specified in options["stream_out"].
   def stream_out_open
-    if @options["stream_out"]
-      stream = write(@options["stream_out"], @options["compress"])
-    else
-      p "OUT"
-      stream = @output
-    end
-
-    stream
+    @options["stream_out"] ? write(@options["stream_out"], @options["compress"]) : @output
   end
 
   # Opens a reads stream to a list of files.
   def read(files)
-    if zipped?(files)
-      stream = zread(files)
-    else
-      stream = nread(files)
-    end
-
-    stream
+    zipped?(files) ? zread(files) : nread(files)
   end
 
   # Opens a write stream to a file and returns a _io_ object.
@@ -452,10 +224,12 @@ class Biopieces
   end
 end
 
+
 # Error class for all exceptions to do with option casts.
 class CastError < StandardError
 end
 
+
 # Class to handle casts of command line options. Each cast prescribes the long and
 # short name of the option, the type, if it is mandatory, the default value, and
 # allowed and disallowed values. An optional list of extra casts can be supplied,
@@ -468,9 +242,11 @@ class Casts < Array
     @cast_list = cast_list
     ubiquitous
     check
-    self << @cast_list
+    self.push *@cast_list
   end
 
+  private
+
   # Add ubiquitous options casts.
   def ubiquitous
     @cast_list << {:long => 'help',       :short => '?', :type => 'flag',   :mandatory => false, :default => nil, :allowed => nil, :disallowed => nil}
@@ -577,4 +353,232 @@ class Casts < Array
   end
 end
 
+
+# Class for parsing argv using OptionParser accordind to given casts.
+# Default options are set, file glob expressions expanded, and options are
+# checked according to the casts. Usage information is printed and exit called
+# if required.
+class OptionHandler
+  REGEX_LIST   = /^(list|files|files!)$/
+  REGEX_INT    = /^(int|uint)$/
+  REGEX_STRING = /^(string|file|file!|dir|dir!|genome)$/
+
+  def initialize(argv, casts, script_path, test=nil)
+    @argv        = argv
+    @casts       = casts
+    @script_path = script_path
+    @test        = test
+  end
+
+  # Parse options from argv using OptionParser and casts denoting long and
+  # short option names. Usage information is printed and exit called.
+  # A hash with options is returned.
+  def options_parse
+    @options = {}
+
+    option_parser = OptionParser.new do |option|
+      @casts.each do |cast|
+        if cast[:type] == 'flag'
+          option.on("-#{cast[:short]}", "--#{cast[:long]}") do |o|
+            @options[cast[:long]] = o
+          end
+        elsif cast[:type] =~ REGEX_LIST
+          option.on( "-#{cast[:short]}", "--#{cast[:long]} A", Array) do |a|
+            @options[cast[:long]] = a
+          end
+        elsif cast[:type] =~ REGEX_INT
+          option.on("-#{cast[:short]}", "--#{cast[:long]} I", Integer) do |i|
+            @options[cast[:long]] = i
+          end
+        elsif cast[:type] =~ REGEX_STRING
+          option.on("-#{cast[:short]}", "--#{cast[:long]} S", String) do |s|
+            @options[cast[:long]] = s
+          end
+        elsif cast[:type] == 'float'
+          option.on("-#{cast[:short]}", "--#{cast[:long]} F", Float) do |f|
+            @options[cast[:long]] = f
+          end
+        else
+          raise ArgumentError, "Unknown option type: '#{cast[:type]}'"
+        end
+      end
+    end
+
+    option_parser.parse!(@argv)
+
+    if print_usage_full?
+      print_usage_and_exit(true)
+    elsif print_usage_short?
+      print_usage_and_exit
+    end
+
+    options_default
+    options_glob
+    options_check
+
+    @options
+  end
+
+  # Given the script name determine the path of the wiki file with the usage info.
+  def wiki_path
+    path = ENV["BP_DIR"] + "/bp_usage/" + File.basename(@script_path, ".rb") + ".wiki"
+    raise "No such wiki file: #{path}" unless File.file? path
+    path
+  end
+
+  # Check if full "usage info" should be printed.
+  def print_usage_full?
+    @options["help"]
+  end
+
+  # Check if short "usage info" should be printed.
+  def print_usage_short?
+    if not $stdin.tty?
+      return false
+    elsif @options["stream_in"]
+      return false
+    elsif @options["data_in"]
+      return false
+    elsif wiki_path =~ /^(list_biopieces|list_genomes|list_mysql_databases|biostat)$/  # TODO get rid of this!
+      return false
+    else
+      return true
+    end
+  end
+
+  # Print usage info by Calling an external script 'print_wiki'
+  # using a system() call and exit. An optional 'full' flag
+  # outputs the full usage info.
+  def print_usage_and_exit(full=nil)
+    if @test
+      return
+    else
+      if full
+        system("print_wiki --data_in #{wiki_path} --help")
+      else
+        system("print_wiki --data_in #{wiki_path}")
+      end
+
+      raise "Failed printing wiki: #{wiki_path}" unless $?.success?
+
+      exit
+    end
+  end
+
+  # Set default options value from cast unless a value is set.
+  def options_default
+    @casts.each do |cast|
+      if cast[:default]
+        @options[cast[:long]] = cast[:default] unless @options.has_key? cast[:long]
+      end
+    end
+  end
+
+  # Expands glob expressions to a full list of paths.
+  # Examples: "*.fna" or "foo.fna,*.fna" or "foo.fna,/bar/*.fna"
+  def options_glob
+    @casts.each do |cast|
+      if cast[:type] == 'files' or cast[:type] == 'files!'
+        if @options.has_key? cast[:long]
+          files = []
+        
+          @options[cast[:long]].each do |path|
+            if path.include? "*"
+              Dir.glob(path).each do |file|
+                files << file if File.file? file
+              end
+            else
+              files << path
+            end
+          end
+
+          @options[cast[:long]] = files
+        end
+      end
+    end
+  end
+
+  # Check all options according to casts.
+  def options_check
+    @casts.each do |cast|
+      options_check_mandatory(cast)
+      options_check_int(cast)
+      options_check_uint(cast)
+      options_check_file(cast)
+      options_check_files(cast)
+      options_check_dir(cast)
+      options_check_allowed(cast)
+      options_check_disallowed(cast)
+    end
+  end
+  
+  # Check if a mandatory option is set and raise if it isn't.
+  def options_check_mandatory(cast)
+    if cast[:mandatory]
+      raise ArgumentError, "Mandatory argument: --#{cast[:long]}" unless @options.has_key? cast[:long]
+    end
+  end
+
+  # Check int type option and raise if not an integer.
+  def options_check_int(cast)
+    if cast[:type] == 'int' and @options.has_key? cast[:long]
+      unless @options[cast[:long]].is_a? Integer
+        raise ArgumentError, "Argument to --#{cast[:long]} must be an integer, not '#{@options[cast[:long]]}'"
+      end
+    end
+  end
+  
+  # Check uint type option and raise if not an unsinged integer.
+  def options_check_uint(cast)
+    if cast[:type] == 'uint' and @options.has_key? cast[:long]
+      unless @options[cast[:long]].is_a? Integer and @options[cast[:long]] >= 0
+        raise ArgumentError, "Argument to --#{cast[:long]} must be an unsigned integer, not '#{@options[cast[:long]]}'"
+      end
+    end
+  end
+
+  # Check file! type argument and raise if file don't exists.
+  def options_check_file(cast)
+    if cast[:type] == 'file!' and @options.has_key? cast[:long]
+      raise ArgumentError, "No such file: '#{@options[cast[:long]]}'" unless File.file? @options[cast[:long]]
+    end
+  end
+
+  # Check files! type argument and raise if files don't exists.
+  def options_check_files(cast)
+    if cast[:type] == 'files!' and @options.has_key? cast[:long]
+      @options[cast[:long]].each do |path|
+        raise ArgumentError, "No such file: '#{path}'" unless File.file? path
+      end
+    end
+  end
+  
+  # Check dir! type argument and raise if directory don't exist.
+  def options_check_dir(cast)
+    if cast[:type] == 'dir!' and @options.has_key? cast[:long]
+      raise ArgumentError, "No such directory: '#{@options[cast[:long]]}'" unless File.directory? @options[cast[:long]]
+    end
+  end
+  
+  # Check options and raise unless allowed.
+  def options_check_allowed(cast)
+    if cast[:allowed] and @options.has_key? cast[:long]
+      allowed_hash = {}
+      cast[:allowed].split(',').each { |a| allowed_hash[a] = 1 }
+  
+      raise ArgumentError, "Argument '#{@options[cast[:long]]}' to --#{cast[:long]} not allowed" unless allowed_hash.has_key? @options[cast[:long]]
+    end
+  end
+  
+  # Check disallowed argument values and raise if disallowed.
+  def options_check_disallowed(cast)
+    if cast[:disallowed] and @options.has_key? cast[:long]
+      cast[:disallowed].split(',').each do |val|
+        raise ArgumentError, "Argument '#{@options[cast[:long]]}' to --#{cast[:long]} is disallowed" if val == @options[cast[:long]]
+      end
+    end
+  end
+end
+
+
 __END__
index d007d356085cfe1093cc80126c9ceefa9b9c7341..7871d6bd3114b711a774e35808886255384d6345 100755 (executable)
@@ -20,12 +20,11 @@ class OptionTest < Test::Unit::TestCase
 
   # >>>>>>>>>>>>>>>>>>>> Testing Options.new <<<<<<<<<<<<<<<<<<<<
 
-  test "Biopieces#parse with all cast keys don't raise" do
-    argv  = []
-    casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}]
-    @bp.expects(:print_usage_and_exit).with()
-    assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
-  end
+   test "Biopieces#parse with all cast keys don't raise" do
+     argv  = []
+     casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}]
+     assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
+   end
 
   test "Biopieces#parse with illegal long cast values raises" do
     [nil, true, false, 1, 0, "a"].each do |long|
@@ -39,7 +38,6 @@ class OptionTest < Test::Unit::TestCase
     ["foo", "!!", "0123"].each do |long|
       argv  = []
       casts = [{:long=>long, :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -56,7 +54,6 @@ class OptionTest < Test::Unit::TestCase
     ["!", "1", "a"].each do |short|
       argv  = []
       casts = [{:long=>"foo", :short=>short, :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -73,7 +70,6 @@ class OptionTest < Test::Unit::TestCase
     TYPES.each do |type|
       argv  = []
       casts = [{:long=>"foo", :short=>"f", :type=>type, :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -88,9 +84,8 @@ class OptionTest < Test::Unit::TestCase
 
   test "Biopieces#parse with legal mandatory cast values don't raise" do
     [true, false].each do |mandatory|
-      argv  = []
+      argv  = [ "--foo", "1" ]
       casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>mandatory, :default=>nil, :allowed=>nil, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -104,10 +99,9 @@ class OptionTest < Test::Unit::TestCase
   end
 
   test "Biopieces#parse with legal default cast values don't raise" do
-    ["foo", nil, 0, 0.0, 1, 1.2].each do |default|
+    [nil, 0, 1, -1].each do |default|
       argv  = []
       casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>default, :allowed=>nil, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -124,7 +118,6 @@ class OptionTest < Test::Unit::TestCase
     ["foo,bar",nil].each do |allowed|
       argv  = []
       casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>allowed, :disallowed=>nil}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -141,7 +134,6 @@ class OptionTest < Test::Unit::TestCase
     ["foo,bar",nil].each do |disallowed|
       argv  = []
       casts = [{:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>disallowed}]
-      @bp.expects(:print_usage_and_exit).with()
       assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
     end
   end
@@ -167,7 +159,6 @@ class OptionTest < Test::Unit::TestCase
     casts = []
     casts << {:long=>"foo", :short=>"f", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}
     casts << {:long=>"bar", :short=>"b", :type=>"int", :mandatory=>false, :default=>nil, :allowed=>nil, :disallowed=>nil}
-    @bp.expects(:print_usage_and_exit).with()
     assert_nothing_raised(CastError) { @bp.parse(argv, casts, SCRIPT_PATH) }
   end
 
@@ -182,13 +173,11 @@ class OptionTest < Test::Unit::TestCase
   test "Biopieces#parse with empty argv and existing wiki file don't raise" do
     argv  = []
     casts = []
-    @bp.expects(:print_usage_and_exit).with()
     assert_nothing_raised { @bp.parse(argv, casts, SCRIPT_PATH) }
   end
 
    test "Biopieces#parse with --help in argv and existing wiki output long usage" do
      argv = ["--help"]
-     @bp.expects(:print_usage_and_exit).with(true)
      assert_nothing_raised { @bp.parse(argv,[],SCRIPT_PATH) }
    end