blob: a96ef9f47eb602c8a04fa71efae785392bf155bb [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Find disabled tests.
This script assumes that it's run in the root directory of a Fuchsia
checkout.
"""
# pylint: disable=consider-using-with,unspecified-encoding
import datetime
import json
import os
import sys
import tempfile
import unittest
import re
# Files matching these types are scraped for various flags and patterns associated with
# disabled tests.
RUST_EXT = ".rs"
DART_EXT = ".dart"
BUILD_EXT = ".gn"
C_EXT = ".cc"
# Mapping language to method of disablement.
# Lines with flags that match these are considered disabled. See
# https://fuchsia.dev/fuchsia-src/development/testing/faq#disable-test for more details on
# language-specific approaches
DISABLED_FLAG_MAP = {
C_EXT: [
"DISABLED_",
".disabled = true",
],
RUST_EXT: [
"#[test]\n#[ignore]",
],
}
# Additionally, tests can be disabled by being commented out. This regex searches files for comments
# that reference disabling or enabling tests or flakes. This is a hacky approach, but catches many
# disabled tests.
TODO_ENABLE = re.compile(r"^(\/\/|\#).*(TODO).*(enable|disable).*(flake|test).*")
# This regex intends to capture a bug, if one is present in a comment caught by the TODO_ENABLE regex.
FXB_REGEX = re.compile(r"fxb.*\/(\d+)")
def main():
args = sys.argv[1:]
tmp_json = args[0]
curpath = os.path.abspath(os.path.curdir)
disabled_tests = []
exclude = set(["third_party"])
# Search for files matching select file extensions
for dirpath, dirs, files in os.walk(curpath):
dirs[:] = [d for d in dirs if d not in exclude]
for filename in files:
fname = os.path.join(dirpath, filename)
file_ext = os.path.splitext(filename)[1]
if file_ext in (RUST_EXT, DART_EXT, BUILD_EXT, C_EXT):
find_disabled_tests(fname, disabled_tests, curpath, file_ext)
with open(tmp_json, "w") as f:
json.dump(disabled_tests, f, indent=1, separators=(",", ": "))
# Identify disabled tests in a file by searching for either a lanague-specific flag or a comment matching
# the TODO_ENABLE regex.
def find_disabled_tests(file_path, disabled_tests, curpath, file_ext):
with open(file_path) as f:
for i, line in enumerate(f.readlines()):
line = line.strip()
# Check for TODO and language-specific flags identifying a disabled tests
if TODO_ENABLE.match(line) or any(
pattern in line for pattern in DISABLED_FLAG_MAP.get(file_ext, [])
):
bug = FXB_REGEX.search(line)
date = str(datetime.date.today()) # E.g. "2021-05-27".
disabled_tests.append(
{
"path": os.path.relpath(file_path, curpath),
"line_number": i + 1,
"bug": bug.group(1) if bug else "",
"compiled": file_ext is BUILD_EXT,
"date_discovered": date,
}
)
class TestFindDisabledTest(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.TemporaryDirectory("find_disabled_tests")
def test_cc_file(self):
got = []
path = os.path.join(self.tempdir.name, "test.cc")
date = str(datetime.date.today()) # E.g. "2021-05-27".
with open(path, "w") as f:
f.write(
"\n".join(
[
"// TODO(fxbug.dev/12345) re-enable this test when de-flaked",
"fn flaky_test_we_need_to_fix() { ... }",
"TEST_F(BlobfsTest, DISABLED_CorruptBlobNotify) { RunBlobCorruptionTest(); }",
]
)
)
find_disabled_tests(path, got, self.tempdir.name, ".cc")
want = [
{
"path": "test.cc",
"line_number": 1,
"bug": "12345",
"compiled": False,
"date": date,
},
{
"path": "test.cc",
"line_number": 3,
"bug": "",
"compiled": False,
"date": date,
},
]
self.assertEqual(got, want)
def test_rs_file(self):
got = []
path = os.path.join(self.tempdir.name, "test.rs")
date = str(datetime.date.today()) # E.g. "2021-05-27".
with open(path, "w") as f:
f.write(
"\n".join(
[
"use std::thread;",
"\n",
"#[test]",
"#[ignore]",
"fn works() {",
"const N: usize = 4;",
"}",
]
)
)
find_disabled_tests(path, got, self.tempdir.name, ".gn")
want = [
{
"path": "test.rs",
"line_number": 1,
"bug": "",
"compiled": False,
"date": date,
},
]
self.assertEqual(got, want)
def tearDown(self):
self.tempdir.cleanup()
if __name__ == "__main__":
main()