Пример #1
0
    def test_trace_gyp(self):
        import trace_inputs
        expected_value = {
            'conditions': [
                [
                    'OS=="%s"' % trace_inputs.get_flavor(),
                    {
                        'variables': {
                            'isolate_dependency_tracked': [
                                # It is run from data/trace_inputs.
                                '../trace_inputs.py',
                                '../%s' % FILENAME,
                            ],
                            'isolate_dependency_untracked': [
                                'trace_inputs/',
                            ],
                        },
                    }
                ],
            ],
        }
        expected_buffer = cStringIO.StringIO()
        trace_inputs.pretty_print(expected_value, expected_buffer)

        cmd = [
            '--cwd',
            'data',
            '--product',
            '.',  # Not tested.
        ] + self.command(True)
        actual = self._execute(cmd)
        self.assertEquals(expected_buffer.getvalue(), actual)
Пример #2
0
  def test_trace_gyp(self):
    import trace_inputs
    expected_value = {
      'conditions': [
        ['OS=="%s"' % trace_inputs.get_flavor(), {
          'variables': {
            'isolate_dependency_tracked': [
              # It is run from data/trace_inputs.
              '../trace_inputs.py',
              '../%s' % FILENAME,
            ],
            'isolate_dependency_untracked': [
              'trace_inputs/',
            ],
          },
        }],
      ],
    }
    expected_buffer = cStringIO.StringIO()
    trace_inputs.pretty_print(expected_value, expected_buffer)

    cmd = [
      '--cwd', 'data',
      '--product', '.',  # Not tested.
    ] + self.command(True)
    actual = self._execute(cmd)
    self.assertEquals(expected_buffer.getvalue(), actual)
Пример #3
0
def load_isolate(content, error):
    """Loads the .isolate file. Returns the command, dependencies and read_only
  flag.
  """
    # Load the .isolate file, process its conditions, retrieve the command and
    # dependencies.
    configs = merge_isolate.load_gyp(merge_isolate.eval_content(content))
    flavor = trace_inputs.get_flavor()
    config = configs.per_os.get(flavor) or configs.per_os.get(None)
    if not config:
        error('Failed to load configuration for \'%s\'' % flavor)
    # Merge tracked and untracked dependencies, isolate.py doesn't care about the
    # trackability of the dependencies, only the build tool does.
    return config.command, config.tracked + config.untracked, config.read_only
Пример #4
0
def load_isolate(content, error):
  """Loads the .isolate file. Returns the command, dependencies and read_only
  flag.
  """
  # Load the .isolate file, process its conditions, retrieve the command and
  # dependencies.
  configs = merge_isolate.load_gyp(merge_isolate.eval_content(content))
  flavor = trace_inputs.get_flavor()
  config = configs.per_os.get(flavor) or configs.per_os.get(None)
  if not config:
    error('Failed to load configuration for \'%s\'' % flavor)
  # Merge tracked and untracked dependencies, isolate.py doesn't care about the
  # trackability of the dependencies, only the build tool does.
  return config.command, config.tracked + config.untracked, config.read_only
