Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / base / android / jni_generator / jni_generator_tests.py
blob22e54cf78e86ade8fd60dba871be8bb52cd467f9
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);
152 private static native Throwable nativeMessWithJavaException(Throwable e);
154 jni_generator.JniParams.SetFullyQualifiedClass(
155 'org/chromium/example/jni_generator/SampleForTests')
156 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
157 natives = jni_generator.ExtractNatives(test_data, 'int')
158 golden_natives = [
159 NativeMethod(return_type='int', static=False,
160 name='Init',
161 params=[],
162 java_class_name=None,
163 type='function'),
164 NativeMethod(return_type='void', static=False, name='Destroy',
165 params=[Param(datatype='int',
166 name='nativeChromeBrowserProvider')],
167 java_class_name=None,
168 type='method',
169 p0_type='ChromeBrowserProvider'),
170 NativeMethod(return_type='long', static=False, name='AddBookmark',
171 params=[Param(datatype='int',
172 name='nativeChromeBrowserProvider'),
173 Param(datatype='String',
174 name='url'),
175 Param(datatype='String',
176 name='title'),
177 Param(datatype='boolean',
178 name='isFolder'),
179 Param(datatype='long',
180 name='parentId')],
181 java_class_name=None,
182 type='method',
183 p0_type='ChromeBrowserProvider'),
184 NativeMethod(return_type='String', static=True,
185 name='GetDomainAndRegistry',
186 params=[Param(datatype='String',
187 name='url')],
188 java_class_name=None,
189 type='function'),
190 NativeMethod(return_type='void', static=True,
191 name='CreateHistoricalTabFromState',
192 params=[Param(datatype='byte[]',
193 name='state'),
194 Param(datatype='int',
195 name='tab_index')],
196 java_class_name=None,
197 type='function'),
198 NativeMethod(return_type='byte[]', static=False,
199 name='GetStateAsByteArray',
200 params=[Param(datatype='View', name='view')],
201 java_class_name=None,
202 type='function'),
203 NativeMethod(return_type='String[]', static=True,
204 name='GetAutofillProfileGUIDs', params=[],
205 java_class_name=None,
206 type='function'),
207 NativeMethod(return_type='void', static=False,
208 name='SetRecognitionResults',
209 params=[Param(datatype='int', name='sessionId'),
210 Param(datatype='String[]', name='results')],
211 java_class_name=None,
212 type='function'),
213 NativeMethod(return_type='long', static=False,
214 name='AddBookmarkFromAPI',
215 params=[Param(datatype='int',
216 name='nativeChromeBrowserProvider'),
217 Param(datatype='String',
218 name='url'),
219 Param(datatype='Long',
220 name='created'),
221 Param(datatype='Boolean',
222 name='isBookmark'),
223 Param(datatype='Long',
224 name='date'),
225 Param(datatype='byte[]',
226 name='favicon'),
227 Param(datatype='String',
228 name='title'),
229 Param(datatype='Integer',
230 name='visits')],
231 java_class_name=None,
232 type='method',
233 p0_type='ChromeBrowserProvider'),
234 NativeMethod(return_type='int', static=False,
235 name='FindAll',
236 params=[Param(datatype='String',
237 name='find')],
238 java_class_name=None,
239 type='function'),
240 NativeMethod(return_type='OnFrameAvailableListener', static=True,
241 name='GetInnerClass',
242 params=[],
243 java_class_name=None,
244 type='function'),
245 NativeMethod(return_type='Bitmap',
246 static=False,
247 name='QueryBitmap',
248 params=[Param(datatype='int',
249 name='nativeChromeBrowserProvider'),
250 Param(datatype='String[]',
251 name='projection'),
252 Param(datatype='String',
253 name='selection'),
254 Param(datatype='String[]',
255 name='selectionArgs'),
256 Param(datatype='String',
257 name='sortOrder'),
259 java_class_name=None,
260 type='method',
261 p0_type='ChromeBrowserProvider'),
262 NativeMethod(return_type='void', static=False,
263 name='GotOrientation',
264 params=[Param(datatype='int',
265 name='nativeDataFetcherImplAndroid'),
266 Param(datatype='double',
267 name='alpha'),
268 Param(datatype='double',
269 name='beta'),
270 Param(datatype='double',
271 name='gamma'),
273 java_class_name=None,
274 type='method',
275 p0_type='content::DataFetcherImplAndroid'),
276 NativeMethod(return_type='Throwable', static=True,
277 name='MessWithJavaException',
278 params=[Param(datatype='Throwable', name='e')],
279 java_class_name=None,
280 type='function')
282 self.assertListEquals(golden_natives, natives)
283 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
284 natives, [], [], TestOptions())
285 self.assertGoldenTextEquals(h.GetContent())
287 def testInnerClassNatives(self):
288 test_data = """
289 class MyInnerClass {
290 @NativeCall("MyInnerClass")
291 private native int nativeInit();
294 natives = jni_generator.ExtractNatives(test_data, 'int')
295 golden_natives = [
296 NativeMethod(return_type='int', static=False,
297 name='Init', params=[],
298 java_class_name='MyInnerClass',
299 type='function')
301 self.assertListEquals(golden_natives, natives)
302 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
303 natives, [], [], TestOptions())
304 self.assertGoldenTextEquals(h.GetContent())
306 def testInnerClassNativesMultiple(self):
307 test_data = """
308 class MyInnerClass {
309 @NativeCall("MyInnerClass")
310 private native int nativeInit();
312 class MyOtherInnerClass {
313 @NativeCall("MyOtherInnerClass")
314 private native int nativeInit();
317 natives = jni_generator.ExtractNatives(test_data, 'int')
318 golden_natives = [
319 NativeMethod(return_type='int', static=False,
320 name='Init', params=[],
321 java_class_name='MyInnerClass',
322 type='function'),
323 NativeMethod(return_type='int', static=False,
324 name='Init', params=[],
325 java_class_name='MyOtherInnerClass',
326 type='function')
328 self.assertListEquals(golden_natives, natives)
329 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
330 natives, [], [], TestOptions())
331 self.assertGoldenTextEquals(h.GetContent())
333 def testInnerClassNativesBothInnerAndOuter(self):
334 test_data = """
335 class MyOuterClass {
336 private native int nativeInit();
337 class MyOtherInnerClass {
338 @NativeCall("MyOtherInnerClass")
339 private native int nativeInit();
343 natives = jni_generator.ExtractNatives(test_data, 'int')
344 golden_natives = [
345 NativeMethod(return_type='int', static=False,
346 name='Init', params=[],
347 java_class_name=None,
348 type='function'),
349 NativeMethod(return_type='int', static=False,
350 name='Init', params=[],
351 java_class_name='MyOtherInnerClass',
352 type='function')
354 self.assertListEquals(golden_natives, natives)
355 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
356 natives, [], [], TestOptions())
357 self.assertGoldenTextEquals(h.GetContent())
359 def testCalledByNatives(self):
360 test_data = """"
361 import android.graphics.Bitmap;
362 import android.view.View;
363 import java.io.InputStream;
364 import java.util.List;
366 class InnerClass {}
368 @CalledByNative
369 InnerClass showConfirmInfoBar(int nativeInfoBar,
370 String buttonOk, String buttonCancel, String title, Bitmap icon) {
371 InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext,
372 buttonOk, buttonCancel,
373 title, icon);
374 return infobar;
376 @CalledByNative
377 InnerClass showAutoLoginInfoBar(int nativeInfoBar,
378 String realm, String account, String args) {
379 AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext,
380 realm, account, args);
381 if (infobar.displayedAccountCount() == 0)
382 infobar = null;
383 return infobar;
385 @CalledByNative("InfoBar")
386 void dismiss();
387 @SuppressWarnings("unused")
388 @CalledByNative
389 private static boolean shouldShowAutoLogin(View view,
390 String realm, String account, String args) {
391 AccountManagerContainer accountManagerContainer =
392 new AccountManagerContainer((Activity)contentView.getContext(),
393 realm, account, args);
394 String[] logins = accountManagerContainer.getAccountLogins(null);
395 return logins.length != 0;
397 @CalledByNative
398 static InputStream openUrl(String url) {
399 return null;
401 @CalledByNative
402 private void activateHardwareAcceleration(final boolean activated,
403 final int iPid, final int iType,
404 final int iPrimaryID, final int iSecondaryID) {
405 if (!activated) {
406 return
409 @CalledByNativeUnchecked
410 private void uncheckedCall(int iParam);
412 @CalledByNative
413 public byte[] returnByteArray();
415 @CalledByNative
416 public boolean[] returnBooleanArray();
418 @CalledByNative
419 public char[] returnCharArray();
421 @CalledByNative
422 public short[] returnShortArray();
424 @CalledByNative
425 public int[] returnIntArray();
427 @CalledByNative
428 public long[] returnLongArray();
430 @CalledByNative
431 public double[] returnDoubleArray();
433 @CalledByNative
434 public Object[] returnObjectArray();
436 @CalledByNative
437 public byte[][] returnArrayOfByteArray();
439 @CalledByNative
440 public Bitmap.CompressFormat getCompressFormat();
442 @CalledByNative
443 public List<Bitmap.CompressFormat> getCompressFormatList();
445 jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo')
446 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
447 called_by_natives = jni_generator.ExtractCalledByNatives(test_data)
448 golden_called_by_natives = [
449 CalledByNative(
450 return_type='InnerClass',
451 system_class=False,
452 static=False,
453 name='showConfirmInfoBar',
454 method_id_var_name='showConfirmInfoBar',
455 java_class_name='',
456 params=[Param(datatype='int', name='nativeInfoBar'),
457 Param(datatype='String', name='buttonOk'),
458 Param(datatype='String', name='buttonCancel'),
459 Param(datatype='String', name='title'),
460 Param(datatype='Bitmap', name='icon')],
461 env_call=('Object', ''),
462 unchecked=False,
464 CalledByNative(
465 return_type='InnerClass',
466 system_class=False,
467 static=False,
468 name='showAutoLoginInfoBar',
469 method_id_var_name='showAutoLoginInfoBar',
470 java_class_name='',
471 params=[Param(datatype='int', name='nativeInfoBar'),
472 Param(datatype='String', name='realm'),
473 Param(datatype='String', name='account'),
474 Param(datatype='String', name='args')],
475 env_call=('Object', ''),
476 unchecked=False,
478 CalledByNative(
479 return_type='void',
480 system_class=False,
481 static=False,
482 name='dismiss',
483 method_id_var_name='dismiss',
484 java_class_name='InfoBar',
485 params=[],
486 env_call=('Void', ''),
487 unchecked=False,
489 CalledByNative(
490 return_type='boolean',
491 system_class=False,
492 static=True,
493 name='shouldShowAutoLogin',
494 method_id_var_name='shouldShowAutoLogin',
495 java_class_name='',
496 params=[Param(datatype='View', name='view'),
497 Param(datatype='String', name='realm'),
498 Param(datatype='String', name='account'),
499 Param(datatype='String', name='args')],
500 env_call=('Boolean', ''),
501 unchecked=False,
503 CalledByNative(
504 return_type='InputStream',
505 system_class=False,
506 static=True,
507 name='openUrl',
508 method_id_var_name='openUrl',
509 java_class_name='',
510 params=[Param(datatype='String', name='url')],
511 env_call=('Object', ''),
512 unchecked=False,
514 CalledByNative(
515 return_type='void',
516 system_class=False,
517 static=False,
518 name='activateHardwareAcceleration',
519 method_id_var_name='activateHardwareAcceleration',
520 java_class_name='',
521 params=[Param(datatype='boolean', name='activated'),
522 Param(datatype='int', name='iPid'),
523 Param(datatype='int', name='iType'),
524 Param(datatype='int', name='iPrimaryID'),
525 Param(datatype='int', name='iSecondaryID'),
527 env_call=('Void', ''),
528 unchecked=False,
530 CalledByNative(
531 return_type='void',
532 system_class=False,
533 static=False,
534 name='uncheckedCall',
535 method_id_var_name='uncheckedCall',
536 java_class_name='',
537 params=[Param(datatype='int', name='iParam')],
538 env_call=('Void', ''),
539 unchecked=True,
541 CalledByNative(
542 return_type='byte[]',
543 system_class=False,
544 static=False,
545 name='returnByteArray',
546 method_id_var_name='returnByteArray',
547 java_class_name='',
548 params=[],
549 env_call=('Void', ''),
550 unchecked=False,
552 CalledByNative(
553 return_type='boolean[]',
554 system_class=False,
555 static=False,
556 name='returnBooleanArray',
557 method_id_var_name='returnBooleanArray',
558 java_class_name='',
559 params=[],
560 env_call=('Void', ''),
561 unchecked=False,
563 CalledByNative(
564 return_type='char[]',
565 system_class=False,
566 static=False,
567 name='returnCharArray',
568 method_id_var_name='returnCharArray',
569 java_class_name='',
570 params=[],
571 env_call=('Void', ''),
572 unchecked=False,
574 CalledByNative(
575 return_type='short[]',
576 system_class=False,
577 static=False,
578 name='returnShortArray',
579 method_id_var_name='returnShortArray',
580 java_class_name='',
581 params=[],
582 env_call=('Void', ''),
583 unchecked=False,
585 CalledByNative(
586 return_type='int[]',
587 system_class=False,
588 static=False,
589 name='returnIntArray',
590 method_id_var_name='returnIntArray',
591 java_class_name='',
592 params=[],
593 env_call=('Void', ''),
594 unchecked=False,
596 CalledByNative(
597 return_type='long[]',
598 system_class=False,
599 static=False,
600 name='returnLongArray',
601 method_id_var_name='returnLongArray',
602 java_class_name='',
603 params=[],
604 env_call=('Void', ''),
605 unchecked=False,
607 CalledByNative(
608 return_type='double[]',
609 system_class=False,
610 static=False,
611 name='returnDoubleArray',
612 method_id_var_name='returnDoubleArray',
613 java_class_name='',
614 params=[],
615 env_call=('Void', ''),
616 unchecked=False,
618 CalledByNative(
619 return_type='Object[]',
620 system_class=False,
621 static=False,
622 name='returnObjectArray',
623 method_id_var_name='returnObjectArray',
624 java_class_name='',
625 params=[],
626 env_call=('Void', ''),
627 unchecked=False,
629 CalledByNative(
630 return_type='byte[][]',
631 system_class=False,
632 static=False,
633 name='returnArrayOfByteArray',
634 method_id_var_name='returnArrayOfByteArray',
635 java_class_name='',
636 params=[],
637 env_call=('Void', ''),
638 unchecked=False,
640 CalledByNative(
641 return_type='Bitmap.CompressFormat',
642 system_class=False,
643 static=False,
644 name='getCompressFormat',
645 method_id_var_name='getCompressFormat',
646 java_class_name='',
647 params=[],
648 env_call=('Void', ''),
649 unchecked=False,
651 CalledByNative(
652 return_type='List<Bitmap.CompressFormat>',
653 system_class=False,
654 static=False,
655 name='getCompressFormatList',
656 method_id_var_name='getCompressFormatList',
657 java_class_name='',
658 params=[],
659 env_call=('Void', ''),
660 unchecked=False,
663 self.assertListEquals(golden_called_by_natives, called_by_natives)
664 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
665 [], called_by_natives, [],
666 TestOptions())
667 self.assertGoldenTextEquals(h.GetContent())
669 def testCalledByNativeParseError(self):
670 try:
671 jni_generator.ExtractCalledByNatives("""
672 @CalledByNative
673 public static int foo(); // This one is fine
675 @CalledByNative
676 scooby doo
677 """)
678 self.fail('Expected a ParseError')
679 except jni_generator.ParseError, e:
680 self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines)
682 def testFullyQualifiedClassName(self):
683 contents = """
684 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
685 // Use of this source code is governed by a BSD-style license that can be
686 // found in the LICENSE file.
688 package org.chromium.content.browser;
690 import org.chromium.base.BuildInfo;
692 self.assertEquals('org/chromium/content/browser/Foo',
693 jni_generator.ExtractFullyQualifiedJavaClassName(
694 'org/chromium/content/browser/Foo.java', contents))
695 self.assertEquals('org/chromium/content/browser/Foo',
696 jni_generator.ExtractFullyQualifiedJavaClassName(
697 'frameworks/Foo.java', contents))
698 self.assertRaises(SyntaxError,
699 jni_generator.ExtractFullyQualifiedJavaClassName,
700 'com/foo/Bar', 'no PACKAGE line')
702 def testMethodNameMangling(self):
703 self.assertEquals('closeV',
704 jni_generator.GetMangledMethodName('close', [], 'void'))
705 self.assertEquals('readI_AB_I_I',
706 jni_generator.GetMangledMethodName('read',
707 [Param(name='p1',
708 datatype='byte[]'),
709 Param(name='p2',
710 datatype='int'),
711 Param(name='p3',
712 datatype='int'),],
713 'int'))
714 self.assertEquals('openJIIS_JLS',
715 jni_generator.GetMangledMethodName('open',
716 [Param(name='p1',
717 datatype='java/lang/String'),],
718 'java/io/InputStream'))
720 def testFromJavaPGenerics(self):
721 contents = """
722 public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
723 implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable {
724 public void dummy();
725 Signature: ()V
728 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
729 TestOptions())
730 self.assertEquals(1, len(jni_from_javap.called_by_natives))
731 self.assertGoldenTextEquals(jni_from_javap.GetContent())
733 def testSnippnetJavap6_7_8(self):
734 content_javap6 = """
735 public class java.util.HashSet {
736 public boolean add(java.lang.Object);
737 Signature: (Ljava/lang/Object;)Z
741 content_javap7 = """
742 public class java.util.HashSet {
743 public boolean add(E);
744 Signature: (Ljava/lang/Object;)Z
748 content_javap8 = """
749 public class java.util.HashSet {
750 public boolean add(E);
751 descriptor: (Ljava/lang/Object;)Z
755 jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
756 TestOptions())
757 jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
758 TestOptions())
759 jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
760 TestOptions())
761 self.assertTrue(jni_from_javap6.GetContent())
762 self.assertTrue(jni_from_javap7.GetContent())
763 self.assertTrue(jni_from_javap8.GetContent())
764 # Ensure the javap7 is correctly parsed and uses the Signature field rather
765 # than the "E" parameter.
766 self.assertTextEquals(jni_from_javap6.GetContent(),
767 jni_from_javap7.GetContent())
768 # Ensure the javap8 is correctly parsed and uses the descriptor field.
769 self.assertTextEquals(jni_from_javap7.GetContent(),
770 jni_from_javap8.GetContent())
772 def testFromJavaP(self):
773 contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
774 'testInputStream.javap'))
775 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
776 TestOptions())
777 self.assertEquals(10, len(jni_from_javap.called_by_natives))
778 self.assertGoldenTextEquals(jni_from_javap.GetContent())
780 def testConstantsFromJavaP(self):
781 for f in ['testMotionEvent.javap', 'testMotionEvent.javap7']:
782 contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
784 jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
785 TestOptions())
786 self.assertEquals(86, len(jni_from_javap.called_by_natives))
787 self.assertGoldenTextEquals(jni_from_javap.GetContent())
789 def testREForNatives(self):
790 # We should not match "native SyncSetupFlow" inside the comment.
791 test_data = """
793 * Invoked when the setup process is complete so we can disconnect from the
794 * native-side SyncSetupFlowHandler.
796 public void destroy() {
797 Log.v(TAG, "Destroying native SyncSetupFlow");
798 if (mNativeSyncSetupFlow != 0) {
799 nativeSyncSetupEnded(mNativeSyncSetupFlow);
800 mNativeSyncSetupFlow = 0;
803 private native void nativeSyncSetupEnded(
804 int nativeAndroidSyncSetupFlowHandler);
806 jni_from_java = jni_generator.JNIFromJavaSource(
807 test_data, 'foo/bar', TestOptions())
809 def testRaisesOnNonJNIMethod(self):
810 test_data = """
811 class MyInnerClass {
812 private int Foo(int p0) {
816 self.assertRaises(SyntaxError,
817 jni_generator.JNIFromJavaSource,
818 test_data, 'foo/bar', TestOptions())
820 def testJniSelfDocumentingExample(self):
821 script_dir = os.path.dirname(sys.argv[0])
822 content = file(os.path.join(script_dir,
823 'java/src/org/chromium/example/jni_generator/SampleForTests.java')
824 ).read()
825 golden_file = os.path.join(script_dir, 'golden_sample_for_tests_jni.h')
826 golden_content = file(golden_file).read()
827 jni_from_java = jni_generator.JNIFromJavaSource(
828 content, 'org/chromium/example/jni_generator/SampleForTests',
829 TestOptions())
830 generated_text = jni_from_java.GetContent()
831 if not self.compareText(golden_content, generated_text):
832 if os.environ.get(REBASELINE_ENV):
833 with file(golden_file, 'w') as f:
834 f.write(generated_text)
835 return
836 self.fail('testJniSelfDocumentingExample')
838 def testNoWrappingPreprocessorLines(self):
839 test_data = """
840 package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday;
842 class ReallyLongClassNamesAreAllTheRage {
843 private static native int nativeTest();
846 jni_from_java = jni_generator.JNIFromJavaSource(
847 test_data, ('com/google/lookhowextremelylongiam/snarf/'
848 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
849 TestOptions())
850 jni_lines = jni_from_java.GetContent().split('\n')
851 line = filter(lambda line: line.lstrip().startswith('#ifndef'),
852 jni_lines)[0]
853 self.assertTrue(len(line) > 80,
854 ('Expected #ifndef line to be > 80 chars: ', line))
856 def testJarJarRemapping(self):
857 test_data = """
858 package org.chromium.example.jni_generator;
860 import org.chromium.example2.Test;
862 import org.chromium.example3.PrefixFoo;
863 import org.chromium.example3.Prefix;
864 import org.chromium.example3.Bar$Inner;
866 class Example {
867 private static native void nativeTest(Test t);
868 private static native void nativeTest2(PrefixFoo t);
869 private static native void nativeTest3(Prefix t);
870 private static native void nativeTest4(Bar$Inner t);
873 jni_generator.JniParams.SetJarJarMappings(
874 """rule org.chromium.example.** com.test.@1
875 rule org.chromium.example2.** org.test2.@1
876 rule org.chromium.example3.Prefix org.test3.Test
877 rule org.chromium.example3.Bar$** org.test3.TestBar$@1""")
878 jni_from_java = jni_generator.JNIFromJavaSource(
879 test_data, 'org/chromium/example/jni_generator/Example', TestOptions())
880 jni_generator.JniParams.SetJarJarMappings('')
881 self.assertGoldenTextEquals(jni_from_java.GetContent())
883 def testImports(self):
884 import_header = """
885 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
886 // Use of this source code is governed by a BSD-style license that can be
887 // found in the LICENSE file.
889 package org.chromium.content.app;
891 import android.app.Service;
892 import android.content.Context;
893 import android.content.Intent;
894 import android.graphics.SurfaceTexture;
895 import android.os.Bundle;
896 import android.os.IBinder;
897 import android.os.ParcelFileDescriptor;
898 import android.os.Process;
899 import android.os.RemoteException;
900 import android.util.Log;
901 import android.view.Surface;
903 import java.util.ArrayList;
905 import org.chromium.base.annotations.CalledByNative;
906 import org.chromium.base.annotations.JNINamespace;
907 import org.chromium.content.app.ContentMain;
908 import org.chromium.content.browser.SandboxedProcessConnection;
909 import org.chromium.content.common.ISandboxedProcessCallback;
910 import org.chromium.content.common.ISandboxedProcessService;
911 import org.chromium.content.common.WillNotRaise.AnException;
912 import org.chromium.content.common.WillRaise.AnException;
914 import static org.chromium.Bar.Zoo;
916 class Foo {
917 public static class BookmarkNode implements Parcelable {
919 public interface PasswordListObserver {
923 jni_generator.JniParams.SetFullyQualifiedClass(
924 'org/chromium/content/app/Foo')
925 jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header)
926 self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in
927 jni_generator.JniParams._imports)
928 self.assertTrue('Lorg/chromium/Bar/Zoo' in
929 jni_generator.JniParams._imports)
930 self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in
931 jni_generator.JniParams._inner_classes)
932 self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in
933 jni_generator.JniParams._inner_classes)
934 self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner;',
935 jni_generator.JniParams.JavaToJni('ContentMain.Inner'))
936 self.assertRaises(SyntaxError,
937 jni_generator.JniParams.JavaToJni,
938 'AnException')
940 def testJniParamsJavaToJni(self):
941 self.assertTextEquals('I', JniParams.JavaToJni('int'))
942 self.assertTextEquals('[B', JniParams.JavaToJni('byte[]'))
943 self.assertTextEquals(
944 '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]'))
946 def testNativesLong(self):
947 test_options = TestOptions()
948 test_options.ptr_type = 'long'
949 test_data = """"
950 private native void nativeDestroy(long nativeChromeBrowserProvider);
952 jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
953 natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type)
954 golden_natives = [
955 NativeMethod(return_type='void', static=False, name='Destroy',
956 params=[Param(datatype='long',
957 name='nativeChromeBrowserProvider')],
958 java_class_name=None,
959 type='method',
960 p0_type='ChromeBrowserProvider',
961 ptr_type=test_options.ptr_type),
963 self.assertListEquals(golden_natives, natives)
964 h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
965 natives, [], [], test_options)
966 self.assertGoldenTextEquals(h.GetContent())
968 def testPureNativeMethodsOption(self):
969 test_data = """
970 package org.chromium.example.jni_generator;
972 /** The pointer to the native Test. */
973 long nativeTest;
975 class Test {
976 private static native long nativeMethod(long nativeTest, int arg1);
979 options = TestOptions()
980 options.pure_native_methods = True
981 jni_from_java = jni_generator.JNIFromJavaSource(
982 test_data, 'org/chromium/example/jni_generator/Test', options)
983 self.assertGoldenTextEquals(jni_from_java.GetContent())
985 def testJNIInitNativeNameOption(self):
986 test_data = """
987 package org.chromium.example.jni_generator;
989 /** The pointer to the native Test. */
990 long nativeTest;
992 class Test {
993 private static native boolean nativeInitNativeClass();
994 private static native int nativeMethod(long nativeTest, int arg1);
997 options = TestOptions()
998 options.jni_init_native_name = 'nativeInitNativeClass'
999 jni_from_java = jni_generator.JNIFromJavaSource(
1000 test_data, 'org/chromium/example/jni_generator/Test', options)
1001 self.assertGoldenTextEquals(jni_from_java.GetContent())
1003 def testEagerCalledByNativesOption(self):
1004 test_data = """
1005 package org.chromium.example.jni_generator;
1007 /** The pointer to the native Test. */
1008 long nativeTest;
1010 class Test {
1011 private static native boolean nativeInitNativeClass();
1012 private static native int nativeMethod(long nativeTest, int arg1);
1013 @CalledByNative
1014 private void testMethodWithParam(int iParam);
1015 @CalledByNative
1016 private static int testStaticMethodWithParam(int iParam);
1017 @CalledByNative
1018 private static double testMethodWithNoParam();
1019 @CalledByNative
1020 private static String testStaticMethodWithNoParam();
1023 options = TestOptions()
1024 options.jni_init_native_name = 'nativeInitNativeClass'
1025 options.eager_called_by_natives = True
1026 jni_from_java = jni_generator.JNIFromJavaSource(
1027 test_data, 'org/chromium/example/jni_generator/Test', options)
1028 self.assertGoldenTextEquals(jni_from_java.GetContent())
1030 def runNativeExportsOption(self, optional):
1031 test_data = """
1032 package org.chromium.example.jni_generator;
1034 /** The pointer to the native Test. */
1035 long nativeTest;
1037 class Test {
1038 private static native boolean nativeInitNativeClass();
1039 private static native int nativeStaticMethod(long nativeTest, int arg1);
1040 private native int nativeMethod(long nativeTest, int arg1);
1041 @CalledByNative
1042 private void testMethodWithParam(int iParam);
1043 @CalledByNative
1044 private String testMethodWithParamAndReturn(int iParam);
1045 @CalledByNative
1046 private static int testStaticMethodWithParam(int iParam);
1047 @CalledByNative
1048 private static double testMethodWithNoParam();
1049 @CalledByNative
1050 private static String testStaticMethodWithNoParam();
1052 class MyInnerClass {
1053 @NativeCall("MyInnerClass")
1054 private native int nativeInit();
1056 class MyOtherInnerClass {
1057 @NativeCall("MyOtherInnerClass")
1058 private native int nativeInit();
1062 options = TestOptions()
1063 options.jni_init_native_name = 'nativeInitNativeClass'
1064 options.native_exports = True
1065 options.native_exports_optional = optional
1066 jni_from_java = jni_generator.JNIFromJavaSource(
1067 test_data, 'org/chromium/example/jni_generator/SampleForTests', options)
1068 return jni_from_java.GetContent()
1070 def testNativeExportsOption(self):
1071 content = self.runNativeExportsOption(False)
1072 self.assertGoldenTextEquals(content)
1074 def testNativeExportsOptionalOption(self):
1075 content = self.runNativeExportsOption(True)
1076 self.assertGoldenTextEquals(content)
1078 def testOuterInnerRaises(self):
1079 test_data = """
1080 package org.chromium.media;
1082 @CalledByNative
1083 static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
1084 return format.getWidth();
1087 def willRaise():
1088 jni_generator.JNIFromJavaSource(
1089 test_data,
1090 'org/chromium/media/VideoCaptureFactory',
1091 TestOptions())
1092 self.assertRaises(SyntaxError, willRaise)
1094 def testSingleJNIAdditionalImport(self):
1095 test_data = """
1096 package org.chromium.foo;
1098 @JNIAdditionalImport(Bar.class)
1099 class Foo {
1101 @CalledByNative
1102 private static void calledByNative(Bar.Callback callback) {
1105 private static native void nativeDoSomething(Bar.Callback callback);
1108 jni_from_java = jni_generator.JNIFromJavaSource(test_data,
1109 'org/chromium/foo/Foo',
1110 TestOptions())
1111 self.assertGoldenTextEquals(jni_from_java.GetContent())
1113 def testMultipleJNIAdditionalImport(self):
1114 test_data = """
1115 package org.chromium.foo;
1117 @JNIAdditionalImport({Bar1.class, Bar2.class})
1118 class Foo {
1120 @CalledByNative
1121 private static void calledByNative(Bar1.Callback callback1,
1122 Bar2.Callback callback2) {
1125 private static native void nativeDoSomething(Bar1.Callback callback1,
1126 Bar2.Callback callback2);
1129 jni_from_java = jni_generator.JNIFromJavaSource(test_data,
1130 'org/chromium/foo/Foo',
1131 TestOptions())
1132 self.assertGoldenTextEquals(jni_from_java.GetContent())
1135 def TouchStamp(stamp_path):
1136 dir_name = os.path.dirname(stamp_path)
1137 if not os.path.isdir(dir_name):
1138 os.makedirs()
1140 with open(stamp_path, 'a'):
1141 os.utime(stamp_path, None)
1144 def main(argv):
1145 parser = optparse.OptionParser()
1146 parser.add_option('--stamp', help='Path to touch on success.')
1147 options, _ = parser.parse_args(argv[1:])
1149 test_result = unittest.main(argv=argv[0:1], exit=False)
1151 if test_result.result.wasSuccessful() and options.stamp:
1152 TouchStamp(options.stamp)
1154 return not test_result.result.wasSuccessful()
1157 if __name__ == '__main__':
1158 sys.exit(main(sys.argv))