gyptest-link-update-manifest.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #!/usr/bin/env python
  2. # Copyright (c) 2013 Google Inc. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """
  6. Make sure binary is relinked when manifest settings are changed.
  7. """
  8. import TestGyp
  9. import os
  10. import sys
  11. if sys.platform == 'win32':
  12. import pywintypes
  13. import win32api
  14. import winerror
  15. RT_MANIFEST = 24
  16. class LoadLibrary(object):
  17. """Context manager for loading and releasing binaries in Windows.
  18. Yields the handle of the binary loaded."""
  19. def __init__(self, path):
  20. self._path = path
  21. self._handle = None
  22. def __enter__(self):
  23. self._handle = win32api.LoadLibrary(self._path)
  24. return self._handle
  25. def __exit__(self, type, value, traceback):
  26. win32api.FreeLibrary(self._handle)
  27. def extract_manifest(path, resource_name):
  28. """Reads manifest from |path| and returns it as a string.
  29. Returns None is there is no such manifest."""
  30. with LoadLibrary(path) as handle:
  31. try:
  32. return win32api.LoadResource(handle, RT_MANIFEST, resource_name)
  33. except pywintypes.error as error:
  34. if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND:
  35. return None
  36. else:
  37. raise
  38. test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
  39. CHDIR = 'linker-flags'
  40. gyp_template = '''
  41. {
  42. 'targets': [
  43. {
  44. 'target_name': 'test_update_manifest',
  45. 'type': 'executable',
  46. 'sources': ['hello.cc'],
  47. 'msvs_settings': {
  48. 'VCLinkerTool': {
  49. 'EnableUAC': 'true',
  50. 'UACExecutionLevel': '%(uac_execution_level)d',
  51. },
  52. 'VCManifestTool': {
  53. 'EmbedManifest': 'true',
  54. 'AdditionalManifestFiles': '%(additional_manifest_files)s',
  55. },
  56. },
  57. },
  58. ],
  59. }
  60. '''
  61. gypfile = 'update-manifest.gyp'
  62. def WriteAndUpdate(uac_execution_level, additional_manifest_files, do_build):
  63. with open(os.path.join(CHDIR, gypfile), 'wb') as f:
  64. f.write(gyp_template % {
  65. 'uac_execution_level': uac_execution_level,
  66. 'additional_manifest_files': additional_manifest_files,
  67. })
  68. test.run_gyp(gypfile, chdir=CHDIR)
  69. if do_build:
  70. test.build(gypfile, chdir=CHDIR)
  71. exe_file = test.built_file_path('test_update_manifest.exe', chdir=CHDIR)
  72. return extract_manifest(exe_file, 1)
  73. manifest = WriteAndUpdate(0, '', True)
  74. test.fail_test('asInvoker' not in manifest)
  75. test.fail_test('35138b9a-5d96-4fbd-8e2d-a2440225f93a' in manifest)
  76. # Make sure that updating .gyp and regenerating doesn't cause a rebuild.
  77. WriteAndUpdate(0, '', False)
  78. test.up_to_date(gypfile, test.ALL, chdir=CHDIR)
  79. # But make sure that changing a manifest property does cause a relink.
  80. manifest = WriteAndUpdate(2, '', True)
  81. test.fail_test('requireAdministrator' not in manifest)
  82. # Adding a manifest causes a rebuild.
  83. manifest = WriteAndUpdate(2, 'extra.manifest', True)
  84. test.fail_test('35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in manifest)