1#!/usr/bin/env python
2
3# Copyright (c) 2013 Yandex LLC. 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"""
8Make sure manifests are embedded in binaries properly. Handling of
9AdditionalManifestFiles is tested too.
10"""
11
12import TestGyp
13
14import sys
15
16if 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
38  def extract_manifest(path, resource_name):
39    """Reads manifest from |path| and returns it as a string.
40    Returns None is there is no such manifest."""
41    with LoadLibrary(path) as handle:
42      try:
43        return win32api.LoadResource(handle, RT_MANIFEST, resource_name)
44      except pywintypes.error as error:
45        if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND:
46          return None
47        else:
48          raise
49
50  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
51  CHDIR = 'linker-flags'
52  test.run_gyp('embed-manifest.gyp', chdir=CHDIR)
53  test.build('embed-manifest.gyp', test.ALL, chdir=CHDIR)
54
55  # The following binaries must contain a manifest embedded.
56  test.fail_test(not extract_manifest(test.built_file_path(
57    'test_manifest_exe.exe', chdir=CHDIR), 1))
58  test.fail_test(not extract_manifest(test.built_file_path(
59    'test_manifest_exe_inc.exe', chdir=CHDIR), 1))
60  test.fail_test(not extract_manifest(test.built_file_path(
61    'test_manifest_dll.dll', chdir=CHDIR), 2))
62  test.fail_test(not extract_manifest(test.built_file_path(
63    'test_manifest_dll_inc.dll', chdir=CHDIR), 2))
64
65  # Must contain the Win7 support GUID, but not the Vista one (from
66  # extra2.manifest).
67  test.fail_test(
68    '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in
69    extract_manifest(test.built_file_path('test_manifest_extra1.exe',
70                                            chdir=CHDIR), 1))
71  test.fail_test(
72    'e2011457-1546-43c5-a5fe-008deee3d3f0' in
73    extract_manifest(test.built_file_path('test_manifest_extra1.exe',
74                                            chdir=CHDIR), 1))
75  # Must contain both.
76  test.fail_test(
77    '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in
78    extract_manifest(test.built_file_path('test_manifest_extra2.exe',
79                                            chdir=CHDIR), 1))
80  test.fail_test(
81    'e2011457-1546-43c5-a5fe-008deee3d3f0' not in
82    extract_manifest(test.built_file_path('test_manifest_extra2.exe',
83                                            chdir=CHDIR), 1))
84
85  # Same as extra2, but using list syntax instead.
86  test.fail_test(
87    '35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in
88    extract_manifest(test.built_file_path('test_manifest_extra_list.exe',
89                                          chdir=CHDIR), 1))
90  test.fail_test(
91    'e2011457-1546-43c5-a5fe-008deee3d3f0' not in
92    extract_manifest(test.built_file_path('test_manifest_extra_list.exe',
93                                          chdir=CHDIR), 1))
94
95  # Test that incremental linking doesn't force manifest embedding.
96  test.fail_test(extract_manifest(test.built_file_path(
97    'test_manifest_exe_inc_no_embed.exe', chdir=CHDIR), 1))
98
99  test.pass_test()
100