diff options
Diffstat (limited to 'tests/test_interpreter.py')
-rw-r--r-- | tests/test_interpreter.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/tests/test_interpreter.py b/tests/test_interpreter.py new file mode 100644 index 0000000..6cbfd44 --- /dev/null +++ b/tests/test_interpreter.py @@ -0,0 +1,162 @@ +import textwrap +from typing import Optional + +import pytest + +from debputy.highlevel_manifest import HighLevelManifest +from debputy.highlevel_manifest_parser import YAMLManifestParser +from debputy.interpreter import extract_shebang_interpreter +from debputy.plugin.api import virtual_path_def +from debputy.plugin.api.test_api import build_virtual_file_system +from debputy.transformation_rules import NormalizeShebangLineTransformation + + +@pytest.mark.parametrize( + "raw_shebang,original_command,command_full_basename,command_stem,correct_command,corrected_shebang_line", + [ + ( + b"#! /usr/bin/false\r\n", + "/usr/bin/false", + "false", + "false", + None, + None, + ), + ( + b"#!/usr/bin/python3 -b", + "/usr/bin/python3", + "python3", + "python", + "/usr/bin/python3", + None, + ), + ( + b"#!/usr/bin/env python3 -b", + "/usr/bin/env python3", + "python3", + "python", + "/usr/bin/python3", + "#! /usr/bin/python3 -b", + ), + ( + b"#! /bin/env python3.12-dbg -b", + "/bin/env python3.12-dbg", + "python3.12-dbg", + "python", + "/usr/bin/python3.12-dbg", + "#! /usr/bin/python3.12-dbg -b", + ), + ( + b"#! /usr/bin/bash", + "/usr/bin/bash", + "bash", + "bash", + "/bin/bash", + "#! /bin/bash", + ), + ( + b"#! /usr/bin/env sh", + "/usr/bin/env sh", + "sh", + "sh", + "/bin/sh", + "#! /bin/sh", + ), + ( + b"#! /usr/local/bin/perl", + "/usr/local/bin/perl", + "perl", + "perl", + "/usr/bin/perl", + "#! /usr/bin/perl", + ), + ], +) +def test_interpreter_detection( + raw_shebang: bytes, + original_command: str, + command_full_basename: str, + command_stem: str, + correct_command: Optional[str], + corrected_shebang_line: Optional[str], +) -> None: + interpreter = extract_shebang_interpreter(raw_shebang) + # The `and ...` part is just to get the raw line in the error message + assert interpreter is not None or raw_shebang == b"" + + assert interpreter.original_command == original_command + assert interpreter.command_full_basename == command_full_basename + assert interpreter.command_stem == command_stem + assert interpreter.correct_command == correct_command + assert interpreter.corrected_shebang_line == corrected_shebang_line + assert interpreter.fixup_needed == (corrected_shebang_line is not None) + + +@pytest.mark.parametrize( + "raw_data", + [ + b"#!#!#! /usr/bin/false", + b"#!perl", # Used in files as an editor hint + b"\x7FELF/usr/bin/perl", + b"\x00\01\x02\x03/usr/bin/perl", + b"PK\x03\x03/usr/bin/perl", + ], +) +def test_interpreter_negative(raw_data: bytes) -> None: + assert extract_shebang_interpreter(raw_data) is None + + +@pytest.fixture +def empty_manifest( + amd64_dpkg_architecture_variables, + dpkg_arch_query, + source_package, + package_single_foo_arch_all_cxt_amd64, + amd64_substitution, + no_profiles_or_build_options, + debputy_plugin_feature_set, +) -> HighLevelManifest: + # We need an empty directory to avoid triggering packager provided files. + debian_dir = build_virtual_file_system([]) + return YAMLManifestParser( + "debian/test-debputy.manifest", + source_package, + package_single_foo_arch_all_cxt_amd64, + amd64_substitution, + amd64_dpkg_architecture_variables, + dpkg_arch_query, + no_profiles_or_build_options, + debputy_plugin_feature_set, + debian_dir=debian_dir, + ).build_manifest() + + +def test_interpreter_rewrite(empty_manifest: HighLevelManifest) -> None: + condition_context = empty_manifest.condition_context("foo") + fs_root = build_virtual_file_system( + [ + virtual_path_def("usr/bin/foo", content="random data"), + virtual_path_def( + "usr/bin/foo.sh", + materialized_content="#!/usr/bin/sh\nset -e\n", + ), + ] + ) + interpreter_normalization = NormalizeShebangLineTransformation() + interpreter_normalization.transform_file_system(fs_root, condition_context) + foo = fs_root.lookup("usr/bin/foo") + foo_sh = fs_root.lookup("usr/bin/foo.sh") + + assert foo.is_file + with foo.open() as fd: + assert fd.read() == "random data" + + assert foo_sh.is_file + with foo_sh.open() as fd: + expected = textwrap.dedent( + """\ + #! /bin/sh + set -e + """ + ) + assert fd.read() == expected |