def test_InvokeRecursive(self):
        include_filename1 = CurrentShell.CreateTempFilename(".SimpleSchema")
        include_filename2 = CurrentShell.CreateTempFilename(".SimpleSchema")

        with open(include_filename1, "w") as f:
            f.write(
                textwrap.dedent(
                    """\
                    simple_schema_include('{}')

                    <a_string1 string>
                    """,
                ).format(include_filename2),
            )

        with CallOnExit(lambda: os.remove(include_filename1)):
            with open(include_filename2, "w") as f:
                f.write(
                    textwrap.dedent(
                        """\
                        <a_string2 string>
                        """,
                    ),
                )

            with CallOnExit(lambda: os.remove(include_filename2)):
                root = _Invoke("simple_schema_include('{}')".format(include_filename1))

        self.assertEqual(len(root.items), 2)
        self.assertEqual(root.items[0].name, "a_string1")
        self.assertEqual(root.items[1].name, "a_string2")
def _ProcessExecuteWorkaround(command_line):
    # I haven't been able to figure out what is causing this, but it appears that VSPerfCmd.exe
    # isn't sending an EOF before terminating during startup. This causes problems for subprocess-
    # based means of forking processes and ends up hanging forever. To work around this, use
    # subprocess.call, which doesn't use standard streams for input and output.
    #
    # Unfortunately, there isn't an easy way to capture the output from subprocess.call, so
    # invoke the command with output redirected to a file, then extract the content from the
    # file itself.
    #
    # This is all a great big hack.

    temp_filename = CurrentShell.CreateTempFilename(
        "._ProcessExecuteWorkaround.output")

    command_line += ' > "{}" 2>&1'.format(temp_filename)

    result = subprocess.call(
        command_line,
        shell=True,
    )

    assert os.path.isfile(temp_filename), temp_filename
    with open(temp_filename) as f:
        output = f.read()

    # For some reason, this file is still in use when we attempt to delete it here.
    # For now, don't delete it as it should be pretty small.
    #
    # FileSystem.RemoveFile(temp_filename)

    return result, output
    def ExtractCoverageInfo(coverage_filename, binary_filename, includes,
                            excludes, output_stream):
        if excludes:
            excludes_func = lambda method_name: any(
                fnmatch(method_name, exclude) for exclude in excludes)
        else:
            excludes_func = lambda method_name: False

        if includes:
            includes_func = lambda method_name: any(
                fnmatch(method_name, include) for include in includes)
        else:
            includes_func = lambda method_name: True

        # ----------------------------------------------------------------------
        def ShouldInclude(method_name):
            return not excludes_func(method_name) and includes_func(
                method_name)

        # ----------------------------------------------------------------------

        temp_filename = CurrentShell.CreateTempFilename()

        command_line = '"{powershell}" -ExecutionPolicy Bypass -NoProfile -File "{filename}" "{coverage}" "{module}" > "{temp_filename}" 2>&1'.format(
            powershell=r"{}\syswow64\WindowsPowerShell\v1.0\powershell.exe".
            format(os.getenv("SystemRoot"), ),
            filename=os.path.join(_script_dir, "CoverageToCsv.ps1"),
            coverage=coverage_filename,
            module=os.path.basename(binary_filename),
            temp_filename=temp_filename,
        )

        result = Process.Execute(command_line, output_stream)
        if result != 0:
            return result

        with CallOnExit(lambda: FileSystem.RemoveFile(temp_filename)):
            covered = 0
            not_covered = 0

            with open(temp_filename, "r") as input:
                reader = csv.reader(input)

                for row in reader:
                    if not isinstance(row, (tuple, list)):
                        raise Exception(row)
                    if len(row) == 1:
                        raise Exception(row[0])

                    method_name = row[1]
                    if not ShouldInclude(method_name):
                        continue

                    covered += int(row[-2])
                    not_covered += int(row[-1])

            return covered, not_covered
