diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_build.py | 45 | ||||
-rw-r--r-- | tests/test_local_apt.py | 169 |
2 files changed, 156 insertions, 58 deletions
diff --git a/tests/test_build.py b/tests/test_build.py index a30cff4..77b1898 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -582,49 +582,64 @@ def sample_source_error_missing_file(monkeypatch, sample_source): Modify index.json to expect missing report.spdx file and cause an error. """ monkeypatch.delitem(index_obj, 'reuse_generate_spdx_report') - return FileNotFoundError + return FileNotFoundError, @error_maker def sample_source_error_index_schema(monkeypatch, sample_source): """Modify index.json to be incompliant with the schema.""" monkeypatch.delitem(index_obj, 'definitions') - return ValidationError + return ValidationError, @error_maker def sample_source_error_bad_comment(monkeypatch, sample_source): """Modify index.json to have an invalid '/' in it.""" - return json.JSONDecodeError, json.dumps(index_obj) + '/something\n' + return json.JSONDecodeError, '^bad_comment: .*', \ + json.dumps(index_obj) + '/something\n' @error_maker def sample_source_error_bad_json(monkeypatch, sample_source): """Modify index.json to not be valid json even after comment stripping.""" - return json.JSONDecodeError, json.dumps(index_obj) + '???/\n' + return json.JSONDecodeError, '', json.dumps(index_obj) + '???\n' @error_maker def sample_source_error_missing_reuse(monkeypatch, sample_source): """Cause mocked reuse process invocation to fail with FileNotFoundError.""" (sample_source / 'mock_reuse_missing').touch() - return build.ReuseError + return build.ReuseError, '^couldnt_execute_reuse_is_it_installed$' @error_maker def sample_source_error_missing_license(monkeypatch, sample_source): """Remove a file to make package REUSE-incompliant.""" (sample_source / 'README.txt.license').unlink() - return build.ReuseError + + error_regex = """^\ +command_reuse --root \\S+ lint_failed + +STDOUT_OUTPUT_heading + +dummy lint output + +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + return build.ReuseError, error_regex @error_maker def sample_source_error_file_outside(monkeypatch, sample_source): """Make index.json illegally reference a file outside srcdir.""" new_list = [*index_obj['copyright'], {'file': '../abc'}] monkeypatch.setitem(index_obj, 'copyright', new_list) - return FileReferenceError + return FileReferenceError, '^path_contains_double_dot_\\.\\./abc$' @error_maker def sample_source_error_reference_itself(monkeypatch, sample_source): """Make index.json illegally reference index.json.""" new_list = [*index_obj['copyright'], {'file': 'index.json'}] monkeypatch.setitem(index_obj, 'copyright', new_list) - return FileReferenceError + return FileReferenceError, '^loading_reserved_index_json$' @error_maker def sample_source_error_report_excluded(monkeypatch, sample_source): @@ -635,7 +650,7 @@ def sample_source_error_report_excluded(monkeypatch, sample_source): new_list = [file_ref for file_ref in index_obj['copyright'] if file_ref['file'] != 'report.spdx'] monkeypatch.setitem(index_obj, 'copyright', new_list) - return FileReferenceError + return FileReferenceError, '^report_spdx_not_in_copyright_list$' @pytest.fixture(params=error_makers) def sample_source_make_errors(request, monkeypatch, sample_source): @@ -644,10 +659,8 @@ def sample_source_make_errors(request, monkeypatch, sample_source): broken versions. Return an error type that should be raised when running test build. """ - index_text = None - error_type = request.param(monkeypatch, sample_source) - if type(error_type) is tuple: - error_type, index_text = error_type + error_type, error_regex, index_text = \ + [*request.param(monkeypatch, sample_source), '', ''][0:3] index_text = index_text or json.dumps(index_obj) @@ -655,13 +668,13 @@ def sample_source_make_errors(request, monkeypatch, sample_source): monkeypatch.setitem(src_files, 'index.json', index_text.encode()) - return error_type + return error_type, error_regex @pytest.mark.subprocess_run(build, run_reuse) @pytest.mark.usefixtures('mock_subprocess_run') def test_build_error(tmpdir, sample_source, sample_source_make_errors): """Try building the sample source package and verify generated errors.""" - error_type = sample_source_make_errors + error_type, error_regex = sample_source_make_errors dstdir = Path(tmpdir) / 'dstdir' tmpdir = Path(tmpdir) / 'example' @@ -669,6 +682,6 @@ def test_build_error(tmpdir, sample_source, sample_source_make_errors): dstdir.mkdir(exist_ok=True) tmpdir.mkdir(exist_ok=True) - with pytest.raises(error_type): + with pytest.raises(error_type, match=error_regex): build.Build(sample_source, Path('index.json'))\ .write_package_files(dstdir) diff --git a/tests/test_local_apt.py b/tests/test_local_apt.py index 4f3a831..1ff52cc 100644 --- a/tests/test_local_apt.py +++ b/tests/test_local_apt.py @@ -290,14 +290,11 @@ def test_local_apt_missing(mock_cache_dir): """ sources_list = local_apt.SourcesList(['deb-src sth', 'deb sth']) - with pytest.raises(local_apt.AptError) as excinfo: + with pytest.raises(local_apt.AptError, + match='^couldnt_execute_apt-get_is_it_installed$'): with local_apt.local_apt(sources_list, local_apt.default_keys) as apt: pass - assert len(excinfo.value.args) == 1 - assert isinstance(excinfo.value.args[0], str) - assert '\n' not in excinfo.value.args[0] - @pytest.mark.subprocess_run(local_apt, make_run_apt_get(update_code=1)) @pytest.mark.usefixtures('mock_subprocess_run', 'mock_gnupg_import') def test_local_apt_update_fail(mock_cache_dir): @@ -307,14 +304,22 @@ def test_local_apt_update_fail(mock_cache_dir): """ sources_list = local_apt.SourcesList(['deb-src sth', 'deb sth']) - with pytest.raises(local_apt.AptError) as excinfo: - with local_apt.local_apt(sources_list, local_apt.default_keys) as apt: - pass + error_regex = """^\ +command_apt-get -c \\S+ update_failed + +STDOUT_OUTPUT_heading + +some output - assert len(excinfo.value.args) == 1 +STDERR_OUTPUT_heading - assert re.match(r'.*\n\n.*\n\nsome output\n\n.*\n\nsome error output', - excinfo.value.args[0]) +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): + with local_apt.local_apt(sources_list, local_apt.default_keys) as apt: + pass @pytest.mark.subprocess_run(local_apt, make_run_apt_get()) @pytest.mark.usefixtures('mock_subprocess_run', 'mock_gnupg_import') @@ -359,17 +364,24 @@ def test_local_apt_install_fail(mock_cache_dir): destination = mock_cache_dir / 'destination' destination.mkdir() - with pytest.raises(local_apt.AptError) as excinfo: + error_regex = f"""^\ +command_apt-get -c \\S+ install --yes --just-print libjs-mathjax_failed + +STDOUT_OUTPUT_heading + +{re.escape(sample_install_stdout)} + +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): local_apt.download_apt_packages(sources_list, local_apt.default_keys, ['libjs-mathjax'], destination, with_deps=True) - assert len(excinfo.value.args) == 1 - - assert re.match(r'^.*\n\n.*\n\n', excinfo.value.args[0]) - assert re.search(r'\n\nsome error output$', excinfo.value.args[0]) - assert sample_install_stdout in excinfo.value.args[0] - assert [*destination.iterdir()] == [] @pytest.mark.subprocess_run(local_apt, make_run_apt_get(download_code=1)) @@ -383,14 +395,73 @@ def test_local_apt_download_fail(mock_cache_dir): destination = mock_cache_dir / 'destination' destination.mkdir() - with pytest.raises(local_apt.AptError) as excinfo: + error_regex = """^\ +command_apt-get -c \\S+ download libjs-mathjax_failed + +STDOUT_OUTPUT_heading + +some output + +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): local_apt.download_apt_packages(sources_list, local_apt.default_keys, ['libjs-mathjax'], destination) - assert len(excinfo.value.args) == 1 + assert [*destination.iterdir()] == [] - assert re.match(r'.*\n\n.*\n\nsome output\n\n.*\n\nsome error output', - excinfo.value.args[0]) +@pytest.fixture +def mock_bad_deb_file(monkeypatch, mock_subprocess_run): + """ + Make mocked 'apt-get download' command produce an incorrectly-named file. + """ + old_run = local_apt.subprocess.run + + def twice_mocked_run(command, **kwargs): + """ + Create an evil file if needed; then act just like the run() function + that got replaced by this one. + """ + if 'download' in command: + destination = Path(kwargs.get('cwd') or Path.cwd()) + (destination / 'arbitrary-name').write_text('anything') + + return old_run(command, **kwargs) + + monkeypatch.setattr(local_apt.subprocess, 'run', twice_mocked_run) + +@pytest.mark.subprocess_run(local_apt, make_run_apt_get()) +@pytest.mark.usefixtures('mock_subprocess_run', 'mock_gnupg_import', + 'mock_bad_deb_file') +def test_local_apt_download_bad_filename(mock_cache_dir): + """ + Verify that the download_apt_packages() function raises a proper error when + 'apt-get download' command produces an incorrectly-named file. + """ + sources_list = local_apt.SourcesList([], 'nabia') + destination = mock_cache_dir / 'destination' + destination.mkdir() + + error_regex = """^\ +apt_download_gave_bad_filename_arbitrary-name + +STDOUT_OUTPUT_heading + +some output + +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): + local_apt.download_apt_packages(sources_list, local_apt.default_keys, + ['libjs-mathjax'], destination) assert [*destination.iterdir()] == [] @@ -405,14 +476,22 @@ def test_local_apt_source_fail(mock_cache_dir): destination = mock_cache_dir / 'destination' destination.mkdir() - with pytest.raises(local_apt.AptError) as excinfo: - local_apt.download_apt_packages(sources_list, local_apt.default_keys, - ['libjs-mathjax'], destination) + error_regex = """^\ +command_apt-get -c \\S* source --download-only \\S+_failed + +STDOUT_OUTPUT_heading - assert len(excinfo.value.args) == 1 +some output - assert re.match(r'.*\n\n.*\n\nsome output\n\n.*\n\nsome error output', - excinfo.value.args[0]) +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): + local_apt.download_apt_packages(sources_list, local_apt.default_keys, + ['libjs-mathjax'], destination) assert [*destination.iterdir()] == [] @@ -421,7 +500,7 @@ def test_sources_list(): list = local_apt.SourcesList([], 'nabia') assert list.identity() == 'nabia' - with pytest.raises(local_apt.DistroError): + with pytest.raises(local_apt.DistroError, match='^distro_nabiał_unknown$'): local_apt.SourcesList([], 'nabiał') list = local_apt.SourcesList(['deb sth', 'deb-src sth'], 'nabia') @@ -557,7 +636,9 @@ def test_piggybacked_system_download(params): assert piggybacked.resolve_file(PurePosixPath('a/b/c')) == None assert piggybacked.resolve_file(PurePosixPath('')) == None - with pytest.raises(FileReferenceError): + output_text = 'loading_.apt-root/a/../../../b_outside_piggybacked_dir' + with pytest.raises(FileReferenceError, + match=f'^{re.escape(output_text)}$'): piggybacked.resolve_file(PurePosixPath('.apt-root/a/../../../b')) root = piggybacked.resolve_file(PurePosixPath('.apt-root/dummy')).parent @@ -615,7 +696,8 @@ def test_piggybacked_system_missing(): Verify that the piggybacked_system() function raises a proper error when 'dpkg-deb' is missing. """ - with pytest.raises(local_apt.AptError) as excinfo: + with pytest.raises(local_apt.AptError, + match='^couldnt_execute_dpkg-deb_is_it_installed$'): with local_apt.piggybacked_system({ 'system': 'apt', 'distribution': 'nabia', @@ -624,11 +706,6 @@ def test_piggybacked_system_missing(): }, None) as piggybacked: pass - assert len(excinfo.value.args) == 1 - - assert '\n' not in excinfo.value.args[0] - - @pytest.mark.subprocess_run(local_apt, lambda c, **kw: run_dpkg_deb(c, 1, **kw)) @pytest.mark.usefixtures('mock_download_packages', 'mock_subprocess_run') def test_piggybacked_system_fail(): @@ -636,7 +713,20 @@ def test_piggybacked_system_fail(): Verify that the piggybacked_system() function raises a proper error when 'dpkg-deb -x' command returns non-0. """ - with pytest.raises(local_apt.AptError) as excinfo: + error_regex = """^\ +command_dpkg-deb -x \\S+\\.deb \\S+_failed + +STDOUT_OUTPUT_heading + +some output + +STDERR_OUTPUT_heading + +some error output\ +$\ +""" + + with pytest.raises(local_apt.AptError, match=error_regex): with local_apt.piggybacked_system({ 'system': 'apt', 'distribution': 'nabia', @@ -644,8 +734,3 @@ def test_piggybacked_system_fail(): 'dependencies': False }, None) as piggybacked: pass - - assert len(excinfo.value.args) == 1 - - assert re.match(r'.*\n\n.*\n\nsome output\n\n.*\n\nsome error output', - excinfo.value.args[0]) |