xref: /trunk/test/aoo-test/src/aootest/expect.py (revision 2cb6d6f119bbe2f78742f1c5c8538cb0d4e72ede)
1################################################################
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20################################################################
21
22"""Known deviations as data: rows of test_name<TAB>kind<TAB>reason in data/expect/*.tsv, applied as pytest marks.
23
24test_name is the pytest item name including its parameter ids, e.g. test_formula_result[DCOUNT.zero.crit];
25a '*' matches any characters. kind is xfail (the item is expected to fail; it is reported XPASS when it starts to pass, and
26fails then under --strict-expect), flaky (it fails in some runs; never strict) or skip. The reason must say what is known, not guess."""
27import re
28
29from aootest.paths import DATA
30
31EXPECT_DIR = DATA / "expect"
32KINDS = ("xfail", "flaky", "skip")
33
34
35class Row:
36    def __init__(self, pattern, kind, reason, origin):
37        self.pattern, self.kind, self.reason, self.origin = pattern, kind, reason, origin
38        self.regex = re.compile("".join(".*" if c == "*" else re.escape(c) for c in pattern))
39        self.used = 0
40
41
42def load(directory=EXPECT_DIR):
43    rows = []
44    for path in sorted(directory.glob("*.tsv")):
45        for n, line in enumerate(open(path, encoding="utf-8"), 1):
46            if not line.strip() or line.startswith("#"):
47                continue
48            parts = line.rstrip("\n").split("\t")
49            if len(parts) != 3 or parts[1] not in KINDS or not parts[2].strip():
50                raise ValueError("%s:%d: expected test_name<TAB>xfail|flaky|skip<TAB>reason" % (path.name, n))
51            rows.append(Row(parts[0], parts[1], parts[2], "%s:%d" % (path.name, n)))
52    return rows
53
54
55def match(rows, name):
56    """The first row that matches the item name, or None."""
57    for r in rows:
58        if r.regex.fullmatch(name):
59            return r
60    return None
61