Files
qiling/tests/test_qltool.py
T
2026-09-05 16:57:28 +08:00

95 lines
3.8 KiB
Python

#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os
import subprocess
import re
import sys
import sysconfig
import tempfile
import unittest
from importlib.metadata import version
from pathlib import Path
class Qltool_Test(unittest.TestCase):
def __run(self, cmdline: str) -> bytes:
try:
output = subprocess.check_output([sys.executable] + cmdline.split(), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"command '{e.cmd}' return with error (code {e.returncode}): {e.output}")
else:
return output
def test_qltool_exec_args(self):
output = self.__run(r'../qltool run -f ../examples/rootfs/x8664_linux/bin/x8664_args --rootfs ../examples/rootfs/x8664_linux --verbose off --args test1 test2 test3')
self.assertEqual(b'arg 2 test3', output.splitlines()[-1])
def test_qltool_shellcode(self):
self.__run(r'../qltool code --os linux --arch x86 --format asm -f ../examples/shellcodes/lin32_execve.asm')
def test_qltool_coverage(self):
os.makedirs(r'./log_test', exist_ok=True)
self.__run(r'../qltool run -f ../examples/rootfs/x8664_efi/bin/TcgPlatformSetupPolicy --rootfs ../examples/rootfs/x8664_efi --coverage-format drcov --coverage-file log_test/TcgPlatformSetupPolicy')
def test_qltool_json(self):
self.__run(r'../qltool run -f ../examples/rootfs/x86_linux/bin/x86_hello --rootfs ../examples/rootfs/x86_linux --verbose off --json')
def test_qltool_filter(self):
filter_pattern = r'^(open|brk)'
output = self.__run(fr'../qltool run -f ../examples/rootfs/arm_linux/bin/arm_hello --rootfs ../examples/rootfs/arm_linux -e {filter_pattern} --log-plain')
# keep only log entries and strip them from log prefix
p = re.compile(rb'^\[\S\]\s+')
log_entries = (p.sub(b'', line) for line in output.splitlines() if p.match(line))
# make sure that all log entries are of the expected regex filter pattern
p = re.compile(filter_pattern.encode())
self.assertTrue(all(p.search(entry) is not None for entry in log_entries))
class InstalledQltool_Test(unittest.TestCase):
"""Exercise the installed distribution outside the source checkout."""
def setUp(self):
directory = tempfile.TemporaryDirectory()
self.addCleanup(directory.cleanup)
self.cwd = directory.name
self.qltool = Path(sysconfig.get_path('scripts')) / ('qltool.exe' if os.name == 'nt' else 'qltool')
def __run(self, *args: str, expected_exit: int = 0) -> str:
result = subprocess.run(
[str(self.qltool), *args], cwd=self.cwd,
env={**os.environ, 'PYTHONPATH': ''},
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, timeout=30
)
self.assertEqual(result.returncode, expected_exit, result.stdout)
return result.stdout
def test_qltool_version_and_examples(self):
self.assertIn(f'Qiling {version("qiling")}', self.__run('--version'))
self.assertIn('qltool code --os linux', self.__run('examples'))
def test_qltool_shellcode_exit_status(self):
# Linux x86 exit(7), using the profiles shipped in the installed wheel.
self.__run('code', '--os', 'linux', '--arch', 'x86', '--format', 'hex',
'--input', 'b801000000bb07000000cd80', '--verbose', 'off',
expected_exit=7)
def test_qltui_import(self):
result = subprocess.run(
[sys.executable, '-I', '-c', 'import qltui; assert callable(qltui.get_data)'],
cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, timeout=30
)
self.assertEqual(result.returncode, 0, result.stdout)
if __name__ == "__main__":
unittest.main()