Chromium Code Reviews| Index: chrome/test/functional/autofill_dataset_generator.py |
| =================================================================== |
| --- chrome/test/functional/autofill_dataset_generator.py (revision 0) |
| +++ chrome/test/functional/autofill_dataset_generator.py (revision 0) |
| @@ -0,0 +1,300 @@ |
| +#!/usr/bin/python |
| +# Copyright (c) 2011 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. |
| + |
| +"""Generates profile dictionaries for Autofill. |
| + |
| +Used to test autofill.AutoFillTest.FormFillLatencyAfterSubmit. |
| +Can be used as a stand alone script with -h to print out help text by running: |
| + python autofill_dataset_generator.py -h |
| +""" |
| + |
| +import codecs |
| +import logging |
| +import random |
| +import re |
| +import sys |
| +import os |
| + |
| + |
| +class NullHandler(logging.Handler): |
| + def emit(self, record): |
| + pass |
| + |
| + |
| +class DatasetGenerator(object): |
| + """Generates a dataset of dictionaries. |
| + |
| + The lists (such as address_construct, city_construct) define the way the |
| + corresponding field is generated. They accomplish this by specifying a |
| + list of function-args lists. |
| + """ |
| + address_construct = [ |
| + [ random.randint, 1, 10000], |
| + [ None, u'foobar'], |
| + [ random.choice, [ u'St', u'Ave', u'Ln', u'Ct', ]], |
| + [ random.choice, [ u'#1', u'#2', u'#3', ]], |
| + ] |
| + |
| + city_construct = [ |
| + [ random.choice, [ u'San Jose', u'San Francisco', u'Sacramento', |
| + u'Los Angeles', ]], |
| + ] |
| + |
| + state_construct = [ |
| + [ None, u'CA'] |
| + ] |
| + |
| + zip_construct = [ |
| + [ None, u'95110'], |
| + ] |
| + |
| + re_single_quote = re.compile("'", re.UNICODE) |
| + logger = logging.getLogger(__name__) |
| + logger.addHandler(NullHandler()) |
| + log_handlers = {'StreamHandler': None} |
| + |
| + def __init__(self, output_filename=None, logging_level=None): |
| + """Constructs dataset generator object. |
| + |
| + Creates 'fields' data member which is a list of pair (two values) lists. |
| + These pairs are comprised of a field key e.g. u'NAME_FIRST' and a |
| + generator method e.g. self.GenerateNameFirst which will generate the value. |
| + If we want the value to always be the same .e.g. u'John' we can use this |
| + instead a a method. We can even use None keyword which will give |
| + a value of u''. |
| + |
| + 'output_pattern' for one field would have been: "{u'NAME_FIRST': u'%s',}" |
| + which is ready to accept a value for the 'NAME_FIRST' field key once |
| + this value is generated. |
| + 'output_pattern' is used in 'GenerateNextDict()' to generate the next |
| + dict line. |
| + |
| + Args: |
| + output_filename: specified filename of generated dataset to be saved. |
| + Default value is None and no saving takes place. |
| + logging_level: set verbosity levels, default is None. |
| + """ |
| + if logging_level: |
| + if not self.log_handlers['StreamHandler']: |
| + console = logging.StreamHandler() |
| + console.setLevel(logging.INFO) |
| + self.log_handlers['StreamHandler'] = console |
| + self.logger.addHandler(console) |
| + self.logger.setLevel(logging_level) |
| + else: |
| + if self.log_handlers['StreamHandler']: |
| + self.logger.removeHandler(self._log_handlers['StreamHandler']) |
| + self.log_handlers['StreamHandler'] = None |
| + |
| + self.output_filename = output_filename |
| + |
| + self.dict_no = 0 |
| + self.fields = [ |
| + [u'NAME_FIRST', self.GenerateNameFirst], |
| + [u'NAME_MIDDLE', None], |
| + [u'NAME_LAST', None], |
| + [u'EMAIL_ADDRESS', self.GenerateEmail], |
| + [u'COMPANY_NAME', None], |
| + [u'ADDRESS_HOME_LINE1', self.GenerateAddress], |
| + [u'ADDRESS_HOME_LINE2', None], |
| + [u'ADDRESS_HOME_CITY', self.GenerateCity], |
| + [u'ADDRESS_HOME_STATE', self.GenerateState], |
| + [u'ADDRESS_HOME_ZIP', self.GenerateZip], |
| + [u'ADDRESS_HOME_COUNTRY', u'United States'], |
| + [u'PHONE_HOME_WHOLE_NUMBER', None], |
| + [u'PHONE_FAX_WHOLE_NUMBER', u'6501234555'], |
| + ] |
| + |
| + self.dict_length = len(self.fields) |
| + self.output_pattern = u"{" |
| + for key_and_method in self.fields: |
| + self.output_pattern += u"u'%s': u'%s', " %(key_and_method[0], "%s") |
| + self.output_pattern = self.output_pattern[:-1] + "}," |
| + |
| + def _GenerateField(self, field_construct): |
| + """Generates each field in each dictionary. |
| + |
| + Args: |
| + field_construct: it is a list of lists. |
| + The first value (index 0) of each containing list is a function or None. |
| + The rest values are the args. If function is None then arg is just |
| + returned. |
| + |
| + Example 1: zip_construct = [[ None, u'95110']]. There is one |
| + containing list only and function here is None and arg is u'95110'. |
| + This just returns u'95110'. |
| + |
| + Example 2: address_construct = [ [ random.randint, 1, 10000], |
| + [ None, u'foobar'] ] This has two containing lists and it will return |
| + the result of: |
| + random.randint(1, 10000) + ' ' + u'foobar' |
| + which could be u'7832 foobar' |
| + """ |
| + parts = [] |
| + for function_and_args in field_construct: |
| + function = function_and_args[0] |
| + args = function_and_args[1:] |
| + if not function: |
| + function = lambda x: x |
| + parts.append(u'%s' %function(*args)) |
| + return (' ').join(parts) |
| + |
| + def GenerateAddress(self): |
| + """Uses _GenerateField() and address_construct to gen a random address. |
| + |
| + Returns random address. |
| + """ |
| + return self._GenerateField(self.address_construct) |
| + |
| + def GenerateCity(self): |
| + """Uses _GenerateField() and city_construct to gen a random city. |
| + |
| + Returns random city. |
| + """ |
| + return self._GenerateField(self.city_construct) |
| + |
| + def GenerateState(self): |
| + """Uses _GenerateField() and state_construct to generate a state. |
| + |
| + Returns random state. |
| + """ |
| + return self._GenerateField(self.state_construct) |
| + |
| + def GenerateZip(self): |
| + """Uses _GenerateField() and zip_construct to generate a zip code. |
| + |
| + Returns random zip code. |
| + """ |
| + return self._GenerateField(self.zip_construct) |
| + |
| + def GenerateCountry(self): |
| + """Uses _GenerateField() and country_construct to generate a country. |
| + |
| + Returns random country. |
| + """ |
| + return self._GenerateField(self.country_construct) |
| + |
| + def GenerateNameFirst(self): |
| + """Generates Numerical First Names. |
| + |
| + Its Name is the number of the current dict. |
| + i.e. u'1', u'2', u'3' |
| + |
| + Returns random first names. |
| + """ |
| + return u'%s' % self.dict_no |
| + |
| + def GenerateEmail(self): |
| + """Generates emails that correspond to the First Name. |
| + |
| + i.e. u'1@example.com', u'2@example.com', u'3@example.com' |
| + |
| + Returns random email addresses. |
| + """ |
| + return u'%s@example.com' % self.dict_no |
| + |
| + |
| + def GenerateNextDict(self): |
| + """Generates next dictionary of the dataset. |
| + |
| + It first increments zero starting dict_no. |
| + |
| + Returns the output dictionary. |
| + """ |
| + self.dict_no += 1 |
| + output_dict = {} |
| + for key, method_or_value in self.fields: |
| + if not method_or_value: |
| + output_dict[key] = '' |
| + elif type(method_or_value) in [str, unicode]: |
| + output_dict[key] = '%s' % method_or_value |
| + else: |
| + output_dict[key] = method_or_value() |
| + output_dict[key] = self.re_single_quote.sub( |
| + r"\'", output_dict[key]) # escaping single quote: "'" -> "\'" |
| + return output_dict |
| + |
| + def GenerateDataset(self, num_of_dict_to_generate=10): |
| + """Generates a list of dictionaries. |
| + |
| + Args: |
| + num_of_dict_to_generate: The number of dictionaries to be generated. |
| + Default value is 10. |
| + |
| + Returns the dictionary list. |
| + """ |
| + if self.output_filename: |
| + output_file = codecs.open( |
| + self.output_filename, mode = 'wb', encoding = 'utf-8-sig') |
| + else: |
| + output_file = None |
| + try: |
| + list_of_dict = [] |
| + if output_file: |
| + output_file.write('[') |
| + output_file.write(os.linesep) |
| + |
| + while self.dict_no < num_of_dict_to_generate: |
| + output_dict = self.GenerateNextDict() |
| + list_of_dict.append(output_dict) |
| + output_line = self.output_pattern %tuple( |
| + [output_dict[key_and_method[0]] for key_and_method in self.fields]) |
| + if output_file: |
| + output_file.write(output_line) |
| + output_file.write(os.linesep) |
| + self.logger.info( |
| + "%d: %s" %(self.dict_no, output_line.encode(sys.stdout.encoding, |
| + 'ignore'))) |
| + |
| + if output_file: |
| + output_file.write(']') |
| + output_file.write(os.linesep) |
| + self.logger.info("%d dictionaries generated SUCCESSFULLY!", self.dict_no) |
| + self.logger.info("--- FINISHED ---") |
| + return list_of_dict |
| + finally: |
| + if output_file: |
| + output_file.close() |
| + |
|
dennis_jeffrey
2011/03/18 21:44:01
Add one more blank line before the start of the ma
dyu1
2011/03/24 19:46:51
Done.
|
| +def main(): |
| + # Command line options. |
| + from optparse import OptionParser |
| + parser = OptionParser() |
| + parser.add_option("-o", "--output", |
| + dest="output_filename", default="", |
| + help="write output to FILE [optional]", metavar="FILE") |
| + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", |
| + default=True, |
| + help="display all [default]") |
| + parser.add_option("-q", "--quiet", action="store_false", dest="verbose", |
| + help="display nothing") |
| + parser.add_option("-l", "--log", dest="logging_level", default = None, |
| + help="LOG_LEVEL: 'debug, 'info', 'warning' or 'error'", |
| + metavar="LOG_LEVEL") |
| + |
| + (options, args) = parser.parse_args() |
| + if args: |
| + parser.print_help() |
| + sys.exit(1) |
| + if not options.verbose: |
| + options.logging_level = None |
| + if options.verbose and not options.logging_level: |
| + options.logging_level = 'info' |
| + if options.logging_level: |
| + if 'debug' in options.logging_level.lower(): |
| + options.logging_level = logging.DEBUG |
| + elif 'info' in options.logging_level.lower(): |
| + options.logging_level = logging.INFO |
| + elif 'warn' in options.logging_level.lower(): |
| + options.logging_level = logging.WARNING |
| + elif 'error' in options.logging_level.lower(): |
| + options.logging_level = logging.ERROR |
| + |
| + gen = DatasetGenerator(options.output_filename, options.logging_level) |
| + gen.GenerateDataset(100) |
| + |
| + |
| +if __name__ == '__main__': |
| + main() |