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