test_main.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import io
  2. import json
  3. from pathlib import Path
  4. import pytest
  5. import re
  6. import responses
  7. from shutil import copytree
  8. from subprocess import run, PIPE
  9. import sys
  10. from testpath import MockCommand, assert_isfile, assert_isdir
  11. from zipfile import ZipFile
  12. from nsist import main
  13. from nsist.util import CACHE_ENV_VAR
  14. from .utils import test_dir, only_on_windows
  15. example_dir = Path(test_dir, 'console_example')
  16. @pytest.fixture()
  17. def console_eg_copy(tmp_path):
  18. dst = tmp_path / 'example'
  19. copytree(str(example_dir), str(dst))
  20. return dst
  21. def respond_python_zip(req):
  22. buf = io.BytesIO()
  23. with ZipFile(buf, 'w') as zf:
  24. zf.writestr('python.exe', b'')
  25. return 200, {}, buf.getvalue()
  26. @responses.activate
  27. def test_console_example(tmp_path, console_eg_copy, monkeypatch):
  28. responses.add_callback('GET', re.compile(r'https://www.python.org/ftp/.*'),
  29. callback=respond_python_zip, content_type='application/zip',
  30. )
  31. monkeypatch.chdir(console_eg_copy)
  32. monkeypatch.setenv(CACHE_ENV_VAR, str(tmp_path / 'cache'))
  33. with MockCommand('makensis') as makensis:
  34. ec = main(['installer.cfg'])
  35. assert ec == 0
  36. assert makensis.get_calls()[0]['argv'][1].endswith('installer.nsi')
  37. build_dir = console_eg_copy / 'build' / 'nsis'
  38. assert_isdir(build_dir)
  39. assert_isfile(build_dir / 'Python' / 'python.exe')
  40. assert_isfile(build_dir / 'pkgs' / 'sample_printer' / '__init__.py')
  41. assert_isfile(build_dir / 'Sample_printer.launch.py')
  42. # To exclude tests requiring network on an unplugged machine, use: pytest -m "not network"
  43. @only_on_windows
  44. @pytest.mark.network
  45. def test_installer(console_eg_copy, tmp_path):
  46. # Create installer
  47. run(
  48. [sys.executable, '-m', 'nsist', 'installer.cfg'],
  49. cwd=str(console_eg_copy),
  50. check=True,
  51. )
  52. installer = console_eg_copy / 'build' / 'nsis' / 'Sample_printer_1.0.exe'
  53. inst_dir = tmp_path / 'inst'
  54. # Run installer
  55. run([str(installer), '/S', '/INSTDIR={}'.format(inst_dir)], check=True)
  56. import os
  57. print(os.listdir(str(inst_dir)))
  58. inst_python = inst_dir / 'Python' / 'python.exe'
  59. inst_launch_script = inst_dir / 'Sample_printer.launch.py'
  60. inst_exe_wrapper = inst_dir / 'bin' / 'pynsist-test-print.exe'
  61. assert_isfile(inst_python)
  62. assert_isfile(inst_launch_script)
  63. assert_isfile(inst_exe_wrapper)
  64. assert_isfile(inst_dir / 'pkgs' / 'sample_printer' / '__init__.py')
  65. # Run installed program
  66. res = run([str(inst_python), str(inst_launch_script)],
  67. check=True, stdout=PIPE)
  68. json_res = json.loads(res.stdout.decode('utf-8', 'replace'))
  69. assert json_res['py_executable'] == str(inst_python)
  70. assert json_res['py_version'].startswith('3.6.3') # Set in installer.cfg
  71. assert json_res['data_file_path'].endswith('data.txt')
  72. assert json_res['data_file_content'] == 'newt'
  73. # Run through command-line wrapper
  74. res2 = run([str(inst_exe_wrapper)], check=True, stdout=PIPE)
  75. json_res2 = json.loads(res2.stdout.decode('utf-8', 'replace'))
  76. assert json_res2 == json_res
  77. # Check command-line wrapper is on PATH
  78. assert str(inst_exe_wrapper.parent) in get_registry_path()
  79. def get_registry_path():
  80. """Read the PATH environment variable from the Windows registry"""
  81. import winreg
  82. res = []
  83. # System-wide part of PATH
  84. with winreg.CreateKey(
  85. winreg.HKEY_LOCAL_MACHINE,
  86. r"System\CurrentControlSet\Control\Session Manager\Environment"
  87. ) as key:
  88. try:
  89. path = winreg.QueryValueEx(key, "PATH")[0]
  90. except WindowsError:
  91. # No value called PATH
  92. pass
  93. else:
  94. res.extend(path.split(';'))
  95. # User part of PATH
  96. with winreg.CreateKey(winreg.HKEY_CURRENT_USER, r"Environment") as key:
  97. try:
  98. path = winreg.QueryValueEx(key, "PATH")[0]
  99. except WindowsError:
  100. # No value called PATH
  101. pass
  102. else:
  103. res.extend(path.split(';'))
  104. return res