|
15 | 15 | ) |
16 | 16 |
|
17 | 17 | TEST_BASE_PATH = pathlib2.Path(__file__).parent |
| 18 | +IGNORE_FILE = f"{TEST_BASE_PATH}/files/packaging_warning/packaging_ignore.yml" |
| 19 | +DIVERSION_WARNING = ( |
| 20 | + "dpkg-shlibdeps: warning: diversions involved - output may be incorrect" |
| 21 | +) |
| 22 | +DIVERSION_FROM = " diversion by libc6 from: /lib/ld-linux-aarch64.so.1" |
| 23 | +DIVERSION_TO = " diversion by libc6 to: /lib/ld-linux-aarch64.so.1.usr-is-merged" |
| 24 | +KNOWN_DIVERSION = [DIVERSION_WARNING, DIVERSION_FROM, DIVERSION_WARNING, DIVERSION_TO] |
18 | 25 |
|
19 | 26 |
|
20 | 27 | def test_parse_ignore_lists(): |
@@ -205,3 +212,210 @@ def test_validate_output_rpm_success(): |
205 | 212 | f"{TEST_BASE_PATH}/files/packaging_warning/packaging_ignore.yml", |
206 | 213 | PackageType.rpm, |
207 | 214 | ) |
| 215 | + |
| 216 | + |
| 217 | +@pytest.mark.parametrize( |
| 218 | + "lines", |
| 219 | + [ |
| 220 | + pytest.param(KNOWN_DIVERSION, id="serial"), |
| 221 | + pytest.param(KNOWN_DIVERSION * 3, id="repeated"), |
| 222 | + pytest.param( |
| 223 | + [DIVERSION_WARNING, DIVERSION_WARNING, DIVERSION_TO, DIVERSION_FROM], |
| 224 | + id="interleaved", |
| 225 | + ), |
| 226 | + pytest.param( |
| 227 | + KNOWN_DIVERSION + [" dh_gencontrol -a"] + KNOWN_DIVERSION, |
| 228 | + id="separate-complete-blocks", |
| 229 | + ), |
| 230 | + ], |
| 231 | +) |
| 232 | +def test_known_arm64_diversion(lines): |
| 233 | + original_lines = lines.copy() |
| 234 | + assert filter_warning_lines(lines, PackageType.deb) == ([], []) |
| 235 | + validate_output("\n".join(lines), IGNORE_FILE, PackageType.deb) |
| 236 | + assert lines == original_lines |
| 237 | + |
| 238 | + |
| 239 | +def test_known_arm64_diversion_topn_noble_output(): |
| 240 | + # Original topn/Noble output, including warning/warning/to/from interleaving. |
| 241 | + output = ( |
| 242 | + TEST_BASE_PATH |
| 243 | + / "files/packaging_warning/sample_warning_build_output_deb_arm64_diversions.txt" |
| 244 | + ).read_text( |
| 245 | + encoding=DEFAULT_ENCODING_FOR_FILE_HANDLING, |
| 246 | + errors=DEFAULT_UNICODE_ERROR_HANDLER, |
| 247 | + ) |
| 248 | + assert filter_warning_lines(output.splitlines(), PackageType.deb) == ([], []) |
| 249 | + validate_output(output, IGNORE_FILE, PackageType.deb) |
| 250 | + |
| 251 | + |
| 252 | +@pytest.mark.parametrize( |
| 253 | + "source,target", |
| 254 | + [ |
| 255 | + pytest.param( |
| 256 | + DIVERSION_FROM.replace("libc6", "other"), |
| 257 | + DIVERSION_TO.replace("libc6", "other"), |
| 258 | + id="unknown-owner", |
| 259 | + ), |
| 260 | + pytest.param( |
| 261 | + DIVERSION_FROM.replace("libc6", "libc6:arm64"), |
| 262 | + DIVERSION_TO, |
| 263 | + id="different-owner-spelling", |
| 264 | + ), |
| 265 | + pytest.param( |
| 266 | + DIVERSION_FROM.replace("diversion by libc6", "local diversion"), |
| 267 | + DIVERSION_TO.replace("diversion by libc6", "local diversion"), |
| 268 | + id="local-diversion", |
| 269 | + ), |
| 270 | + pytest.param( |
| 271 | + DIVERSION_FROM.replace("aarch64", "x86-64"), |
| 272 | + DIVERSION_TO.replace("aarch64", "x86-64"), |
| 273 | + id="other-architecture", |
| 274 | + ), |
| 275 | + pytest.param( |
| 276 | + DIVERSION_FROM.replace("/lib/", "/usr/lib/"), |
| 277 | + DIVERSION_TO, |
| 278 | + id="other-source-path", |
| 279 | + ), |
| 280 | + pytest.param( |
| 281 | + DIVERSION_FROM, |
| 282 | + DIVERSION_TO.replace(".usr-is-merged", ".distrib"), |
| 283 | + id="other-target-path", |
| 284 | + ), |
| 285 | + pytest.param("", DIVERSION_TO, id="missing-source"), |
| 286 | + pytest.param(DIVERSION_FROM, "", id="missing-target"), |
| 287 | + pytest.param(DIVERSION_FROM, DIVERSION_TO + ".extra", id="target-suffix"), |
| 288 | + pytest.param(DIVERSION_FROM + " extra", DIVERSION_TO, id="extra-text"), |
| 289 | + pytest.param(DIVERSION_FROM.lstrip(), DIVERSION_TO, id="missing-indent"), |
| 290 | + pytest.param("\t" + DIVERSION_FROM, DIVERSION_TO, id="extra-indent"), |
| 291 | + pytest.param(DIVERSION_FROM, DIVERSION_TO + " ", id="trailing-space"), |
| 292 | + pytest.param( |
| 293 | + DIVERSION_FROM.replace("from:", "from"), |
| 294 | + DIVERSION_TO, |
| 295 | + id="malformed-record", |
| 296 | + ), |
| 297 | + pytest.param( |
| 298 | + DIVERSION_FROM, |
| 299 | + DIVERSION_TO.replace("to: /lib/ld-linux-aarch64.so.1.usr-is-merged", "to:"), |
| 300 | + id="incomplete-record", |
| 301 | + ), |
| 302 | + ], |
| 303 | +) |
| 304 | +@pytest.mark.parametrize("interleaved", [False, True]) |
| 305 | +def test_unknown_diversion_context(source, target, interleaved): |
| 306 | + if interleaved: |
| 307 | + lines = [DIVERSION_WARNING, DIVERSION_WARNING, target, source] |
| 308 | + else: |
| 309 | + lines = [DIVERSION_WARNING, source, DIVERSION_WARNING, target] |
| 310 | + assert filter_warning_lines(lines, PackageType.deb) == ( |
| 311 | + [DIVERSION_WARNING, DIVERSION_WARNING], |
| 312 | + [], |
| 313 | + ) |
| 314 | + # Valid records elsewhere must not rescue missing or unknown context. |
| 315 | + output = "\n".join(KNOWN_DIVERSION + lines + KNOWN_DIVERSION) |
| 316 | + with pytest.raises(SystemExit) as error: |
| 317 | + validate_output(output, IGNORE_FILE, PackageType.deb) |
| 318 | + assert error.value.code == 1 |
| 319 | + |
| 320 | + |
| 321 | +@pytest.mark.parametrize( |
| 322 | + "lines", |
| 323 | + [ |
| 324 | + pytest.param([DIVERSION_WARNING], id="no-context"), |
| 325 | + pytest.param([DIVERSION_WARNING, DIVERSION_FROM], id="source-only"), |
| 326 | + pytest.param([DIVERSION_WARNING, DIVERSION_TO], id="target-only"), |
| 327 | + pytest.param( |
| 328 | + [DIVERSION_WARNING, DIVERSION_WARNING, DIVERSION_FROM], |
| 329 | + id="truncated-interleaving", |
| 330 | + ), |
| 331 | + pytest.param([DIVERSION_WARNING, DIVERSION_FROM] * 2, id="unbalanced-source"), |
| 332 | + pytest.param([DIVERSION_WARNING, DIVERSION_TO] * 2, id="unbalanced-target"), |
| 333 | + pytest.param(KNOWN_DIVERSION + [DIVERSION_WARNING], id="extra-warning"), |
| 334 | + pytest.param( |
| 335 | + KNOWN_DIVERSION + [DIVERSION_FROM, DIVERSION_TO], |
| 336 | + id="extra-details", |
| 337 | + ), |
| 338 | + pytest.param( |
| 339 | + [DIVERSION_FROM, DIVERSION_WARNING, DIVERSION_WARNING, DIVERSION_TO], |
| 340 | + id="detail-before-warning", |
| 341 | + ), |
| 342 | + pytest.param( |
| 343 | + [DIVERSION_WARNING, DIVERSION_FROM, DIVERSION_TO, DIVERSION_WARNING], |
| 344 | + id="detail-overtakes-warning", |
| 345 | + ), |
| 346 | + pytest.param( |
| 347 | + KNOWN_DIVERSION |
| 348 | + + ["dpkg-shlibdeps: warning: cannot find library libunknown.so"], |
| 349 | + id="other-shlibdeps-warning", |
| 350 | + ), |
| 351 | + pytest.param( |
| 352 | + KNOWN_DIVERSION + ["dpkg-shlibdeps: error: unknown diagnostic"], |
| 353 | + id="extra-diagnostic-type", |
| 354 | + ), |
| 355 | + pytest.param( |
| 356 | + KNOWN_DIVERSION + [" local diversion from: /unknown"], |
| 357 | + id="extra-local-diversion", |
| 358 | + ), |
| 359 | + pytest.param( |
| 360 | + KNOWN_DIVERSION + [DIVERSION_WARNING + " extra"], |
| 361 | + id="nonliteral-warning", |
| 362 | + ), |
| 363 | + ], |
| 364 | +) |
| 365 | +def test_incomplete_or_ambiguous_diversion_block(lines): |
| 366 | + assert filter_warning_lines(lines, PackageType.deb) == ( |
| 367 | + [line for line in lines if "warning" in line.lower()], |
| 368 | + [], |
| 369 | + ) |
| 370 | + with pytest.raises(SystemExit) as error: |
| 371 | + validate_output("\n".join(lines), IGNORE_FILE, PackageType.deb) |
| 372 | + assert error.value.code == 1 |
| 373 | + |
| 374 | + |
| 375 | +@pytest.mark.parametrize( |
| 376 | + "boundary", |
| 377 | + ["", "unrelated output", " dh_gencontrol -a", "compiler: warning: unrelated"], |
| 378 | +) |
| 379 | +def test_diversion_context_does_not_cross_boundaries(boundary): |
| 380 | + lines = [ |
| 381 | + DIVERSION_WARNING, |
| 382 | + DIVERSION_FROM, |
| 383 | + boundary, |
| 384 | + DIVERSION_WARNING, |
| 385 | + DIVERSION_TO, |
| 386 | + ] |
| 387 | + base_warnings, _ = filter_warning_lines(lines, PackageType.deb) |
| 388 | + assert base_warnings.count(DIVERSION_WARNING) == 2 |
| 389 | + with pytest.raises(SystemExit): |
| 390 | + validate_output("\n".join(lines), IGNORE_FILE, PackageType.deb) |
| 391 | + |
| 392 | + |
| 393 | +@pytest.mark.parametrize("before", [False, True]) |
| 394 | +def test_unrelated_diversion_warning_remains_fatal(before): |
| 395 | + missing_context = [DIVERSION_WARNING] |
| 396 | + blocks = ( |
| 397 | + [missing_context, KNOWN_DIVERSION] |
| 398 | + if before |
| 399 | + else [KNOWN_DIVERSION, missing_context] |
| 400 | + ) |
| 401 | + lines = blocks[0] + [" dh_gencontrol -a"] + blocks[1] |
| 402 | + assert filter_warning_lines(lines, PackageType.deb) == ([DIVERSION_WARNING], []) |
| 403 | + with pytest.raises(SystemExit): |
| 404 | + validate_output("\n".join(lines), IGNORE_FILE, PackageType.deb) |
| 405 | + |
| 406 | + |
| 407 | +def test_known_diversion_does_not_ignore_lintian(): |
| 408 | + lintian_lines = ["package: W: unknown-warning", "package: E: unknown-error"] |
| 409 | + lines = KNOWN_DIVERSION + ["Now running lintian"] + lintian_lines |
| 410 | + assert filter_warning_lines(lines, PackageType.deb) == ([], lintian_lines) |
| 411 | + with pytest.raises(SystemExit): |
| 412 | + validate_output("\n".join(lines), IGNORE_FILE, PackageType.deb) |
| 413 | + |
| 414 | + |
| 415 | +def test_known_diversion_not_ignored_for_rpm(): |
| 416 | + assert filter_warning_lines(KNOWN_DIVERSION, PackageType.rpm) == ( |
| 417 | + [DIVERSION_WARNING, DIVERSION_WARNING], |
| 418 | + [], |
| 419 | + ) |
| 420 | + with pytest.raises(SystemExit): |
| 421 | + validate_output("\n".join(KNOWN_DIVERSION), IGNORE_FILE, PackageType.rpm) |
0 commit comments