Merge tools/gyp from https://chromium.googlesource.com/external/gyp.git at a61e860884929dd46cb55de7916a7ba067a8a655

This commit was generated by merge_from_chromium.py.

Change-Id: Ide13800347ff3790abe692dc84e71b17656a7a56
diff --git a/pylib/gyp/generator/make.py b/pylib/gyp/generator/make.py
index 8c31d10..e726646 100644
--- a/pylib/gyp/generator/make.py
+++ b/pylib/gyp/generator/make.py
@@ -1138,9 +1138,12 @@
     for output, res in gyp.xcode_emulation.GetMacBundleResources(
         generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
         map(Sourceify, map(self.Absolutify, resources))):
-      self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
-                      part_of_all=True)
-      bundle_deps.append(output)
+      _, ext = os.path.splitext(output)
+      if ext != '.xcassets':
+        # Make does not supports '.xcassets' emulation.
+        self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
+                        part_of_all=True)
+        bundle_deps.append(output)
 
 
   def WriteMacInfoPlist(self, bundle_deps):
diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
index 63c1228..cfb13fc 100644
--- a/pylib/gyp/generator/ninja.py
+++ b/pylib/gyp/generator/ninja.py
@@ -564,9 +564,10 @@
     stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
 
     if self.is_mac_bundle:
-      self.WriteMacBundleResources(
+      xcassets = self.WriteMacBundleResources(
           extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends)
-      self.WriteMacInfoPlist(mac_bundle_depends)
+      partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends)
+      self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends)
 
     return stamp
 
@@ -760,15 +761,66 @@
 
   def WriteMacBundleResources(self, resources, bundle_depends):
     """Writes ninja edges for 'mac_bundle_resources'."""
+    xcassets = []
     for output, res in gyp.xcode_emulation.GetMacBundleResources(
         generator_default_variables['PRODUCT_DIR'],
         self.xcode_settings, map(self.GypPathToNinja, resources)):
       output = self.ExpandSpecial(output)
-      self.ninja.build(output, 'mac_tool', res,
-                       variables=[('mactool_cmd', 'copy-bundle-resource')])
-      bundle_depends.append(output)
+      if os.path.splitext(output)[-1] != '.xcassets':
+        self.ninja.build(output, 'mac_tool', res,
+                         variables=[('mactool_cmd', 'copy-bundle-resource')])
+        bundle_depends.append(output)
+      else:
+        xcassets.append(res)
+    return xcassets
 
-  def WriteMacInfoPlist(self, bundle_depends):
+  def WriteMacXCassets(self, xcassets, bundle_depends):
+    """Writes ninja edges for 'mac_bundle_resources' .xcassets files.
+
+    This add an invocation of 'actool' via the 'mac_tool.py' helper script.
+    It assumes that the assets catalogs define at least one imageset and
+    thus an Assets.car file will be generated in the application resources
+    directory. If this is not the case, then the build will probably be done
+    at each invocation of ninja."""
+    if not xcassets:
+      return
+
+    extra_arguments = {}
+    settings_to_arg = {
+        'XCASSETS_APP_ICON': 'app-icon',
+        'XCASSETS_LAUNCH_IMAGE': 'launch-image',
+    }
+    settings = self.xcode_settings.xcode_settings[self.config_name]
+    for settings_key, arg_name in settings_to_arg.iteritems():
+      value = settings.get(settings_key)
+      if value:
+        extra_arguments[arg_name] = value
+
+    partial_info_plist = None
+    if extra_arguments:
+      partial_info_plist = self.GypPathToUniqueOutput(
+          'assetcatalog_generated_info.plist')
+      extra_arguments['output-partial-info-plist'] = partial_info_plist
+
+    outputs = []
+    outputs.append(
+        os.path.join(
+            self.xcode_settings.GetBundleResourceFolder(),
+            'Assets.car'))
+    if partial_info_plist:
+      outputs.append(partial_info_plist)
+
+    keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor)
+    extra_env = self.xcode_settings.GetPerTargetSettings()
+    env = self.GetSortedXcodeEnv(additional_settings=extra_env)
+    env = self.ComputeExportEnvString(env)
+
+    bundle_depends.extend(self.ninja.build(
+        outputs, 'compile_xcassets', xcassets,
+        variables=[('env', env), ('keys', keys)]))
+    return partial_info_plist
+
+  def WriteMacInfoPlist(self, partial_info_plist, bundle_depends):
     """Write build rules for bundle Info.plist files."""
     info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
         generator_default_variables['PRODUCT_DIR'],
@@ -788,6 +840,12 @@
     env = self.GetSortedXcodeEnv(additional_settings=extra_env)
     env = self.ComputeExportEnvString(env)
 
+    if partial_info_plist:
+      intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist')
+      info_plist = self.ninja.build(
+          intermediate_plist, 'merge_infoplist',
+          [partial_info_plist, info_plist])
+
     keys = self.xcode_settings.GetExtraPlistItems(self.config_name)
     keys = QuoteShellArgument(json.dumps(keys), self.flavor)
     self.ninja.build(out, 'copy_infoplist', info_plist,
@@ -1528,7 +1586,7 @@
   elif flavor == 'win':
     exts = gyp.MSVSUtil.TARGET_TYPE_EXT
     default_variables.setdefault('OS', 'win')
-    default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable'] 
+    default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable']
     default_variables['STATIC_LIB_PREFIX'] = ''
     default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library']
     default_variables['SHARED_LIB_PREFIX'] = ''
@@ -2115,6 +2173,14 @@
       description='COPY INFOPLIST $in',
       command='$env ./gyp-mac-tool copy-info-plist $in $out $keys')
     master_ninja.rule(
+      'merge_infoplist',
+      description='MERGE INFOPLISTS $in',
+      command='$env ./gyp-mac-tool merge-info-plist $out $in')
+    master_ninja.rule(
+      'compile_xcassets',
+      description='COMPILE XCASSETS $in',
+      command='$env ./gyp-mac-tool compile-xcassets $keys $in')
+    master_ninja.rule(
       'mac_tool',
       description='MACTOOL $mactool_cmd $in',
       command='$env ./gyp-mac-tool $mactool_cmd $in $out')
diff --git a/pylib/gyp/mac_tool.py b/pylib/gyp/mac_tool.py
index 821e291..e5d8a2b 100755
--- a/pylib/gyp/mac_tool.py
+++ b/pylib/gyp/mac_tool.py
@@ -266,6 +266,66 @@
       os.remove(link)
     os.symlink(dest, link)
 
