Exemple #1
0
 def test_unified_diff_handles_unicode_inputs(self):
     # Though expected and actual files should always be read in with no
     # encoding (and be stored as str objects), test unicode inputs just to
     # be safe.
     unified_diff(u'exp', 'act', 'exp.txt', 'act.txt')
     unified_diff(u'a\xac\u1234\u20ac\U00008000', 'act', 'exp.txt',
                  'act.txt')
 def create_artifacts(self, typ_artifacts, force_overwrite=False):
     # TODO (rmhasan): See if you can can only output diff files for
     # non empty text.
     super(FailureText, self).create_artifacts(typ_artifacts,
                                               force_overwrite)
     expected_text = self.expected_driver_output.text or ''
     actual_text = self.actual_driver_output.text or ''
     artifacts_abs_path = self.filesystem.join(
         self.result_directory, typ_artifacts.ArtifactsSubDirectory())
     diff_content = unified_diff(
         expected_text, actual_text,
         self.filesystem.join(artifacts_abs_path,
                              self.expected_artifact_filename),
         self.filesystem.join(artifacts_abs_path,
                              self.actual_artifact_filename))
     diff_filename = self.port.output_filename(self.test_name,
                                               FILENAME_SUFFIX_DIFF, '.txt')
     html_diff_content = html_diff(expected_text, actual_text)
     html_diff_filename = self.port.output_filename(
         self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')
     self._write_to_artifacts(typ_artifacts, 'text_diff', diff_filename,
                              diff_content, force_overwrite)
     self._write_to_artifacts(typ_artifacts, 'pretty_text_diff',
                              html_diff_filename, html_diff_content,
                              force_overwrite)
Exemple #3
0
 def create_artifacts(self, typ_artifacts, force_overwrite=False):
     # TODO (rmhasan): See if you can can only output diff files for
     # non empty text.
     super(FailureText, self).create_artifacts(typ_artifacts,
                                               force_overwrite)
     expected_text = self.expected_driver_output.text or ''
     actual_text = self.actual_driver_output.text or ''
     artifacts_abs_path = self.filesystem.join(
         self.result_directory, typ_artifacts.ArtifactsSubDirectory())
     diff_content = unified_diff(
         expected_text, actual_text,
         self.filesystem.join(artifacts_abs_path,
                              self.expected_artifact_filename),
         self.filesystem.join(artifacts_abs_path,
                              self.actual_artifact_filename))
     diff_filename = self.port.output_filename(self.test_name,
                                               FILENAME_SUFFIX_DIFF, '.txt')
     html_diff_content = html_diff(expected_text, actual_text)
     html_diff_filename = self.port.output_filename(
         self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')
     # TODO(crbug/1197331): Investigate why some cases in PY2
     # throw DecodeError while encoding the 'str' type here.
     if six.PY3:
         diff_content = diff_content.encode('utf8', 'replace')
         html_diff_content = html_diff_content.encode('utf8', 'replace')
     else:
         diff_content = diff_content
         html_diff_content = html_diff_content
     self._write_to_artifacts(typ_artifacts, 'text_diff', diff_filename,
                              diff_content, force_overwrite)
     self._write_to_artifacts(typ_artifacts, 'pretty_text_diff',
                              html_diff_filename, html_diff_content,
                              force_overwrite)
Exemple #4
0
    def _handle_text_outputs(self, actual_metadata, root_node, results_dir,
                             path_so_far):
        """Produces actual, expected and diff text outputs."""
        # If the test passed, there are no artifacts to output. Note that if a
        # baseline file (*.ini file) exists, an actual of PASS means that the
        # test matched the baseline, not that the test itself passed. As such,
        # we still correctly produce artifacts in the case where someone fixes a
        # baselined test.
        if root_node["actual"] == "PASS":
            return

        # Note that the actual_metadata is a list of strings, so we join
        # them on new lines when writing to file.
        actual_text = "\n".join(actual_metadata)
        actual_subpath = self._write_text_artifact(
            test_failures.FILENAME_SUFFIX_ACTUAL, results_dir, path_so_far,
            actual_text)
        root_node["artifacts"]["actual_text"] = [actual_subpath]

        # Try to locate the expected output of this test, if it exists.
        expected_subpath, expected_text = \
            self._maybe_write_expected_output(results_dir, path_so_far)
        if expected_subpath:
            root_node["artifacts"]["expected_text"] = [expected_subpath]
            diff_content = unified_diff(expected_text, actual_text,
                                        expected_subpath, actual_subpath)
            diff_subpath = self._write_text_artifact(
                test_failures.FILENAME_SUFFIX_DIFF, results_dir, path_so_far,
                diff_content)
            root_node["artifacts"]["text_diff"] = [diff_subpath]

            # The html_diff library requires str arguments but the file
            # contents is read-in as unicode. In python3 the contents comes
            # in as a str, but in python2 it remains type unicode, so we
            # have to encode it to get the str version.
            if six.PY2:
                expected_text = expected_text.encode('utf8')
                actual_text = actual_text.encode('utf8')

            html_diff_content = html_diff(expected_text, actual_text)
            if six.PY2:
                # Ensure the diff itself is properly decoded, to avoid
                # UnicodeDecodeErrors when writing to file. This can happen if
                # the diff contains unicode characters but the file is written
                # as ascii because of the default system-level encoding.
                html_diff_content = unicode(html_diff_content, 'utf8')

            html_diff_subpath = self._write_text_artifact(
                test_failures.FILENAME_SUFFIX_HTML_DIFF,
                results_dir,
                path_so_far,
                html_diff_content,
                extension=".html")
            root_node["artifacts"]["pretty_text_diff"] = [html_diff_subpath]
    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        # TODO (rmhasan): See if you can can only output diff files for
        # non empty text.
        super(FailureText, self).create_artifacts(typ_artifacts,
                                                  force_overwrite)

        actual_text = ''
        expected_text = ''
        if self.expected_driver_output.text is not None:
            if six.PY3:
                # TODO(crbug/1197331): We should not decode here looks like.
                # html_diff expects it to be bytes for comparing to account
                # various types of encodings.
                # html_diff.py and unified_diff.py use str types during
                # diff fixup. Will handle it later.
                expected_text = self.expected_driver_output.text.decode(
                    'utf8', 'replace')
            else:
                expected_text = self.expected_driver_output.text

        if self.actual_driver_output.text is not None:
            if six.PY3:
                # TODO(crbug/1197331): ditto as in the case of expected_text above.
                actual_text = self.actual_driver_output.text.decode(
                    'utf8', 'replace')
            else:
                actual_text = self.actual_driver_output.text

        artifacts_abs_path = self.filesystem.join(
            self.result_directory, typ_artifacts.ArtifactsSubDirectory())
        diff_content = unified_diff(
            expected_text, actual_text,
            self.filesystem.join(artifacts_abs_path,
                                 self.expected_artifact_filename),
            self.filesystem.join(artifacts_abs_path,
                                 self.actual_artifact_filename))
        diff_filename = self.port.output_filename(self.test_name,
                                                  FILENAME_SUFFIX_DIFF, '.txt')
        html_diff_content = html_diff(expected_text, actual_text)
        html_diff_filename = self.port.output_filename(
            self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')

        # TODO(crbug/1197331): Revisit while handling the diff modules.
        if diff_content and six.PY3:
            diff_content = diff_content.encode('utf8', 'replace')
        if html_diff_content and six.PY3:
            html_diff_content = html_diff_content.encode('utf8', 'replace')

        self._write_to_artifacts(typ_artifacts, 'text_diff', diff_filename,
                                 diff_content, force_overwrite)
        self._write_to_artifacts(typ_artifacts, 'pretty_text_diff',
                                 html_diff_filename, html_diff_content,
                                 force_overwrite)
 def test_unified_diff_handles_unicode_file_names(self):
     # Make sure that we don't run into decoding exceptions when the
     # filenames are unicode, with regular or malformed input (expected or
     # actual input is always raw bytes, not unicode).
     unified_diff('exp', 'act', 'exp.txt', 'act.txt')
     unified_diff('exp', 'act', u'exp.txt', 'act.txt')
     unified_diff('exp', 'act', u'a\xac\u1234\u20ac\U00008000', 'act.txt')
Exemple #7
0
    def _handle_log_artifact(self, log_artifact, root_node, results_dir,
                             path_so_far):
        # If the test passed, there are no artifacts to output. Note that if a
        # baseline file (*.ini file) exists, an actual of PASS means that the
        # test matched the baseline, not that the test itself passed. As such,
        # we still correctly produce artifacts in the case where someone fixes a
        # baselined test.
        if root_node["actual"] == "PASS":
            return

        # Note that the log_artifact is a list of strings, so we join
        # them on new lines when writing to file.
        actual_text = "\n".join(log_artifact)
        actual_subpath = self._write_text_artifact(
            test_failures.FILENAME_SUFFIX_ACTUAL, results_dir, path_so_far,
            actual_text)
        root_node["artifacts"]["actual_text"] = [actual_subpath]
        # Try to locate the expected output of this test, if it exists.
        expected_subpath, expected_text = \
            self._maybe_write_expected_output(results_dir, path_so_far)
        if expected_subpath:
            root_node["artifacts"]["expected_text"] = [expected_subpath]

        diff_content = unified_diff(expected_text, actual_text,
                                    expected_subpath, actual_subpath)
        diff_subpath = self._write_text_artifact(
            test_failures.FILENAME_SUFFIX_DIFF, results_dir, path_so_far,
            diff_content)
        root_node["artifacts"]["text_diff"] = [diff_subpath]
        # We pass the text as bytes here because the html_diff library
        # requires that but the file contents is read-in as unicode.
        html_diff_content = html_diff(expected_text.encode('utf-8'),
                                      actual_text.encode('utf-8'))
        # Ensure the diff itself is properly decoded, to avoid
        # UnicodeDecodeErrors when writing to file. This can happen if
        # the diff contains unicode characters but the file is written
        # as ascii because of the default system-level encoding.
        html_diff_content = unicode(html_diff_content, 'utf-8')
        html_diff_subpath = self._write_text_artifact(
            test_failures.FILENAME_SUFFIX_HTML_DIFF,
            results_dir,
            path_so_far,
            html_diff_content,
            extension=".html")
        root_node["artifacts"]["pretty_text_diff"] = [html_diff_subpath]
    def create_text_diff_and_write_result(self, actual_text, expected_text):
        # FIXME: This function is actually doing the diffs as well as writing results.
        # It might be better to extract code which does 'diff' and make it a separate function.
        actual_text = actual_text or ''
        expected_text = expected_text or ''

        # Output a plain-text diff file.
        file_type = '.txt'
        actual_filename = self._output_abspath(self.FILENAME_SUFFIX_ACTUAL, file_type)
        expected_filename = self._output_abspath(self.FILENAME_SUFFIX_EXPECTED, file_type)
        diff = unified_diff(expected_text, actual_text, expected_filename, actual_filename)
        diff_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFF, file_type)
        self._write_file(diff_filename, diff)

        # Output a HTML diff file.
        html_diff_filename = self._output_abspath(self.FILENAME_SUFFIX_HTML_DIFF, '.html')
        html_diff_contents = html_diff(expected_text, actual_text)
        self._write_file(html_diff_filename, html_diff_contents)
 def test_unified_diff_handles_non_ascii_chars(self):
     unified_diff('exp' + chr(255), 'act', 'exp.txt', 'act.txt')
     unified_diff('exp' + chr(255), 'act', u'exp.txt', 'act.txt')
 def test_unified_diff_missing_newline(self):
     self.assertEqual(
         unified_diff('Hello\n\nWorld', 'Hello\n\nWorld\n\n\n', 'exp.txt', 'act.txt'),
         '--- exp.txt\n+++ act.txt\n@@ -1,3 +1,5 @@\n Hello\n \n-World\n\\ No newline at end of file\n+World\n+\n+\n')
 def test_unified_diff(self):
     self.assertEqual(
         unified_diff('foo\n', 'bar\n', 'exp.txt', 'act.txt'),
         '--- exp.txt\n+++ act.txt\n@@ -1 +1 @@\n-foo\n+bar\n')
Exemple #12
0
    def _process_test_leaves(self, results_dir, delim, root_node, path_so_far):
        """Finds and processes each test leaf below the specified root.

        This will recursively traverse the trie of results in the json output,
        keeping track of the path to each test and identifying leaves by the
        presence of certain attributes.

        Args:
            results_dir: str path to the dir that results are stored
            delim: str delimiter to be used for test names
            root_node: dict representing the root of the trie we're currently
                looking at
            path_so_far: str the path to the current root_node in the trie
        """
        if "actual" in root_node:
            # Found a leaf, process it
            if "artifacts" not in root_node:
                return
            log_artifact = root_node["artifacts"].pop("log", None)
            if log_artifact:
                # Note that the log_artifact is a list of strings, so we join
                # them on new lines when writing to file.
                actual_text = "\n".join(log_artifact)
                actual_subpath = self._write_text_artifact(
                    test_failures.FILENAME_SUFFIX_ACTUAL, results_dir,
                    path_so_far, actual_text)
                root_node["artifacts"]["actual_text"] = [actual_subpath]
                # Try to locate the expected output of this test, if it exists.
                expected_subpath, expected_text = \
                    self._maybe_write_expected_output(results_dir, path_so_far)
                if expected_subpath:
                    root_node["artifacts"]["expected_text"] = [
                        expected_subpath
                    ]

                diff_content = unified_diff(expected_text, actual_text,
                                            expected_subpath, actual_subpath)
                diff_subpath = self._write_text_artifact(
                    test_failures.FILENAME_SUFFIX_DIFF, results_dir,
                    path_so_far, diff_content)
                root_node["artifacts"]["text_diff"] = [diff_subpath]
                # We pass the text as bytes here because the html_diff library
                # requires that but the file contents is read-in as unicode.
                html_diff_content = html_diff(expected_text.encode('utf-8'),
                                              actual_text.encode('utf-8'))
                # Ensure the diff itself is properly decoded, to avoid
                # UnicodeDecodeErrors when writing to file. This can happen if
                # the diff contains unicode characters but the file is written
                # as ascii because of the default system-level encoding.
                html_diff_content = unicode(html_diff_content, 'utf-8')
                html_diff_subpath = self._write_text_artifact(
                    test_failures.FILENAME_SUFFIX_HTML_DIFF,
                    results_dir,
                    path_so_far,
                    html_diff_content,
                    extension=".html")
                root_node["artifacts"]["pretty_text_diff"] = [
                    html_diff_subpath
                ]

            screenshot_artifact = root_node["artifacts"].pop(
                "screenshots", None)
            if screenshot_artifact:
                screenshot_paths_dict = self._write_screenshot_artifact(
                    results_dir, path_so_far, screenshot_artifact)
                for screenshot_key, path in screenshot_paths_dict.items():
                    root_node["artifacts"][screenshot_key] = [path]

            crashlog_artifact = root_node["artifacts"].pop(
                "wpt_crash_log", None)
            if crashlog_artifact:
                # Note that the crashlog_artifact is a list of strings, so we
                # join them on new lines when writing to file.
                artifact_subpath = self._write_text_artifact(
                    test_failures.FILENAME_SUFFIX_CRASH_LOG, results_dir,
                    path_so_far, "\n".join(crashlog_artifact))
                if artifact_subpath:
                    root_node["artifacts"]["crash_log"] = [artifact_subpath]

            return

        # We're not at a leaf node, continue traversing the trie.
        for key in root_node:
            # Append the key to the path, separated by the delimiter. However if
            # the path is empty, skip the delimiter to avoid a leading slash in
            # the path.
            new_path = path_so_far + delim + key if path_so_far else key
            self._process_test_leaves(results_dir, delim, root_node[key],
                                      new_path)