Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package


# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This generates the input file for automated_ui_tests.exe.

We take in a list of possible actions separated  by new lines, the number of
commands per file, and the number of actions per command, and generate
a single random file, or one or more files containing all possible commands,
or one file with a partial set of possible commands starting at a certain
command number.

Example usage:
  python auto_ui_test_input_generator.py --commands-per-file 50
      --actions-per-command 5 --action-list-file possible_actions.txt
      --output random_file.txt

  Generates a file called random_file.txt with 50 commands containing 5 actions
  each randomly chosen from the list of new line separated actions in

  python auto_ui_test_input_generator.py --commands-per-file 200
      --actions-per-command 6 --partial-coverage-from 700
      --action-list-file possible_actions.txt
      --output partial_coverage.txt

  Generates a file called partial_coverage.txt with 200 commands containing 6
  actions each starting at command #700 and ending at command #899 and chosen
  from the list of new line separated actions possible_actions.txt

  --action-list-file input_file_name
    Name of file containing possible actions separated  by new lines. You can
    find supported actions in the automated_ui_tests.h documentation.

  --output output_file_name
    Name of XML file that will be outputted for use as input for

  --commands-per-file commands_per_file
    Number of commands per file.

  --actions-per-command actions_per_command
    Number of actions per command.

    If full_coverage flag is set will output as many files as neccesary to cover
    every combination of possible actions. Files will be named
    output_file_name_1.txt, output_file_name_2.txt, etc...
    If --full-coverage is true, --full-coverage-one-file and
    --partial-coverage-from are ignored.

    Just like --full_coverage, but outputs to just one file.
    Ignores commands_per_file. This is very likely to cause memory errors on
    large action sets. If --full coverage-one-file is true,
    --partial-coverage-from is ignored.

  --partial-coverage-from command_to_start_at
    Outputs a part of the full coverage, starting at command number
    |command_to_start_at| and ending at command number |command_to_start_at| +
    |commands_per_file|. Command numbering starts at 0, and the maximum
    command number is number_of_actions_we_choose_from ^ actions_per_command -
    If |command_to_start_at| + |commands_per_file| is greater than the maximum
    command number, then only the commands up to the maximum command number
    are printed.

    Silence progress messages.

import optparse
import os.path
import random
import xml.dom.minidom

00080 class ComprehensiveListGenerator:
  """Generates a comprehensive list of all the ways to choose x combinations
  from an input list, with replacement.

  Init takes |list_length|, which is the length of the of the combination and
  |source_list|, which is the list we want to choose from.
  GetNextPortionOfSourceList() returns a list of length |list_length| with a
  portion of the complete list of all combinations or None once all possible
  combinations have been returned.

  >>> list_gen = ComprehensiveListGenerator(2, ['a','b','c'])
  >>> print list_gen.GetNextPortionOfSourceList()
  >>> print list_gen.GetNextPortionOfSourceList()
  >>> print list_gen.GetNextPortionOfSourceList()
  >>> ...print list_gen.GetNextPortionOfSourceList() 6 more times...
  >>> print list_gen.GetNextPortionOfSourceList()
  >>> list_gen.SetIntegerListToCombinationNumber(2)
  >>> print list_gen.GetCurrentPortionOfSourceList()
  >>> print list_gen.GetNextPortionOfSourceList()
  >>> list_gen.SetIntegerListToCombinationNumber(8)
  >>> print list_gen.GetCurrentPortionOfSourceList()
  >>> list_gen.SetIntegerListToCombinationNumber(9)
  >>> print list_gen.GetCurrentPortionOfSourceList()

    __list_length:    Length of the resulting combinations.
    __source_list:    The list we are pulling combinations from.
    __integer_list:   A list of integers representing which indices of
                    |source_list| to return.

  def __init__(self, list_length, source_list):
    self.__list_length = list_length
    self.__integer_list = None
    self.__source_list = source_list

00125   def SetIntegerListToCombinationNumber(self, combo_number):
    """ Sets the integer list to represent the |combo_number|th number in the
    sequence, counting from 0.

      combo_number: Number to set the integer list to represent.

    Returns: Sets integer_list to None and returns False if the combo_number is
    out of range (bigger than the maximum number of combinations possible or
    less than 0)
    if (combo_number < 0 or
       combo_number >= len(self.__source_list) ** self.__list_length):
     self.__integer_list = None
     return False
    if self.__integer_list == None:
     self.__integer_list = []
     for i in range(self.__list_length):
    reversed_range = range(self.__list_length)
    index_max_value = len(self.__source_list)
    quotient = 0
    for index in reversed_range:
      quotient, remainder = divmod(combo_number, index_max_value)
      combo_number = quotient
      self.__integer_list[index] = remainder

    return True

