aboutsummaryrefslogtreecommitdiff
path: root/llvm_tools/bisect_clang_crashes_unittest.py
blob: 22c9be19c3a1ff80c0ea9c456e9f64d88d551079 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for bisect_clang_crashes."""

import glob
import logging
import os.path
import subprocess
import unittest
import unittest.mock as mock

import bisect_clang_crashes


class Test(unittest.TestCase):
    """Tests for bisect_clang_crashes."""

    class _SilencingFilter(object):
        """Silences all log messages.

        Also collects info about log messages that would've been emitted.
        """

        def __init__(self):
            self.messages = []

        def filter(self, record):
            self.messages.append(record.getMessage())
            return 0

    @mock.patch.object(subprocess, "check_output")
    def test_get_artifacts(self, mock_gsutil_ls):
        pattern = (
            "gs://chromeos-toolchain-artifacts/clang-crash-diagnoses/"
            "**/*clang_crash_diagnoses.tar.xz"
        )
        mock_gsutil_ls.return_value = "artifact1\nartifact2\nartifact3"
        results = bisect_clang_crashes.get_artifacts(pattern)
        self.assertEqual(results, ["artifact1", "artifact2", "artifact3"])
        mock_gsutil_ls.assert_called_once_with(
            ["gsutil.py", "ls", pattern],
            stderr=subprocess.STDOUT,
            encoding="utf-8",
        )

    @mock.patch.object(os.path, "exists")
    @mock.patch.object(glob, "glob")
    def test_get_crash_reproducers_succeed(
        self, mock_file_search, mock_file_check
    ):
        working_dir = "SomeDirectory"
        mock_file_search.return_value = ["a.c", "b.cpp", "c.cc"]
        mock_file_check.side_effect = [True, True, True]
        results = bisect_clang_crashes.get_crash_reproducers(working_dir)
        mock_file_search.assert_called_once_with("%s/*.c*" % working_dir)
        self.assertEqual(mock_file_check.call_count, 3)
        self.assertEqual(mock_file_check.call_args_list[0], mock.call("a.sh"))
        self.assertEqual(mock_file_check.call_args_list[1], mock.call("b.sh"))
        self.assertEqual(mock_file_check.call_args_list[2], mock.call("c.sh"))
        self.assertEqual(
            results, [("a.c", "a.sh"), ("b.cpp", "b.sh"), ("c.cc", "c.sh")]
        )

    @mock.patch.object(os.path, "exists")
    @mock.patch.object(glob, "glob")
    def test_get_crash_reproducers_no_matching_script(
        self, mock_file_search, mock_file_check
    ):
        def silence_logging():
            root = logging.getLogger()
            filt = self._SilencingFilter()
            root.addFilter(filt)
            self.addCleanup(root.removeFilter, filt)
            return filt

        log_filter = silence_logging()
        working_dir = "SomeDirectory"
        mock_file_search.return_value = ["a.c", "b.cpp", "c.cc"]
        mock_file_check.side_effect = [True, False, True]
        results = bisect_clang_crashes.get_crash_reproducers(working_dir)
        mock_file_search.assert_called_once_with("%s/*.c*" % working_dir)
        self.assertEqual(mock_file_check.call_count, 3)
        self.assertEqual(mock_file_check.call_args_list[0], mock.call("a.sh"))
        self.assertEqual(mock_file_check.call_args_list[1], mock.call("b.sh"))
        self.assertEqual(mock_file_check.call_args_list[2], mock.call("c.sh"))
        self.assertEqual(results, [("a.c", "a.sh"), ("c.cc", "c.sh")])
        self.assertTrue(
            any(
                "could not find the matching script of b.cpp" in x
                for x in log_filter.messages
            ),
            log_filter.messages,
        )


if __name__ == "__main__":
    unittest.main()