diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d85ed75..23b96af 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -70,8 +70,11 @@ jobs: Rename-Item -Path "./dist/$((Get-ChildItem -Path "./dist").Name)" -NewName "Ghidrathon.zip" tar -xf ./dist/Ghidrathon.zip -C ../tmp/ghidra/ghidra_PUBLIC/Ghidra/Extensions/ - name: Set Ghidrathon Python interpreter - run: python util/ghidrathon_configure.py ../tmp/ghidra/ghidra_PUBLIC + run: python util/ghidrathon_configure.py ../tmp/ghidra/ghidra_PUBLIC -d - name: Run tests run: | - ../tmp/ghidra/ghidra_PUBLIC/support/analyzeHeadless ${{ github.workspace }}/../tmp/ghidra test -Import ${{ github.workspace }}/../tmp/ghidra/ghidra_PUBLIC/GPL/DemanglerGnu/os/linux_x86_64/demangler_gnu_v2_24 -PostScript ${{ github.workspace }}/data/python/tests/hello.py -PostScript ${{ github.workspace }}/data/python/tests/runall.py + ../tmp/ghidra/ghidra_PUBLIC/support/analyzeHeadless ${{ github.workspace }}/../tmp/ghidra test -Import ${{ github.workspace }}/../tmp/ghidra/ghidra_PUBLIC/GPL/DemanglerGnu/os/linux_x86_64/demangler_gnu_v2_24 -PostScript ${{ github.workspace }}/data/python/tests/hello.py -PostScript ${{ github.workspace }}/data/python/tests/runall.py > ../tmp/log.txt + - name: Check tests + run: | + python -c "import pathlib, sys;log_text=pathlib.Path('../tmp/log.txt').read_text(encoding='utf-8');print(log_text);sys.exit(0 if 'runall.py called exit with code -1' not in log_text else -1)" python -c "import pathlib, sys; sys.exit(0 if pathlib.Path('hello.txt').exists() else -1)" diff --git a/data/python/tests/runall.py b/data/python/tests/runall.py index 3584b1d..4ef29d3 100644 --- a/data/python/tests/runall.py +++ b/data/python/tests/runall.py @@ -16,6 +16,7 @@ import unittest import pathlib +import sys def main(): @@ -24,8 +25,8 @@ def main(): directory = str(pathlib.Path(__file__).resolve().parent) suite = loader.discover(directory, pattern="test_*.py") - _ = unittest.TextTestRunner(verbosity=2, failfast=True).run(suite) + return 0 if unittest.TextTestRunner(verbosity=2, failfast=True).run(suite).wasSuccessful() else -1 if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/util/ghidrathon_configure.py b/util/ghidrathon_configure.py index c2a9247..7a3e2ce 100644 --- a/util/ghidrathon_configure.py +++ b/util/ghidrathon_configure.py @@ -6,12 +6,15 @@ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. +import importlib.util import argparse import pathlib import logging import sys +SUPPORTED_JEP_VERSION = "4.2.0" + logger = logging.getLogger(__name__) handler = logging.StreamHandler() @@ -28,20 +31,80 @@ def main(args): if args.debug: logger.setLevel(logging.DEBUG) + jep_spec = importlib.util.find_spec("jep") + if jep_spec is None: + logger.error( + "Jep is not installed. Please install Jep version %s before configuring Ghidrathon.", SUPPORTED_JEP_VERSION + ) + return -1 + + jep_version_file: pathlib.path = pathlib.Path(jep_spec.origin).parent / "version.py" + if not all((jep_version_file.exists(), jep_version_file.is_file())): + logger.error( + "Jep file %s is not valid. Please verify your Jep install is correct before configuring Ghidrathon.", + jep_version_file, + ) + return -1 + + logger.debug('Verifying Jep version.py file located at "%s".', jep_version_file) + + if SUPPORTED_JEP_VERSION not in jep_version_file.read_text(encoding="utf-8"): + logger.error( + "Jep version is not supported. Please install Jep version %s before configuring Ghidrathon.", + SUPPORTED_JEP_VERSION, + ) + return -1 + install_path: pathlib.Path = args.ghidrathon_install_directory if not all((install_path.exists(), install_path.is_dir())): - logger.error('"%s" does not exist or is not a directory.', str(install_path)) + logger.error( + 'Ghidra install directory "%s" is not valid. Please specify the absolute path of your Ghidra install directory.', + install_path, + ) return -1 + python_path: pathlib.Path = pathlib.Path("None" if not sys.executable else sys.executable) + if not all((python_path.exists(), python_path.is_file())): + logger.error( + 'sys.executable value "%s" is not valid. Please verify your Python environment is correct before configuring Ghidrathon.', + python_path, + ) + return -1 + + logger.debug('Using Python interpreter located at "%s".', python_path) + save_path: pathlib.Path = install_path / "ghidrathon.save" try: - save_path.write_text(sys.executable, encoding="utf-8") + save_path.write_text(str(python_path), encoding="utf-8") + except Exception as e: + logger.error('Failed to write "%s" to "%s" (%s).', python_path, save_path, e) + return -1 + + try: + logger.debug("Python configuration:") + logger.debug("Python %s", sys.version) + + for k, v in { + "sys.executable": sys.executable, + "sys._base_executable": sys._base_executable, + "sys.prefix": sys.prefix, + "sys.base_prefix": sys.base_prefix, + "sys.exec_prefix": sys.exec_prefix, + "sys.base_exec_prefix": sys.base_exec_prefix, + }.items(): + logger.debug('%s: "%s"', k, v) except Exception as e: - logger.error('Failed to write "%s" to "%s" (%s).', sys.executable, str(save_path), e) + logger.error( + "Failed to verify Python environment (%s). Please verify your Python environment is correct before configuring Ghidrathon.", + e, + ) return -1 - logger.debug('Wrote "%s" to "%s".', sys.executable, str(save_path)) - logger.info("Please restart Ghidra for these changes to take effect.") + logger.debug('Wrote "%s" to "%s".', python_path, save_path) + logger.info( + 'Ghidrathon has been configured to use the Python interpreter located at "%s". Please restart Ghidra for these changes to take effect.', + python_path, + ) return 0