Пример #5
0
def process_inputs(prevdict, indir, infiles, level, read_only):
    """Returns a dictionary of input files, populated with the files' mode and
  hash.

  |prevdict| is the previous dictionary. It is used to retrieve the cached sha-1
  to skip recalculating the hash.

  |level| determines the amount of information retrieved.
  1 loads no information.  2 loads minimal stat() information. 3 calculates the
  sha-1 of the file's content.

  The file mode is manipulated if read_only is True. In practice, we only save
  one of 4 modes: 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r). On windows, mode
  is not set since all files are 'executable' by default.
  """
    assert level in (NO_INFO, STATS_ONLY, WITH_HASH)
    outdict = {}
    for infile in infiles:
        filepath = os.path.join(indir, infile)
        outdict[infile] = {}
        if level >= STATS_ONLY:
            filestats = os.stat(filepath)
            if trace_inputs.get_flavor() != 'win':
                filemode = stat.S_IMODE(filestats.st_mode)
                # Remove write access for non-owner.
                filemode &= ~(stat.S_IWGRP | stat.S_IWOTH)
                if read_only:
                    filemode &= ~stat.S_IWUSR
                if filemode & stat.S_IXUSR:
                    filemode |= (stat.S_IXGRP | stat.S_IXOTH)
                else:
                    filemode &= ~(stat.S_IXGRP | stat.S_IXOTH)
                outdict[infile]['mode'] = filemode
            outdict[infile]['size'] = filestats.st_size
            # Used to skip recalculating the hash. Use the most recent update time.
            outdict[infile]['timestamp'] = int(round(filestats.st_mtime))
            # If the timestamp wasn't updated, carry on the sha-1.
            if (prevdict.get(infile, {}).get('timestamp')
                    == outdict[infile]['timestamp']
                    and 'sha-1' in prevdict[infile]):
                # Reuse the previous hash.
                outdict[infile]['sha-1'] = prevdict[infile]['sha-1']

        if level >= WITH_HASH and not outdict[infile].get('sha-1'):
            h = hashlib.sha1()
            with open(filepath, 'rb') as f:
                h.update(f.read())
            outdict[infile]['sha-1'] = h.hexdigest()
    return outdict
Пример #6
0
def process_inputs(prevdict, indir, infiles, level, read_only):
  """Returns a dictionary of input files, populated with the files' mode and
  hash.

  |prevdict| is the previous dictionary. It is used to retrieve the cached sha-1
  to skip recalculating the hash.

  |level| determines the amount of information retrieved.
  1 loads no information.  2 loads minimal stat() information. 3 calculates the
  sha-1 of the file's content.

  The file mode is manipulated if read_only is True. In practice, we only save
  one of 4 modes: 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r). On windows, mode
  is not set since all files are 'executable' by default.
  """
  assert level in (NO_INFO, STATS_ONLY, WITH_HASH)
  outdict = {}
  for infile in infiles:
    filepath = os.path.join(indir, infile)
    outdict[infile] = {}
    if level >= STATS_ONLY:
      filestats = os.stat(filepath)
      if trace_inputs.get_flavor() != 'win':
        filemode = stat.S_IMODE(filestats.st_mode)
        # Remove write access for non-owner.
        filemode &= ~(stat.S_IWGRP | stat.S_IWOTH)
        if read_only:
          filemode &= ~stat.S_IWUSR
        if filemode & stat.S_IXUSR:
          filemode |= (stat.S_IXGRP | stat.S_IXOTH)
        else:
          filemode &= ~(stat.S_IXGRP | stat.S_IXOTH)
        outdict[infile]['mode'] = filemode
      outdict[infile]['size'] = filestats.st_size
      # Used to skip recalculating the hash. Use the most recent update time.
      outdict[infile]['timestamp'] = int(round(filestats.st_mtime))
      # If the timestamp wasn't updated, carry on the sha-1.
      if (prevdict.get(infile, {}).get('timestamp') ==
          outdict[infile]['timestamp'] and
          'sha-1' in prevdict[infile]):
        # Reuse the previous hash.
        outdict[infile]['sha-1'] = prevdict[infile]['sha-1']

    if level >= WITH_HASH and not outdict[infile].get('sha-1'):
      h = hashlib.sha1()
      with open(filepath, 'rb') as f:
        h.update(f.read())
      outdict[infile]['sha-1'] = h.hexdigest()
  return outdict