예제 #4
0
    def EnumTrackedFiles(cls, repo_root):
        temp_filename = CurrentShell.CreateTempFilename()

        result, output = cls.Execute(
            repo_root, 'git ls-files > "{}"'.format(temp_filename))
        assert result == 0, (result, output)

        assert os.path.isfile(temp_filename), temp_filename
        with CallOnExit(lambda: os.remove(temp_filename)):
            with open(temp_filename) as f:
                for line in f.readlines():
                    line = line.strip()
                    if line:
                        yield os.path.join(repo_root, line)
예제 #5
0
            def FileWriter(filename, mode):
                """\
                Method that writes to a temporary location and only copies to the intended
                destination if there are changes. This prevents full rebuilds (which are
                triggered based on timestamps) on files that haven't changed.
                """

                temp_filename = CurrentShell.CreateTempFilename()
                with open(temp_filename, mode) as f:
                    yield f

                if not os.path.isfile(filename) or CalcHash(temp_filename) != CalcHash(filename):
                    FileSystem.RemoveFile(filename)
                    shutil.move(temp_filename, filename)
                else:
                    FileSystem.RemoveFile(temp_filename)
def EntryPoint(
    arg,
    output_stream=sys.stdout,
):
    args = arg
    del arg

    # One of the args will be the filename
    input_filename = None

    for arg in args:
        if arg.startswith("-assume-filename="):
            input_filename = arg[len("-assume-filename=") :]
            break

    if input_filename is None:
        raise Exception("Unable to extract the filename from '{}'".format(args))

    # Write the contents from stdin to a temp file
    input_content = sys.stdin.read()
    assert input_content

    temp_filename = CurrentShell.CreateTempFilename(os.path.splitext(input_filename)[1])

    with open(temp_filename, "w") as f:
        f.write(input_content)

    with CallOnExit(lambda: FileSystem.RemoveFile(temp_filename)):
        # Invoke the script
        script_name = "Formatter"
        if CurrentShell.CategoryName != "Linux":
            script_name = CurrentShell.CreateScriptName(script_name)

        command_line = '"{script}" Format "{filename}" /quiet "/plugin_arg=hint_filename:{original_filename}"'.format(
            script=script_name,
            filename=temp_filename,
            original_filename=input_filename.replace(":", "\\:"),
        )

        result, formatted_output = Process.Execute(command_line)

    output_stream.write(formatted_output)
    return result
예제 #7
0
    def test_Invoke(self):
        include_filename = CurrentShell.CreateTempFilename(".SimpleSchema")

        with open(include_filename, "w") as f:
            f.write(
                textwrap.dedent(
                    """\
                    <a_string string>
                    """, ), )

        with CallOnExit(lambda: os.remove(include_filename)):
            root = _Invoke(
                "simple_schema_include('{}')".format(include_filename))

        self.assertEqual(len(root.items), 1)

        item = root.items[0]

        self.assertEqual(item.name, "a_string")
    def _InvokeImpl(cls, invoke_reason, context, status_stream, verbose_stream,
                    verbose):
        with status_stream.DoneManager(
                associated_stream=verbose_stream) as (this_dm,
                                                      this_verbose_stream):
            generated_python_context = cls._GenerateScriptContent(context)
            assert generated_python_context

            temp_filename = CurrentShell.CreateTempFilename(".py")
            with open(temp_filename, 'w') as f:
                f.write(generated_python_context)

            if context["preserve_temp_dir"]:
                this_dm.stream.write("Writing to '{}'\n".format(temp_filename))
                cleanup_func = lambda: None
            else:
                cleanup_func = lambda: os.remove(temp_filename)

            try:
                sink = six.moves.StringIO()

                this_dm.result = cls._Compile(
                    context, temp_filename,
                    StreamDecorator([
                        sink,
                        this_verbose_stream,
                    ]))
                if this_dm.result != 0:
                    if not verbose:
                        this_dm.stream.write(sink.getvalue())

                return this_dm.result

            finally:
                if this_dm.result == 0:
                    cleanup_func()
