Commit c10750cf authored by Peter Kotwicz's avatar Peter Kotwicz Committed by Commit Bot

Convert monochrome_apk_checker.py to typ

The benefit of converting the test to typ is that it makes adding other
monochrome tests easier.

BUG=1115604

Change-Id: Id36ae6cc9e60efa27d54a1f37f39f7004b9c3619
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2456189
Commit-Queue: Peter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@google.com>
Cr-Commit-Position: refs/heads/master@{#814863}
parent 8e18b7f3
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import argparse
import re import re
import os import os
import posixpath import posixpath
...@@ -14,6 +13,16 @@ import subprocess ...@@ -14,6 +13,16 @@ import subprocess
from contextlib import closing from contextlib import closing
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
SRC_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(CUR_DIR))))
TYP_DIR = os.path.join(
SRC_DIR, 'third_party', 'catapult', 'third_party', 'typ')
if TYP_DIR not in sys.path:
sys.path.insert(0, TYP_DIR)
import typ
def BuildFileMatchRegex(*file_matchers): def BuildFileMatchRegex(*file_matchers):
return re.compile('^' + '|'.join(file_matchers) + '$') return re.compile('^' + '|'.join(file_matchers) + '$')
...@@ -141,7 +150,13 @@ def DumpAPK(apk): ...@@ -141,7 +150,13 @@ def DumpAPK(apk):
match.group('cmpr') == 0)) match.group('cmpr') == 0))
return apk_entries return apk_entries
def VerifySameFile(monochrome_dict, apk, changes, apk_name):
def DeobfuscateFilename(obfuscated_filename, pathmap):
return pathmap.get(obfuscated_filename, obfuscated_filename)
class MonochromeApkCheckerTest(typ.TestCase):
def VerifySameFile(self, monochrome_dict, apk, changes, apk_name):
"""Verify apk file content matches same files in monochrome. """Verify apk file content matches same files in monochrome.
Verify files from apk are same as those in monochrome except files Verify files from apk are same as those in monochrome except files
...@@ -153,17 +168,15 @@ def VerifySameFile(monochrome_dict, apk, changes, apk_name): ...@@ -153,17 +168,15 @@ def VerifySameFile(monochrome_dict, apk, changes, apk_name):
m = monochrome_dict.get(a.filename) m = monochrome_dict.get(a.filename)
if m and m.CRC != a.CRC and not changes.match(m.filename): if m and m.CRC != a.CRC and not changes.match(m.filename):
diff.append(a.filename) diff.append(a.filename)
if len(diff): self.assertEquals(len(diff), 0, """\
msg = """\
Unless specifcially excepted, all files in {0} should be exactly the same as Unless specifcially excepted, all files in {0} should be exactly the same as
the similarly named file in Monochrome. However these files were present in the similarly named file in Monochrome. However these files were present in
both monochrome and {0}, but had different contents: both monochrome and {0}, but had different contents:
{1} {1}
""".format(apk_name, '\n'.join(diff)) """.format(apk_name, '\n'.join(diff)))
raise Exception(msg)
def VerifyUncompressed(monochrome, apk, apk_name): def VerifyUncompressed(self, monochrome, apk, apk_name):
"""Verify uncompressed files in apk are a subset of those in monochrome. """Verify uncompressed files in apk are a subset of those in monochrome.
Verify files not being compressed in apk are also uncompressed in Verify files not being compressed in apk are also uncompressed in
...@@ -172,16 +185,14 @@ def VerifyUncompressed(monochrome, apk, apk_name): ...@@ -172,16 +185,14 @@ def VerifyUncompressed(monochrome, apk, apk_name):
uncompressed = [i.filename for i in apk if i.uncompressed ] uncompressed = [i.filename for i in apk if i.uncompressed ]
monochrome_uncompressed = [i.filename for i in monochrome if i.uncompressed] monochrome_uncompressed = [i.filename for i in monochrome if i.uncompressed]
compressed = [u for u in uncompressed if u not in monochrome_uncompressed] compressed = [u for u in uncompressed if u not in monochrome_uncompressed]
if len(compressed): self.assertEquals(len(compressed), 0, """\
msg = """\
Uncompressed files in {0} should also be uncompressed in Monochrome. Uncompressed files in {0} should also be uncompressed in Monochrome.
However these files were uncompressed in {0} but compressed in Monochrome: However these files were uncompressed in {0} but compressed in Monochrome:
{1} {1}
""".format(apk_name, '\n'.join(compressed)) """.format(apk_name, '\n'.join(compressed)))
raise Exception(msg)
def SuperSetOf(monochrome, apk, apk_name): def SuperSetOf(self, monochrome, apk, apk_name):
"""Verify Monochrome is super set of apk.""" """Verify Monochrome is super set of apk."""
def exists_in_some_form(f): def exists_in_some_form(f):
...@@ -198,21 +209,19 @@ def SuperSetOf(monochrome, apk, apk_name): ...@@ -198,21 +209,19 @@ def SuperSetOf(monochrome, apk, apk_name):
return any(x.endswith(name) for x in monochrome) return any(x.endswith(name) for x in monochrome)
missing_files = [f for f in apk if not exists_in_some_form(f)] missing_files = [f for f in apk if not exists_in_some_form(f)]
if len(missing_files): self.assertEquals(len(missing_files), 0, """\
msg = """\
Monochrome is expected to have a superset of the files in {0}. Monochrome is expected to have a superset of the files in {0}.
However these files were present in {0} but not in Monochrome: However these files were present in {0} but not in Monochrome:
{1} {1}
""".format(apk_name, '\n'.join(missing_files)) """.format(apk_name, '\n'.join(missing_files)))
raise Exception(msg)
def RemoveSpecific(apk_entries, specific): def RemoveSpecific(self, apk_entries, specific):
return [i for i in apk_entries return [i for i in apk_entries
if not specific.search(i.filename) ] if not specific.search(i.filename) ]
def LoadPathmap(pathmap_path): def LoadPathmap(self, pathmap_path):
"""Load the pathmap of obfuscated resource paths. """Load the pathmap of obfuscated resource paths.
Returns: A dict mapping from obfuscated paths to original paths or an Returns: A dict mapping from obfuscated paths to original paths or an
...@@ -232,87 +241,41 @@ def LoadPathmap(pathmap_path): ...@@ -232,87 +241,41 @@ def LoadPathmap(pathmap_path):
return pathmap return pathmap
def DeobfuscateFilename(obfuscated_filename, pathmap): def testApkChecker(self):
return pathmap.get(obfuscated_filename, obfuscated_filename) options = self.context
def ParseArgs(args):
"""Parses command line options.
Returns:
An Namespace from argparse.parse_args()
"""
parser = argparse.ArgumentParser(
prog='monochrome_apk_checker',
description='This script enforces expectations about similarities '
'between Chrome, Monochrome and Webview APKs.',
epilog='If the release APK is obfuscated, you will find its pathmap next '
'to the apk in your output directory, ending with ".pathmap".')
required_args = parser.add_argument_group('required arguments')
required_args.add_argument(
'--monochrome-apk', required=True, help='The path to the monochrome APK.')
parser.add_argument(
'--monochrome-pathmap', help='The monochrome APK resources pathmap path.')
required_args.add_argument(
'--chrome-apk',
required=True,
help='The path to the chrome APK.')
parser.add_argument(
'--chrome-pathmap', help='The chrome APK resources pathmap path.')
required_args.add_argument(
'--system-webview-apk',
required=True,
help='The path to the system webview APK.')
parser.add_argument(
'--system-webview-pathmap',
help='The system webview APK resources pathmap path.')
# This script is called from test bots that sometimes would add extra unneeded
# arguments. Just ignore unknown ones. crbug.com/1084351
parsed, _ = parser.parse_known_args(args)
return parsed
def main():
options = ParseArgs(sys.argv[1:])
monochrome = DumpAPK(options.monochrome_apk) monochrome = DumpAPK(options.monochrome_apk)
monochrome_pathmap = LoadPathmap(options.monochrome_pathmap) monochrome_pathmap = self.LoadPathmap(options.monochrome_pathmap)
monochrome_files = [ monochrome_files = [
DeobfuscateFilename(f.filename, monochrome_pathmap) for f in monochrome DeobfuscateFilename(f.filename, monochrome_pathmap)
for f in monochrome
] ]
monochrome_dict = dict([(DeobfuscateFilename(i.filename, monochrome_pathmap), monochrome_dict = dict([(DeobfuscateFilename(i.filename, monochrome_pathmap),
i) for i in monochrome]) i) for i in monochrome])
chrome = RemoveSpecific(DumpAPK(options.chrome_apk), chrome = self.RemoveSpecific(DumpAPK(options.chrome_apk),
CHROME_SPECIFIC) CHROME_SPECIFIC)
if len(chrome) == 0: self.assertTrue(len(chrome) > 0,
raise Exception(
'Chrome should have common files with Monochrome. However the passed ' 'Chrome should have common files with Monochrome. However the passed '
'in APKs do not have any files in common. Are you sure you are passing ' 'in APKs do not have any files in common. Are you sure you are passing '
'in the right arguments?') 'in the right arguments?')
webview = RemoveSpecific(DumpAPK(options.system_webview_apk), webview = self.RemoveSpecific(DumpAPK(options.system_webview_apk),
WEBVIEW_SPECIFIC) WEBVIEW_SPECIFIC)
if len(webview) == 0: self.assertTrue(len(webview) > 0,
raise Exception(
'Webview should have common files with Monochrome. However the passed ' 'Webview should have common files with Monochrome. However the passed '
'in APKs do not have any files in common. Are you sure you are passing ' 'in APKs do not have any files in common. Are you sure you are passing '
'in the right arguments?') 'in the right arguments?')
def check_apk(apk, pathmap, apk_name): def check_apk(apk, pathmap, apk_name):
apk_files = [DeobfuscateFilename(f.filename, pathmap) for f in apk] apk_files = [DeobfuscateFilename(f.filename, pathmap) for f in apk]
SuperSetOf(monochrome_files, apk_files, apk_name) self.SuperSetOf(monochrome_files, apk_files, apk_name)
VerifyUncompressed(monochrome, apk, apk_name) self.VerifyUncompressed(monochrome, apk, apk_name)
chrome_pathmap = LoadPathmap(options.chrome_pathmap) chrome_pathmap = self.LoadPathmap(options.chrome_pathmap)
check_apk(chrome, chrome_pathmap, 'Chrome') check_apk(chrome, chrome_pathmap, 'Chrome')
VerifySameFile(monochrome_dict, chrome, CHROME_CHANGES, 'Chrome') self.VerifySameFile(monochrome_dict, chrome, CHROME_CHANGES, 'Chrome')
webview_pathmap = LoadPathmap(options.system_webview_pathmap) webview_pathmap = self.LoadPathmap(options.system_webview_pathmap)
check_apk(webview, webview_pathmap, 'Webview') check_apk(webview, webview_pathmap, 'Webview')
VerifySameFile(monochrome_dict, webview, WEBVIEW_CHANGES, 'Webview') self.VerifySameFile(monochrome_dict, webview, WEBVIEW_CHANGES, 'Webview')
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/env python2.7
#
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
SRC_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(CUR_DIR))))
TYP_DIR = os.path.join(
SRC_DIR, 'third_party', 'catapult', 'third_party', 'typ')
if TYP_DIR not in sys.path:
sys.path.insert(0, TYP_DIR)
import typ
def create_argument_parser():
""" Creates command line parser. """
parser = typ.ArgumentParser()
required_args = parser.add_argument_group('required arguments')
required_args.add_argument(
'--monochrome-apk', required=True, help='The path to the monochrome APK.')
parser.add_argument(
'--monochrome-pathmap', help='The monochrome APK resources pathmap path.')
required_args.add_argument(
'--chrome-apk',
required=True,
help='The path to the chrome APK.')
parser.add_argument(
'--chrome-pathmap', help='The chrome APK resources pathmap path.')
required_args.add_argument(
'--system-webview-apk',
required=True,
help='The path to the system webview APK.')
parser.add_argument(
'--system-webview-pathmap',
help='The system webview APK resources pathmap path.')
return parser
def main(argv):
argument_parser = create_argument_parser()
runner = typ.Runner()
runner.parse_args(argument_parser, argv[1:])
runner.args.top_level_dirs = [ os.path.dirname(__file__) ]
runner.context = runner.args
# Needs to be set to enable customizing runner.context
runner.win_multiprocessing = typ.WinMultiprocessing.importable
return_code, _, _ = runner.run()
return return_code
if __name__ == '__main__':
sys.exit(main(sys.argv))
...@@ -1249,8 +1249,7 @@ ...@@ -1249,8 +1249,7 @@
}, },
"monochrome_apk_checker": { "monochrome_apk_checker": {
"args": [ "args": [
"--script", "../../chrome/android/monochrome/scripts/monochrome_python_tests.py",
"../../chrome/android/monochrome/scripts/monochrome_apk_checker.py",
"--chrome-apk", "--chrome-apk",
"apks/ChromePublic.apk", "apks/ChromePublic.apk",
"--chrome-pathmap", "--chrome-pathmap",
...@@ -1265,7 +1264,7 @@ ...@@ -1265,7 +1264,7 @@
"apks/MonochromePublic.apk.pathmap.txt", "apks/MonochromePublic.apk.pathmap.txt",
], ],
"label": "//chrome/android/monochrome:monochrome_apk_checker", "label": "//chrome/android/monochrome:monochrome_apk_checker",
"script": "//testing/scripts/monochrome_apk_checker_wrapper.py", "script": "//testing/scripts/run_isolated_script_test.py",
"type": "script", "type": "script",
}, },
"monochrome_public_test_ar_apk": { "monochrome_public_test_ar_apk": {
......
#!/usr/bin/env python
#
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This is just a wrapper script around monochrome_apk_checker.py that
# understands and uses the isolated-script arguments
import argparse
import json
import os
import sys
import subprocess
import time
import common
def _PathExists(path):
return path is not None and os.path.exists(path)
def _ForwardOptionalArgs(args):
forwardable_args = []
if _PathExists(args.monochrome_pathmap):
forwardable_args += ['--monochrome-pathmap', args.monochrome_pathmap]
if _PathExists(args.chrome_pathmap):
forwardable_args += ['--chrome-pathmap', args.chrome_pathmap]
if _PathExists(args.system_webview_pathmap):
forwardable_args += [
'--system-webview-pathmap', args.system_webview_pathmap
]
return forwardable_args
def main():
parser = argparse.ArgumentParser(prog='monochrome_apk_checker_wrapper')
parser.add_argument('--script',
required=True,
help='The path to the monochrome_apk_checker.py script')
parser.add_argument('--isolated-script-test-output',
required=True)
# Only run one test, we check that it's the test we expect.
parser.add_argument('--isolated-script-test-filter')
# Ignored, but required to satisfy the isolated_script interface.
# We aren't a perf test, so don't have any perf output.
parser.add_argument('--isolated-script-test-perf-output')
# We must intercept the pathmap args since they are always passed by the
# trybots but the files in question may not actually exist (path shortening
# may not be enabled for all apks). Check if the files exist and forward the
# arg iff they are.
parser.add_argument(
'--monochrome-pathmap', help='The monochrome APK resources pathmap path.')
parser.add_argument(
'--chrome-pathmap', help='The chrome APK resources pathmap path.')
parser.add_argument(
'--system-webview-pathmap',
help='The system webview APK resources pathmap path.')
args, extra = parser.parse_known_args(sys.argv[1:])
if args.isolated_script_test_filter and (
'monochrome_apk_checker' not in args.isolated_script_test_filter):
parser.error('isolated-script-test-filter has invalid test: %s' %
(args.isolated_script_test_filter))
cmd = [args.script] + extra + _ForwardOptionalArgs(args)
start_time = time.time()
ret = subprocess.call(cmd)
success = ret == 0
# Schema is at //docs/testing/json_test_results_format.md
with open(args.isolated_script_test_output, 'w') as fp:
test = {
'expected': 'PASS',
'actual': 'PASS' if success else 'FAIL',
}
if not success:
test['is_unexpected'] = True
json.dump({
'version': 3,
'interrupted': False,
'path_delimiter': '/',
'seconds_since_epoch': start_time,
'num_failures_by_type': {
'PASS': int(success),
'FAIL': int(not success),
},
'tests': {
'monochrome_apk_checker': test,
}
}, fp)
return ret
# This is not really a "script test" so does not need to manually add
# any additional compile targets.
def main_compile_targets(args):
json.dump([], args.output)
if __name__ == '__main__':
# Conform minimally to the protocol defined by ScriptTest.
if 'compile_targets' in sys.argv:
funcs = {
'run': None,
'compile_targets': main_compile_targets,
}
sys.exit(common.run_script(sys.argv[1:], funcs))
sys.exit(main())
...@@ -59,6 +59,7 @@ KNOWN_TYP_TEST_RUNNERS = { ...@@ -59,6 +59,7 @@ KNOWN_TYP_TEST_RUNNERS = {
'metrics_python_tests.py', 'metrics_python_tests.py',
'run_mac_signing_tests.py', 'run_mac_signing_tests.py',
'run_polymer_tools_tests.py', 'run_polymer_tools_tests.py',
'monochrome_python_tests.py',
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment