4c728ac4893c064923c4ad0c13d80d432e22944a
[platform/framework/web/crosswalk.git] / src / xwalk / app / tools / android / make_apk_test.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2013, 2014 Intel Corporation. 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 import optparse
8 import os
9 import shutil
10 import subprocess
11 import sys
12 import unittest
13 import warnings
14
15 from customize import ReplaceSpaceWithUnderscore
16
17
18 def Clean(name, app_version):
19   if os.path.exists(name):
20     shutil.rmtree(name)
21   if options.mode == 'shared':
22     if os.path.isfile(name + '_' + app_version + '.apk'):
23       os.remove(name + '_' + app_version + '.apk')
24   else:
25     if os.path.isfile(name + '_' + app_version + '_x86.apk'):
26       os.remove(name + '_' + app_version + '_x86.apk')
27     if os.path.isfile(name + '_' + app_version + '_arm.apk'):
28       os.remove(name + '_' + app_version + '_arm.apk')
29
30
31 def CompareSizeForCompressor(mode, original, ext, name, fun):
32   size = 0
33   compressed_size = 0
34   mode_list = ['all', 'js', 'css']
35
36   www_dir = os.path.join(name, 'assets', 'www')
37   if os.path.exists(www_dir):
38     size = GetFileSize(original)
39     compressed_file = os.path.join(www_dir, ext, 'test.' + ext)
40     compressed_size = GetFileSize(compressed_file)
41
42     if mode in mode_list:
43       fun(compressed_size < size)
44     else:
45       fun(size == compressed_size)
46   else:
47     print('Error: %s is not exist.' % www_dir)
48
49
50 def GetFileSize(file_path):
51   size = 0
52   if os.path.exists(file_path):
53     size = os.path.getsize(file_path)
54   return size
55
56
57 def RunCommand(command):
58   """Runs the command list, return the output."""
59   proc = subprocess.Popen(command, stdout=subprocess.PIPE,
60                           stderr=subprocess.STDOUT, shell=False)
61   return proc.communicate()[0]
62
63
64 def GetResultWithOption(mode=None, manifest=None, name=None, package=None):
65   app_url = None
66   if manifest is not None:
67     manifest = '--manifest=' + manifest
68   else:
69     app_url = '--app-url=http://www.intel.com'
70   if name is not None:
71     name = '--name=' + name
72   if package is not None:
73     package = '--package=' + package
74
75   cmd = ['python', 'make_apk.py',
76          '--app-version=1.0.0',
77          '%s' % manifest,
78          '%s' % name,
79          '%s' % package,
80          '%s' % app_url,
81          '%s' % mode]
82   return RunCommand(cmd)
83
84
85 class TestMakeApk(unittest.TestCase):
86   @classmethod
87   def setUpClass(cls):
88     cls._original_dir = os.getcwd()
89     if options.tool_path:
90       target_dir = os.path.expanduser(options.tool_path)
91     elif options.build_dir and options.target:
92       target_dir = os.path.join(options.build_dir,
93                                 options.target,
94                                 'xwalk_app_template')
95     if os.path.exists(target_dir):
96       # Prepare the test data.
97       test_src_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),
98                                   'test_data')
99       test_des_dir = os.path.join(target_dir, 'test_data')
100       if not os.path.exists(test_des_dir):
101         shutil.copytree(test_src_dir, test_des_dir)
102       os.chdir(target_dir)
103     else:
104       unittest.SkipTest('xwalk_app_template folder doesn\'t exist. '
105                         'Skipping all tests in make_apk_test.py')
106     cls._mode = ''
107     if options.mode == 'shared':
108       cls._mode = '--mode=shared'
109     elif options.mode == 'embedded':
110       cls._mode = '--mode=embedded'
111     cls.fakeNativeLibrary()
112
113   @classmethod
114   def tearDownClass(cls):
115     # Clean the test data.
116     if options.tool_path:
117       test_data_dir = os.path.join(os.path.expanduser(options.tool_path),
118                                    'test_data')
119     elif options.build_dir and options.target:
120       test_data_dir = os.path.join(options.build_dir,
121                                    options.target,
122                                    'xwalk_app_template',
123                                    'test_data')
124     if os.path.exists(test_data_dir):
125       shutil.rmtree(test_data_dir)
126     cls.restoreNativeLibrary()
127     os.chdir(cls._original_dir)
128
129   @staticmethod
130   def fakeNativeLibrary():
131     # To reduce the time consumption of make_apk test for embedded mode,
132     # replace the original native library with an empty library.
133     # Because it doesn't affect the result of test.
134     if options.mode == 'embedded':
135       native_library_dir = 'native_libs'
136       native_library_temp_dir = 'temp'
137       shutil.copytree(native_library_dir, native_library_temp_dir)
138       for root, _, files in os.walk(native_library_dir):
139         if 'libxwalkcore.so' in files:
140           native_library_path = os.path.join(root, 'libxwalkcore.so')
141           # Remove the original library
142           os.remove(native_library_path)
143           # Create an empty library file
144           open(native_library_path, 'a').close()
145
146   @staticmethod
147   def restoreNativeLibrary():
148     # Restore the original native library for embedded mode.
149     if options.mode == 'embedded':
150       native_library_dir = 'native_libs'
151       native_library_temp_dir = 'temp'
152       if os.path.exists(native_library_dir):
153         shutil.rmtree(native_library_dir)
154       shutil.move(native_library_temp_dir, native_library_dir)
155
156   @staticmethod
157   def archs():
158     x86_native_lib_path = os.path.join('native_libs', 'x86', 'libs',
159                                        'x86', 'libxwalkcore.so')
160     arm_native_lib_path = os.path.join('native_libs', 'armeabi-v7a', 'libs',
161                                        'armeabi-v7a', 'libxwalkcore.so')
162     arch_list = []
163     if os.path.isfile(x86_native_lib_path):
164       arch_list.append('x86')
165     if os.path.isfile(arm_native_lib_path):
166       arch_list.append('arm')
167     return arch_list
168
169   def checkApks(self, apk_name, app_version):
170     # Check whether some files are contained in the given APK.
171     if self._mode.find('shared') != -1:
172       apk_path = '%s_%s.apk' % (apk_name, app_version)
173       self.checkApk(apk_path, '')
174     elif self._mode.find('embedded') != -1:
175       x86_apk_path = '%s_%s_x86.apk' % (apk_name, app_version)
176       if os.path.exists(x86_apk_path):
177         self.checkApk(x86_apk_path, 'x86')
178       arm_apk_path = '%s_%s_arm.apk' % (apk_name, app_version)
179       if os.path.exists(arm_apk_path):
180         self.checkApk(arm_apk_path, 'arm')
181
182   def checkApk(self, apk_path, arch):
183     # Check whether some files are contained in the given apk
184     # for specified arch.
185     cmd = ['jar', 'tvf', apk_path]
186     out = RunCommand(cmd)
187     common_files = ['AndroidManifest.xml', 'classes.dex']
188     for res_file in common_files:
189       self.assertTrue(out.find(res_file) != -1)
190     if self._mode.find('embedded') != -1:
191       embedded_related_files = ['icudtl.dat',
192                                 'xwalk.pak',
193                                 'device_capabilities_api.js',
194                                 'launch_screen_api.js',
195                                 'presentation_api.js',
196                                 'screen_orientation_api.js']
197       for res_file in embedded_related_files:
198         self.assertTrue(out.find(res_file) != -1)
199     if arch == 'x86':
200       self.assertTrue(out.find('x86/libxwalkcore.so') != -1)
201     elif arch == 'arm':
202       self.assertTrue(out.find('armeabi-v7a/libxwalkcore.so') != -1)
203
204   def testName(self):
205     cmd = ['python', 'make_apk.py', '--app-version=1.0.0',
206            '--package=org.xwalk.example', self._mode]
207     out = RunCommand(cmd)
208     Clean('Example', '1.0.0')
209     self.assertTrue(out.find('The APK name is required!') != -1)
210
211     cmd = ['python', 'make_apk.py', '--name=Test_Example',
212            '--app-version=1.0.0', '--app-url=http://www.intel.com',
213            '--package=org.xwalk.example', self._mode]
214     out = RunCommand(cmd)
215     self.assertTrue(out.find('The APK name is required!') == -1)
216     Clean('Test_Example', '1.0.0')
217
218     invalid_chars = '\/:.*?"<>|-'
219     for c in invalid_chars:
220       invalid_name = '--name=Example' + c
221       cmd = ['python', 'make_apk.py', invalid_name,
222              '--app-version=1.0.0', '--package=org.xwalk.example',
223              '--app-url=http://www.intel.com', self._mode]
224       out = RunCommand(cmd)
225       self.assertTrue(out.find('invalid characters') != -1)
226
227   def testToolVersion(self):
228     cmd = ['python', 'make_apk.py', '--version']
229     out = RunCommand(cmd)
230     self.assertTrue(out.find('Crosswalk app packaging tool version') != -1)
231
232   def testAppDescriptionAndVersion(self):
233     cmd = ['python', 'make_apk.py', '--name=Example',
234            '--package=org.xwalk.example', '--app-version=1.0.0',
235            '--description=a sample application',
236            '--app-url=http://www.intel.com', self._mode]
237     RunCommand(cmd)
238     self.addCleanup(Clean, 'Example', '1.0.0')
239     manifest = 'Example/AndroidManifest.xml'
240     with open(manifest, 'r') as content_file:
241       content = content_file.read()
242     self.assertTrue(os.path.exists(manifest))
243     self.assertTrue(content.find('description') != -1)
244     self.assertTrue(content.find('versionName') != -1)
245     self.checkApks('Example', '1.0.0')
246
247   def testAppVersionCode(self):
248     cmd = ['python', 'make_apk.py', '--name=Example',
249            '--package=org.xwalk.example', '--app-version=1.0.0',
250            '--description=a sample application',
251            '--app-versionCode=3',
252            '--app-url=http://www.intel.com', self._mode]
253     RunCommand(cmd)
254     self.addCleanup(Clean, 'Example', '1.0.0')
255     manifest = 'Example/AndroidManifest.xml'
256     with open(manifest, 'r') as content_file:
257       content = content_file.read()
258     self.assertTrue(os.path.exists(manifest))
259     self.assertTrue(content.find('versionCode="3"') != -1)
260     self.checkApks('Example', '1.0.0')
261
262   def testAppVersionCodeBase(self):
263     # Arch option only works for embedded mode,
264     # so only test it for embedded mode.
265     if self._mode.find('embedded') == -1:
266       return
267     if 'x86' in self.archs():
268       arch = '--arch=x86'
269       versionCode = 'versionCode="60000003"'
270     else:
271       arch = '--arch=arm'
272       versionCode = 'versionCode="20000003"'
273     cmd = ['python', 'make_apk.py', '--name=Example',
274            '--package=org.xwalk.example', '--app-version=1.0.0',
275            '--description=a sample application',
276            '--app-versionCodeBase=3',
277            arch,
278            '--app-url=http://www.intel.com', self._mode]
279     RunCommand(cmd)
280     self.addCleanup(Clean, 'Example', '1.0.0')
281     manifest = 'Example/AndroidManifest.xml'
282     with open(manifest, 'r') as content_file:
283       content = content_file.read()
284     self.assertTrue(os.path.exists(manifest))
285     self.assertTrue(content.find(versionCode) != -1)
286     self.checkApks('Example', '1.0.0')
287
288   def testAppBigVersionCodeBase(self):
289     # Arch option only works for embedded mode,
290     # so only test it for embedded mode.
291     if self._mode.find('embedded') == -1:
292       return
293     if 'x86' in self.archs():
294       arch = '--arch=x86'
295     else:
296       arch = '--arch=arm'
297     cmd = ['python', 'make_apk.py', '--name=Example',
298            '--package=org.xwalk.example', '--app-version=1.0.0',
299            '--description=a sample application',
300            '--app-versionCodeBase=30000000',
301            arch,
302            '--app-url=http://www.intel.com', self._mode]
303     RunCommand(cmd)
304     self.addCleanup(Clean, 'Example', '1.0.0')
305     manifest = 'Example/AndroidManifest.xml'
306     self.assertFalse(os.path.exists(manifest))
307
308   def testPermissions(self):
309     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
310            '--package=org.xwalk.example', '--permissions=geolocation',
311            '--app-url=http://www.intel.com', self._mode]
312     RunCommand(cmd)
313     self.addCleanup(Clean, 'Example', '1.0.0')
314     manifest = 'Example/AndroidManifest.xml'
315     with open(manifest, 'r') as content_file:
316       content = content_file.read()
317     self.assertTrue(os.path.exists(manifest))
318     self.assertTrue(content.find('ACCESS_FINE_LOCATION') != -1)
319     self.checkApks('Example', '1.0.0')
320
321   def testPermissionsWithError(self):
322     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
323            '--package=org.xwalk.example', '--permissions=UndefinedPermission',
324            '--app-url=http://www.intel.com', self._mode]
325     out = RunCommand(cmd)
326     self.assertTrue(out.find('related API is not supported.') != -1)
327     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
328            '--package=org.xwalk.example',
329            '--permissions=Contacts.Geolocation.Messaging',
330            '--app-url=http://www.intel.com', self._mode]
331     out = RunCommand(cmd)
332     self.assertTrue(out.find('related API is not supported.') != -1)
333
334   def testPackage(self):
335     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
336            self._mode]
337     out = RunCommand(cmd)
338     self.addCleanup(Clean, 'Example', '1.0.0')
339     self.assertTrue(out.find('The package name is required!') != -1)
340     Clean('Example', '1.0.0')
341     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
342            '--package=org.xwalk.example', self._mode]
343     out = RunCommand(cmd)
344     self.assertTrue(out.find('The package name is required!') == -1)
345
346   def testEntry(self):
347     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
348            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
349            self._mode]
350     out = RunCommand(cmd)
351     self.addCleanup(Clean, 'Example', '1.0.0')
352     self.assertTrue(out.find('The entry is required.') == -1)
353     self.checkApks('Example', '1.0.0')
354     Clean('Example', '1.0.0')
355
356     test_entry_root = 'test_data/entry'
357     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
358            '--package=org.xwalk.example', '--app-root=%s' % test_entry_root,
359            '--app-local-path=index.html', self._mode]
360     out = RunCommand(cmd)
361     self.assertTrue(out.find('The entry is required.') == -1)
362     self.checkApks('Example', '1.0.0')
363
364   def testEntryWithErrors(self):
365     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
366            '--package=org.xwalk.example', self._mode]
367     out = RunCommand(cmd)
368     self.addCleanup(Clean, 'Example', '1.0.0')
369     self.assertTrue(out.find('The entry is required.') != -1)
370     self.assertFalse(os.path.exists('Example.apk'))
371     Clean('Example', '1.0.0')
372
373     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
374            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
375            '--app-root=.', self._mode]
376     out = RunCommand(cmd)
377     self.assertTrue(out.find('The entry is required.') != -1)
378     self.assertFalse(os.path.exists('Example.apk'))
379     Clean('Example', '1.0.0')
380
381     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
382            '--package=org.xwalk.example', '--app-root=./', self._mode]
383     out = RunCommand(cmd)
384     self.assertTrue(out.find('The entry is required.') != -1)
385     self.assertFalse(os.path.exists('Example.apk'))
386     Clean('Example', '1.0.0')
387
388     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
389            '--package=org.xwalk.example', '--app-local-path=index.html',
390            self._mode]
391     out = RunCommand(cmd)
392     self.assertTrue(out.find('The entry is required.') != -1)
393     self.assertFalse(os.path.exists('Example.apk'))
394     Clean('Example', '1.0.0')
395
396     manifest_path = os.path.join('test_data', 'manifest',
397                                  'manifest_app_launch_local_path.json')
398     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
399            self._mode]
400     out = RunCommand(cmd)
401     self.assertTrue(
402         out.find('Please make sure that the local path file') != -1)
403     self.assertFalse(os.path.exists('Example.apk'))
404
405   def testIconByOption(self):
406     icon = os.path.join('test_data', 'manifest', 'icons', 'icon_96.png')
407     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
408            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
409            '--icon=%s' % icon, self._mode]
410     RunCommand(cmd)
411     self.addCleanup(Clean, 'Example', '1.0.0')
412     manifest = 'Example/AndroidManifest.xml'
413     with open(manifest, 'r') as content_file:
414       content = content_file.read()
415     self.assertTrue(content.find('drawable/icon_96') != -1)
416     self.checkApks('Example', '1.0.0')
417
418   def testIconByManifest(self):
419     manifest_path = os.path.join('test_data', 'manifest', 'manifest_icon.json')
420     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
421            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
422            '--manifest=%s' % manifest_path, self._mode]
423     RunCommand(cmd)
424     self.addCleanup(Clean, 'Example', '1.0.0')
425     manifest = 'Example/AndroidManifest.xml'
426     with open(manifest, 'r') as content_file:
427       content = content_file.read()
428     self.assertTrue(content.find('drawable/icon') != -1)
429     self.checkApks('Example', '1.0.0')
430
431   def testFullscreen(self):
432     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
433            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
434            '-f', self._mode]
435     RunCommand(cmd)
436     self.addCleanup(Clean, 'Example', '1.0.0')
437     theme = 'Example/res/values/theme.xml'
438     with open(theme, 'r') as content_file:
439       content = content_file.read()
440     self.assertTrue(os.path.exists(theme))
441     self.assertTrue(
442         content.find(
443             '<item name="android:windowFullscreen">true</item>') != -1)
444     self.checkApks('Example', '1.0.0')
445
446   def testEnableRemoteDebugging(self):
447     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
448            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
449            '--enable-remote-debugging', self._mode]
450     RunCommand(cmd)
451     self.addCleanup(Clean, 'Example', '1.0.0')
452     activity = 'Example/src/org/xwalk/example/ExampleActivity.java'
453     with open(activity, 'r') as content_file:
454       content = content_file.read()
455     self.assertTrue(os.path.exists(activity))
456     self.assertTrue(content.find('setRemoteDebugging') != -1)
457     self.checkApks('Example', '1.0.0')
458     Clean('Example', '1.0.0')
459     manifest_path = os.path.join('test_data', 'manifest', 'manifest.json')
460     cmd = ['python', 'make_apk.py', '--enable-remote-debugging',
461            '--manifest=%s' % manifest_path, self._mode]
462     RunCommand(cmd)
463     activity = 'Example/src/org/xwalk/example/ExampleActivity.java'
464     with open(activity, 'r') as content_file:
465       content = content_file.read()
466     self.assertTrue(os.path.exists(activity))
467     self.assertTrue(content.find('setRemoteDebugging') != -1)
468     self.checkApks('Example', '1.0.0')
469
470   def testKeystore(self):
471     keystore_path = os.path.join('test_data', 'keystore',
472                                  'xwalk-test.keystore')
473     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
474            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
475            '--keystore-path=%s' % keystore_path, '--keystore-alias=xwalk-test',
476            '--keystore-passcode=xwalk-test', self._mode]
477     RunCommand(cmd)
478     self.addCleanup(Clean, 'Example', '1.0.0')
479     self.assertTrue(os.path.exists('Example'))
480     apk_list = ['Example.apk', 'Example_x86.apk', 'Example_arm.apk']
481     for apk in apk_list:
482       if os.path.isfile(apk):
483         cmd = ['jarsigner', '-verify', '-keystore',
484                keystore_path, '-verbose', apk]
485         out = RunCommand(cmd)
486         self.assertTrue(out.find('smk') != -1)
487     self.checkApks('Example', '1.0.0')
488
489   def testManifest(self):
490     manifest_path = os.path.join('test_data', 'manifest', 'manifest.json')
491     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
492            self._mode]
493     RunCommand(cmd)
494     self.addCleanup(Clean, 'Example', '1.0.0')
495     manifest = 'Example/AndroidManifest.xml'
496     with open(manifest, 'r') as content_file:
497       content = content_file.read()
498     self.assertTrue(os.path.exists(manifest))
499     self.assertTrue(content.find('android.permission.READ_CONTACTS') != -1)
500     self.assertTrue(content.find('android.permission.WRITE_CONTACTS') != -1)
501     self.assertTrue(
502         content.find('android.permission.ACCESS_FINE_LOCATION') != -1)
503     self.assertTrue(content.find('android.permission.READ_SMS') != -1)
504     self.assertTrue(content.find('android.permission.RECEIVE_SMS') != -1)
505     self.assertTrue(content.find('android.permission.SEND_SMS') != -1)
506     self.assertTrue(content.find('android.permission.WRITE_SMS') != -1)
507     theme = 'Example/res/values/theme.xml'
508     with open(theme, 'r') as content_file:
509       content = content_file.read()
510     self.assertTrue(os.path.exists(theme))
511     self.assertTrue(
512         content.find(
513             '<item name="android:windowFullscreen">true</item>') != -1)
514     self.assertTrue(os.path.exists('Example'))
515     self.checkApks('Example', '1.0.0')
516
517   def testManifestWithSpecificValue(self):
518     manifest_path = os.path.join('test_data', 'manifest',
519                                  'manifest_app_launch_local_path.json')
520     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
521            self._mode]
522     out = RunCommand(cmd)
523     self.addCleanup(Clean, 'Example', '1.0.0')
524     self.assertTrue(out.find('no app launch path') == -1)
525     self.checkApks('Example', '1.0.0')
526
527   def testManifestWithError(self):
528     manifest_path = os.path.join('test_data', 'manifest',
529                                  'manifest_no_app_launch_path.json')
530     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
531            '--verbose', self._mode]
532     out = RunCommand(cmd)
533     self.assertTrue(out.find('no app launch path') != -1)
534     manifest_path = os.path.join('test_data', 'manifest',
535                                  'manifest_no_name.json')
536     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
537            '--verbose', self._mode]
538     out = RunCommand(cmd)
539     self.assertTrue(out.find('no \'name\' field') != -1)
540     manifest_path = os.path.join('test_data', 'manifest',
541                                  'manifest_no_version.json')
542     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
543            '--verbose', self._mode]
544     out = RunCommand(cmd)
545     self.assertTrue(out.find('no \'version\' field') != -1)
546     manifest_path = os.path.join('test_data', 'manifest',
547                                  'manifest_permissions_format_error.json')
548     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
549            '--verbose', self._mode]
550     out = RunCommand(cmd)
551     self.assertTrue(out.find('\'Permissions\' field error') != -1)
552     manifest_path = os.path.join('test_data', 'manifest',
553                                  'manifest_permissions_field_error.json')
554     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
555            '--verbose', self._mode]
556     out = RunCommand(cmd)
557     self.assertTrue(out.find('\'Permissions\' field error') != -1)
558     manifest_path = os.path.join('test_data', 'manifest',
559                                  'manifest_not_supported_permission.json')
560     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path,
561            '--verbose', self._mode]
562     out = RunCommand(cmd)
563     self.assertTrue(
564         out.find('\'Telephony\' related API is not supported') != -1)
565
566   def testExtensionsWithOneExtension(self):
567     # Test with an existed extension.
568     extension_path = 'test_data/extensions/myextension'
569     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
570            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
571            '--extensions=%s' % extension_path, self._mode]
572     RunCommand(cmd)
573     self.addCleanup(Clean, 'Example', '1.0.0')
574     self.assertTrue(os.path.exists('Example'))
575     extensions_config_json = 'Example/assets/extensions-config.json'
576     self.assertTrue(os.path.exists(extensions_config_json))
577     with open(extensions_config_json, 'r') as content_file:
578       content = content_file.read()
579     self.assertTrue(
580         content.find('xwalk-extensions/myextension/myextension.js'))
581     self.assertTrue(content.find('com.example.extension.MyExtension'))
582     extension_js = 'Example/assets/xwalk-extensions/myextension/myextension.js'
583     self.assertTrue(os.path.exists(extension_js))
584     extension_jar = 'Example/xwalk-extensions/myextension/myextension.jar'
585     self.assertTrue(os.path.exists(extension_jar))
586     self.checkApks('Example', '1.0.0')
587
588   def testExtensionsWithNonExtension(self):
589     # Test with a non-existed extension.
590     extension_path = 'test_data/extensions/myextension'
591     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
592            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
593            '--extensions=%s1' % extension_path, self._mode, '--verbose']
594     out = RunCommand(cmd)
595     error_msg = 'Error: can\'t find the extension directory'
596     self.assertTrue(out.find(error_msg) != -1)
597     self.assertTrue(out.find('Exiting with error code: 9') != -1)
598
599   def testExtensionWithPermissions(self):
600     test_entry_root = 'test_data/entry'
601     # Add redundant separators for test.
602     extension_path = 'test_data//extensions/contactextension/'
603     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
604            '--package=org.xwalk.example', '--app-root=%s' % test_entry_root,
605            '--app-local-path=contactextension.html',
606            '--extensions=%s' % extension_path, self._mode]
607     RunCommand(cmd)
608     self.addCleanup(Clean, 'Example', '1.0.0')
609     self.assertTrue(os.path.exists('Example'))
610     manifest = 'Example/AndroidManifest.xml'
611     with open(manifest, 'r') as content_file:
612       content = content_file.read()
613     self.assertTrue(os.path.exists(manifest))
614     self.assertTrue(content.find('android.permission.WRITE_CONTACTS') != -1)
615     self.assertTrue(content.find('android.permission.READ_CONTACTS') != -1)
616     self.checkApks('Example', '1.0.0')
617
618   def testXPK(self):
619     xpk_file = os.path.join('test_data', 'xpk', 'example.xpk')
620     cmd = ['python', 'make_apk.py', '--xpk=%s' % xpk_file, self._mode]
621     RunCommand(cmd)
622     self.addCleanup(Clean, 'Example', '1.0.0')
623     self.assertTrue(os.path.exists('Example'))
624     self.checkApks('Example', '1.0.0')
625
626   def testXPKWithError(self):
627     xpk_file = os.path.join('test_data', 'xpk', 'error.xpk')
628     cmd = ['python', 'make_apk.py', '--xpk=%s' % xpk_file, self._mode]
629     out = RunCommand(cmd)
630     error_msg = 'XPK doesn\'t contain manifest file'
631     self.assertTrue(out.find(error_msg) != -1)
632     self.assertFalse(os.path.exists('Example'))
633
634   def testOrientation(self):
635     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
636            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
637            '--orientation=landscape', self._mode]
638     RunCommand(cmd)
639     self.addCleanup(Clean, 'Example', '1.0.0')
640     manifest = 'Example/AndroidManifest.xml'
641     with open(manifest, 'r') as content_file:
642       content = content_file.read()
643     self.assertTrue(os.path.exists(manifest))
644     self.assertTrue(content.find('landscape') != -1)
645     self.assertTrue(os.path.exists('Example'))
646     self.checkApks('Example', '1.0.0')
647
648   def testArch(self):
649     # Arch option only works for embedded mode,
650     # so only test it for embedded mode.
651     if self._mode.find('embedded') != -1:
652       cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
653              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
654              '--arch=x86', self._mode]
655       RunCommand(cmd)
656       self.addCleanup(Clean, 'Example', '1.0.0')
657       if 'x86' in self.archs():
658         self.assertTrue(os.path.isfile('Example_1.0.0_x86.apk'))
659         self.checkApk('Example_1.0.0_x86.apk', 'x86')
660       else:
661         self.assertFalse(os.path.isfile('Example_1.0.0_x86.apk'))
662       self.assertFalse(os.path.isfile('Example_1.0.0_arm.apk'))
663       Clean('Example', '1.0.0')
664       cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
665              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
666              '--arch=arm', self._mode]
667       RunCommand(cmd)
668       if 'arm' in self.archs():
669         self.assertTrue(os.path.isfile('Example_1.0.0_arm.apk'))
670         self.checkApk('Example_1.0.0_arm.apk', 'arm')
671       else:
672         self.assertFalse(os.path.isfile('Example_1.0.0._arm.apk'))
673       self.assertFalse(os.path.isfile('Example_1.0.0_x86.apk'))
674       Clean('Example', '1.0.0')
675       cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
676              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
677              self._mode]
678       RunCommand(cmd)
679       if 'arm' in self.archs():
680         self.assertTrue(os.path.isfile('Example_1.0.0_arm.apk'))
681         self.checkApk('Example_1.0.0_arm.apk', 'arm')
682       else:
683         self.assertFalse(os.path.isfile('Example_1.0.0._arm.apk'))
684       if 'x86' in self.archs():
685         self.assertTrue(os.path.isfile('Example_1.0.0_x86.apk'))
686         self.checkApk('Example_1.0.0_x86.apk', 'x86')
687       else:
688         self.assertFalse(os.path.isfile('Example_1.0.0._x86.apk'))
689       Clean('Example', '1.0.0')
690       cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
691              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
692              '--arch=undefined', self._mode]
693       out = RunCommand(cmd)
694       error_msg = 'invalid choice: \'undefined\''
695       self.assertTrue(out.find(error_msg) != -1)
696
697   def testVerbose(self):
698     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
699            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
700            '--verbose', self._mode]
701     result = RunCommand(cmd)
702     self.addCleanup(Clean, 'Example', '1.0.0')
703     self.assertTrue(result.find('aapt') != -1)
704     self.assertTrue(result.find('crunch') != -1)
705     self.assertTrue(result.find('apkbuilder') != -1)
706     self.assertTrue(os.path.exists('Example'))
707     self.checkApks('Example', '1.0.0')
708
709   def executeCommandAndVerifyResult(self, exec_file):
710     # Test all of supported options with empty 'mode' option.
711     icon_path = './app_src/res/drawable-xhdpi/crosswalk.png'
712     extension_path = 'test_data/extensions/myextension'
713     arch = ''
714     icon = ''
715     if exec_file.find("make_apk.py") != -1:
716       arch = '--arch=x86'
717       icon = '--icon=%s' % icon_path
718     cmd = ['python', '%s' % exec_file,
719            '--app-version=1.0.0',
720            '--app-url=http://www.intel.com',
721            '%s' % arch,
722            '--description=a sample application',
723            '--enable-remote-debugging',
724            '--extensions=%s' % extension_path,
725            '--fullscreen',
726            '--keep-screen-on',
727            '%s' % icon,
728            '--name=Example',
729            '--orientation=landscape',
730            '--package=org.xwalk.example',
731            '--permissions=geolocation']
732     RunCommand(cmd)
733     self.addCleanup(Clean, 'Example', '1.0.0')
734     activity = 'Example/src/org/xwalk/example/ExampleActivity.java'
735     with open(activity, 'r') as content_file:
736       content = content_file.read()
737     self.assertTrue(os.path.exists(activity))
738     # Test remote debugging option.
739     self.assertTrue(content.find('setRemoteDebugging') != -1)
740     # Test keep screen on option
741     self.assertTrue(content.find('FLAG_KEEP_SCREEN_ON') != -1)
742
743     manifest = 'Example/AndroidManifest.xml'
744     with open(manifest, 'r') as content_file:
745       content = content_file.read()
746     self.assertTrue(os.path.exists(manifest))
747     # Test permission option.
748     self.assertTrue(content.find('ACCESS_FINE_LOCATION') != -1)
749     # Test description option.
750     self.assertTrue(content.find('description') != -1)
751     # Test app version option.
752     self.assertTrue(content.find('versionName') != -1)
753     # Test orientation option.
754     self.assertTrue(content.find('landscape') != -1)
755     # Test fullscreen option
756     theme = 'Example/res/values/theme.xml'
757     with open(theme, 'r') as content_file:
758       content = content_file.read()
759     self.assertTrue(os.path.exists(theme))
760     self.assertTrue(
761         content.find(
762             '<item name="android:windowFullscreen">true</item>') != -1)
763     # Test extensions option.
764     extensions_config_json = 'Example/assets/extensions-config.json'
765     self.assertTrue(os.path.exists(extensions_config_json))
766     with open(extensions_config_json, 'r') as content_file:
767       content = content_file.read()
768       js_file_name = 'xwalk-extensions/myextension/myextension.js'
769       self.assertTrue(content.find(js_file_name))
770       self.assertTrue(content.find('com.example.extension.MyExtension'))
771     extension_js = 'Example/assets/xwalk-extensions/myextension/myextension.js'
772     self.assertTrue(os.path.exists(extension_js))
773     extension_jar = 'Example/xwalk-extensions/myextension/myextension.jar'
774     self.assertTrue(os.path.exists(extension_jar))
775
776   def testEmptyMode(self):
777     self.executeCommandAndVerifyResult('make_apk.py')
778
779   def testCustomizeFile(self):
780     cmd = ['python', 'make_apk.py',
781            '--app-url=http://www.intel.com',
782            '--app-version=1.0.0',
783            '--name=Example',
784            '--package=org.xwalk.example',
785            '--verbose']
786     RunCommand(cmd)
787     manifest = 'Example/AndroidManifest.xml'
788     if not os.path.exists(manifest):
789       print 'The \'%s\' was not generated, please check it.' % manifest
790       sys.exit(1)
791
792     self.executeCommandAndVerifyResult('customize.py')
793
794   def testLaunchScreen(self):
795     # Prepare launch screen resources.
796     launch_screen_path = os.path.join('test_data', 'launchScreen')
797     orientations = ['default', 'portrait', 'landscape']
798     dimensions = ['0_75', '1', '1_5', '2']
799     img_types = ['img', 'bg']
800     for orientation in orientations:
801       for dimension in dimensions:
802         for img_type in img_types:
803           name = orientation + '_' + img_type + '_' + dimension
804           path_tmp = os.path.join(launch_screen_path, name)
805           _file = open(path_tmp,'w+')
806           _file.write(name)
807           _file.close()
808     # Run Test.
809     manifest_path = os.path.join('test_data', 'launchScreen', 'manifest.json')
810     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path, self._mode]
811     RunCommand(cmd)
812     # Check theme.xml.
813     theme_path = os.path.join('Example', 'res', 'values', 'theme.xml')
814     self.assertTrue(os.path.exists(theme_path))
815     with open(theme_path, 'r') as content_file:
816       content = content_file.read()
817     self.assertTrue(content.find('@drawable/launchscreen_bg') != -1)
818     # Check launchscreen_bg.xml
819     launch_screen_bg_path = os.path.join(
820         "Example", 'res', 'drawable', 'launchscreen_bg.xml')
821     self.assertTrue(os.path.exists(launch_screen_bg_path))
822     with open(launch_screen_bg_path, 'r') as content_file:
823       content = content_file.read()
824     self.assertTrue(content.find('@drawable/launchscreen_bg_img') != -1)
825     # Check resource images
826     for orientation in orientations:
827       for dimension in dimensions:
828         drawable = 'drawable'
829         if orientation == 'portrait':
830           drawable = drawable + '-port'
831         elif orientation == 'landscape':
832           drawable = drawable + '-land'
833         if dimension == '0_75':
834           drawable = drawable + '-ldpi'
835         elif dimension == '1':
836           drawable = drawable + '-mdpi'
837         elif dimension == '1_5':
838           drawable = drawable + '-hdpi'
839         elif dimension == '2':
840           drawable = drawable + '-xhdpi'
841         # Check background image
842         bg_drawable = os.path.join(
843             "Example", 'res', drawable, 'launchscreen_bg_img')
844         self.assertTrue(os.path.exists(bg_drawable))
845         with open(bg_drawable, 'r') as content_file:
846           content = content_file.read()
847         name = orientation + '_' + 'bg' + '_' + dimension
848         self.assertTrue(content == name)
849         # Check foreground image
850         fg_drawable = os.path.join(
851             "Example", 'res', drawable, 'launchscreen_img')
852         self.assertTrue(os.path.exists(fg_drawable))
853         with open(fg_drawable, 'r') as content_file:
854           content = content_file.read()
855         name = orientation + '_' + 'img' + '_' + dimension
856         self.assertTrue(content == name)
857     self.checkApks('Example', '1.0.0')
858     Clean('Example', '1.0.0')
859
860   def testTargetDir(self):
861     test_option = ['./', '../', '~/']
862     for option in test_option:
863       cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
864              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
865              '--target-dir=%s' % option, self._mode]
866       RunCommand(cmd)
867       self.addCleanup(Clean, os.path.expanduser('%sExample' % option), '1.0.0')
868       if self._mode.find('shared') != -1:
869         apk_path = os.path.expanduser('%sExample_1.0.0.apk' % option)
870         self.assertTrue(os.path.exists(apk_path))
871         self.checkApk(apk_path, '')
872       elif self._mode.find('embedded') != -1:
873         for arch in self.archs():
874           apk_path = os.path.expanduser('%sExample_1.0.0_%s.apk'
875                                         % (option, arch))
876           self.assertTrue(os.path.exists(apk_path))
877           self.checkApk(apk_path, arch)
878
879   def testCompressor(self):
880     app_root = os.path.join('test_data', 'compressor')
881     css_folder = os.path.join('test_data', 'compressor', 'css')
882     css_file = os.path.join(css_folder, 'test.css')
883     js_folder = os.path.join('test_data', 'compressor', 'js')
884     js_file = os.path.join(js_folder, 'test.js')
885     fun = self.assertTrue
886     name = 'Example'
887
888     cmd = ['python', 'customize.py',
889            '--name=%s' % name,
890            '--compressor',
891            '--app-root=%s' % app_root]
892     RunCommand(cmd)
893     CompareSizeForCompressor('all', css_file, 'css', name, fun)
894     CompareSizeForCompressor('all', js_file, 'js', name, fun)
895
896     cmd = ['python', 'customize.py',
897            '--name=%s' % name,
898            '--app-root=%s' % app_root,
899            '--compressor']
900     RunCommand(cmd)
901     CompareSizeForCompressor('all', css_file, 'css', name, fun)
902     CompareSizeForCompressor('all', js_file, 'js', name, fun)
903
904     cmd = ['python', 'customize.py',
905            '--name=%s' % name,
906            '--compressor=js',
907            '--app-root=%s' % app_root]
908     RunCommand(cmd)
909     CompareSizeForCompressor('js', js_file, 'js', name, fun)
910
911     cmd = ['python', 'customize.py',
912            '--name=%s' % name,
913            '--compressor=css',
914            '--app-root=%s' % app_root]
915     RunCommand(cmd)
916     CompareSizeForCompressor('css', css_file, 'css', name, fun)
917
918     cmd = ['python', 'customize.py',
919            '--name=%s' % name,
920            '--app-root=%s' % app_root]
921     RunCommand(cmd)
922     CompareSizeForCompressor(None, css_file, 'css', name, fun)
923     CompareSizeForCompressor(None, js_file, 'js', name, fun)
924
925     cmd = ['python', 'customize.py',
926            '--name=%s' % name,
927            '--app-root=%s' % app_root,
928            '--compressor=other']
929     RunCommand(cmd)
930     CompareSizeForCompressor(None, css_file, 'css', name, fun)
931     CompareSizeForCompressor(None, js_file, 'js', name, fun)
932
933     Clean(name, '1.0.0')
934
935   def testInvalidCharacter(self):
936     version = '1.0.0'
937     start_with_letters = ' should be started with letters'
938     app_name_error = 'app name' + start_with_letters
939     package_name_error = 'package name' + start_with_letters
940     parse_error = 'parser error in manifest.json file'
941     directory = os.path.join('test_data', 'manifest', 'invalidchars')
942
943     manifest_path = os.path.join(directory, 'manifest_with_space_name.json')
944     result = GetResultWithOption(self._mode, manifest_path)
945     self.assertTrue(result.find(app_name_error) != -1)
946
947     manifest_path = os.path.join(directory, 'manifest_with_chinese_name.json')
948     result = GetResultWithOption(self._mode, manifest_path)
949     self.assertTrue(result.find(app_name_error) != -1)
950
951     manifest_path = os.path.join(directory, 'manifest_parse_error.json')
952     result = GetResultWithOption(self._mode, manifest_path)
953     self.assertTrue(result.find(parse_error) != -1)
954
955     manifest_path = os.path.join(directory, 'manifest_with_invalid_name.json')
956     result = GetResultWithOption(self._mode, manifest_path)
957     self.assertTrue(result.find(app_name_error) != -1)
958
959     manifest_path = os.path.join(directory, 'manifest_contain_space_name.json')
960     result = GetResultWithOption(self._mode, manifest_path)
961     self.assertTrue(result.find(app_name_error) == -1)
962
963     package = 'org.xwalk.example'
964     name = '_hello'
965     result = GetResultWithOption(self._mode, name=name, package=package)
966     self.assertTrue(result.find(app_name_error) != -1)
967
968     name = '123hello'
969     result = GetResultWithOption(self._mode, name=name, package=package)
970     self.assertTrue(result.find(app_name_error) != -1)
971
972     name = 'hello_'
973     result = GetResultWithOption(self._mode, name=name, package=package)
974     self.assertTrue(result.find(app_name_error) == -1)
975     Clean(name, version)
976
977     name = 'xwalk'
978     package = 'org.xwalk._example'
979     result = GetResultWithOption(self._mode, name=name, package=package)
980     self.assertTrue(result.find(package_name_error) != -1)
981
982     package = 'org.xwalk.123example'
983     result = GetResultWithOption(self._mode, name=name, package=package)
984     self.assertTrue(result.find(package_name_error) != -1)
985
986     package = 'org.xwalk.example_'
987     result = GetResultWithOption(self._mode, name=name, package=package)
988     self.assertTrue(result.find(package_name_error) == -1)
989     Clean(name, version)
990
991
992   def VerifyResultForAppNameWithSpace(self, manifest=None, name=None,
993                                       package=None):
994     version = '1.0.0'
995     GetResultWithOption(manifest=manifest, name=name, package=package)
996     if name is None:
997       name = 'app name '
998     replaced_name = ReplaceSpaceWithUnderscore(name)
999     manifest = replaced_name + '/AndroidManifest.xml'
1000     with open(manifest, 'r') as content_file:
1001       content = content_file.read()
1002     self.assertTrue(os.path.exists(manifest))
1003     self.assertTrue(name in content)
1004     Clean(replaced_name, version)
1005
1006
1007   def testAppNameWithSpace(self):
1008     name = 'app name'
1009     package = 'org.xwalk.app_name'
1010
1011     self.VerifyResultForAppNameWithSpace(name=name, package=package)
1012
1013     name = 'app name '
1014     self.VerifyResultForAppNameWithSpace(name=name, package=package)
1015
1016     directory = os.path.join('test_data', 'manifest', 'invalidchars')
1017     manifest_path = os.path.join(directory, 'manifest_contain_space_name.json')
1018     self.VerifyResultForAppNameWithSpace(manifest=manifest_path)
1019
1020
1021 def SuiteWithModeOption():
1022   # Gather all the tests for the specified mode option.
1023   test_suite = unittest.TestSuite()
1024   test_suite.addTest(TestMakeApk('testAppBigVersionCodeBase'))
1025   test_suite.addTest(TestMakeApk('testAppVersionCode'))
1026   test_suite.addTest(TestMakeApk('testAppVersionCodeBase'))
1027   test_suite.addTest(TestMakeApk('testAppDescriptionAndVersion'))
1028   test_suite.addTest(TestMakeApk('testArch'))
1029   test_suite.addTest(TestMakeApk('testEnableRemoteDebugging'))
1030   test_suite.addTest(TestMakeApk('testEntry'))
1031   test_suite.addTest(TestMakeApk('testEntryWithErrors'))
1032   test_suite.addTest(TestMakeApk('testExtensionsWithOneExtension'))
1033   test_suite.addTest(TestMakeApk('testExtensionsWithNonExtension'))
1034   test_suite.addTest(TestMakeApk('testExtensionWithPermissions'))
1035   test_suite.addTest(TestMakeApk('testFullscreen'))
1036   test_suite.addTest(TestMakeApk('testIconByOption'))
1037   test_suite.addTest(TestMakeApk('testIconByManifest'))
1038   test_suite.addTest(TestMakeApk('testInvalidCharacter'))
1039   test_suite.addTest(TestMakeApk('testKeystore'))
1040   test_suite.addTest(TestMakeApk('testManifest'))
1041   test_suite.addTest(TestMakeApk('testManifestWithError'))
1042   test_suite.addTest(TestMakeApk('testName'))
1043   test_suite.addTest(TestMakeApk('testOrientation'))
1044   test_suite.addTest(TestMakeApk('testPackage'))
1045   test_suite.addTest(TestMakeApk('testPermissions'))
1046   test_suite.addTest(TestMakeApk('testPermissionsWithError'))
1047   test_suite.addTest(TestMakeApk('testXPK'))
1048   test_suite.addTest(TestMakeApk('testXPKWithError'))
1049   test_suite.addTest(TestMakeApk('testTargetDir'))
1050   test_suite.addTest(TestMakeApk('testLaunchScreen'))
1051   return test_suite
1052
1053
1054 def SuiteWithEmptyModeOption():
1055   # Gather all the tests for empty mode option.
1056   test_suite = unittest.TestSuite()
1057   test_suite.addTest(TestMakeApk('testAppNameWithSpace'))
1058   test_suite.addTest(TestMakeApk('testCompressor'))
1059   test_suite.addTest(TestMakeApk('testCustomizeFile'))
1060   test_suite.addTest(TestMakeApk('testEmptyMode'))
1061   test_suite.addTest(TestMakeApk('testToolVersion'))
1062   test_suite.addTest(TestMakeApk('testVerbose'))
1063   return test_suite
1064
1065
1066 def TestSuiteRun(test_runner, suite):
1067   results = test_runner.run(suite)
1068   return results.wasSuccessful()
1069
1070
1071 if __name__ == '__main__':
1072   parser = optparse.OptionParser()
1073   info = ('The build directory for xwalk.'
1074           'Such as: --build-dir=src/out')
1075   parser.add_option('--build-dir', help=info)
1076   info = ('The build target for xwalk.'
1077           'Such as: --target=Release')
1078   parser.add_option('--target', help=info)
1079   info = ('The path of package tool.')
1080   parser.add_option('--tool-path', help=info)
1081   info = ('The packaging mode for xwalk. Such as: --mode=embedded.'
1082           'Please refer the detail to the option of make_apk.py.')
1083   parser.add_option('--mode', help=info)
1084   options, dummy = parser.parse_args()
1085   if len(sys.argv) == 1:
1086     parser.print_help()
1087     sys.exit(1)
1088
1089   del sys.argv[1:]
1090   mode_suite = SuiteWithModeOption()
1091   empty_mode_suite = SuiteWithEmptyModeOption()
1092   runner = unittest.TextTestRunner(verbosity=2)
1093   if options.build_dir or options.target:
1094     warnings.warn(('"--build-dir" and "--target" will be deprecated soon, '
1095                    'please leverage "--tool-path" instead.'),
1096                   Warning)
1097   test_result = True
1098   if options.mode:
1099     test_result = TestSuiteRun(runner, mode_suite)
1100   else:
1101     # Run tests in both embedded and shared mode
1102     # when the mode option isn't specified.
1103     options.mode = 'embedded'
1104     print 'Run tests in embedded mode.'
1105     test_result = TestSuiteRun(runner, mode_suite)
1106     options.mode = 'shared'
1107     print 'Run tests in shared mode.'
1108     test_result = TestSuiteRun(runner, mode_suite) and test_result
1109     options.mode = ''
1110     print 'Run test without \'--mode\' option.'
1111     test_result = TestSuiteRun(runner, empty_mode_suite) and test_result
1112   if not test_result:
1113     sys.exit(1)