+  def ExecCompileXcassets(self, keys, *inputs):
+    """Compiles multiple .xcassets files into a single .car file.
+
+    This invokes 'actool' to compile all the inputs .xcassets files. The
+    |keys| arguments is a json-encoded dictionary of extra arguments to
+    pass to 'actool' when the asset catalogs contains an application icon
+    or a launch image.
+
+    Note that 'actool' does not create the Assets.car file if the asset
+    catalogs does not contains imageset.
+    """
+    command_line = [
+      'xcrun', 'actool', '--output-format', 'human-readable-text',
+      '--compress-pngs', '--notices', '--warnings', '--errors',
+    ]
+    is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ
+    if is_iphone_target:
+      platform = os.environ['CONFIGURATION'].split('-')[-1]
+      if platform not in ('iphoneos', 'iphonesimulator'):
+        platform = 'iphonesimulator'
+      command_line.extend([
+          '--platform', platform, '--target-device', 'iphone',
+          '--target-device', 'ipad', '--minimum-deployment-target',
+          os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile',
+          os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']),
+      ])
+    else:
+      command_line.extend([
+          '--platform', 'macosx', '--target-device', 'mac',
+          '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'],
+          '--compile',
+          os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']),
+      ])
+    if keys:
+      keys = json.loads(keys)
+      for key, value in keys.iteritems():
+        arg_name = '--' + key
+        if isinstance(value, bool):
+          if value:
+            command_line.append(arg_name)
+        elif isinstance(value, list):
+          for v in value:
+            command_line.append(arg_name)
+            command_line.append(str(v))
+        else:
+          command_line.append(arg_name)
+          command_line.append(str(value))
+    # Note: actool crashes if inputs path are relative, so use os.path.abspath
+    # to get absolute path name for inputs.
+    command_line.extend(map(os.path.abspath, inputs))
+    subprocess.check_call(command_line)
+
+  def ExecMergeInfoPlist(self, output, *inputs):
+    """Merge multiple .plist files into a single .plist file."""
+    merged_plist = {}
+    for path in inputs:
+      plist = self._LoadPlistMaybeBinary(path)
+      self._MergePlist(merged_plist, plist)
+    plistlib.writePlist(merged_plist, output)
+
   def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning):
     """Code sign a bundle.
 
@@ -402,6 +462,19 @@
           'security', 'cms', '-D', '-i', profile_path, '-o', temp.name])
       return self._LoadPlistMaybeBinary(temp.name)
 
+  def _MergePlist(self, merged_plist, plist):
+    """Merge |plist| into |merged_plist|."""
+    for key, value in plist.iteritems():
+      if isinstance(value, dict):
+        merged_value = merged_plist.get(key, {})
+        if isinstance(merged_value, dict):
+          self._MergePlist(merged_value, value)
+          merged_plist[key] = merged_value
+        else:
+          merged_plist[key] = value
+      else:
+        merged_plist[key] = value
+
   def _LoadPlistMaybeBinary(self, plist_path):
     """Loads into a memory a plist possibly encoded in binary format.
 
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json b/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2db2b1c
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,58 @@
+{
+  "images" : [
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
new file mode 100644
index 0000000..0a87b6e
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "filename" : "super_sylvain.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "filename" : "super_sylvain@2x.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "filename" : "super_sylvain@3x.png"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
new file mode 100644
index 0000000..0ba7691
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
Binary files differ
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
new file mode 100644
index 0000000..edfa6a5
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
Binary files differ
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
new file mode 100644
index 0000000..e0652ef
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
Binary files differ
diff --git a/test/ios/app-bundle/test-assets-catalog.gyp b/test/ios/app-bundle/test-assets-catalog.gyp
new file mode 100644
index 0000000..9a12d07
--- /dev/null
+++ b/test/ios/app-bundle/test-assets-catalog.gyp
@@ -0,0 +1,45 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'conditions': [
+    ['"<(GENERATOR)"=="ninja"', {
+      'make_global_settings': [
+        ['CC', '/usr/bin/clang'],
+        ['CXX', '/usr/bin/clang++'],
+      ],
+    }],
+  ],
+  'targets': [
+    {
+      'target_name': 'test_app',
+      'product_name': 'Test App Assets Catalog Gyp',
+      'type': 'executable',
+      'mac_bundle': 1,
+      'sources': [
+        'TestApp/main.m',
+      ],
+      'mac_bundle_resources': [
+        'TestApp/English.lproj/InfoPlist.strings',
+        'TestApp/English.lproj/MainMenu.xib',
+        'TestApp/English.lproj/Main_iPhone.storyboard',
+        'TestApp/Images.xcassets',
+      ],
+      'link_settings': {
+        'libraries': [
+          '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+          '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+        ],
+      },
+      'xcode_settings': {
+        'OTHER_CFLAGS': [
+          '-fobjc-abi-version=2',
+        ],
+        'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+        'SDKROOT': 'iphonesimulator',  # -isysroot
+        'IPHONEOS_DEPLOYMENT_TARGET': '7.0',
+        'CONFIGURATION_BUILD_DIR':'build/Default',
+      },
+    },
+  ],
+}
diff --git a/test/ios/gyptest-app-ios-assets-catalog.py b/test/ios/gyptest-app-ios-assets-catalog.py
new file mode 100755
index 0000000..efd96ac
--- /dev/null
+++ b/test/ios/gyptest-app-ios-assets-catalog.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that ios app bundles are built correctly.
+"""
+
+import TestGyp
+import TestMac
+
+import os.path
+import sys
+
+# Xcode supports for assets catalog was introduced in Xcode 6.0
+if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600':
+  test_gyp_path = 'test-assets-catalog.gyp'
+  test_app_path = 'Test App Assets Catalog Gyp.app'
+
+  test = TestGyp.TestGyp(formats=['xcode', 'ninja'])
+  test.run_gyp(test_gyp_path, chdir='app-bundle')
+  test.build(test_gyp_path, test.ALL, chdir='app-bundle')
+
+  # Test that the extension is .bundle
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Test App Assets Catalog Gyp'),
+      chdir='app-bundle')
+
+  # Info.plist
+  info_plist = test.built_file_path(
+      os.path.join(test_app_path, 'Info.plist'),
+      chdir='app-bundle')
+  # Resources
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/InfoPlist.strings'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/MainMenu.nib'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/Main_iPhone.storyboardc'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Assets.car'),
+      chdir='app-bundle')
+
+  # Packaging
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'PkgInfo'),
+      chdir='app-bundle')
+  test.built_file_must_match(
+      os.path.join(test_app_path, 'PkgInfo'), 'APPLause',
+      chdir='app-bundle')
+
+  test.pass_test()
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json b/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2db2b1c
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,58 @@
+{
+  "images" : [
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
new file mode 100644
index 0000000..0a87b6e
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "filename" : "super_sylvain.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "filename" : "super_sylvain@2x.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "filename" : "super_sylvain@3x.png"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
new file mode 100644
index 0000000..0ba7691
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
Binary files differ
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
new file mode 100644
index 0000000..edfa6a5
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
Binary files differ
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
new file mode 100644
index 0000000..e0652ef
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
Binary files differ
diff --git a/test/mac/app-bundle/test-assets-catalog.gyp b/test/mac/app-bundle/test-assets-catalog.gyp
new file mode 100644
index 0000000..25f94a1
--- /dev/null
+++ b/test/mac/app-bundle/test-assets-catalog.gyp
@@ -0,0 +1,43 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'targets': [
+    {
+      'target_name': 'dep_framework',
+      'product_name': 'Dependency Framework',
+      'type': 'shared_library',
+      'mac_bundle': 1,
+      'sources': [ 'empty.c', ],
+    },
+    {
+      'target_name': 'test_app',
+      'product_name': 'Test App Assets Catalog Gyp',
+      'type': 'executable',
+      'mac_bundle': 1,
+      'dependencies': [ 'dep_framework', ],
+      'sources': [
+        'TestApp/main.m',
+        'TestApp/TestApp_Prefix.pch',
+        'TestApp/TestAppAppDelegate.h',
+        'TestApp/TestAppAppDelegate.m',
+      ],
+      'mac_bundle_resources': [
+        'TestApp/English.lproj/InfoPlist.strings',  # UTF-8
+        'TestApp/English.lproj/utf-16be.strings',
+        'TestApp/English.lproj/utf-16le.strings',
+        'TestApp/English.lproj/MainMenu.xib',
+        'TestApp/Images.xcassets',
+      ],
+      'link_settings': {
+        'libraries': [
+          '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+        ],
+      },
+      'xcode_settings': {
+        'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+        'MACOSX_DEPLOYMENT_TARGET': '10.9',
+      },
+    },
+  ],
+}
diff --git a/test/mac/gyptest-app-assets-catalog.py b/test/mac/gyptest-app-assets-catalog.py
new file mode 100755
index 0000000..ecb5a78
--- /dev/null
+++ b/test/mac/gyptest-app-assets-catalog.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that app bundles are built correctly.
+"""
+
+import TestGyp
+import TestMac
+
+import os
+import plistlib
+import subprocess
+import sys
+
+
+def ExpectEq(expected, actual):
+  if expected != actual:
+    print >>sys.stderr, 'Expected "%s", got "%s"' % (expected, actual)
+    test.fail_test()
+
+def ls(path):
+  '''Returns a list of all files in a directory, relative to the directory.'''
+  result = []
+  for dirpath, _, files in os.walk(path):
+    for f in files:
+      result.append(os.path.join(dirpath, f)[len(path) + 1:])
+  return result
+
+# Xcode supports for assets catalog was introduced in Xcode 6.0
+if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600':
+  test_gyp_path = 'test-assets-catalog.gyp'
+  test_app_path = 'Test App Assets Catalog Gyp.app'
+
+  test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
+  test.run_gyp(test_gyp_path, chdir='app-bundle')
+  test.build(test_gyp_path, test.ALL, chdir='app-bundle')
+
+  # Binary
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Contents/MacOS/Test App Assets Catalog Gyp'),
+      chdir='app-bundle')
+
+  # Info.plist
+  info_plist = test.built_file_path(
+      os.path.join(test_app_path, 'Contents/Info.plist'),
+      chdir='app-bundle')
+  test.must_exist(info_plist)
+  test.must_contain(
+      info_plist,
+      'com.google.Test-App-Assets-Catalog-Gyp')  # Variable expansion
+  test.must_not_contain(info_plist, '${MACOSX_DEPLOYMENT_TARGET}');
+
+  if test.format != 'make':
+    # TODO: Synthesized plist entries aren't hooked up in the make generator.
+    machine = subprocess.check_output(['sw_vers', '-buildVersion']).rstrip('\n')
+    plist = plistlib.readPlist(info_plist)
+    ExpectEq(machine, plist['BuildMachineOSBuild'])
+
+    expected = ''
+    version = TestMac.Xcode.SDKVersion()
+    expected = 'macosx' + version
+    ExpectEq(expected, plist['DTSDKName'])
+    sdkbuild = TestMac.Xcode.SDKBuild()
+    if not sdkbuild:
+      # Above command doesn't work in Xcode 4.2.
+      sdkbuild = plist['BuildMachineOSBuild']
+    ExpectEq(sdkbuild, plist['DTSDKBuild'])
+    ExpectEq(TestMac.Xcode.Version(), plist['DTXcode'])
+    ExpectEq(TestMac.Xcode.Build(), plist['DTXcodeBuild'])
+
+  # Resources
+  strings_files = ['InfoPlist.strings', 'utf-16be.strings', 'utf-16le.strings']
+  for f in strings_files:
+    strings = test.built_file_path(
+        os.path.join(test_app_path, 'Contents/Resources/English.lproj', f),
+        chdir='app-bundle')
+    test.must_exist(strings)
+    # Xcodes writes UTF-16LE with BOM.
+    contents = open(strings, 'rb').read()
+    if not contents.startswith('\xff\xfe' + '/* Localized'.encode('utf-16le')):
+      test.fail_test()
+
+  test.built_file_must_exist(
+      os.path.join(
+          test_app_path, 'Contents/Resources/English.lproj/MainMenu.nib'),
+      chdir='app-bundle')
+
+  # make does not supports .xcassets files
+  extra_content_files = []
+  if test.format != 'make':
+    extra_content_files = ['Contents/Resources/Assets.car']
+    for f in extra_content_files:
+      test.built_file_must_exist(
+          os.path.join(test_app_path, f),
+          chdir='app-bundle')
+
+  # Packaging
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Contents/PkgInfo'),
+      chdir='app-bundle')
+  test.built_file_must_match(
+      os.path.join(test_app_path, 'Contents/PkgInfo'), 'APPLause',
+      chdir='app-bundle')
+
+  # Check that no other files get added to the bundle.
+  if set(ls(test.built_file_path(test_app_path, chdir='app-bundle'))) != \
+     set(['Contents/MacOS/Test App Assets Catalog Gyp',
+          'Contents/Info.plist',
+          'Contents/Resources/English.lproj/MainMenu.nib',
+          'Contents/PkgInfo',
+          ] + extra_content_files +
+         [os.path.join('Contents/Resources/English.lproj', f)
+             for f in strings_files]):
+    test.fail_test()
+
+  test.pass_test()