00155   def __IncrementIntegerListIndex(self, index):
    """ Increments the given index of integer_list, rolling over to 0 and
    incrementing the a lower index if the index is incremented above the last
    index of source_list

      index: The index integer_list to attempt to increment.

    Returns: False if it is impossible to incremement any index in the list
    which is less than or equal to the given index.
    self.__integer_list[index] += 1
    if self.__integer_list[index] >= len(self.__source_list):
      # We've incremented beyond the length of source_list, so reset to zero...
      self.__integer_list[index] = 0
      # And if our index is high enough, increment the next index. Otherwise
      # we can't increment any further and should return false.
      if index > 0:
        return self.__IncrementIntegerListIndex(index-1)
        # Restart the integer list at the beginning
        self.__integer_list = None
        return False
    # Successfuly incremented the index, return true.
    return True

00181   def __IncrementIntegerList(self):
    """ Gets the next integer list in the series by attempting to increment the
    final index of integer_list.

    Returns: False if we can't increment any index in the integer_list.

    # If the list is empty we just started, so populate it with zeroes.
    if self.__integer_list == None:
      self.__integer_list = []
      for i in range(self.__list_length):
      return True
      return self.__IncrementIntegerListIndex(self.__list_length-1)

00197   def GetCurrentPortionOfSourceList(self):
    """ Returns the current portion of source_list corresponding to the

    For example, if our current state is:
      integer_list = [0,1,0,2]
      source_list = ['a','b','c','d']
    Then calling GetCurrentPortionOfSourceList() returns:

    Returns: None if the integer_list is empty, otherwise a list of length
    list_length with a combination of elements from source_list
    portion_list = []
    if self.__integer_list == None:
      return None

    for index in range(self.__list_length):

    return portion_list

00219   def GetNextPortionOfSourceList(self):
    """ Increments the integer_list and then returns the current portion of
    source_list corresponding to the integer_list.

    This is the only function outside users should be calling. It will advance
    to the next combination of elements from source_list, and return it. See
    the class documentation for proper use.

    Returns: None if all possible combinations of source_list have previously
    been returned. Otherwise a new list of length list_length with a combination
    of elements from source_list.
    if self.__IncrementIntegerList():
      return self.GetCurrentPortionOfSourceList()
      return None

00236 class AutomatedTestInputGenerator:
  """Creates a random file with with the name |file_name| with
  the number of commands and actions specified in the command line.

    __commands_per_file: Number of commands per file.
    __actions_per_command: Number of actions per command.
    __actions_list: A list of strings representing the possible actions.
    __is_verbose: If true, print progress messages
  def __init__(self):
    (options,args) = ParseCommandLine()
    input_file = open(options.input_file_name)
    actions_list = []
    for line in input_file.readlines():
      if not line.startswith('#'):

    self.__commands_per_file = options.commands_per_file
    self.__actions_per_command = options.actions_per_command
    self.__actions_list = [action.strip() for action in actions_list]
    self.__is_verbose = options.is_verbose

00260   def __CreateDocument(self):
    """ Create the starter XML document.

    Returns: A tuple containing the XML document and its root element named
    "Command List".
    doc = xml.dom.minidom.Document()
    root_element = doc.createElement("CommandList")
    return doc, root_element

00271   def __WriteToOutputFile(self, file_name, output):
    """Writes |output| to file with name |filename|. Overwriting any
       pre-existing file.

      file_name: Name of the file to create.
      output: The string to write to file.
    output_file = open(file_name, 'w')

00283   def CreateRandomFile(self, file_name):
    """Creates a random file with with the name |file_name| with
       the number of commands and actions specified in the command line.

      file_name - Name of the file to create.

    output_doc, root_element = self.__CreateDocument()
    for command_num in range(0, self.__commands_per_file):
      command_element = output_doc.createElement("command")
      for action_num in range(0,self.__actions_per_command):
        action_element = output_doc.createElement(
    self.__WriteToOutputFile(file_name, output_doc.toprettyxml())

00303   def __AddCommandToDoc(self, output_doc, root_element, command, command_num):
    """Adds a given command to the output XML document

      output_doc - The output XML document. Used to create elements.
      root_element - The root element of the XML document. (What we add the
                     command to)
      command - The name of the command element we create and add to the doc.
      command_num - The number of the command.

    command_element = output_doc.createElement("command")
    command_element.setAttribute("number", str(command_num))
    for action in command:
      action_element = output_doc.createElement(action)

00323   def CreateComprehensiveFile(self, file_name, start_command, write_to_end):
    """Creates one file containing all or part of the comprehensive list of
    commands starting at a set command.

      file_name - Name of the file to create.
      start_command - Command number to start at.
      write_to_end - If true, writes all remaining commands, starting at
                     start_command. (If start_command is 0, this would write all
                     possible commands to one file.) If false, write only
                     commands_per_file commands starting at start_command

    list_generator = ComprehensiveListGenerator(self.__actions_per_command,
    output_doc, root_element = self.__CreateDocument()
    command_counter = start_command
    end_command = start_command + self.__commands_per_file
    is_complete = False
    # Set the underlying integer representation of the command to the
    # the starting command number.
    command = list_generator.GetCurrentPortionOfSourceList()
    while (command != None and
          (write_to_end == True or command_counter < end_command)):
      self.__AddCommandToDoc(output_doc, root_element, command, command_counter)
      command_counter += 1;
      command = list_generator.GetNextPortionOfSourceList()

    self.__WriteToOutputFile(file_name, output_doc.toprettyxml())

00356   def CreateComprehensiveFiles(self, file_name):
    """Creates a comprehensive coverage of all possible combinations from
    action_list of length commands_per_file. Names them |file_name|_1,
    |file_name|_2, and so on.

      file_name - Name of the file to create.

    list_generator = ComprehensiveListGenerator(self.__actions_per_command,

    is_complete = False
    file_counter = 0
    # Split the file name so we can include the file number before the
    # extension.
    base_file_name, extension = os.path.splitext(file_name)
    command_num = 0

    while is_complete == False:
      output_doc, root_element = self.__CreateDocument()
      file_counter += 1
      if self.__is_verbose and file_counter % 200 == 0:
        print "Created " + str(file_counter) + " files... "

      for i in range(self.__commands_per_file):
        # Get the next sequence of actions as a list.
        command = list_generator.GetNextPortionOfSourceList()
        if command == None:
          is_complete = True

        # Parse through the list and add them to the output document as children
        # of a command element
        self.__AddCommandToDoc(output_doc, root_element, command, command_num)
        command_num += 1

      # Finished the commands for this file, so write it and start on next file.
      self.__WriteToOutputFile(base_file_name + "_" + str(file_counter) +
                             extension, output_doc.toprettyxml())

def ParseCommandLine():
  """Parses the command line.

  Return: List of options and their values and a list of arguments which were
  parser = optparse.OptionParser()
  parser.add_option("-i", "--action-list-file", dest="input_file_name",
                    type="string", action="store",
                    help="input file with a test of newline separated actions"
                    "which are possible. Default is 'possible_actions.txt'")
  parser.add_option("-o", "--output", dest="output_file_name", type="string",
                    action="store", default="automated_ui_tests.txt",
                    help="the file to output the command list to")
  parser.add_option("-c", "--commands-per-file", dest="commands_per_file",
                    type="int", action="store", default=500,
                    help="number of commands per file")
  parser.add_option("-a", "--actions-per-command", dest="actions_per_command",
                    type="int", action="store", default=5,
                    help="number of actions per command")
  parser.add_option("-f", "--full-coverage", dest="full_coverage",
                    action="store_true", help="Output files for every possible"
                    "combination. Default is to output just one random file.")
  parser.add_option("-q", "--quiet",
                    action="store_false", dest="is_verbose", default=True,
                    help="don't print progress message while creating files")
  parser.add_option("-1", "--full-coverage-one-file",
                    action="store_true", dest="full_coverage_one_file",
                    help="complete coverage all outputted to one file")
  parser.add_option("-p", "--partial-coverage-from", dest="start_at_command",
                    type="int", action="store", default=-1,
                    help="partial list from the complete coverage, starting at"
                    "command #start_at_command")

  return parser.parse_args()

def main():
  (options,args) = ParseCommandLine()
  test_generator = AutomatedTestInputGenerator()
  if options.full_coverage == True:
    if options.full_coverage_one_file and options.is_verbose == True:
      print ("Error: Both --full-coverage and --full-coverage-one-file present,"
            " ignoring --full-coverage-one-file")
    if options.start_at_command >= 0 and options.is_verbose == True:
      print ("Error: Both --full-coverage and --partial-coverage-from present,"
            " ignoring --partial-coverage-from")
    if options.is_verbose == True:
      print "Starting to write comprehensive files:"
    if options.is_verbose == True:
      print "Finished writing comprehensive files."
  elif options.full_coverage_one_file:
    if options.start_at_command >= 0 and options.is_verbose == True:
      print ("Error: Both --full-coverage-one-file present and"
            "--partial-coverage-from present, ignoring --partial-coverage-from")
    if options.is_verbose == True:
      print "Starting to write comprehensive file:"
    test_generator.CreateComprehensiveFile(options.output_file_name, 0, True)
    if options.is_verbose == True:
      print "Finished writing comprehensive file."
  elif options.start_at_command >= 0:
    if options.is_verbose == True:
      print "Starting to write partial file:"
                                           options.start_at_command , False)
    if options.is_verbose == True:
      print "Finished writing partial file."
    if options.is_verbose == True:
      print "Output written to file: " + options.output_file_name

if __name__ == '__main__':

Generated by  Doxygen 1.6.0   Back to index