blob: 22c9be19c3a1ff80c0ea9c456e9f64d88d551079 [file] [log] [blame]
#!/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()