From ba0c5ea90d0e6b2e8b20696e54fea13ead6dda93 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Fri, 28 Mar 2014 15:59:04 +0000 Subject: [PATCH] Updates to Android.mk generation. Generate SkUserConfig. Include arm64 as another build flavor. Add tests. gyp/common_conditions.gypi: Add conditions for Android framework. These will get written into the generated SkUserConfig. include/core/SkUserConfig.h: Generated version that will ultimately be checked into Android (but not here). platform_tools/android/bin/gyp_to_android.py: Generate SkUserConfig. Add arm64 (note that arm64 is not currently respected by our gyp files, so it results in use _none.cpp for the various opts). Reset the common defines, which are now passed to the generated SkUserConfig. platform_tools/android/gyp_gen/generate_user_config.py: New script to generate SkUserConfig.h. platform_tools/android/gyp_gen/gypd_parser.py: Fix a lint error (unused import). platform_tools/android/gyp_gen/makefile_writer.py: Append any remaining DEFINES to LOCAL_CFLAGS (previously this was done during parsing). Add a warning for arm64 (corresponds to downstream Android.mk). platform_tools/android/gyp_gen/vars_dict_lib.py: Add OrderedSet.reset(). Add DEFINES to VarsDict. platform_tools/android/tests/expectations/: Add and update expectations files. platform_tools/android/tests/generate_user_config_tests.py: New test for generate_user_config.py platform_tools/android/tests/inputs/SkUserConfig.h: Input to the new test, so we don't have to update the expectations each time the real SkUserConfig.h changes. platform_tools/android/tests/makefile_writer_tests.py: Add a way to rebaseline test_write_local_vars, which has changed. Refactor EXPECTATIONS_DIR and compare_files into a separate file for sharing with generate_user_config_tests.py. platform_tools/android/tests/utils.py: Common code for tests. platform_tools/android/tests/var_dict_tests.py: Use a for loop to test the new key (DEFINES) and future proof this test to test any new keys in the future. BUG=skia:1975 R=djsollen@google.com, halcanary@google.com Author: scroggo@google.com Review URL: https://codereview.chromium.org/198063002 git-svn-id: http://skia.googlecode.com/svn/trunk@13975 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/common_conditions.gypi | 22 +++- platform_tools/android/bin/gyp_to_android.py | 24 +++- .../android/gyp_gen/generate_user_config.py | 96 ++++++++++++++++ platform_tools/android/gyp_gen/gypd_parser.py | 4 +- platform_tools/android/gyp_gen/makefile_writer.py | 18 ++- platform_tools/android/gyp_gen/vars_dict_lib.py | 11 ++ .../android/tests/expectations/Android.mk | 13 +++ .../android/tests/expectations/SkUserConfig.h | 43 +++++++ .../tests/expectations/write_local_vars_append_arm | 3 + .../tests/expectations/write_local_vars_append_foo | 3 + .../expectations/write_local_vars_append_no_name | 3 + .../expectations/write_local_vars_no_append_arm | 3 + .../expectations/write_local_vars_no_append_foo | 3 + .../write_local_vars_no_append_no_name | 3 + .../android/tests/generate_user_config_tests.py | 89 +++++++++++++++ platform_tools/android/tests/inputs/SkUserConfig.h | 10 ++ .../android/tests/makefile_writer_tests.py | 125 +++++++++++---------- platform_tools/android/tests/ordered_set_tests.py | 9 ++ platform_tools/android/tests/utils.py | 36 ++++++ platform_tools/android/tests/var_dict_tests.py | 26 +---- 20 files changed, 452 insertions(+), 92 deletions(-) create mode 100644 platform_tools/android/gyp_gen/generate_user_config.py create mode 100644 platform_tools/android/tests/expectations/SkUserConfig.h create mode 100644 platform_tools/android/tests/generate_user_config_tests.py create mode 100644 platform_tools/android/tests/inputs/SkUserConfig.h create mode 100644 platform_tools/android/tests/utils.py diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi index d7bc5ab..82f63f3 100644 --- a/gyp/common_conditions.gypi +++ b/gyp/common_conditions.gypi @@ -253,9 +253,27 @@ # draw-time, at which point we know which SkTypeface is being drawn 'SK_USE_FREETYPE_EMBOLDEN', # Android provides at least FreeType 2.4.0 at runtime. - 'SK_FONTHOST_FREETYPE_RUNTIME_VERSION=0x020400', + 'SK_FONTHOST_FREETYPE_RUNTIME_VERSION 0x020400', # Skia should not use dlopen on Android. - 'SK_CAN_USE_DLOPEN=0', + 'SK_CAN_USE_DLOPEN 0', + 'SK_SFNTLY_SUBSETTER "sample/chromium/font_subsetter.h"', + # When built as part of the system image we can enable certian non-NDK + # compliant optimizations. + 'SK_BUILD_FOR_ANDROID_FRAMEWORK', + # Android Text Tuning + 'SK_GAMMA_APPLY_TO_A8', + 'SK_GAMMA_EXPONENT 1.4', + 'SK_GAMMA_CONTRAST 0.0', + # Optimizations for chromium (m30) + 'GR_GL_CUSTOM_SETUP_HEADER "gl/GrGLConfig_chrome.h"', + 'IGNORE_ROT_AA_RECT_OPT', + # Disable this check because it is too strict for some chromium-specific + # subclasses of SkPixelRef. See bug: crbug.com/171776. + 'SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK', + 'SkLONGLONG int64_t', + 'SK_DEFAULT_FONT_CACHE_LIMIT (768 * 1024)', + 'SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_android.h"', + 'SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_pthread.h"', ], }], diff --git a/platform_tools/android/bin/gyp_to_android.py b/platform_tools/android/bin/gyp_to_android.py index 191d039..c8abfb6 100644 --- a/platform_tools/android/bin/gyp_to_android.py +++ b/platform_tools/android/bin/gyp_to_android.py @@ -26,6 +26,7 @@ GYP_GEN_DIR = os.path.join(SKIA_DIR, 'platform_tools', 'android', 'gyp_gen') sys.path.append(GYP_GEN_DIR) import gypd_parser +import generate_user_config import makefile_writer import vars_dict_lib @@ -106,13 +107,31 @@ def main(target_dir=None): mips_var_dict = generate_var_dict(tmp_folder, main_gyp_file, 'mips', False) + arm64_var_dict = generate_var_dict(tmp_folder, main_gyp_file, 'arm64', + False) + # Compute the intersection of all targets. All the files in the intersection # should be part of the makefile always. Each dict will now contain trimmed # lists containing only variable definitions specific to that configuration. var_dict_list = [default_var_dict, arm_var_dict, arm_neon_var_dict, - x86_var_dict, mips_var_dict] + x86_var_dict, mips_var_dict, arm64_var_dict] common = vars_dict_lib.intersect(var_dict_list) + # Create SkUserConfig + user_config = os.path.join(SKIA_DIR, 'include', 'config', 'SkUserConfig.h') + if target_dir: + dst_dir = target_dir + else: + dst_dir = os.path.join(SKIA_DIR, 'include', 'core') + + generate_user_config.generate_user_config( + original_sk_user_config=user_config, target_dir=dst_dir, + ordered_set=common.DEFINES) + + # Now that the defines have been written to SkUserConfig, they are not + # needed in Android.mk. + common.DEFINES.reset() + # Further trim arm_neon_var_dict with arm_var_dict. After this call, # arm_var_dict (which will now be the intersection) includes all definitions # used by both arm and arm + neon, and arm_neon_var_dict will only contain @@ -134,6 +153,9 @@ def main(target_dir=None): deviations_from_common.append(makefile_writer.VarsDictData(mips_var_dict, 'mips')) + deviations_from_common.append(makefile_writer.VarsDictData(arm64_var_dict, + 'arm64')) + makefile_writer.write_android_mk(target_dir=target_dir, common=common, deviations_from_common=deviations_from_common) diff --git a/platform_tools/android/gyp_gen/generate_user_config.py b/platform_tools/android/gyp_gen/generate_user_config.py new file mode 100644 index 0000000..fd99ba2 --- /dev/null +++ b/platform_tools/android/gyp_gen/generate_user_config.py @@ -0,0 +1,96 @@ +#!/usr/bin/python + +# Copyright 2014 Google Inc. +# +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Function for generating the SkUserConfig file, customized for Android.""" + +import os + + +AUTOGEN_WARNING = ( +""" +/////////////////////////////////////////////////////////////////////////////// +// +// THIS FILE IS AUTOGENERATED BY GYP_TO_ANDROID.PY. DO NOT EDIT. +// +// This file contains Skia's upstream include/config/SkUserConfig.h as a +// reference, followed by the actual defines set for Android. +// +/////////////////////////////////////////////////////////////////////////////// + +""" +) + +BUILD_GUARD = 'SkUserConfig_Android_DEFINED' + + +def generate_user_config(original_sk_user_config, target_dir, ordered_set): + """Generate the SkUserConfig file specific to the Android framework. + + Android needs its #defines in its skia/include/core directory, so that other + libraries which use Skia's headers get the right definitions. This function + takes the existing sample version of SkUserConfig, checked into Skia, and + appends the defines from ordered_set, which is expected to be a + vars_dict_lib.OrderedSet containing the defines. The result is written to + target_dir/SkUserConfig.h + + Args: + original_sk_user_config: Path to original SkUserConfig.h + target_dir: Directory within which the modified SkUserConfig.h will be + written. Its name will be the same basename as + original_sk_user_config. If None, the new file will be written to the + working directory. + ordered_set: A vars_dict_lib.OrderedSet, containing a list of defines to + be appended to SkUserConfig. + + Raises: + AssertionError: If original_sk_user_config does not exist. + """ + + assert os.path.exists(original_sk_user_config) + + dst_filename = os.path.basename(original_sk_user_config) + if target_dir: + dst_filename = os.path.join(target_dir, dst_filename) + + with open(dst_filename, 'w') as dst: + dst.write(AUTOGEN_WARNING) + + # Copy the original exactly. This is merely for reference. Many of the + # defines written to the file below, either manually or generated from the + # gyp files, have explanations in the original SkUserConfig.h + with open(original_sk_user_config, 'r') as original: + for line in original: + dst.write(line) + + # Now add the defines specific to Android. Write a custom build guard to + # ensure they don't get defined more than once. + dst.write('\n// Android defines:\n') + dst.write('#ifndef ' + BUILD_GUARD + '\n') + dst.write('#define ' + BUILD_GUARD + '\n') + + # Add conditional defines manually: + + # do this build check for other tools that still read this header + dst.write('#ifdef ANDROID\n') + dst.write('\t#include \n') + dst.write('#endif\n\n') + + dst.write('#if __BYTE_ORDER == __BIG_ENDIAN\n') + dst.write('\t#define SK_CPU_BENDIAN\n') + dst.write('\t#undef SK_CPU_LENDIAN\n') + dst.write('#else\n') + dst.write('\t#define SK_CPU_LENDIAN\n') + dst.write('\t#undef SK_CPU_BENDIAN\n') + dst.write('#endif\n\n') + + # Now add the defines from the gyp files. + for item in ordered_set: + # Although our defines may have '=' in them, when written to the header + # there should be a space between the macro and what it replaces. + dst.write('#define ' + item.replace('=', ' ') + '\n') + + dst.write('\n#endif // ' + BUILD_GUARD + '\n') diff --git a/platform_tools/android/gyp_gen/gypd_parser.py b/platform_tools/android/gyp_gen/gypd_parser.py index b547c42..fc4dc68 100644 --- a/platform_tools/android/gyp_gen/gypd_parser.py +++ b/platform_tools/android/gyp_gen/gypd_parser.py @@ -9,8 +9,6 @@ Functions for parsing the gypd output from gyp. """ -import vars_dict_lib - def parse_dictionary(var_dict, d, current_target_name): """ Helper function to get the meaningful entries in a dictionary. @@ -89,7 +87,7 @@ def parse_dictionary(var_dict, d, current_target_name): var_dict.LOCAL_EXPORT_C_INCLUDE_DIRS.add(include) for define in d.get('defines', []): - var_dict.LOCAL_CFLAGS.add('-D' + define) + var_dict.DEFINES.add(define) def parse_gypd(var_dict, path, desired_targets=None): diff --git a/platform_tools/android/gyp_gen/makefile_writer.py b/platform_tools/android/gyp_gen/makefile_writer.py index ea767f6..f4cdbef 100644 --- a/platform_tools/android/gyp_gen/makefile_writer.py +++ b/platform_tools/android/gyp_gen/makefile_writer.py @@ -44,19 +44,28 @@ def write_local_vars(f, var_dict, append, name): @param name If not None, a string to be appended to each key. """ for key in var_dict.keys(): + _key = key + _items = var_dict[key] if key == 'LOCAL_CFLAGS': # Always append LOCAL_CFLAGS. This allows us to define some early on in # the makefile and not overwrite them. _append = True + elif key == 'DEFINES': + # For DEFINES, we want to append to LOCAL_CFLAGS. + _append = True + _key = 'LOCAL_CFLAGS' + _items_with_D = [] + for define in _items: + _items_with_D.append('-D' + define) + _items = _items_with_D elif key == 'KNOWN_TARGETS': # KNOWN_TARGETS are not needed in the final make file. continue else: _append = append - _key = key if name: _key += '_' + name - write_group(f, _key, var_dict[key], _append) + write_group(f, _key, _items, _append) AUTOGEN_WARNING = ( @@ -186,6 +195,11 @@ def write_android_mk(target_dir, common, deviations_from_common): f.write('\tLOCAL_CFLAGS += -DNO_FALLBACK_FONT\n') f.write('endif\n\n') + f.write('ifeq ($(TARGET_ARCH),arm64)\n') + f.write(' $(warning TODOArm64: Unlike arm32, arm64 has no inline' + ' assembly for performance critical code.)\n') + f.write('endif\n\n') + write_local_vars(f, common, False, None) for data in deviations_from_common: diff --git a/platform_tools/android/gyp_gen/vars_dict_lib.py b/platform_tools/android/gyp_gen/vars_dict_lib.py index eedb8a3..a4ef67e 100644 --- a/platform_tools/android/gyp_gen/vars_dict_lib.py +++ b/platform_tools/android/gyp_gen/vars_dict_lib.py @@ -8,6 +8,10 @@ import collections import types +# The goal of this class is to store a set of unique items in the order in +# which they are inserted. This is important for the final makefile, where +# we want to make sure the image decoders are in a particular order. See +# images.gyp for more information. class OrderedSet(object): """ Ordered set of unique items that supports addition and removal. @@ -57,6 +61,12 @@ class OrderedSet(object): """ return self.__li[index] + def reset(self): + """ + Reset to empty. + """ + self.__li = [] + VAR_NAMES = ['LOCAL_CFLAGS', 'LOCAL_CPPFLAGS', 'LOCAL_SRC_FILES', @@ -64,6 +74,7 @@ VAR_NAMES = ['LOCAL_CFLAGS', 'LOCAL_STATIC_LIBRARIES', 'LOCAL_C_INCLUDES', 'LOCAL_EXPORT_C_INCLUDE_DIRS', + 'DEFINES', 'KNOWN_TARGETS'] class VarsDict(collections.namedtuple('VarsDict', VAR_NAMES)): diff --git a/platform_tools/android/tests/expectations/Android.mk b/platform_tools/android/tests/expectations/Android.mk index 6b5ff8b..ced1a29 100644 --- a/platform_tools/android/tests/expectations/Android.mk +++ b/platform_tools/android/tests/expectations/Android.mk @@ -49,6 +49,10 @@ ifeq ($(NO_FALLBACK_FONT),true) LOCAL_CFLAGS += -DNO_FALLBACK_FONT endif +ifeq ($(TARGET_ARCH),arm64) + $(warning TODOArm64: Unlike arm32, arm64 has no inline assembly for performance critical code.) +endif + LOCAL_CFLAGS += \ local_cflags @@ -70,6 +74,9 @@ LOCAL_C_INCLUDES := \ LOCAL_EXPORT_C_INCLUDE_DIRS := \ local_export_c_include_dirs +LOCAL_CFLAGS += \ + -Ddefines + ifeq ($(COND), true) LOCAL_CFLAGS_foo += \ local_cflags_foo @@ -92,6 +99,9 @@ LOCAL_C_INCLUDES_foo += \ LOCAL_EXPORT_C_INCLUDE_DIRS_foo += \ local_export_c_include_dirs_foo +LOCAL_CFLAGS_foo += \ + -Ddefines_foo + endif LOCAL_CFLAGS_bar += \ @@ -115,6 +125,9 @@ LOCAL_C_INCLUDES_bar += \ LOCAL_EXPORT_C_INCLUDE_DIRS_bar += \ local_export_c_include_dirs_bar +LOCAL_CFLAGS_bar += \ + -Ddefines_bar + include external/stlport/libstlport.mk LOCAL_MODULE:= libskia include $(BUILD_SHARED_LIBRARY) diff --git a/platform_tools/android/tests/expectations/SkUserConfig.h b/platform_tools/android/tests/expectations/SkUserConfig.h new file mode 100644 index 0000000..57827ad --- /dev/null +++ b/platform_tools/android/tests/expectations/SkUserConfig.h @@ -0,0 +1,43 @@ + +/////////////////////////////////////////////////////////////////////////////// +// +// THIS FILE IS AUTOGENERATED BY GYP_TO_ANDROID.PY. DO NOT EDIT. +// +// This file contains Skia's upstream include/config/SkUserConfig.h as a +// reference, followed by the actual defines set for Android. +// +/////////////////////////////////////////////////////////////////////////////// + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Unchanging SkUserConfig.h for testing generate_user_config. + */ + +// Android defines: +#ifndef SkUserConfig_Android_DEFINED +#define SkUserConfig_Android_DEFINED +#ifdef ANDROID + #include +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN + #define SK_CPU_BENDIAN + #undef SK_CPU_LENDIAN +#else + #define SK_CPU_LENDIAN + #undef SK_CPU_BENDIAN +#endif + +#define SK_BUILD_FOR_ANDROID +#define SK_BUILD_FOR_ANDROID_FRAMEWORK +#define SK_SCALAR_IS_FLOAT +#define foo +#define bar + +#endif // SkUserConfig_Android_DEFINED diff --git a/platform_tools/android/tests/expectations/write_local_vars_append_arm b/platform_tools/android/tests/expectations/write_local_vars_append_arm index d9f5c88..3e5f180 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_append_arm +++ b/platform_tools/android/tests/expectations/write_local_vars_append_arm @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES_arm += \ LOCAL_EXPORT_C_INCLUDE_DIRS_arm += \ local_export_c_include_dirs +LOCAL_CFLAGS_arm += \ + -Ddefines + diff --git a/platform_tools/android/tests/expectations/write_local_vars_append_foo b/platform_tools/android/tests/expectations/write_local_vars_append_foo index be9a814..66c4f91 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_append_foo +++ b/platform_tools/android/tests/expectations/write_local_vars_append_foo @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES_foo += \ LOCAL_EXPORT_C_INCLUDE_DIRS_foo += \ local_export_c_include_dirs +LOCAL_CFLAGS_foo += \ + -Ddefines + diff --git a/platform_tools/android/tests/expectations/write_local_vars_append_no_name b/platform_tools/android/tests/expectations/write_local_vars_append_no_name index 302a4fe..e0b31c5 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_append_no_name +++ b/platform_tools/android/tests/expectations/write_local_vars_append_no_name @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES += \ LOCAL_EXPORT_C_INCLUDE_DIRS += \ local_export_c_include_dirs +LOCAL_CFLAGS += \ + -Ddefines + diff --git a/platform_tools/android/tests/expectations/write_local_vars_no_append_arm b/platform_tools/android/tests/expectations/write_local_vars_no_append_arm index 01aaecb..c77a9bb 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_no_append_arm +++ b/platform_tools/android/tests/expectations/write_local_vars_no_append_arm @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES_arm := \ LOCAL_EXPORT_C_INCLUDE_DIRS_arm := \ local_export_c_include_dirs +LOCAL_CFLAGS_arm += \ + -Ddefines + diff --git a/platform_tools/android/tests/expectations/write_local_vars_no_append_foo b/platform_tools/android/tests/expectations/write_local_vars_no_append_foo index 22c8306..d93b242 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_no_append_foo +++ b/platform_tools/android/tests/expectations/write_local_vars_no_append_foo @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES_foo := \ LOCAL_EXPORT_C_INCLUDE_DIRS_foo := \ local_export_c_include_dirs +LOCAL_CFLAGS_foo += \ + -Ddefines + diff --git a/platform_tools/android/tests/expectations/write_local_vars_no_append_no_name b/platform_tools/android/tests/expectations/write_local_vars_no_append_no_name index 6742050..e7caec4 100644 --- a/platform_tools/android/tests/expectations/write_local_vars_no_append_no_name +++ b/platform_tools/android/tests/expectations/write_local_vars_no_append_no_name @@ -19,3 +19,6 @@ LOCAL_C_INCLUDES := \ LOCAL_EXPORT_C_INCLUDE_DIRS := \ local_export_c_include_dirs +LOCAL_CFLAGS += \ + -Ddefines + diff --git a/platform_tools/android/tests/generate_user_config_tests.py b/platform_tools/android/tests/generate_user_config_tests.py new file mode 100644 index 0000000..50f80db --- /dev/null +++ b/platform_tools/android/tests/generate_user_config_tests.py @@ -0,0 +1,89 @@ +#!/usr/bin/python + +# Copyright 2014 Google Inc. +# +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Test generate_user_config.py. +""" + +import argparse +import os +import shutil +import sys +import tempfile +import test_variables +import unittest +import utils + +sys.path.append(test_variables.GYP_GEN_DIR) + +from generate_user_config import generate_user_config as gen_config + +# Name of SkUserConfig file. +USER_CONFIG_NAME = 'SkUserConfig.h' +# Path to unchanging Dummy SkUserConfig file. +FULL_DUMMY_PATH = os.path.join(os.path.dirname(__file__), 'inputs', + USER_CONFIG_NAME) +REBASELINE_MSG = ('If you\'ve modified generate_user_config.py, run ' + '"generate_user_config_tests.py --rebaseline" to rebaseline') + +def generate_dummy_user_config(original_sk_user_config, target_dir): + # Add an arbitrary set of defines + defines = [ 'SK_BUILD_FOR_ANDROID', + 'SK_BUILD_FOR_ANDROID_FRAMEWORK', + 'SK_SCALAR_IS_FLOAT', + 'foo', + 'bar' ] + gen_config(original_sk_user_config=original_sk_user_config, + target_dir=target_dir, ordered_set=defines) + + +class GenUserConfigTest(unittest.TestCase): + + def test_missing_sk_user_config(self): + tmp = tempfile.mkdtemp() + original = os.path.join(tmp, 'filename') + assert not os.path.exists(original) + + with self.assertRaises(AssertionError): + ordered_set = [ 'define' ] + gen_config(original_sk_user_config=original, target_dir=tmp, + ordered_set=ordered_set) + shutil.rmtree(tmp) + + def test_gen_config(self): + tmp = tempfile.mkdtemp() + generate_dummy_user_config(FULL_DUMMY_PATH, tmp) + actual_name = os.path.join(tmp, USER_CONFIG_NAME) + utils.compare_to_expectation(actual_name=actual_name, + expectation_name=USER_CONFIG_NAME, + assert_true=self.assertTrue, msg=REBASELINE_MSG) + shutil.rmtree(tmp) + + +def main(): + loader = unittest.TestLoader() + suite = loader.loadTestsFromTestCase(GenUserConfigTest) + results = unittest.TextTestRunner(verbosity=2).run(suite) + print repr(results) + if not results.wasSuccessful(): + raise Exception('failed one or more unittests') + + +def rebaseline(): + generate_dummy_user_config(FULL_DUMMY_PATH, utils.EXPECTATIONS_DIR) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('-r', '--rebaseline', help='Rebaseline expectations.', + action='store_true') + args = parser.parse_args() + + if args.rebaseline: + rebaseline() + else: + main() + diff --git a/platform_tools/android/tests/inputs/SkUserConfig.h b/platform_tools/android/tests/inputs/SkUserConfig.h new file mode 100644 index 0000000..a8f97eb --- /dev/null +++ b/platform_tools/android/tests/inputs/SkUserConfig.h @@ -0,0 +1,10 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Unchanging SkUserConfig.h for testing generate_user_config. + */ diff --git a/platform_tools/android/tests/makefile_writer_tests.py b/platform_tools/android/tests/makefile_writer_tests.py index 9a764b5..1b42bf3 100644 --- a/platform_tools/android/tests/makefile_writer_tests.py +++ b/platform_tools/android/tests/makefile_writer_tests.py @@ -16,14 +16,16 @@ import sys import tempfile import test_variables import unittest +import utils sys.path.append(test_variables.GYP_GEN_DIR) import makefile_writer import vars_dict_lib -EXPECTATIONS_DIR = os.path.join(os.path.dirname(__file__), 'expectations') MAKEFILE_NAME = 'Android.mk' +REBASELINE_MSG = ('If you\'ve modified makefile_writer.py, run ' + '"makefile_writer_tests.py --rebaseline" to rebaseline') def generate_dummy_vars_dict(name): """Create a VarsDict and fill it with dummy entries. @@ -42,6 +44,31 @@ def generate_dummy_vars_dict(name): vars_dict[key].add(entry) return vars_dict +def generate_write_local_vars_params(): + """Generator to compute params for write_local_vars tests. + + Each iteration yields a new tuple: (filename, append, name), specific to a + way to call write_local_vars for the tests. + + Yields: + filename: filename corresponding to the expectation file for this + combination of params to write_local_vars. + append: boolean to pass as append parameter to write_local_vars. + name: string to pass as name parameter to write_local_vars. + """ + for append in [ True, False ]: + for name in [ None, 'arm', 'foo' ]: + filename = 'write_local_vars' + if append: + filename += '_append' + else: + filename += '_no_append' + if name: + filename += '_' + name + else: + filename += '_no_name' + + yield (filename, append, name) def generate_dummy_vars_dict_data(name, condition): """Create a dummy VarsDictData. @@ -94,26 +121,6 @@ class MakefileWriterTest(unittest.TestCase): self.assertEqual(f.tell(), 0) f.close() - def __compare_files(self, actual_name, expectation_name, msg=None): - """Check that two files are identical. - - Assert line by line that the files match. - - Args: - actual_name: Full path to the test file. - expectation_name: Basename of the expectations file within which - to compare. The file is expected to be in - platform_tools/android/tests/expectations. - msg: Message to pass to assertEqual. - Raises: - AssertionError: If the files do not match. - """ - with open(actual_name, 'r') as result: - with open(os.path.join(EXPECTATIONS_DIR, - expectation_name)) as expectation: - for line in result: - self.assertEqual(line, expectation.readline(), msg) - def test_write_group(self): animals = ('dog', 'cat', 'mouse', 'elephant') fd, filename = tempfile.mkstemp() @@ -121,56 +128,44 @@ class MakefileWriterTest(unittest.TestCase): makefile_writer.write_group(f, 'animals', animals, False) os.close(fd) # Now confirm that it matches expectations - self.__compare_files(filename, 'animals.txt') + utils.compare_to_expectation(filename, 'animals.txt', self.assertTrue) with open(filename, 'w') as f: makefile_writer.write_group(f, 'animals_append', animals, True) # Now confirm that it matches expectations - self.__compare_files(filename, 'animals_append.txt') + utils.compare_to_expectation(filename, 'animals_append.txt', + self.assertTrue) os.remove(filename) def test_write_local_vars(self): vars_dict = generate_dummy_vars_dict(None) - - # Call variations of write_local_vars. - for append in [ True, False ]: - for name in [ None, 'arm', 'foo' ]: - # Now write to a temporary file. - fd, outfile = tempfile.mkstemp() - with open(outfile, 'w') as f: - makefile_writer.write_local_vars(f, vars_dict, append, name) - os.close(fd) - - # Compare to the expected file. - filename = 'write_local_vars' - if append: - filename += '_append' - else: - filename += '_no_append' - if name: - filename += '_' + name - else: - filename += '_no_name' - self.__compare_files(outfile, filename) - - # KNOWN_TARGETS is always a part of the input VarsDict, but it should - # not be written to the resulting file. - # Note that this assumes none of our dummy entries is 'KNOWN_TARGETS'. - known_targets_name = 'KNOWN_TARGETS' - self.assertEqual(len(vars_dict[known_targets_name]), 1) - - with open(outfile, 'r') as f: - self.assertNotIn(known_targets_name, f.read()) - os.remove(outfile) + # Compare various ways of calling write_local_vars to expectations. + for (filename, append, name) in generate_write_local_vars_params(): + fd, outfile = tempfile.mkstemp() + with open(outfile, 'w') as f: + makefile_writer.write_local_vars(f, vars_dict, append, name) + os.close(fd) + + # Compare to the expected file. + utils.compare_to_expectation(outfile, filename, self.assertTrue, + REBASELINE_MSG) + + # KNOWN_TARGETS is always a key in the input VarsDict, but it should not + # be written to the resulting file. + # Note that this assumes none of our dummy entries is 'KNOWN_TARGETS'. + known_targets_name = 'KNOWN_TARGETS' + self.assertEqual(len(vars_dict[known_targets_name]), 1) + + with open(outfile, 'r') as f: + self.assertNotIn(known_targets_name, f.read()) + os.remove(outfile) def test_write_android_mk(self): outdir = tempfile.mkdtemp() generate_dummy_makefile(outdir) - self.__compare_files(os.path.join(outdir, MAKEFILE_NAME), MAKEFILE_NAME, - 'If you\'ve modified makefile_writer.py, run ' + - '"makefile_writer_tests.py --rebaseline" ' + - 'to rebaseline') + utils.compare_to_expectation(os.path.join(outdir, MAKEFILE_NAME), + MAKEFILE_NAME, self.assertTrue, REBASELINE_MSG) shutil.rmtree(outdir) @@ -184,15 +179,23 @@ def main(): raise Exception('failed one or more unittests') +def rebaseline(): + generate_dummy_makefile(utils.EXPECTATIONS_DIR) + + vars_dict = generate_dummy_vars_dict(None) + for (filename, append, name) in generate_write_local_vars_params(): + with open(os.path.join(utils.EXPECTATIONS_DIR, filename), 'w') as f: + makefile_writer.write_local_vars(f, vars_dict, append, name) + + if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument('-r', '--rebaseline', - help='Rebaseline expectation for Android.mk', + parser.add_argument('-r', '--rebaseline', help='Rebaseline expectations.', action='store_true') args = parser.parse_args() if args.rebaseline: - generate_dummy_makefile(EXPECTATIONS_DIR) + rebaseline() else: main() diff --git a/platform_tools/android/tests/ordered_set_tests.py b/platform_tools/android/tests/ordered_set_tests.py index 248f0f6..01016d9 100644 --- a/platform_tools/android/tests/ordered_set_tests.py +++ b/platform_tools/android/tests/ordered_set_tests.py @@ -59,6 +59,15 @@ class OrderedSetTest(unittest.TestCase): self.assertEqual(len(self.__set), RANGE-i-1) self.assertFalse(dummy_var in self.__set) + # Test reset(), for a range of ranges. + for subrange in range(RANGE): + for i in range(subrange): + self.__set.add(create_dummy_var(i)) + self.assertEqual(len(self.__set), subrange) + self.__set.reset() + self.assertEqual(len(self.__set), 0) + + def main(): loader = unittest.TestLoader() suite = loader.loadTestsFromTestCase(OrderedSetTest) diff --git a/platform_tools/android/tests/utils.py b/platform_tools/android/tests/utils.py new file mode 100644 index 0000000..0a96996 --- /dev/null +++ b/platform_tools/android/tests/utils.py @@ -0,0 +1,36 @@ +#!/usr/bin/python + +# Copyright 2014 Google Inc. +# +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Common code for tests. +""" +import filecmp +import os + +EXPECTATIONS_DIR = os.path.join(os.path.dirname(__file__), 'expectations') + +def compare_to_expectation(actual_name, expectation_name, assert_true, + msg=None): + """Check that a generated file matches its expectation in EXPECTATIONS_DIR. + + Assert that the generated file and expectation file are identical. + + Args: + actual_name: Full path to the test file. + expectation_name: Basename of the expectations file within which + to compare. The file is expected to be in + platform_tools/android/tests/expectations. + assert_true: function for asserting a statement is True + + Args: + condition: statement to check for True. + msg: message to print if the files are not equal. + + msg: Message to pass to assert_true. + """ + full_expectations_path = os.path.join(EXPECTATIONS_DIR, expectation_name) + assert_true(filecmp.cmp(actual_name, full_expectations_path), msg) diff --git a/platform_tools/android/tests/var_dict_tests.py b/platform_tools/android/tests/var_dict_tests.py index 8cd9677..94f0492 100644 --- a/platform_tools/android/tests/var_dict_tests.py +++ b/platform_tools/android/tests/var_dict_tests.py @@ -60,29 +60,9 @@ class VarsDictTest(unittest.TestCase): for i in range(RANGE): v_dict = VarsDict() # Add something common to each field, as well as a unique entry - v_dict.LOCAL_CFLAGS.add('cflag') - v_dict.LOCAL_CFLAGS.add(str(i)) - - v_dict.LOCAL_CPPFLAGS.add('cppflag') - v_dict.LOCAL_CPPFLAGS.add(str(i)) - - v_dict.LOCAL_SRC_FILES.add('src') - v_dict.LOCAL_SRC_FILES.add(str(i)) - - v_dict.LOCAL_SHARED_LIBRARIES.add('shared') - v_dict.LOCAL_SHARED_LIBRARIES.add(str(i)) - - v_dict.LOCAL_STATIC_LIBRARIES.add('static') - v_dict.LOCAL_STATIC_LIBRARIES.add(str(i)) - - v_dict.LOCAL_C_INCLUDES.add('includes') - v_dict.LOCAL_C_INCLUDES.add(str(i)) - - v_dict.LOCAL_EXPORT_C_INCLUDE_DIRS.add('exports') - v_dict.LOCAL_EXPORT_C_INCLUDE_DIRS.add(str(i)) - - v_dict.KNOWN_TARGETS.add('known') - v_dict.KNOWN_TARGETS.add(str(i)) + for key in v_dict.keys(): + v_dict[key].add(key.lower()) + v_dict[key].add(str(i)) self.assert_consistency(v_dict) -- 2.7.4