File: test_includes.py

package info (click to toggle)
firefox 148.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,719,544 kB
  • sloc: cpp: 7,618,291; javascript: 6,701,749; ansic: 3,781,787; python: 1,418,389; xml: 638,647; asm: 438,962; java: 186,285; sh: 62,894; makefile: 19,011; objc: 13,092; perl: 12,763; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (115 lines) | stat: -rw-r--r-- 3,691 bytes parent folder | download | duplicates (2)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
import re

import mozunit
import yaml

LINTER = "includes"

topsrcdir = os.path.join(os.path.dirname(__file__), "..", "..", "..")
api_yaml = os.path.join(topsrcdir, "mfbt", "api.yml")
assert os.path.exists(api_yaml), f"includes linter configuration missing in {api_yaml}"


def check_symbols_unicity(symbols):
    sorted_symbols = sorted(symbols)
    sorted_symbols_set = sorted(set(symbols))
    if sorted_symbols != sorted_symbols_set:
        # Not the most efficient implementation, but it rarely happens and it's readable.
        duplicates = [x for x in sorted_symbols_set if sorted_symbols.count(x) > 1]
        raise AssertionError(
            f"symbol{'s' if len(duplicates) > 1 else ''} listed more than once: {', '.join(duplicates)}"
        )


def test_lint_api_yml(lint):

    with open(api_yaml) as fd:
        description = yaml.safe_load(fd)

    category_re = {
        "variables": r"\b{}\b",
        "functions": r"\b{}\b",
        "macros": r"\b{}\b",
        "types": r"\b{}\b",
        "literal": r'\boperator""{}\b',
    }

    # Ensure all listed file exist and contain the described symbols
    mfbt_dir = os.path.join(topsrcdir, "mfbt")
    for header, categories in description.items():
        header_path = os.path.join(mfbt_dir, header)
        assert os.path.exists(header_path), (
            f"{header} described in {api_yaml}, but missing in mfbt/"
        )

        with open(header_path) as fd:
            header_content = fd.read()

        # NOTE: This detects removal of symbols in mfbt/* not reflected in
        # api.yml, but not addition of symbols.
        for category in ("variables", "functions", "macros", "types", "literal"):
            symbols = categories.get(category, [])
            check_symbols_unicity(symbols)
            for symbol in symbols:
                symbol_found = re.search(
                    category_re[category].format(symbol), header_content
                )
                assert symbol_found, (
                    f"{symbol} described as a {category} available in {header}, but cannot be found there"
                )


def test_lint_mfbt_includes(lint, paths):
    results = lint(paths("correct_assert.h"))
    assert not results

    results = lint(paths("incorrect_assert.h"))
    assert len(results) == 1
    assert results[0].message.endswith(
        "incorrect_assert.h includes Assertions.h but does not reference any of its API"
    )

    results = lint(paths("correct_literal.h"))
    assert not results

    results = lint(paths("incorrect_literal.h"))
    assert len(results) == 1
    assert results[0].message.endswith(
        "incorrect_literal.h includes Literals.h but does not reference any of its API"
    )


def test_lint_std_includes(lint, paths):
    results = lint(paths("correct_tuple.h"))
    assert not results

    results = lint(paths("incorrect_tuple.h"))
    assert len(results) == 1
    assert results[0].message.endswith(
        "incorrect_tuple.h includes <tuple> but does not reference any of its API"
    )


def test_lint_c_std_includes(lint, paths):
    results = lint(paths("correct_stdio.h"))
    assert not results

    results = lint(paths("correct_cstdio.h"))
    assert not results

    results = lint(paths("incorrect_stdio.h"))
    assert len(results) == 1
    assert results[0].message.endswith(
        "incorrect_stdio.h includes <stdio.h> but does not reference any of its API"
    )

    results = lint(paths("incorrect_cstdio.h"))
    assert len(results) == 1
    assert results[0].message.endswith(
        "incorrect_cstdio.h includes <cstdio> but does not reference any of its API"
    )


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