Пример #7
0
def load_isolate(content, error):
    """Loads the .isolate file and returns the information unprocessed.

  Returns the command, dependencies and read_only flag. The dependencies are
  fixed to use os.path.sep.
  """
    # Load the .isolate file, process its conditions, retrieve the command and
    # dependencies.
    configs = merge_isolate.load_gyp(merge_isolate.eval_content(content))
    flavor = trace_inputs.get_flavor()
    config = configs.per_os.get(flavor) or configs.per_os.get(None)
    if not config:
        error("Failed to load configuration for '%s'" % flavor)
    # Merge tracked and untracked dependencies, isolate.py doesn't care about the
    # trackability of the dependencies, only the build tool does.
    dependencies = [f.replace("/", os.path.sep) for f in config.tracked + config.untracked]
    return config.command, dependencies, config.read_only
Пример #8
0
def load_isolate(content, variables, error):
    """Loads the .isolate file. Returns the command, dependencies and read_only
  flag.
  """
    # Load the .isolate file, process its conditions, retrieve the command and
    # dependencies.
    configs = merge_isolate.load_gyp(merge_isolate.eval_content(content))
    flavor = trace_inputs.get_flavor()
    config = configs.per_os.get(flavor) or configs.per_os.get(None)
    if not config:
        error('Failed to load configuration for \'%s\'' % flavor)

    # Convert the variables and merge tracked and untracked dependencies.
    # isolate.py doesn't care about the trackability of the dependencies.
    infiles = [eval_variables(f, variables) for f in config.tracked
               ] + [eval_variables(f, variables) for f in config.untracked]
    command = [eval_variables(i, variables) for i in config.command]
    return command, infiles, config.read_only
Пример #9
0
def process_input(filepath, prevdict, level, read_only):
  """Processes an input file, a dependency, and return meta data about it.

  Arguments:
  - filepath: File to act on.
  - prevdict: the previous dictionary. It is used to retrieve the cached sha-1
              to skip recalculating the hash.
  - level: determines the amount of information retrieved.
  - read_only: If True, the file mode is manipulated. In practice, only save
               one of 4 modes: 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r). On
               windows, mode is not set since all files are 'executable' by
               default.
  """
  assert level in (NO_INFO, STATS_ONLY, WITH_HASH)
  out = {}
  if level >= STATS_ONLY:
    filestats = os.stat(filepath)
    if trace_inputs.get_flavor() != 'win':
      filemode = stat.S_IMODE(filestats.st_mode)
      # Remove write access for non-owner.
      filemode &= ~(stat.S_IWGRP | stat.S_IWOTH)
      if read_only:
        filemode &= ~stat.S_IWUSR
      if filemode & stat.S_IXUSR:
        filemode |= (stat.S_IXGRP | stat.S_IXOTH)
      else:
        filemode &= ~(stat.S_IXGRP | stat.S_IXOTH)
      out['mode'] = filemode
    out['size'] = filestats.st_size
    # Used to skip recalculating the hash. Use the most recent update time.
    out['timestamp'] = int(round(filestats.st_mtime))
    # If the timestamp wasn't updated, carry on the sha-1.
    if (prevdict.get('timestamp') == out['timestamp'] and
        'sha-1' in prevdict):
      # Reuse the previous hash.
      out['sha-1'] = prevdict['sha-1']

  if level >= WITH_HASH and not out.get('sha-1'):
    h = hashlib.sha1()
    with open(filepath, 'rb') as f:
      h.update(f.read())
    out['sha-1'] = h.hexdigest()
  return out
