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