You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
3.6 KiB
102 lines
3.6 KiB
#!/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()
|