Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / base / android / jni_generator / jni_generator_tests.py
blob21534ef44585fbedc361e7b2fe3e3151c1534c0e
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Tests for jni_generator.py.
8 This test suite contains various tests for the JNI generator.
9 It exercises the low-level parser all the way up to the
10 code generator and ensures the output matches a golden
11 file.
12 """
14 import difflib
15 import inspect
16 import optparse
17 import os
18 import sys
19 import unittest
20 import jni_generator
21 from jni_generator import CalledByNative, JniParams, NativeMethod, Param
24 SCRIPT_NAME = 'base/android/jni_generator/jni_generator.py'
25 INCLUDES = (
26 'base/android/jni_generator/jni_generator_helper.h'
29 # Set this environment variable in order to regenerate the golden text
30 # files.
31 REBASELINE_ENV = 'REBASELINE'
33 class TestOptions(object):
34 """The mock options object which is passed to the jni_generator.py script."""
36 def __init__(self):
37 self.namespace = None
38 self.script_name = SCRIPT_NAME
39 self.includes = INCLUDES
40 self.pure_native_methods = False
41 self.ptr_type = 'long'
42 self.jni_init_native_name = None
43 self.eager_called_by_natives = False
44 self.cpp = 'cpp'
45 self.javap = 'javap'
46 self.native_exports = False
47 self.native_exports_optional = False
49 class TestGenerator(unittest.TestCase):
50 def assertObjEquals(self, first, second):
51 dict_first = first.__dict__
52 dict_second = second.__dict__
53 self.assertEquals(dict_first.keys(), dict_second.keys())
54 for key, value in dict_first.iteritems():
55 if (type(value) is list and len(value) and
56 isinstance(type(value[0]), object)):
57 self.assertListEquals(value, second.__getattribute__(key))
58 else:
59 actual = second.__getattribute__(key)
60 self.assertEquals(value, actual,
61 'Key ' + key + ': ' + str(value) + '!=' + str(actual))
63 def assertListEquals(self, first, second):
64 self.assertEquals(len(first), len(second))
65 for i in xrange(len(first)):
66 if isinstance(first[i], object):
67 self.assertObjEquals(first[i], second[i])
68 else:
69 self.assertEquals(first[i], second[i])
71 def assertTextEquals(self, golden_text, generated_text):
72 if not self.compareText(golden_text, generated_text):
73 self.fail('Golden text mismatch.')
75 def compareText(self, golden_text, generated_text):
76 def FilterText(text):
77 return [
78 l.strip() for l in text.split('\n')
79 if not l.startswith('// Copyright')
81 stripped_golden = FilterText(golden_text)
82 stripped_generated = FilterText(generated_text)
83 if stripped_golden == stripped_generated:
84 return True
85 print self.id()
86 for line in difflib.context_diff(stripped_golden, stripped_generated):
87 print line
88 print '\n\nGenerated'
89 print '=' * 80
90 print generated_text
91 print '=' * 80
92 print 'Run with:'
93 print 'REBASELINE=1', sys.argv[0]
94 print 'to regenerate the data files.'
96 def _ReadGoldenFile(self, golden_file):
97 if not os.path.exists(golden_file):
98 return None
99 with file(golden_file, 'r') as f:
100 return f.read()
102 def assertGoldenTextEquals(self, generated_text):
103 script_dir = os.path.dirname(sys.argv[0])
104 # This is the caller test method.
105 caller = inspect.stack()[1][3]
106 self.assertTrue(caller.startswith('test'),
107 'assertGoldenTextEquals can only be called from a '
108 'test* method, not %s' % caller)
109 golden_file = os.path.join(script_dir, caller + '.golden')
110 golden_text = self._ReadGoldenFile(golden_file)
111 if os.environ.get(REBASELINE_ENV):
112 if golden_text != generated_text:
113 with file(golden_file, 'w') as f:
114 f.write(generated_text)
115 return
116 self.assertTextEquals(golden_text, generated_text)
118 def testInspectCaller(self):
119 def willRaise():
120 # This function can only be called from a test* method.
121 self.assertGoldenTextEquals('')
122 self.assertRaises(AssertionError, willRaise)
124 def testNatives(self):
125 test_data = """"
126 interface OnFrameAvailableListener {}
127 private native int nativeInit();
128 private native void nativeDestroy(int nativeChromeBrowserProvider);
129 private native long nativeAddBookmark(
130 int nativeChromeBrowserProvider,
131 String url, String title, boolean isFolder, long parentId);
132 private static native String nativeGetDomainAndRegistry(String url);
133 private static native void nativeCreateHistoricalTabFromState(
134 byte[] state, int tab_index);
135 private native byte[] nativeGetStateAsByteArray(View view);
136 private static native String[] nativeGetAutofillProfileGUIDs();
137 private native void nativeSetRecognitionResults(
138 int sessionId, String[] results);
139 private native long nativeAddBookmarkFromAPI(
140 int nativeChromeBrowserProvider,
141 String url, Long created, Boolean isBookmark,
142 Long date, byte[] favicon, String title, Integer visits);
143 native int nativeFindAll(String find);
144 private static native OnFrameAvailableListener nativeGetInnerClass();
145 private native Bitmap nativeQueryBitmap(
146 int nativeChromeBrowserProvider,
147 String[] projection, String selection,
148 String[] selectionArgs, String sortOrder);
149 private native void nativeGotOrientation(
150 int nativeDataFetcherImplAndroid,
151 double alpha, double beta, double gamma);
153 jni_generator.JniParams.SetFullyQualifiedClass(
154 'org/chromium/example/jni_generator/SampleForTests')
155 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
156 natives = jni_generator.ExtractNatives(test_data, 'int')
157 golden_natives = [
158 NativeMethod(return_type='int', static=False,
159 name='Init',
160 params=[],
161 java_class_name=None,
162 type='function'),
163 NativeMethod(return_type='void', static=False, name='Destroy',
164 params=[Param(datatype='int',
165 name='nativeChromeBrowserProvider')],
166 java_class_name=None,
167 type='method',
168 p0_type='ChromeBrowserProvider'),
169 NativeMethod(return_type='long', static=False, name='AddBookmark',
170 params=[Param(datatype='int',
171 name='nativeChromeBrowserProvider'),
172 Param(datatype='String',
173 name='url'),
174 Param(datatype='String',
175 name='title'),
176 Param(datatype='boolean',
177 name='isFolder'),
178 Param(datatype='long',
179 name='parentId')],
180 java_class_name=None,
181 type='method',
182 p0_type='ChromeBrowserProvider'),
183 NativeMethod(return_type='String', static=True,
184 name='GetDomainAndRegistry',
185 params=[Param(datatype='String',
186 name='url')],
187 java_class_name=None,
188 type='function'),
189 NativeMethod(return_type='void', static=True,
190 name='CreateHistoricalTabFromState',
191 params=[Param(datatype='byte[]',
192 name='state'),
193 Param(datatype='int',
194 name='tab_index')],
195 java_class_name=None,
196 type='function'),
197 NativeMethod(return_type='byte[]', static=False,
198 name='GetStateAsByteArray',
199 params=[Param(datatype='View', name='view')],
200 java_class_name=None,
201 type='function'),
202 NativeMethod(return_type='String[]', static=True,
203 name='GetAutofillProfileGUIDs', params=[],
204 java_class_name=None,
205 type='function'),
206 NativeMethod(return_type='void', static=False,
207 name='SetRecognitionResults',
208 params=[Param(datatype='int', name='sessionId'),
209 Param(datatype='String[]', name='results')],
210 java_class_name=None,
211 type='function'),
212 NativeMethod(return_type='long', static=False,
213 name='AddBookmarkFromAPI',
214 params=[Param(datatype='int',
215 name='nativeChromeBrowserProvider'),
216 Param(datatype='String',
217 name='url'),
218 Param(datatype='Long',
219 name='created'),
220 Param(datatype='Boolean',
221 name='isBookmark'),
222 Param(datatype='Long',
223 name='date'),
224 Param(datatype='byte[]',
225 name='favicon'),
226 Param(datatype='String',
227 name='title'),
228 Param(datatype='Integer',
229 name='visits')],
230 java_class_name=None,
231 type='method',
232 p0_type='ChromeBrowserProvider'),
233 NativeMethod(return_type='int', static=False,
234 name='FindAll',
235 params=[Param(datatype='String',
236 name='find')],
237 java_class_name=None,
238 type='function'),
239 NativeMethod(return_type='OnFrameAvailableListener', static=True,
240 name='GetInnerClass',
241 params=[],
242 java_class_name=None,
243 type='function'),
244 NativeMethod(return_type='Bitmap',
245 static=False,
246 name='QueryBitmap',
247 params=[Param(datatype='int',
248 name='nativeChromeBrowserProvider'),
249 Param(datatype='String[]',
250 name='projection'),
251 Param(datatype='String',
252 name='selection'),
253 Param(datatype='String[]',
254 name='selectionArgs'),
255 Param(datatype='String',
256 name='sortOrder'),
258 java_class_name=None,
259 type='method',
260 p0_type='ChromeBrowserProvider'),
261 NativeMethod(return_type='void', static=False,
262 name='GotOrientation',
263 params=[Param(datatype='int',
264 name='nativeDataFetcherImplAndroid'),
265 Param(datatype='double',
266 name='alpha'),
267 Param(datatype='double',
268 name='beta'),
269 Param(datatype='double',
270 name='gamma'),
272 java_class_name=None,
273 type='method',
274 p0_type='content::DataFetcherImplAndroid'),
276 self.assertListEquals(golden_natives, natives)
277 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
278 natives, [], [], TestOptions())
279 self.assertGoldenTextEquals(h.GetContent())
281 def testInnerClassNatives(self):
282 test_data = """
283 class MyInnerClass {
284 @NativeCall("MyInnerClass")
285 private native int nativeInit();
288 natives = jni_generator.ExtractNatives(test_data, 'int')
289 golden_natives = [
290 NativeMethod(return_type='int', static=False,
291 name='Init', params=[],
292 java_class_name='MyInnerClass',
293 type='function')
295 self.assertListEquals(golden_natives, natives)
296 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
297 natives, [], [], TestOptions())
298 self.assertGoldenTextEquals(h.GetContent())
300 def testInnerClassNativesMultiple(self):
301 test_data = """
302 class MyInnerClass {
303 @NativeCall("MyInnerClass")
304 private native int nativeInit();
306 class MyOtherInnerClass {
307 @NativeCall("MyOtherInnerClass")
308 private native int nativeInit();
311 natives = jni_generator.ExtractNatives(test_data, 'int')
312 golden_natives = [
313 NativeMethod(return_type='int', static=False,
314 name='Init', params=[],
315 java_class_name='MyInnerClass',
316 type='function'),
317 NativeMethod(return_type='int', static=False,
318 name='Init', params=[],
319 java_class_name='MyOtherInnerClass',
320 type='function')
322 self.assertListEquals(golden_natives, natives)
323 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
324 natives, [], [], TestOptions())
325 self.assertGoldenTextEquals(h.GetContent())
327 def testInnerClassNativesBothInnerAndOuter(self):
328 test_data = """
329 class MyOuterClass {
330 private native int nativeInit();
331 class MyOtherInnerClass {
332 @NativeCall("MyOtherInnerClass")
333 private native int nativeInit();
337 natives = jni_generator.ExtractNatives(test_data, 'int')
338 golden_natives = [
339 NativeMethod(return_type='int', static=False,
340 name='Init', params=[],
341 java_class_name=None,
342 type='function'),
343 NativeMethod(return_type='int', static=False,
344 name='Init', params=[],
345 java_class_name='MyOtherInnerClass',
346 type='function')
348 self.assertListEquals(golden_natives, natives)
349 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
350 natives, [], [], TestOptions())
351 self.assertGoldenTextEquals(h.GetContent())
353 def testCalledByNatives(self):
354 test_data = """"
355 import android.graphics.Bitmap;
356 import android.view.View;
357 import java.io.InputStream;
358 import java.util.List;
360 class InnerClass {}
362 @CalledByNative
363 InnerClass showConfirmInfoBar(int nativeInfoBar,
364 String buttonOk, String buttonCancel, String title, Bitmap icon) {
365 InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext,
366 buttonOk, buttonCancel,
367 title, icon);
368 return infobar;
370 @CalledByNative
371 InnerClass showAutoLoginInfoBar(int nativeInfoBar,
372 String realm, String account, String args) {
373 AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext,
374 realm, account, args);
375 if (infobar.displayedAccountCount() == 0)
376 infobar = null;
377 return infobar;
379 @CalledByNative("InfoBar")
380 void dismiss();
381 @SuppressWarnings("unused")
382 @CalledByNative
383 private static boolean shouldShowAutoLogin(View view,
384 String realm, String account, String args) {
385 AccountManagerContainer accountManagerContainer =
386 new AccountManagerContainer((Activity)contentView.getContext(),
387 realm, account, args);
388 String[] logins = accountManagerContainer.getAccountLogins(null);
389 return logins.length != 0;
391 @CalledByNative
392 static InputStream openUrl(String url) {
393 return null;
395 @CalledByNative
396 private void activateHardwareAcceleration(final boolean activated,
397 final int iPid, final int iType,
398 final int iPrimaryID, final int iSecondaryID) {
399 if (!activated) {
400 return
403 @CalledByNativeUnchecked
404 private void uncheckedCall(int iParam);
406 @CalledByNative
407 public byte[] returnByteArray();
409 @CalledByNative
410 public boolean[] returnBooleanArray();
412 @CalledByNative
413 public char[] returnCharArray();
415 @CalledByNative
416 public short[] returnShortArray();
418 @CalledByNative
419 public int[] returnIntArray();
421 @CalledByNative
422 public long[] returnLongArray();
424 @CalledByNative
425 public double[] returnDoubleArray();
427 @CalledByNative
428 public Object[] returnObjectArray();
430 @CalledByNative
431 public byte[][] returnArrayOfByteArray();
433 @CalledByNative
434 public Bitmap.CompressFormat getCompressFormat();
436 @CalledByNative
437 public List<Bitmap.CompressFormat> getCompressFormatList();
439 jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo')
440 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
441 called_by_natives = jni_generator.ExtractCalledByNatives(test_data)
442 golden_called_by_natives = [
443 CalledByNative(
444 return_type='InnerClass',
445 system_class=False,
446 static=False,
447 name='showConfirmInfoBar',
448 method_id_var_name='showConfirmInfoBar',
449 java_class_name='',
450 params=[Param(datatype='int', name='nativeInfoBar'),
451 Param(datatype='String', name='buttonOk'),
452 Param(datatype='String', name='buttonCancel'),
453 Param(datatype='String', name='title'),
454 Param(datatype='Bitmap', name='icon')],
455 env_call=('Object', ''),
456 unchecked=False,
458 CalledByNative(
459 return_type='InnerClass',
460 system_class=False,
461 static=False,
462 name='showAutoLoginInfoBar',
463 method_id_var_name='showAutoLoginInfoBar',
464 java_class_name='',
465 params=[Param(datatype='int', name='nativeInfoBar'),
466 Param(datatype='String', name='realm'),
467 Param(datatype='String', name='account'),
468 Param(datatype='String', name='args')],
469 env_call=('Object', ''),
470 unchecked=False,
472 CalledByNative(
473 return_type='void',
474 system_class=False,
475 static=False,
476 name='dismiss',
477 method_id_var_name='dismiss',
478 java_class_name='InfoBar',
479 params=[],
480 env_call=('Void', ''),
481 unchecked=False,
483 CalledByNative(
484 return_type='boolean',
485 system_class=False,
486 static=True,
487 name='shouldShowAutoLogin',
488 method_id_var_name='shouldShowAutoLogin',
489 java_class_name='',
490 params=[Param(datatype='View', name='view'),
491 Param(datatype='String', name='realm'),
492 Param(datatype='String', name='account'),
493 Param(datatype='String', name='args')],
494 env_call=('Boolean', ''),
495 unchecked=False,
497 CalledByNative(
498 return_type='InputStream',
499 system_class=False,
500 static=True,
501 name='openUrl',
502 method_id_var_name='openUrl',
503 java_class_name='',
504 params=[Param(datatype='String', name='url')],
505 env_call=('Object', ''),
506 unchecked=False,
508 CalledByNative(
509 return_type='void',
510 system_class=False,
511 static=False,
512 name='activateHardwareAcceleration',
513 method_id_var_name='activateHardwareAcceleration',
514 java_class_name='',
515 params=[Param(datatype='boolean', name='activated'),
516 Param(datatype='int', name='iPid'),
517 Param(datatype='int', name='iType'),
518 Param(datatype='int', name='iPrimaryID'),
519 Param(datatype='int', name='iSecondaryID'),
521 env_call=('Void', ''),
522 unchecked=False,
524 CalledByNative(
525 return_type='void',
526 system_class=False,
527 static=False,
528 name='uncheckedCall',
529 method_id_var_name='uncheckedCall',
530 java_class_name='',
531 params=[Param(datatype='int', name='iParam')],
532 env_call=('Void', ''),
533 unchecked=True,
535 CalledByNative(
536 return_type='byte[]',
537 system_class=False,
538 static=False,
539 name='returnByteArray',
540 method_id_var_name='returnByteArray',
541 java_class_name='',
542 params=[],
543 env_call=('Void', ''),
544 unchecked=False,
546 CalledByNative(
547 return_type='boolean[]',
548 system_class=False,
549 static=False,
550 name='returnBooleanArray',
551 method_id_var_name='returnBooleanArray',
552 java_class_name='',
553 params=[],
554 env_call=('Void', ''),
555 unchecked=False,
557 CalledByNative(
558 return_type='char[]',
559 system_class=False,
560 static=False,
561 name='returnCharArray',
562 method_id_var_name='returnCharArray',
563 java_class_name='',
564 params=[],
565 env_call=('Void', ''),
566 unchecked=False,
568 CalledByNative(
569 return_type='short[]',
570 system_class=False,
571 static=False,
572 name='returnShortArray',
573 method_id_var_name='returnShortArray',
574 java_class_name='',
575 params=[],
576 env_call=('Void', ''),
577 unchecked=False,
579 CalledByNative(
580 return_type='int[]',
581 system_class=False,
582 static=False,
583 name='returnIntArray',
584 method_id_var_name='returnIntArray',
585 java_class_name='',
586 params=[],
587 env_call=('Void', ''),
588 unchecked=False,
590 CalledByNative(
591 return_type='long[]',
592 system_class=False,
593 static=False,
594 name='returnLongArray',
595 method_id_var_name='returnLongArray',
596 java_class_name='',
597 params=[],
598 env_call=('Void', ''),
599 unchecked=False,
601 CalledByNative(
602 return_type='double[]',
603 system_class=False,
604 static=False,
605 name='returnDoubleArray',
606 method_id_var_name='returnDoubleArray',
607 java_class_name='',
608 params=[],
609 env_call=('Void', ''),
610 unchecked=False,
612 CalledByNative(
613 return_type='Object[]',
614 system_class=False,
615 static=False,
616 name='returnObjectArray',
617 method_id_var_name='returnObjectArray',
618 java_class_name='',
619 params=[],
620 env_call=('Void', ''),
621 unchecked=False,
623 CalledByNative(
624 return_type='byte[][]',
625 system_class=False,
626 static=False,
627 name='returnArrayOfByteArray',
628 method_id_var_name='returnArrayOfByteArray',
629 java_class_name='',
630 params=[],
631 env_call=('Void', ''),
632 unchecked=False,
634 CalledByNative(
635 return_type='Bitmap.CompressFormat',
636 system_class=False,
637 static=False,
638 name='getCompressFormat',
639 method_id_var_name='getCompressFormat',
640 java_class_name='',
641 params=[],
642 env_call=('Void', ''),
643 unchecked=False,
645 CalledByNative(
646 return_type='List<Bitmap.CompressFormat>',
647 system_class=False,
648 static=False,
649 name='getCompressFormatList',
650 method_id_var_name='getCompressFormatList',
651 java_class_name='',
652 params=[],
653 env_call=('Void', ''),
654 unchecked=False,
657 self.assertListEquals(golden_called_by_natives, called_by_natives)
658 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
659 [], called_by_natives, [],
660 TestOptions())
661 self.assertGoldenTextEquals(h.GetContent())
663 def testCalledByNativeParseError(self):
664 try:
665 jni_generator.ExtractCalledByNatives("""
666 @CalledByNative
667 public static int foo(); // This one is fine
669 @CalledByNative
670 scooby doo
671 """)
672 self.fail('Expected a ParseError')
673 except jni_generator.ParseError, e:
674 self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines)
676 def testFullyQualifiedClassName(self):
677 contents = """
678 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
679 // Use of this source code is governed by a BSD-style license that can be
680 // found in the LICENSE file.
682 package org.chromium.content.browser;
684 import org.chromium.base.BuildInfo;
686 self.assertEquals('org/chromium/content/browser/Foo',
687 jni_generator.ExtractFullyQualifiedJavaClassName(
688 'org/chromium/content/browser/Foo.java', contents))
689 self.assertEquals('org/chromium/content/browser/Foo',
690 jni_generator.ExtractFullyQualifiedJavaClassName(
691 'frameworks/Foo.java', contents))
692 self.assertRaises(SyntaxError,
693 jni_generator.ExtractFullyQualifiedJavaClassName,
694 'com/foo/Bar', 'no PACKAGE line')
696 def testMethodNameMangling(self):
697 self.assertEquals('closeV',
698 jni_generator.GetMangledMethodName('close', [], 'void'))
699 self.assertEquals('readI_AB_I_I',
700 jni_generator.GetMangledMethodName('read',
701 [Param(name='p1',
702 datatype='byte[]'),
703 Param(name='p2',
704 datatype='int'),
705 Param(name='p3',
706 datatype='int'),],
707 'int'))
708 self.assertEquals('openJIIS_JLS',
709 jni_generator.GetMangledMethodName('open',
710 [Param(name='p1',
711 datatype='java/lang/String'),],
712 'java/io/InputStream'))
714 def testFromJavaPGenerics(self):
715 contents = """
716 public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
717 implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable {
718 public void dummy();
719 Signature: ()V
722 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
723 TestOptions())
724 self.assertEquals(1, len(jni_from_javap.called_by_natives))
725 self.assertGoldenTextEquals(jni_from_javap.GetContent())
727 def testSnippnetJavap6_7_8(self):
728 content_javap6 = """
729 public class java.util.HashSet {
730 public boolean add(java.lang.Object);
731 Signature: (Ljava/lang/Object;)Z
735 content_javap7 = """
736 public class java.util.HashSet {
737 public boolean add(E);
738 Signature: (Ljava/lang/Object;)Z
742 content_javap8 = """
743 public class java.util.HashSet {
744 public boolean add(E);
745 descriptor: (Ljava/lang/Object;)Z
749 jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
750 TestOptions())
751 jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
752 TestOptions())
753 jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
754 TestOptions())
755 self.assertTrue(jni_from_javap6.GetContent())
756 self.assertTrue(jni_from_javap7.GetContent())
757 self.assertTrue(jni_from_javap8.GetContent())
758 # Ensure the javap7 is correctly parsed and uses the Signature field rather
759 # than the "E" parameter.
760 self.assertTextEquals(jni_from_javap6.GetContent(),
761 jni_from_javap7.GetContent())
762 # Ensure the javap8 is correctly parsed and uses the descriptor field.
763 self.assertTextEquals(jni_from_javap7.GetContent(),
764 jni_from_javap8.GetContent())
766 def testFromJavaP(self):
767 contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
768 'testInputStream.javap'))
769 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
770 TestOptions())
771 self.assertEquals(10, len(jni_from_javap.called_by_natives))
772 self.assertGoldenTextEquals(jni_from_javap.GetContent())
774 def testConstantsFromJavaP(self):
775 for f in ['testMotionEvent.javap', 'testMotionEvent.javap7']:
776 contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
778 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
779 TestOptions())
780 self.assertEquals(86, len(jni_from_javap.called_by_natives))
781 self.assertGoldenTextEquals(jni_from_javap.GetContent())
783 def testREForNatives(self):
784 # We should not match "native SyncSetupFlow" inside the comment.
785 test_data = """
787 * Invoked when the setup process is complete so we can disconnect from the
788 * native-side SyncSetupFlowHandler.
790 public void destroy() {
791 Log.v(TAG, "Destroying native SyncSetupFlow");
792 if (mNativeSyncSetupFlow != 0) {
793 nativeSyncSetupEnded(mNativeSyncSetupFlow);
794 mNativeSyncSetupFlow = 0;
797 private native void nativeSyncSetupEnded(
798 int nativeAndroidSyncSetupFlowHandler);
800 jni_from_java = jni_generator.JNIFromJavaSource(
801 test_data, 'foo/bar', TestOptions())
803 def testRaisesOnNonJNIMethod(self):
804 test_data = """
805 class MyInnerClass {
806 private int Foo(int p0) {
810 self.assertRaises(SyntaxError,
811 jni_generator.JNIFromJavaSource,
812 test_data, 'foo/bar', TestOptions())
814 def testJniSelfDocumentingExample(self):
815 script_dir = os.path.dirname(sys.argv[0])
816 content = file(os.path.join(script_dir,
817 'java/src/org/chromium/example/jni_generator/SampleForTests.java')
818 ).read()
819 golden_file = os.path.join(script_dir, 'golden_sample_for_tests_jni.h')
820 golden_content = file(golden_file).read()
821 jni_from_java = jni_generator.JNIFromJavaSource(
822 content, 'org/chromium/example/jni_generator/SampleForTests',
823 TestOptions())
824 generated_text = jni_from_java.GetContent()
825 if not self.compareText(golden_content, generated_text):
826 if os.environ.get(REBASELINE_ENV):
827 with file(golden_file, 'w') as f:
828 f.write(generated_text)
829 return
830 self.fail('testJniSelfDocumentingExample')
832 def testNoWrappingPreprocessorLines(self):
833 test_data = """
834 package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday;
836 class ReallyLongClassNamesAreAllTheRage {
837 private static native int nativeTest();
840 jni_from_java = jni_generator.JNIFromJavaSource(
841 test_data, ('com/google/lookhowextremelylongiam/snarf/'
842 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
843 TestOptions())
844 jni_lines = jni_from_java.GetContent().split('\n')
845 line = filter(lambda line: line.lstrip().startswith('#ifndef'),
846 jni_lines)[0]
847 self.assertTrue(len(line) > 80,
848 ('Expected #ifndef line to be > 80 chars: ', line))
850 def testJarJarRemapping(self):
851 test_data = """
852 package org.chromium.example.jni_generator;
854 import org.chromium.example2.Test;
856 import org.chromium.example3.PrefixFoo;
857 import org.chromium.example3.Prefix;
858 import org.chromium.example3.Bar$Inner;
860 class Example {
861 private static native void nativeTest(Test t);
862 private static native void nativeTest2(PrefixFoo t);
863 private static native void nativeTest3(Prefix t);
864 private static native void nativeTest4(Bar$Inner t);
867 jni_generator.JniParams.SetJarJarMappings(
868 """rule org.chromium.example.** com.test.@1
869 rule org.chromium.example2.** org.test2.@1
870 rule org.chromium.example3.Prefix org.test3.Test
871 rule org.chromium.example3.Bar$** org.test3.TestBar$@1""")
872 jni_from_java = jni_generator.JNIFromJavaSource(
873 test_data, 'org/chromium/example/jni_generator/Example', TestOptions())
874 jni_generator.JniParams.SetJarJarMappings('')
875 self.assertGoldenTextEquals(jni_from_java.GetContent())
877 def testImports(self):
878 import_header = """
879 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
880 // Use of this source code is governed by a BSD-style license that can be
881 // found in the LICENSE file.
883 package org.chromium.content.app;
885 import android.app.Service;
886 import android.content.Context;
887 import android.content.Intent;
888 import android.graphics.SurfaceTexture;
889 import android.os.Bundle;
890 import android.os.IBinder;
891 import android.os.ParcelFileDescriptor;
892 import android.os.Process;
893 import android.os.RemoteException;
894 import android.util.Log;
895 import android.view.Surface;
897 import java.util.ArrayList;
899 import org.chromium.base.CalledByNative;
900 import org.chromium.base.JNINamespace;
901 import org.chromium.content.app.ContentMain;
902 import org.chromium.content.browser.SandboxedProcessConnection;
903 import org.chromium.content.common.ISandboxedProcessCallback;
904 import org.chromium.content.common.ISandboxedProcessService;
905 import org.chromium.content.common.WillNotRaise.AnException;
906 import org.chromium.content.common.WillRaise.AnException;
908 import static org.chromium.Bar.Zoo;
910 class Foo {
911 public static class BookmarkNode implements Parcelable {
913 public interface PasswordListObserver {
917 jni_generator.JniParams.SetFullyQualifiedClass(
918 'org/chromium/content/app/Foo')
919 jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header)
920 self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in
921 jni_generator.JniParams._imports)
922 self.assertTrue('Lorg/chromium/Bar/Zoo' in
923 jni_generator.JniParams._imports)
924 self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in
925 jni_generator.JniParams._inner_classes)
926 self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in
927 jni_generator.JniParams._inner_classes)
928 self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner;',
929 jni_generator.JniParams.JavaToJni('ContentMain.Inner'))
930 self.assertRaises(SyntaxError,
931 jni_generator.JniParams.JavaToJni,
932 'AnException')
934 def testJniParamsJavaToJni(self):
935 self.assertTextEquals('I', JniParams.JavaToJni('int'))
936 self.assertTextEquals('[B', JniParams.JavaToJni('byte[]'))
937 self.assertTextEquals(
938 '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]'))
940 def testNativesLong(self):
941 test_options = TestOptions()
942 test_options.ptr_type = 'long'
943 test_data = """"
944 private native void nativeDestroy(long nativeChromeBrowserProvider);
946 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
947 natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type)
948 golden_natives = [
949 NativeMethod(return_type='void', static=False, name='Destroy',
950 params=[Param(datatype='long',
951 name='nativeChromeBrowserProvider')],
952 java_class_name=None,
953 type='method',
954 p0_type='ChromeBrowserProvider',
955 ptr_type=test_options.ptr_type),
957 self.assertListEquals(golden_natives, natives)
958 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
959 natives, [], [], test_options)
960 self.assertGoldenTextEquals(h.GetContent())
962 def testPureNativeMethodsOption(self):
963 test_data = """
964 package org.chromium.example.jni_generator;
966 /** The pointer to the native Test. */
967 long nativeTest;
969 class Test {
970 private static native long nativeMethod(long nativeTest, int arg1);
973 options = TestOptions()
974 options.pure_native_methods = True
975 jni_from_java = jni_generator.JNIFromJavaSource(
976 test_data, 'org/chromium/example/jni_generator/Test', options)
977 self.assertGoldenTextEquals(jni_from_java.GetContent())
979 def testJNIInitNativeNameOption(self):
980 test_data = """
981 package org.chromium.example.jni_generator;
983 /** The pointer to the native Test. */
984 long nativeTest;
986 class Test {
987 private static native boolean nativeInitNativeClass();
988 private static native int nativeMethod(long nativeTest, int arg1);
991 options = TestOptions()
992 options.jni_init_native_name = 'nativeInitNativeClass'
993 jni_from_java = jni_generator.JNIFromJavaSource(
994 test_data, 'org/chromium/example/jni_generator/Test', options)
995 self.assertGoldenTextEquals(jni_from_java.GetContent())
997 def testEagerCalledByNativesOption(self):
998 test_data = """
999 package org.chromium.example.jni_generator;
1001 /** The pointer to the native Test. */
1002 long nativeTest;
1004 class Test {
1005 private static native boolean nativeInitNativeClass();
1006 private static native int nativeMethod(long nativeTest, int arg1);
1007 @CalledByNative
1008 private void testMethodWithParam(int iParam);
1009 @CalledByNative
1010 private static int testStaticMethodWithParam(int iParam);
1011 @CalledByNative
1012 private static double testMethodWithNoParam();
1013 @CalledByNative
1014 private static String testStaticMethodWithNoParam();
1017 options = TestOptions()
1018 options.jni_init_native_name = 'nativeInitNativeClass'
1019 options.eager_called_by_natives = True
1020 jni_from_java = jni_generator.JNIFromJavaSource(
1021 test_data, 'org/chromium/example/jni_generator/Test', options)
1022 self.assertGoldenTextEquals(jni_from_java.GetContent())
1024 def runNativeExportsOption(self, optional):
1025 test_data = """
1026 package org.chromium.example.jni_generator;
1028 /** The pointer to the native Test. */
1029 long nativeTest;
1031 class Test {
1032 private static native boolean nativeInitNativeClass();
1033 private static native int nativeStaticMethod(long nativeTest, int arg1);
1034 private native int nativeMethod(long nativeTest, int arg1);
1035 @CalledByNative
1036 private void testMethodWithParam(int iParam);
1037 @CalledByNative
1038 private String testMethodWithParamAndReturn(int iParam);
1039 @CalledByNative
1040 private static int testStaticMethodWithParam(int iParam);
1041 @CalledByNative
1042 private static double testMethodWithNoParam();
1043 @CalledByNative
1044 private static String testStaticMethodWithNoParam();
1046 class MyInnerClass {
1047 @NativeCall("MyInnerClass")
1048 private native int nativeInit();
1050 class MyOtherInnerClass {
1051 @NativeCall("MyOtherInnerClass")
1052 private native int nativeInit();
1056 options = TestOptions()
1057 options.jni_init_native_name = 'nativeInitNativeClass'
1058 options.native_exports = True
1059 options.native_exports_optional = optional
1060 jni_from_java = jni_generator.JNIFromJavaSource(
1061 test_data, 'org/chromium/example/jni_generator/SampleForTests', options)
1062 return jni_from_java.GetContent()
1064 def testNativeExportsOption(self):
1065 content = self.runNativeExportsOption(False)
1066 self.assertGoldenTextEquals(content)
1068 def testNativeExportsOptionalOption(self):
1069 content = self.runNativeExportsOption(True)
1070 self.assertGoldenTextEquals(content)
1072 def testOuterInnerRaises(self):
1073 test_data = """
1074 package org.chromium.media;
1076 @CalledByNative
1077 static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
1078 return format.getWidth();
1081 def willRaise():
1082 jni_generator.JNIFromJavaSource(
1083 test_data,
1084 'org/chromium/media/VideoCaptureFactory',
1085 TestOptions())
1086 self.assertRaises(SyntaxError, willRaise)
1088 def testSingleJNIAdditionalImport(self):
1089 test_data = """
1090 package org.chromium.foo;
1092 @JNIAdditionalImport(Bar.class)
1093 class Foo {
1095 @CalledByNative
1096 private static void calledByNative(Bar.Callback callback) {
1099 private static native void nativeDoSomething(Bar.Callback callback);
1102 jni_from_java = jni_generator.JNIFromJavaSource(test_data,
1103 'org/chromium/foo/Foo',
1104 TestOptions())
1105 self.assertGoldenTextEquals(jni_from_java.GetContent())
1107 def testMultipleJNIAdditionalImport(self):
1108 test_data = """
1109 package org.chromium.foo;
1111 @JNIAdditionalImport({Bar1.class, Bar2.class})
1112 class Foo {
1114 @CalledByNative
1115 private static void calledByNative(Bar1.Callback callback1,
1116 Bar2.Callback callback2) {
1119 private static native void nativeDoSomething(Bar1.Callback callback1,
1120 Bar2.Callback callback2);
1123 jni_from_java = jni_generator.JNIFromJavaSource(test_data,
1124 'org/chromium/foo/Foo',
1125 TestOptions())
1126 self.assertGoldenTextEquals(jni_from_java.GetContent())
1129 def TouchStamp(stamp_path):
1130 dir_name = os.path.dirname(stamp_path)
1131 if not os.path.isdir(dir_name):
1132 os.makedirs()
1134 with open(stamp_path, 'a'):
1135 os.utime(stamp_path, None)
1138 def main(argv):
1139 parser = optparse.OptionParser()
1140 parser.add_option('--stamp', help='Path to touch on success.')
1141 options, _ = parser.parse_args(argv[1:])
1143 test_result = unittest.main(argv=argv[0:1], exit=False)
1145 if test_result.result.wasSuccessful() and options.stamp:
1146 TouchStamp(options.stamp)
1148 return not test_result.result.wasSuccessful()
1151 if __name__ == '__main__':
1152 sys.exit(main(sys.argv))