예제 #9
0
    def Execute(
        cls,
        compiler,
        context,
        command_line,
        includes=None,
        excludes=None,
        verbose=False,
    ):
        assert command_line

        includes = includes or []
        excludes = excludes or []

        # Get the name of the script to execute
        if command_line.lower().startswith("python"):
            filename = command_line[len("python"):].replace('"', '').strip()
            assert os.path.isfile(filename), filename
        else:
            filename = command_line

        # Attempt to extract include and exclude information from the source
        disable_code_coverage = False

        if not disable_code_coverage and not includes and not includes:
            regex = re.compile(
                textwrap.dedent(r"""(?#
                        Header              )^.*?#\s*(?#
                        Label               )code_coverage\s*:\s*(?#
                        Action              )(?P<action>\S+)(?#
                        +Optional           )(?:(?#
                            Assignment      )\s*=\s*(?#
                            +Quote          )(?P<quote>")?(?#
                            Name            )(?P<name>.+?)(?#
                            -Quote          )(?P=quote)?(?#
                        -Optional           ))?(?#
                        Suffix              )\s*$(?#
                        )"""))

            for index, line in enumerate(open(filename).readlines()):
                match = regex.match(line)
                if not match:
                    continue

                action = match.group("action").lower()

                if action == "disable":
                    disable_code_coverage = True

                elif action in [
                        "include",
                        "exclude",
                ]:
                    referenced_filename = match.group("name")
                    referenced_filename = os.path.abspath(
                        os.path.join(os.path.dirname(filename),
                                     referenced_filename))

                    if not os.path.isfile(referenced_filename):
                        raise Exception(
                            "'{}', referenced on line {}, is not a valid filename"
                            .format(referenced_filename, index + 1))

                    if action == "include":
                        includes.append(referenced_filename)
                    elif action == "exclude":
                        excludes.append(referenced_filename)
                    else:
                        assert False, action

                else:
                    raise Exception(
                        "'{}' is not a supported action".format(action))

        if disable_code_coverage:
            return StandardTestExecutor.Execute(
                compiler,
                context,
                'python "{}"'.format(filename),
            )

        # Attempt to determine include and exclude information based on the original filename
        if not disable_code_coverage and not includes and not excludes:
            sut_filename = compiler.TestToItemName(filename)

            # Import by python fullpath
            dirname, basename = os.path.split(sut_filename)

            stack = [
                basename,
            ]

            while True:
                potential_filename = os.path.join(dirname, "__init__.py")
                if not os.path.isfile(potential_filename):
                    break

                potential_dirname, basename = os.path.split(dirname)

                stack.append(basename)

                if potential_dirname == dirname:
                    break

                dirname = potential_dirname

            stack.reverse()

            includes.append("*/{}".format('/'.join(stack)))

        # Run the process and calculate code coverage
        temp_filename = CurrentShell.CreateTempFilename(".py")

        with open(temp_filename, 'w') as f:
            f.write(
                textwrap.dedent("""\
                from coverage.cmdline import main

                main()
                """))

        with CallOnExit(lambda: FileSystem.RemoveFile(temp_filename)):
            command_line_template = 'python "{}" "{{}}"'.format(temp_filename)

            # Run the process
            start_time = time.time()

            command_line = '{} {} {} {}'.format(
                command_line_template.format("run"),
                '"--include={}"'.format(','.join(includes))
                if includes else '',
                '"--omit={}"'.format(','.join(excludes)) if excludes else '',
                filename,
            )

            test_result, test_output = Process.Execute(command_line)
            test_time = str(
                datetime.timedelta(seconds=(time.time() - start_time)))

            # Get the coverage info
            start_time = time.time()

            xml_temp_filename = CurrentShell.CreateTempFilename(".xml")

            command_line = '{} -o "{}"'.format(
                command_line_template.format("xml"),
                xml_temp_filename,
            )

            coverage_result, coverage_output = Process.Execute(command_line)
            coverage_time = str(
                datetime.timedelta(seconds=(time.time() - start_time)))
            coverage_data_filename = xml_temp_filename

        # Get the percentage info
        if not os.path.isfile(coverage_data_filename):
            if coverage_result == 0:
                coverage_result = -1

            coverage_data_filename = None

        if coverage_result != 0:
            percentage = None
            percentages = None
        else:
            root = ET.fromstring(open(coverage_data_filename).read())

            percentage = float(root.attrib["line-rate"]) * 100

            percentages = OrderedDict()

            for package in root.findall("packages/package"):
                for class_ in package.findall("classes/class"):
                    percentages[class_.attrib["filename"]] = float(
                        class_.attrib["line-rate"]) * 100

        return cls.ExecuteResult(
            test_result,
            test_output,
            test_time,
            coverage_result,
            coverage_output,
            coverage_time,
            coverage_data_filename,
            percentage,
            percentages,
        )
    def _InvokeImpl(
        cls,
        invoke_reason,
        context,
        status_stream,
        verbose_stream,
        verbose,
    ):
        # If the file is being invoked as a test file, measure the file under test
        # rather than the test itself.
        filename = context["input"]

        try:
            filename = cls.TestToItemName(filename)
        except:
            pass

        assert os.path.isfile(filename), filename

        if os.path.basename(filename) == "__init__.py" and os.path.getsize(
                filename) == 0:
            return 0

        # Create the lint file
        configuration_file = os.getenv(
            cls.CONFIGURATION_ENVIRONMENT_VAR_NAME) or os.path.join(
                _script_dir, "PythonVerifier.default_configuration")
        assert os.path.isfile(configuration_file), configuration_file

        # Write the python script that invokes the linter
        temp_filename = CurrentShell.CreateTempFilename(".py")
        with open(temp_filename, 'w') as f:
            f.write(
                textwrap.dedent("""\
                import sys

                from pylint import lint

                lint.Run([ r"--rcfile={config}",
                           r"--msg-template={{path}}({{line}}): [{{msg_id}}] {{msg}}",
                           r"{filename}",
                         ])
                """).format(
                    config=configuration_file,
                    filename=filename,
                ))

        with CallOnExit(lambda: FileSystem.RemoveFile(temp_filename)):
            # Run the generated file
            command_line = 'python "{}"'.format(temp_filename)

            sink = six.moves.StringIO()
            output_stream = StreamDecorator([
                sink,
                verbose_stream,
            ])

            regex_sink = six.moves.StringIO()
            Process.Execute(command_line,
                            StreamDecorator([
                                regex_sink,
                                output_stream,
                            ]))
            regex_sink = regex_sink.getvalue()

            result = 0

            # Extract the results
            match = re.search(
                r"Your code has been rated at (?P<score>[-\d\.]+)/(?P<max>[\d\.]+)",
                regex_sink,
                re.MULTILINE,
            )

            if not match:
                result = -1
            else:
                score = float(match.group("score"))
                max_score = float(match.group("max"))
                assert max_score != 0.0

                # Don't measure scores for files in Impl directories
                is_impl_file = os.path.basename(filename).endswith("Impl")

                if is_impl_file and not context["explicit_passing_score"]:
                    passing_score = None
                else:
                    passing_score = context["passing_score"]

                output_stream.write(
                    textwrap.dedent("""\
                    Score:                  {score} (out of {max_score})
                    Passing Score:          {passing_score}{explicit}

                    """).format(
                        score=score,
                        max_score=max_score,
                        passing_score=passing_score,
                        explicit=" (explicitly provided)"
                        if context["explicit_passing_score"] else '',
                    ))

                if passing_score is not None and score < passing_score:
                    result = -1

            if result != 0 and not verbose:
                status_stream.write(sink.getvalue())

            return result