|
86 | 86 | for suffix in _SYNTHETIC_SUITE_SUFFIXES |
87 | 87 | ) |
88 | 88 |
|
| 89 | +# The GitLab sanitizer gtest jobs run native binaries that never link a JDK, |
| 90 | +# so their cells carry no jdk axis and no slow-suite suffix -- three tokens |
| 91 | +# only (the quarantine.txt gtest section documents the shape). Without these |
| 92 | +# in the universe, cells_overlap() fails closed for every gtest glob and two |
| 93 | +# genuinely disjoint entries (asan vs tsan) read as duplicates. |
| 94 | +SYNTHETIC_CELLS += tuple( |
| 95 | + "glibc-{}-{}".format(config, arch) |
| 96 | + for config in _SYNTHETIC_CONFIGS |
| 97 | + for arch in KNOWN_ARCHES |
| 98 | +) |
| 99 | + |
89 | 100 |
|
90 | 101 | def _matches_any_synthetic_cell(globs): |
91 | 102 | return any(any(fnmatch.fnmatch(cell, g) for g in globs) for cell in SYNTHETIC_CELLS) |
@@ -184,9 +195,31 @@ def covers(entry, test_id): |
184 | 195 | # the merge gate for the entire repository from one validate-clean |
185 | 196 | # line. |
186 | 197 | prefix = pattern[:-1] |
187 | | - if not test_id.startswith(prefix): |
| 198 | + if test_id.startswith(prefix): |
| 199 | + # The remainder may carry a trailing "/0"-style suffix: Java |
| 200 | + # writes none, but gtest value-parameterized cases are named |
| 201 | + # "Case/0", and the Java rule's only real constraint is that the |
| 202 | + # remainder holds no further class/case separator dot. |
| 203 | + return "." not in test_id[len(prefix):] |
| 204 | + # GoogleTest bakes its suite decorations into the XML classname, not |
| 205 | + # into the entry: value-parameterized suites are "<inst>/<suite>" |
| 206 | + # (the "/0" lands on the case name), typed suites "<suite>/<typeidx>", |
| 207 | + # and combinations "<inst>/<suite>/<typeidx>". Reduce the classname to |
| 208 | + # its bare suite -- drop a trailing all-digits segment, then take the |
| 209 | + # last "/" segment -- and compare that. Java classnames never contain |
| 210 | + # "/", so this branch is unreachable for a Java id. |
| 211 | + cls, _, _ = test_id.rpartition(".") |
| 212 | + if not cls or "/" not in cls: |
188 | 213 | return False |
189 | | - return "." not in test_id[len(prefix):] |
| 214 | + segments = cls.split("/") |
| 215 | + if len(segments) > 1 and segments[-1].isdigit(): |
| 216 | + segments.pop() |
| 217 | + if segments[-1] + "." == prefix: |
| 218 | + return True |
| 219 | + # A decorated entry ("MyInst/WobblySuite.*") also covers the typed |
| 220 | + # variants of its own instantiation ("MyInst/WobblySuite/0.case"): |
| 221 | + # the full undecorated classname must equal the prefix's suite too. |
| 222 | + return "/".join(segments) + "." == prefix |
190 | 223 | return test_id == pattern |
191 | 224 |
|
192 | 225 |
|
@@ -317,6 +350,12 @@ def complain(line, message): |
317 | 350 | "normalises the report's id to that shape -- drop the '()'" |
318 | 351 | ).format(entry["test"])) |
319 | 352 |
|
| 353 | + # A decorated gtest suite name ("<inst>/<Suite>.*") in a class-wide |
| 354 | + # entry is valid and narrower than the bare-suite form: covers() |
| 355 | + # matches it directly against the decorated classname, muting only |
| 356 | + # that instantiation. No complaint - just do not claim it matches |
| 357 | + # nothing. |
| 358 | + |
320 | 359 | if _INVOCATION_INDEX_RE.match(entry["test"].rsplit(".", 1)[-1]): |
321 | 360 | complain(line, ( |
322 | 361 | "test '{}' names an invocation index. @ParameterizedTest and " |
|
0 commit comments