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.
16 def Clean(name, app_version):
17 if os.path.exists(name):
19 if options.mode == 'shared':
20 if os.path.isfile(name + '_' + app_version + '.apk'):
21 os.remove(name + '_' + app_version + '.apk')
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')
29 def CompareSizeForCompressor(mode, original, ext, name, fun):
32 mode_list = ['all', 'js', 'css']
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)
41 fun(compressed_size < size)
43 fun(size == compressed_size)
45 print('Error: %s is not exist.' % www_dir)
48 def GetFileSize(file_path):
50 if os.path.exists(file_path):
51 size = os.path.getsize(file_path)
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]
62 def GetResultWithOption(mode, manifest=None, name=None, package=None):
64 if manifest is not None:
65 manifest = '--manifest=' + manifest
67 app_url = '--app-url=http://www.intel.com'
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',
79 return RunCommand(cmd)
82 class TestMakeApk(unittest.TestCase):
85 cls._original_dir = os.getcwd()
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,
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__)),
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)
101 unittest.SkipTest('xwalk_app_template folder doesn\'t exist. '
102 'Skipping all tests in make_apk_test.py')
104 if options.mode == 'shared':
105 cls._mode = '--mode=shared'
106 elif options.mode == 'embedded':
107 cls._mode = '--mode=embedded'
108 cls.fakeNativeLibrary()
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),
116 elif options.build_dir and options.target:
117 test_data_dir = os.path.join(options.build_dir,
119 'xwalk_app_template',
121 if os.path.exists(test_data_dir):
122 shutil.rmtree(test_data_dir)
123 cls.restoreNativeLibrary()
124 os.chdir(cls._original_dir)
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()
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)
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')
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')
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')
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',
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)
197 self.assertTrue(out.find('x86/libxwalkcore.so') != -1)
199 self.assertTrue(out.find('armeabi-v7a/libxwalkcore.so') != -1)
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)
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')
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)
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)
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]
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')
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]
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')
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:
264 if 'x86' in self.archs():
266 versionCode = 'versionCode="60000003"'
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',
275 '--app-url=http://www.intel.com', self._mode]
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')
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:
290 if 'x86' in self.archs():
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',
299 '--app-url=http://www.intel.com', self._mode]
301 self.addCleanup(Clean, 'Example', '1.0.0')
302 manifest = 'Example/AndroidManifest.xml'
303 self.assertFalse(os.path.exists(manifest))
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]
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')
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)
331 def testPackage(self):
332 cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
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)
344 cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
345 '--package=org.xwalk.example', '--app-url=http://www.intel.com',
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')
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')
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')
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')
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')
385 cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
386 '--package=org.xwalk.example', '--app-local-path=index.html',
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')
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,
397 out = RunCommand(cmd)
399 out.find('Please make sure that the local path file') != -1)
400 self.assertFalse(os.path.exists('Example.apk'))
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]
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')
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]
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')
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',
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))
440 '<item name="android:windowFullscreen">true</item>') != -1)
441 self.checkApks('Example', '1.0.0')
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]
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]
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')
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]
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']
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')
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,
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)
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))
510 '<item name="android:windowFullscreen">true</item>') != -1)
511 self.assertTrue(os.path.exists('Example'))
512 self.checkApks('Example', '1.0.0')
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,
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')
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)
561 out.find('\'Telephony\' related API is not supported') != -1)
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]
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()
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')
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)
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]
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')
616 xpk_file = os.path.join('test_data', 'xpk', 'example.xpk')
617 cmd = ['python', 'make_apk.py', '--xpk=%s' % xpk_file, self._mode]
619 self.addCleanup(Clean, 'Example', '1.0.0')
620 self.assertTrue(os.path.exists('Example'))
621 self.checkApks('Example', '1.0.0')
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'))
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]
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')
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]
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')
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]
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')
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',
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')
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')
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)
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')
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'
712 if exec_file.find("make_apk.py") != -1:
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',
719 '--description=a sample application',
720 '--enable-remote-debugging',
721 '--extensions=%s' % extension_path,
726 '--orientation=landscape',
727 '--package=org.xwalk.example',
728 '--permissions=geolocation']
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)
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))
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))
773 def testEmptyMode(self):
774 self.executeCommandAndVerifyResult('make_apk.py')
776 def testCustomizeFile(self):
777 cmd = ['python', 'make_apk.py',
778 '--app-url=http://www.intel.com',
779 '--app-version=1.0.0',
781 '--package=org.xwalk.example',
784 manifest = 'Example/AndroidManifest.xml'
785 if not os.path.exists(manifest):
786 print 'The \'%s\' was not generated, please check it.' % manifest
789 self.executeCommandAndVerifyResult('customize.py')
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+')
806 manifest_path = os.path.join('test_data', 'launchScreen', 'manifest.json')
807 cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path, self._mode]
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')
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]
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'
873 self.assertTrue(os.path.exists(apk_path))
874 self.checkApk(apk_path, arch)
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
885 cmd = ['python', 'customize.py',
888 '--app-root=%s' % app_root]
890 CompareSizeForCompressor('all', css_file, 'css', name, fun)
891 CompareSizeForCompressor('all', js_file, 'js', name, fun)
893 cmd = ['python', 'customize.py',
895 '--app-root=%s' % app_root,
898 CompareSizeForCompressor('all', css_file, 'css', name, fun)
899 CompareSizeForCompressor('all', js_file, 'js', name, fun)
901 cmd = ['python', 'customize.py',
904 '--app-root=%s' % app_root]
906 CompareSizeForCompressor('js', js_file, 'js', name, fun)
908 cmd = ['python', 'customize.py',
911 '--app-root=%s' % app_root]
913 CompareSizeForCompressor('css', css_file, 'css', name, fun)
915 cmd = ['python', 'customize.py',
917 '--app-root=%s' % app_root]
919 CompareSizeForCompressor(None, css_file, 'css', name, fun)
920 CompareSizeForCompressor(None, js_file, 'js', name, fun)
922 cmd = ['python', 'customize.py',
924 '--app-root=%s' % app_root,
925 '--compressor=other']
927 CompareSizeForCompressor(None, css_file, 'css', name, fun)
928 CompareSizeForCompressor(None, js_file, 'js', name, fun)
932 def testInvalidCharacter(self):
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')
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)
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)
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)
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)
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)
960 package = 'org.xwalk.example'
962 result = GetResultWithOption(self._mode, name=name, package=package)
963 self.assertTrue(result.find(app_name_error) != -1)
966 result = GetResultWithOption(self._mode, name=name, package=package)
967 self.assertTrue(result.find(app_name_error) != -1)
970 result = GetResultWithOption(self._mode, name=name, package=package)
971 self.assertTrue(result.find(app_name_error) == -1)
975 package = 'org.xwalk._example'
976 result = GetResultWithOption(self._mode, name=name, package=package)
977 self.assertTrue(result.find(package_name_error) != -1)
979 package = 'org.xwalk.123example'
980 result = GetResultWithOption(self._mode, name=name, package=package)
981 self.assertTrue(result.find(package_name_error) != -1)
983 package = 'org.xwalk.example_'
984 result = GetResultWithOption(self._mode, name=name, package=package)
985 self.assertTrue(result.find(package_name_error) == -1)
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'))
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'))
1033 def TestSuiteRun(test_runner, suite):
1034 results = test_runner.run(suite)
1035 return results.wasSuccessful()
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:
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.'),
1066 test_result = TestSuiteRun(runner, mode_suite)
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
1077 print 'Run test without \'--mode\' option.'
1078 test_result = TestSuiteRun(runner, empty_mode_suite) and test_result