Пример #10
0
def process_input(filepath, prevdict, level, read_only):
    """Processes an input file, a dependency, and return meta data about it.

  Arguments:
  - filepath: File to act on.
  - prevdict: the previous dictionary. It is used to retrieve the cached sha-1
              to skip recalculating the hash.
  - level: determines the amount of information retrieved.
  - read_only: If True, the file mode is manipulated. In practice, only save
               one of 4 modes: 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r). On
               windows, mode is not set since all files are 'executable' by
               default.
  """
    assert level in (NO_INFO, STATS_ONLY, WITH_HASH)
    out = {}
    if level >= STATS_ONLY:
        filestats = os.stat(filepath)
        if trace_inputs.get_flavor() != 'win':
            filemode = stat.S_IMODE(filestats.st_mode)
            # Remove write access for non-owner.
            filemode &= ~(stat.S_IWGRP | stat.S_IWOTH)
            if read_only:
                filemode &= ~stat.S_IWUSR
            if filemode & stat.S_IXUSR:
                filemode |= (stat.S_IXGRP | stat.S_IXOTH)
            else:
                filemode &= ~(stat.S_IXGRP | stat.S_IXOTH)
            out['mode'] = filemode
        out['size'] = filestats.st_size
        # Used to skip recalculating the hash. Use the most recent update time.
        out['timestamp'] = int(round(filestats.st_mtime))
        # If the timestamp wasn't updated, carry on the sha-1.
        if (prevdict.get('timestamp') == out['timestamp']
                and 'sha-1' in prevdict):
            # Reuse the previous hash.
            out['sha-1'] = prevdict['sha-1']

    if level >= WITH_HASH and not out.get('sha-1'):
        h = hashlib.sha1()
        with open(filepath, 'rb') as f:
            h.update(f.read())
        out['sha-1'] = h.hexdigest()
    return out
