Revision 7d272015
Added by koszko over 1 year ago
tests/test_build.py | ||
---|---|---|
10 | 10 |
import pytest |
11 | 11 |
import json |
12 | 12 |
import shutil |
13 |
import functools as ft |
|
13 | 14 |
|
14 | 15 |
from tempfile import TemporaryDirectory |
15 | 16 |
from pathlib import Path, PurePosixPath |
... | ... | |
255 | 256 |
|
256 | 257 |
yield sample_source |
257 | 258 |
|
259 |
def collect(list): |
|
260 |
"""Decorate function by appending it to the specified list.""" |
|
261 |
def decorator(function): |
|
262 |
"""The actual decorator that will be applied.""" |
|
263 |
list.append(function) |
|
264 |
return function |
|
265 |
|
|
266 |
return decorator |
|
267 |
|
|
258 | 268 |
variant_makers = [] |
259 |
def variant_maker(function): |
|
260 |
"""Decorate function by placing it in variant_makers array.""" |
|
261 |
variant_makers.append(function) |
|
262 |
return function |
|
263 | 269 |
|
264 |
@variant_maker
|
|
270 |
@collect(variant_makers)
|
|
265 | 271 |
def sample_source_change_index_json(monkeypatch, sample_source): |
266 | 272 |
""" |
267 | 273 |
Return a non-standard path for index.json. Ensure parent directories exist. |
... | ... | |
272 | 278 |
path.parent.mkdir() |
273 | 279 |
return path |
274 | 280 |
|
275 |
@variant_maker
|
|
281 |
@collect(variant_makers)
|
|
276 | 282 |
def sample_source_add_comments(monkeypatch, sample_source): |
277 | 283 |
"""Add index.json comments that should be preserved.""" |
278 | 284 |
for dictionary in index_obj, *index_obj['definitions'], *expected: |
279 | 285 |
monkeypatch.setitem(dictionary, 'comment', 'index.json comment') |
280 | 286 |
|
281 |
@variant_maker
|
|
287 |
@collect(variant_makers)
|
|
282 | 288 |
def sample_source_remove_spdx(monkeypatch, sample_source): |
283 | 289 |
"""Remove spdx report generation.""" |
284 | 290 |
monkeypatch.delitem(index_obj, 'reuse_generate_spdx_report') |
... | ... | |
297 | 303 |
# raise an error if called. |
298 | 304 |
(sample_source / 'mock_reuse_missing').touch() |
299 | 305 |
|
300 |
@variant_maker
|
|
306 |
@collect(variant_makers)
|
|
301 | 307 |
def sample_source_remove_additional_files(monkeypatch, sample_source): |
302 | 308 |
"""Use default value ([]) for 'additionall_files' property.""" |
303 | 309 |
monkeypatch.delitem(index_obj, 'additional_files') |
... | ... | |
305 | 311 |
for name in 'README.txt', 'README.txt.license', '.reuse/dep5': |
306 | 312 |
monkeypatch.delitem(src_files, name) |
307 | 313 |
|
308 |
@variant_maker
|
|
314 |
@collect(variant_makers)
|
|
309 | 315 |
def sample_source_remove_script(monkeypatch, sample_source): |
310 | 316 |
"""Use default value ([]) for 'scripts' property in one of the resources.""" |
311 | 317 |
monkeypatch.delitem(index_obj['definitions'][2], 'scripts') |
... | ... | |
315 | 321 |
for files in dist_files, src_files: |
316 | 322 |
monkeypatch.delitem(files, 'message.js') |
317 | 323 |
|
318 |
@variant_maker
|
|
324 |
@collect(variant_makers)
|
|
319 | 325 |
def sample_source_remove_payloads(monkeypatch, sample_source): |
320 | 326 |
"""Use default value ({}) for 'payloads' property in mapping.""" |
321 | 327 |
monkeypatch.delitem(index_obj['definitions'][0], 'payloads') |
322 | 328 |
|
323 | 329 |
monkeypatch.setitem(expected_mapping, 'payloads', {}) |
324 | 330 |
|
325 |
@variant_maker
|
|
331 |
@collect(variant_makers)
|
|
326 | 332 |
def sample_source_remove_uuids(monkeypatch, sample_source): |
327 | 333 |
"""Don't use UUIDs (they are optional).""" |
328 | 334 |
for definition in index_obj['definitions']: |
... | ... | |
332 | 338 |
if 'uuid' in description: |
333 | 339 |
monkeypatch.delitem(description, 'uuid') |
334 | 340 |
|
335 |
@variant_maker
|
|
341 |
@collect(variant_makers)
|
|
336 | 342 |
def sample_source_add_extra_props(monkeypatch, sample_source): |
337 | 343 |
"""Add some unrecognized properties that should be stripped.""" |
338 | 344 |
to_process = [index_obj] |
... | ... | |
346 | 352 |
if k != 'payloads') |
347 | 353 |
monkeypatch.setitem(processed, 'spurious_property', 'some_value') |
348 | 354 |
|
349 |
@variant_maker
|
|
355 |
@collect(variant_makers)
|
|
350 | 356 |
def sample_source_make_version_2(monkeypatch, sample_source, |
351 | 357 |
expected_documents_to_modify=[]): |
352 |
"""Increase sources' schema version from to 2.""" |
|
358 |
"""Increase sources' schema version from 1 to 2."""
|
|
353 | 359 |
for obj in index_obj, *expected_documents_to_modify: |
354 | 360 |
monkeypatch.setitem(obj, '$schema', obj['$schema'].replace('1', '2')) |
355 | 361 |
|
356 |
@variant_maker |
|
357 |
def sample_source_cors_bypass_ignored(monkeypatch, sample_source, value=True): |
|
362 |
permission_variant_makers = [] |
|
363 |
|
|
364 |
@collect(permission_variant_makers) |
|
365 |
def sample_source_bool_perm_ignored(permission, monkeypatch, sample_source, |
|
366 |
value=True): |
|
358 | 367 |
""" |
359 |
Specify CORS bypass permissions in sources, but keep sources' schema version
|
|
368 |
Specify a boolean permissions in sources, but keep sources' schema version
|
|
360 | 369 |
at 1. |
361 | 370 |
""" |
362 | 371 |
for definition in index_obj['definitions']: |
363 |
monkeypatch.setitem(definition, 'permissions', {'cors_bypass': value})
|
|
372 |
monkeypatch.setitem(definition, 'permissions', {permission: value})
|
|
364 | 373 |
|
365 |
@variant_maker
|
|
366 |
def sample_source_cors_bypass(monkeypatch, sample_source):
|
|
367 |
"""Specify CORS bypass permissions in sources."""
|
|
368 |
sample_source_cors_bypass_ignored(monkeypatch, sample_source, value=True)
|
|
374 |
@collect(permission_variant_makers)
|
|
375 |
def sample_source_bool_perm(permission, monkeypatch, sample_source):
|
|
376 |
"""Specify a boolean permission in sources."""
|
|
377 |
sample_source_bool_perm_ignored(permission, monkeypatch, sample_source)
|
|
369 | 378 |
sample_source_make_version_2(monkeypatch, sample_source, expected_items) |
370 | 379 |
|
371 | 380 |
for obj in expected_items: |
372 |
monkeypatch.setitem(obj, 'permissions', {'cors_bypass': True})
|
|
381 |
monkeypatch.setitem(obj, 'permissions', {permission: True})
|
|
373 | 382 |
|
374 |
@variant_maker
|
|
375 |
def sample_source_cors_bypass_defaults(monkeypatch, sample_source):
|
|
383 |
@collect(permission_variant_makers)
|
|
384 |
def sample_source_bool_perm_defaults(permission, monkeypatch, sample_source):
|
|
376 | 385 |
""" |
377 |
Specify CORS bypass permissions in sources but use the default value |
|
378 |
("False"). |
|
386 |
Specify a boolean permission in sources but use the default value ("False"). |
|
379 | 387 |
""" |
380 |
sample_source_cors_bypass_ignored(monkeypatch, sample_source, value=False) |
|
388 |
sample_source_bool_perm_ignored(permission, monkeypatch, sample_source, |
|
389 |
value=False) |
|
381 | 390 |
sample_source_make_version_2(monkeypatch, sample_source) |
382 | 391 |
|
383 |
@variant_maker |
|
392 |
for permission in 'cors_bypass', 'eval': |
|
393 |
for variant_maker in permission_variant_makers: |
|
394 |
variant_makers.append(ft.partial(variant_maker, permission)) |
|
395 |
|
|
396 |
@collect(variant_makers) |
|
384 | 397 |
def sample_source_req_mappings_ignored(monkeypatch, sample_source, |
385 | 398 |
value=[{'identifier': 'mapping-dep'}]): |
386 | 399 |
""" |
... | ... | |
389 | 402 |
for definition in index_obj['definitions']: |
390 | 403 |
monkeypatch.setitem(definition, 'required_mappings', value); |
391 | 404 |
|
392 |
@variant_maker
|
|
405 |
@collect(variant_makers)
|
|
393 | 406 |
def sample_source_req_mappings(monkeypatch, sample_source): |
394 | 407 |
"""Specify dependencies on mappings.""" |
395 | 408 |
sample_source_req_mappings_ignored(monkeypatch, sample_source) |
... | ... | |
399 | 412 |
monkeypatch.setitem(obj, 'required_mappings', |
400 | 413 |
[{'identifier': 'mapping-dep'}]) |
401 | 414 |
|
402 |
@variant_maker
|
|
415 |
@collect(variant_makers)
|
|
403 | 416 |
def sample_source_req_mappings_defaults(monkeypatch, sample_source): |
404 | 417 |
"""Specify dependencies of a mapping, but use the default value ("[]").""" |
405 | 418 |
sample_source_req_mappings_ignored(monkeypatch, sample_source, value=[]) |
406 | 419 |
sample_source_make_version_2(monkeypatch, sample_source) |
407 | 420 |
|
408 |
@variant_maker
|
|
421 |
@collect(variant_makers)
|
|
409 | 422 |
def sample_source_combined_def(monkeypatch, sample_source): |
410 | 423 |
"""Define mapping and resource together.""" |
411 | 424 |
sample_source_make_version_2(monkeypatch, sample_source) |
... | ... | |
432 | 445 |
monkeypatch.setitem(expected_source_description['definitions'][0], |
433 | 446 |
'version', new_mapping_ver) |
434 | 447 |
|
435 |
@variant_maker
|
|
448 |
@collect(variant_makers)
|
|
436 | 449 |
def sample_source_minmax_haketilo_ver_ignored(monkeypatch, sample_source, |
437 | 450 |
min_ver=[1, 2], max_ver=[1, 2]): |
438 | 451 |
""" |
... | ... | |
443 | 456 |
monkeypatch.setitem(mapping_def, 'min_haketilo_version', min_ver) |
444 | 457 |
monkeypatch.setitem(mapping_def, 'max_haketilo_version', max_ver) |
445 | 458 |
|
446 |
@variant_maker
|
|
459 |
@collect(variant_makers)
|
|
447 | 460 |
def sample_source_minmax_haketilo_ver(monkeypatch, sample_source): |
448 | 461 |
"""Specify version constraints on Haketilo.""" |
449 | 462 |
sample_source_minmax_haketilo_ver_ignored(monkeypatch, sample_source) |
... | ... | |
452 | 465 |
monkeypatch.setitem(expected_mapping, 'min_haketilo_version', [1, 2]) |
453 | 466 |
monkeypatch.setitem(expected_mapping, 'max_haketilo_version', [1, 2]) |
454 | 467 |
|
455 |
@variant_maker
|
|
468 |
@collect(variant_makers)
|
|
456 | 469 |
def sample_source_minmax_haketilo_ver_default(monkeypatch, sample_source): |
457 | 470 |
"""Specify version constraints on Haketilo, but use default values.""" |
458 | 471 |
sample_source_minmax_haketilo_ver_ignored(monkeypatch, sample_source, |
... | ... | |
466 | 479 |
'othersystem/other-something.tar.gz' |
467 | 480 |
] |
468 | 481 |
|
469 |
@variant_maker
|
|
482 |
@collect(variant_makers)
|
|
470 | 483 |
def sample_source_add_piggyback_ignored(monkeypatch, sample_source, |
471 | 484 |
extra_build_args={}): |
472 | 485 |
""" |
... | ... | |
484 | 497 |
'dependencies': False |
485 | 498 |
}) |
486 | 499 |
|
487 |
@variant_maker
|
|
500 |
@collect(variant_makers)
|
|
488 | 501 |
def sample_source_add_piggyback(monkeypatch, sample_source, |
489 | 502 |
extra_build_args={}): |
490 | 503 |
"""Add piggybacked foreign system packages.""" |
... | ... | |
528 | 541 |
archive_path.parent.mkdir(parents=True, exist_ok=True) |
529 | 542 |
archive_path.write_text(f'dummy {archive_path.name}') |
530 | 543 |
|
531 |
@variant_maker
|
|
544 |
@collect(variant_makers)
|
|
532 | 545 |
def sample_source_add_piggyback_pass_archives(monkeypatch, sample_source): |
533 | 546 |
""" |
534 | 547 |
Add piggybacked foreign system packages, use pre-downloaded foreign package |
... | ... | |
542 | 555 |
sample_source_add_piggyback(monkeypatch, sample_source, |
543 | 556 |
{'piggyback_files': foreign_packages_dir}) |
544 | 557 |
|
545 |
@variant_maker
|
|
558 |
@collect(variant_makers)
|
|
546 | 559 |
def sample_source_add_piggyback_find_archives(monkeypatch, sample_source): |
547 | 560 |
""" |
548 | 561 |
Add piggybacked foreign system packages, use pre-downloaded foreign package |
... | ... | |
555 | 568 |
|
556 | 569 |
sample_source_add_piggyback(monkeypatch, sample_source) |
557 | 570 |
|
558 |
@variant_maker
|
|
571 |
@collect(variant_makers)
|
|
559 | 572 |
def sample_source_add_piggyback_no_download(monkeypatch, sample_source, |
560 | 573 |
pass_directory_to_build=False): |
561 | 574 |
""" |
... | ... | |
678 | 691 |
try_validate('api_source_description', expected_source_description) |
679 | 692 |
|
680 | 693 |
error_makers = [] |
681 |
def error_maker(function): |
|
682 |
"""Decorate function by placing it in error_makers array.""" |
|
683 |
error_makers.append(function) |
|
684 | 694 |
|
685 |
@error_maker
|
|
695 |
@collect(error_makers)
|
|
686 | 696 |
def sample_source_error_missing_file(monkeypatch, sample_source): |
687 | 697 |
""" |
688 | 698 |
Modify index.json to expect missing report.spdx file and cause an error. |
... | ... | |
690 | 700 |
monkeypatch.delitem(index_obj, 'reuse_generate_spdx_report') |
691 | 701 |
return FileReferenceError, '^referenced_file_report.spdx_missing$' |
692 | 702 |
|
693 |
@error_maker
|
|
703 |
@collect(error_makers)
|
|
694 | 704 |
def sample_source_error_index_schema(monkeypatch, sample_source): |
695 | 705 |
"""Modify index.json to be incompliant with the schema.""" |
696 | 706 |
monkeypatch.delitem(index_obj, 'definitions') |
697 | 707 |
return ValidationError, |
698 | 708 |
|
699 |
@error_maker
|
|
709 |
@collect(error_makers)
|
|
700 | 710 |
def sample_source_error_bad_comment(monkeypatch, sample_source): |
701 | 711 |
"""Modify index.json to have an invalid '/' in it.""" |
702 | 712 |
return json.JSONDecodeError, '^bad_comment: .*', \ |
703 | 713 |
json.dumps(index_obj) + '/something\n' |
704 | 714 |
|
705 |
@error_maker
|
|
715 |
@collect(error_makers)
|
|
706 | 716 |
def sample_source_error_bad_json(monkeypatch, sample_source): |
707 | 717 |
"""Modify index.json to not be valid json even after comment stripping.""" |
708 | 718 |
return json.JSONDecodeError, '', json.dumps(index_obj) + '???\n' |
709 | 719 |
|
710 |
@error_maker
|
|
720 |
@collect(error_makers)
|
|
711 | 721 |
def sample_source_error_missing_reuse(monkeypatch, sample_source): |
712 | 722 |
"""Cause mocked reuse process invocation to fail with FileNotFoundError.""" |
713 | 723 |
(sample_source / 'mock_reuse_missing').touch() |
714 | 724 |
return build.ReuseError, '^couldnt_execute_reuse_is_it_installed$' |
715 | 725 |
|
716 |
@error_maker
|
|
726 |
@collect(error_makers)
|
|
717 | 727 |
def sample_source_error_missing_license(monkeypatch, sample_source): |
718 | 728 |
"""Remove a file to make package REUSE-incompliant.""" |
719 | 729 |
(sample_source / 'README.txt.license').unlink() |
... | ... | |
733 | 743 |
|
734 | 744 |
return build.ReuseError, error_regex |
735 | 745 |
|
736 |
@error_maker
|
|
746 |
@collect(error_makers)
|
|
737 | 747 |
def sample_source_error_file_outside(monkeypatch, sample_source): |
738 | 748 |
"""Make index.json illegally reference a file outside srcdir.""" |
739 | 749 |
new_list = [*index_obj['copyright'], {'file': '../abc'}] |
740 | 750 |
monkeypatch.setitem(index_obj, 'copyright', new_list) |
741 | 751 |
return FileReferenceError, '^path_contains_double_dot_\\.\\./abc$' |
742 | 752 |
|
743 |
@error_maker
|
|
753 |
@collect(error_makers)
|
|
744 | 754 |
def sample_source_error_reference_itself(monkeypatch, sample_source): |
745 | 755 |
"""Make index.json illegally reference index.json.""" |
746 | 756 |
new_list = [*index_obj['copyright'], {'file': 'index.json'}] |
747 | 757 |
monkeypatch.setitem(index_obj, 'copyright', new_list) |
748 | 758 |
return FileReferenceError, '^loading_reserved_index_json$' |
749 | 759 |
|
750 |
@error_maker
|
|
760 |
@collect(error_makers)
|
|
751 | 761 |
def sample_source_error_report_excluded(monkeypatch, sample_source): |
752 | 762 |
""" |
753 | 763 |
Make index.json require generation of report.spdx but don't include it among |
... | ... | |
758 | 768 |
monkeypatch.setitem(index_obj, 'copyright', new_list) |
759 | 769 |
return FileReferenceError, '^report_spdx_not_in_copyright_list$' |
760 | 770 |
|
761 |
@error_maker
|
|
771 |
@collect(error_makers)
|
|
762 | 772 |
def sample_source_error_combined_unsupported(monkeypatch, sample_source): |
763 | 773 |
""" |
764 | 774 |
Define mapping and resource together but leave source schema version at 1.x |
Also available in: Unified diff
add "eval" permission