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