Пример #11
0
def main():
  """Handles CLI and normalizes the input arguments to pass them to isolate().
  """
  default_variables = [('OS', trace_inputs.get_flavor())]
  if sys.platform in ('win32', 'cygwin'):
    default_variables.append(('EXECUTABLE_SUFFIX', '.exe'))
  else:
    default_variables.append(('EXECUTABLE_SUFFIX', ''))
  valid_modes = sorted(VALID_MODES.keys() + ['noop'])
  parser = optparse.OptionParser(
      usage='%prog [options] [.isolate file]',
      description=sys.modules[__name__].__doc__)
  parser.format_description = lambda *_: parser.description
  parser.add_option(
      '-v', '--verbose',
      action='count',
      default=int(os.environ.get('ISOLATE_DEBUG', 0)),
      help='Use multiple times')
  parser.add_option(
      '-m', '--mode',
      choices=valid_modes,
      help='Determines the action to be taken: %s' % ', '.join(valid_modes))
  parser.add_option(
      '-r', '--result',
      metavar='FILE',
      help='Result file to store the json manifest')
  parser.add_option(
      '-V', '--variable',
      nargs=2,
      action='append',
      default=default_variables,
      dest='variables',
      metavar='FOO BAR',
      help='Variables to process in the .isolate file, default: %default')
  parser.add_option(
      '-o', '--outdir', metavar='DIR',
      help='Directory used to recreate the tree or store the hash table. '
           'If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will '
           'be used. Otherwise, for run and remap, uses a /tmp subdirectory. '
           'For the other modes, defaults to the directory containing --result')

  options, args = parser.parse_args()
  levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
  logging.basicConfig(
      level=levels[min(len(levels)-1, options.verbose)],
      format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')

  if not options.mode:
    parser.error('--mode is required')
  if not options.result:
    parser.error('--result is required.')

  if len(args) > 1:
    logging.debug('%s' % sys.argv)
    parser.error('Use only one argument which should be a .isolate file')

  # Make sure the paths make sense. On Windows, / and \ are often mixed together
  # in a path.
  result_file = os.path.abspath(options.result.replace('/', os.path.sep))

  if options.mode == 'noop':
    # This undocumented mode is to help transition since some builders do not
    # have all the test data files checked out. Touch result_file and exit
    # silently.
    open(result_file, 'a').close()
    return 0

  # input_file may be None.
  input_file = (
      os.path.abspath(args[0].replace('/', os.path.sep)) if args else None)
  # out_dir may be None.
  out_dir = (
      os.path.abspath(options.outdir.replace('/', os.path.sep))
      if options.outdir else None)
  # Fix variables.
  variables = dict(options.variables)

  # After basic validation, pass this to isolate().
  return isolate(
      result_file,
      input_file,
      options.mode,
      variables,
      out_dir,
      parser.error)
Пример #12
0
def main():
    default_variables = ['OS=%s' % trace_inputs.get_flavor()]
    if sys.platform in ('win32', 'cygwin'):
        default_variables.append('EXECUTABLE_SUFFIX=.exe')
    else:
        default_variables.append('EXECUTABLE_SUFFIX=')
    valid_modes = get_valid_modes()
    parser = optparse.OptionParser(usage='%prog [options] [.isolate file]',
                                   description=sys.modules[__name__].__doc__)
    parser.format_description = lambda *_: parser.description
    parser.add_option('-v',
                      '--verbose',
                      action='count',
                      default=int(os.environ.get('ISOLATE_DEBUG', 0)),
                      help='Use multiple times')
    parser.add_option('-m',
                      '--mode',
                      choices=valid_modes,
                      help='Determines the action to be taken: %s' %
                      ', '.join(valid_modes))
    parser.add_option('-r',
                      '--result',
                      metavar='FILE',
                      help='Result file to store the json manifest')
    parser.add_option(
        '-V',
        '--variable',
        action='append',
        default=default_variables,
        dest='variables',
        metavar='FOO=BAR',
        help='Variables to process in the .isolate file, default: %default')
    parser.add_option(
        '-o',
        '--outdir',
        metavar='DIR',
        help='Directory used to recreate the tree or store the hash table. '
        'If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will '
        'be used. Otherwise, for run and remap, uses a /tmp subdirectory. '
        'For the other modes, defaults to the directory containing --result')

    options, args = parser.parse_args()
    level = [logging.ERROR, logging.INFO,
             logging.DEBUG][min(2, options.verbose)]
    logging.basicConfig(
        level=level,
        format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')

    if not options.mode:
        parser.error('--mode is required')
    if len(args) != 1:
        parser.error('Use only one argument which should be a .isolate file')

    input_file = os.path.abspath(args[0])
    isolate_dir = os.path.dirname(input_file)

    # Extract the variables.
    variables = dict(i.split('=', 1) for i in options.variables)
    # Process path variables as a special case. First normalize it, verifies it
    # exists, convert it to an absolute path, then set it as relative to
    # isolate_dir.
    for i in ('PRODUCT_DIR', ):
        if i not in variables:
            continue
        variable = os.path.normpath(variables[i])
        if not os.path.isdir(variable):
            parser.error('%s=%s is not a directory' % (i, variable))
        variable = os.path.abspath(variable)
        # All variables are relative to the input file.
        variables[i] = os.path.relpath(variable, isolate_dir)

    command, infiles, read_only = load_isolate(
        open(input_file, 'r').read(), variables, parser.error)

    # The trick used to determine the root directory is to look at "how far" back
    # up it is looking up.
    root_dir = isolate_dir.replace(os.path.sep, '/')
    for i in infiles:
        i = i.replace(os.path.sep, '/')
        x = isolate_dir.replace(os.path.sep, '/')
        while i.startswith('../'):
            i = i[3:]
            assert not i.startswith('/')
            x = posixpath.dirname(x)
        if root_dir.startswith(x):
            root_dir = x
    root_dir = root_dir.replace('/', os.path.sep)
    # The relative directory is automatically determined by the relative path
    # between root_dir and the directory containing the .isolate file.
    relative_dir = os.path.relpath(isolate_dir, root_dir)
    logging.debug('relative_dir: %s' % relative_dir)

    logging.debug('variables: %s' %
                  ', '.join('%s=%s' % (k, v)
                            for k, v in variables.iteritems()))
    logging.debug('command: %s' % command)
    logging.debug('infiles: %s' % infiles)
    logging.debug('read_only: %s' % read_only)
    infiles = [normpath(os.path.join(relative_dir, f)) for f in infiles]
    logging.debug('processed infiles: %s' % infiles)

    try:
        return isolate(options.outdir, root_dir, infiles, options.mode,
                       read_only, command, relative_dir, options.result)
    except run_test_from_archive.MappingError, e:
        print >> sys.stderr, str(e)
        return 1
Пример #13
0
def main():
    default_variables = [('OS', trace_inputs.get_flavor())]
    if sys.platform in ('win32', 'cygwin'):
        default_variables.append(('EXECUTABLE_SUFFIX', '.exe'))
    else:
        default_variables.append(('EXECUTABLE_SUFFIX', ''))
    valid_modes = get_valid_modes() + ['noop']
    parser = optparse.OptionParser(usage='%prog [options] [.isolate file]',
                                   description=sys.modules[__name__].__doc__)
    parser.format_description = lambda *_: parser.description
    parser.add_option('-v',
                      '--verbose',
                      action='count',
                      default=int(os.environ.get('ISOLATE_DEBUG', 0)),
                      help='Use multiple times')
    parser.add_option('-m',
                      '--mode',
                      choices=valid_modes,
                      help='Determines the action to be taken: %s' %
                      ', '.join(valid_modes))
    parser.add_option('-r',
                      '--result',
                      metavar='FILE',
                      help='Result file to store the json manifest')
    parser.add_option(
        '-V',
        '--variable',
        nargs=2,
        action='append',
        default=default_variables,
        dest='variables',
        metavar='FOO BAR',
        help='Variables to process in the .isolate file, default: %default')
    parser.add_option(
        '-o',
        '--outdir',
        metavar='DIR',
        help='Directory used to recreate the tree or store the hash table. '
        'If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will '
        'be used. Otherwise, for run and remap, uses a /tmp subdirectory. '
        'For the other modes, defaults to the directory containing --result')

    options, args = parser.parse_args()
    level = [logging.ERROR, logging.INFO,
             logging.DEBUG][min(2, options.verbose)]
    logging.basicConfig(
        level=level,
        format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')

    if not options.mode:
        parser.error('--mode is required')
    if len(args) != 1:
        logging.debug('%s' % sys.argv)
        parser.error('Use only one argument which should be a .isolate file')

    if options.mode == 'noop':
        # This undocumented mode is to help transition since some builders do not
        # have all the test data files checked out. Exit silently.
        return 0

    root_dir, infiles, data = process_options(dict(options.variables),
                                              options.result, args[0],
                                              parser.error)

    try:
        resultcode, data = isolate(options.outdir, options.mode, root_dir,
                                   infiles, data)
    except run_test_from_archive.MappingError, e:
        print >> sys.stderr, str(e)
        return 1
Пример #14
0
def main():
    """Handles CLI and normalizes the input arguments to pass them to isolate().
  """
    default_variables = [("OS", trace_inputs.get_flavor())]
    if sys.platform in ("win32", "cygwin"):
        default_variables.append(("EXECUTABLE_SUFFIX", ".exe"))
    else:
        default_variables.append(("EXECUTABLE_SUFFIX", ""))
    valid_modes = sorted(VALID_MODES.keys() + ["noop"])
    parser = optparse.OptionParser(usage="%prog [options] [.isolate file]", description=sys.modules[__name__].__doc__)
    parser.format_description = lambda *_: parser.description
    parser.add_option(
        "-v", "--verbose", action="count", default=int(os.environ.get("ISOLATE_DEBUG", 0)), help="Use multiple times"
    )
    parser.add_option(
        "-m", "--mode", choices=valid_modes, help="Determines the action to be taken: %s" % ", ".join(valid_modes)
    )
    parser.add_option("-r", "--result", metavar="FILE", help="Result file to store the json manifest")
    parser.add_option(
        "-V",
        "--variable",
        nargs=2,
        action="append",
        default=default_variables,
        dest="variables",
        metavar="FOO BAR",
        help="Variables to process in the .isolate file, default: %default",
    )
    parser.add_option(
        "-o",
        "--outdir",
        metavar="DIR",
        help="Directory used to recreate the tree or store the hash table. "
        "If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will "
        "be used. Otherwise, for run and remap, uses a /tmp subdirectory. "
        "For the other modes, defaults to the directory containing --result",
    )

    options, args = parser.parse_args()
    levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
    logging.basicConfig(
        level=levels[min(len(levels) - 1, options.verbose)],
        format="%(levelname)5s %(module)15s(%(lineno)3d): %(message)s",
    )

    if not options.mode:
        parser.error("--mode is required")
    if not options.result:
        parser.error("--result is required.")

    if len(args) > 1:
        logging.debug("%s" % sys.argv)
        parser.error("Use only one argument which should be a .isolate file")

    if options.mode == "noop":
        # This undocumented mode is to help transition since some builders do not
        # have all the test data files checked out. Exit silently.
        return 0

    # Make sure the paths make sense. On Windows, / and \ are often mixed together
    # in a path.
    result_file = os.path.abspath(options.result.replace("/", os.path.sep))
    # input_file may be None.
    input_file = os.path.abspath(args[0].replace("/", os.path.sep)) if args else None
    # out_dir may be None.
    out_dir = os.path.abspath(options.outdir.replace("/", os.path.sep)) if options.outdir else None
    # Fix variables.
    variables = dict(options.variables)

    # After basic validation, pass this to isolate().
    return isolate(result_file, input_file, options.mode, variables, out_dir, parser.error)
Пример #15
0
def main():
  default_variables = [('OS', trace_inputs.get_flavor())]
  if sys.platform in ('win32', 'cygwin'):
    default_variables.append(('EXECUTABLE_SUFFIX', '.exe'))
  else:
    default_variables.append(('EXECUTABLE_SUFFIX', ''))
  valid_modes = get_valid_modes() + ['noop']
  parser = optparse.OptionParser(
      usage='%prog [options] [.isolate file]',
      description=sys.modules[__name__].__doc__)
  parser.format_description = lambda *_: parser.description
  parser.add_option(
      '-v', '--verbose',
      action='count',
      default=int(os.environ.get('ISOLATE_DEBUG', 0)),
      help='Use multiple times')
  parser.add_option(
      '-m', '--mode',
      choices=valid_modes,
      help='Determines the action to be taken: %s' % ', '.join(valid_modes))
  parser.add_option(
      '-r', '--result',
      metavar='FILE',
      help='Result file to store the json manifest')
  parser.add_option(
      '-V', '--variable',
      nargs=2,
      action='append',
      default=default_variables,
      dest='variables',
      metavar='FOO BAR',
      help='Variables to process in the .isolate file, default: %default')
  parser.add_option(
      '-o', '--outdir', metavar='DIR',
      help='Directory used to recreate the tree or store the hash table. '
           'If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will '
           'be used. Otherwise, for run and remap, uses a /tmp subdirectory. '
           'For the other modes, defaults to the directory containing --result')

  options, args = parser.parse_args()
  level = [logging.ERROR, logging.INFO, logging.DEBUG][min(2, options.verbose)]
  logging.basicConfig(
      level=level,
      format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')

  if not options.mode:
    parser.error('--mode is required')
  if len(args) != 1:
    logging.debug('%s' % sys.argv)
    parser.error('Use only one argument which should be a .isolate file')

  if options.mode == 'noop':
    # This undocumented mode is to help transition since some builders do not
    # have all the test data files checked out. Exit silently.
    return 0

  root_dir, infiles, data = process_options(
      dict(options.variables), options.result, args[0], parser.error)

  try:
    resultcode, data = isolate(
        options.outdir,
        options.mode,
        root_dir,
        infiles,
        data)
  except run_test_from_archive.MappingError, e:
    print >> sys.stderr, str(e)
    return 1
Пример #16
0
def main():
    """Handles CLI and normalizes the input arguments to pass them to isolate().
  """
    default_variables = [('OS', trace_inputs.get_flavor())]
    if sys.platform in ('win32', 'cygwin'):
        default_variables.append(('EXECUTABLE_SUFFIX', '.exe'))
    else:
        default_variables.append(('EXECUTABLE_SUFFIX', ''))
    valid_modes = sorted(VALID_MODES.keys() + ['noop'])
    parser = optparse.OptionParser(usage='%prog [options] [.isolate file]',
                                   description=sys.modules[__name__].__doc__)
    parser.format_description = lambda *_: parser.description
    parser.add_option('-v',
                      '--verbose',
                      action='count',
                      default=int(os.environ.get('ISOLATE_DEBUG', 0)),
                      help='Use multiple times')
    parser.add_option('-m',
                      '--mode',
                      choices=valid_modes,
                      help='Determines the action to be taken: %s' %
                      ', '.join(valid_modes))
    parser.add_option('-r',
                      '--result',
                      metavar='FILE',
                      help='Result file to store the json manifest')
    parser.add_option(
        '-V',
        '--variable',
        nargs=2,
        action='append',
        default=default_variables,
        dest='variables',
        metavar='FOO BAR',
        help='Variables to process in the .isolate file, default: %default')
    parser.add_option(
        '-o',
        '--outdir',
        metavar='DIR',
        help='Directory used to recreate the tree or store the hash table. '
        'If the environment variable ISOLATE_HASH_TABLE_DIR exists, it will '
        'be used. Otherwise, for run and remap, uses a /tmp subdirectory. '
        'For the other modes, defaults to the directory containing --result')

    options, args = parser.parse_args()
    levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
    logging.basicConfig(
        level=levels[min(len(levels) - 1, options.verbose)],
        format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')

    if not options.mode:
        parser.error('--mode is required')
    if not options.result:
        parser.error('--result is required.')

    if len(args) > 1:
        logging.debug('%s' % sys.argv)
        parser.error('Use only one argument which should be a .isolate file')

    # Make sure the paths make sense. On Windows, / and \ are often mixed together
    # in a path.
    result_file = os.path.abspath(options.result.replace('/', os.path.sep))

    if options.mode == 'noop':
        # This undocumented mode is to help transition since some builders do not
        # have all the test data files checked out. Touch result_file and exit
        # silently.
        open(result_file, 'a').close()
        return 0

    # input_file may be None.
    input_file = (os.path.abspath(args[0].replace('/', os.path.sep))
                  if args else None)
    # out_dir may be None.
    out_dir = (os.path.abspath(options.outdir.replace('/', os.path.sep))
               if options.outdir else None)
    # Fix variables.
    variables = dict(options.variables)

    # After basic validation, pass this to isolate().
    return isolate(result_file, input_file, options.mode, variables, out_dir,
                   parser.error)
Пример #17
0
    test_cases = (
      ('"foo"', ['foo']),
      ('"foo", "bar"', ['foo', 'bar']),
      ('"foo"..., "bar"', ['foo', 'bar']),
      ('"foo", "bar"...', ['foo', 'bar']),
    )
    for actual, expected in test_cases:
      self.assertEquals(expected, trace_inputs.process_quoted_arguments(actual))


def join_norm(*args):
  """Joins and normalizes path in a single step."""
  return unicode(os.path.normpath(os.path.join(*args)))


if trace_inputs.get_flavor() == 'linux':
  class StraceInputs(unittest.TestCase):
    # Represents the root process pid (an arbitrary number).
    _ROOT_PID = 27
    _CHILD_PID = 14
    _GRAND_CHILD_PID = 70

    @staticmethod
    def _load_context(lines, initial_cwd):
      context = trace_inputs.Strace.Context(lambda _: False, initial_cwd)
      for line in lines:
        context.on_line(*line)
      return context.to_results().flatten()

    def _test_lines(self, lines, initial_cwd, files, command=None):
      filepath = join_norm(initial_cwd, '../out/unittests')