Upstream version 5.34.92.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
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.ExtractImportsAndInnerClasses(test_data)
152     natives = jni_generator.ExtractNatives(test_data, 'int')
153     golden_natives = [
154         NativeMethod(return_type='int', static=False,
155                      name='Init',
156                      params=[],
157                      java_class_name=None,
158                      type='function'),
159         NativeMethod(return_type='void', static=False, name='Destroy',
160                      params=[Param(datatype='int',
161                                    name='nativeChromeBrowserProvider')],
162                      java_class_name=None,
163                      type='method',
164                      p0_type='ChromeBrowserProvider'),
165         NativeMethod(return_type='long', static=False, name='AddBookmark',
166                      params=[Param(datatype='int',
167                                    name='nativeChromeBrowserProvider'),
168                              Param(datatype='String',
169                                    name='url'),
170                              Param(datatype='String',
171                                    name='title'),
172                              Param(datatype='boolean',
173                                    name='isFolder'),
174                              Param(datatype='long',
175                                    name='parentId')],
176                      java_class_name=None,
177                      type='method',
178                      p0_type='ChromeBrowserProvider'),
179         NativeMethod(return_type='String', static=True,
180                      name='GetDomainAndRegistry',
181                      params=[Param(datatype='String',
182                                    name='url')],
183                      java_class_name=None,
184                      type='function'),
185         NativeMethod(return_type='void', static=True,
186                      name='CreateHistoricalTabFromState',
187                      params=[Param(datatype='byte[]',
188                                    name='state'),
189                              Param(datatype='int',
190                                    name='tab_index')],
191                      java_class_name=None,
192                      type='function'),
193         NativeMethod(return_type='byte[]', static=False,
194                      name='GetStateAsByteArray',
195                      params=[Param(datatype='View', name='view')],
196                      java_class_name=None,
197                      type='function'),
198         NativeMethod(return_type='String[]', static=True,
199                      name='GetAutofillProfileGUIDs', params=[],
200                      java_class_name=None,
201                      type='function'),
202         NativeMethod(return_type='void', static=False,
203                      name='SetRecognitionResults',
204                      params=[Param(datatype='int', name='sessionId'),
205                              Param(datatype='String[]', name='results')],
206                      java_class_name=None,
207                      type='function'),
208         NativeMethod(return_type='long', static=False,
209                      name='AddBookmarkFromAPI',
210                      params=[Param(datatype='int',
211                                    name='nativeChromeBrowserProvider'),
212                              Param(datatype='String',
213                                    name='url'),
214                              Param(datatype='Long',
215                                    name='created'),
216                              Param(datatype='Boolean',
217                                    name='isBookmark'),
218                              Param(datatype='Long',
219                                    name='date'),
220                              Param(datatype='byte[]',
221                                    name='favicon'),
222                              Param(datatype='String',
223                                    name='title'),
224                              Param(datatype='Integer',
225                                    name='visits')],
226                      java_class_name=None,
227                      type='method',
228                      p0_type='ChromeBrowserProvider'),
229         NativeMethod(return_type='int', static=False,
230                      name='FindAll',
231                      params=[Param(datatype='String',
232                                    name='find')],
233                      java_class_name=None,
234                      type='function'),
235         NativeMethod(return_type='OnFrameAvailableListener', static=True,
236                      name='GetInnerClass',
237                      params=[],
238                      java_class_name=None,
239                      type='function'),
240         NativeMethod(return_type='Bitmap',
241                      static=False,
242                      name='QueryBitmap',
243                      params=[Param(datatype='int',
244                                    name='nativeChromeBrowserProvider'),
245                              Param(datatype='String[]',
246                                    name='projection'),
247                              Param(datatype='String',
248                                    name='selection'),
249                              Param(datatype='String[]',
250                                    name='selectionArgs'),
251                              Param(datatype='String',
252                                    name='sortOrder'),
253                             ],
254                      java_class_name=None,
255                      type='method',
256                      p0_type='ChromeBrowserProvider'),
257         NativeMethod(return_type='void', static=False,
258                      name='GotOrientation',
259                      params=[Param(datatype='int',
260                                    name='nativeDataFetcherImplAndroid'),
261                              Param(datatype='double',
262                                    name='alpha'),
263                              Param(datatype='double',
264                                    name='beta'),
265                              Param(datatype='double',
266                                    name='gamma'),
267                             ],
268                      java_class_name=None,
269                      type='method',
270                      p0_type='content::DataFetcherImplAndroid'),
271     ]
272     self.assertListEquals(golden_natives, natives)
273     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
274                                              natives, [], TestOptions())
275     self.assertGoldenTextEquals(h.GetContent())
276
277   def testInnerClassNatives(self):
278     test_data = """
279     class MyInnerClass {
280       @NativeCall("MyInnerClass")
281       private native int nativeInit();
282     }
283     """
284     natives = jni_generator.ExtractNatives(test_data, 'int')
285     golden_natives = [
286         NativeMethod(return_type='int', static=False,
287                      name='Init', params=[],
288                      java_class_name='MyInnerClass',
289                      type='function')
290     ]
291     self.assertListEquals(golden_natives, natives)
292     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
293                                              natives, [], TestOptions())
294     self.assertGoldenTextEquals(h.GetContent())
295
296   def testInnerClassNativesMultiple(self):
297     test_data = """
298     class MyInnerClass {
299       @NativeCall("MyInnerClass")
300       private native int nativeInit();
301     }
302     class MyOtherInnerClass {
303       @NativeCall("MyOtherInnerClass")
304       private native int nativeInit();
305     }
306     """
307     natives = jni_generator.ExtractNatives(test_data, 'int')
308     golden_natives = [
309         NativeMethod(return_type='int', static=False,
310                      name='Init', params=[],
311                      java_class_name='MyInnerClass',
312                      type='function'),
313         NativeMethod(return_type='int', static=False,
314                      name='Init', params=[],
315                      java_class_name='MyOtherInnerClass',
316                      type='function')
317     ]
318     self.assertListEquals(golden_natives, natives)
319     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
320                                              natives, [], TestOptions())
321     self.assertGoldenTextEquals(h.GetContent())
322
323   def testInnerClassNativesBothInnerAndOuter(self):
324     test_data = """
325     class MyOuterClass {
326       private native int nativeInit();
327       class MyOtherInnerClass {
328         @NativeCall("MyOtherInnerClass")
329         private native int nativeInit();
330       }
331     }
332     """
333     natives = jni_generator.ExtractNatives(test_data, 'int')
334     golden_natives = [
335         NativeMethod(return_type='int', static=False,
336                      name='Init', params=[],
337                      java_class_name=None,
338                      type='function'),
339         NativeMethod(return_type='int', static=False,
340                      name='Init', params=[],
341                      java_class_name='MyOtherInnerClass',
342                      type='function')
343     ]
344     self.assertListEquals(golden_natives, natives)
345     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
346                                              natives, [], TestOptions())
347     self.assertGoldenTextEquals(h.GetContent())
348
349   def testCalledByNatives(self):
350     test_data = """"
351     import android.graphics.Bitmap;
352     import android.view.View;
353     import java.io.InputStream;
354     import java.util.List;
355
356     class InnerClass {}
357
358     @CalledByNative
359     InnerClass showConfirmInfoBar(int nativeInfoBar,
360             String buttonOk, String buttonCancel, String title, Bitmap icon) {
361         InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext,
362                                              buttonOk, buttonCancel,
363                                              title, icon);
364         return infobar;
365     }
366     @CalledByNative
367     InnerClass showAutoLoginInfoBar(int nativeInfoBar,
368             String realm, String account, String args) {
369         AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext,
370                 realm, account, args);
371         if (infobar.displayedAccountCount() == 0)
372             infobar = null;
373         return infobar;
374     }
375     @CalledByNative("InfoBar")
376     void dismiss();
377     @SuppressWarnings("unused")
378     @CalledByNative
379     private static boolean shouldShowAutoLogin(View view,
380             String realm, String account, String args) {
381         AccountManagerContainer accountManagerContainer =
382             new AccountManagerContainer((Activity)contentView.getContext(),
383             realm, account, args);
384         String[] logins = accountManagerContainer.getAccountLogins(null);
385         return logins.length != 0;
386     }
387     @CalledByNative
388     static InputStream openUrl(String url) {
389         return null;
390     }
391     @CalledByNative
392     private void activateHardwareAcceleration(final boolean activated,
393             final int iPid, final int iType,
394             final int iPrimaryID, final int iSecondaryID) {
395       if (!activated) {
396           return
397       }
398     }
399     @CalledByNativeUnchecked
400     private void uncheckedCall(int iParam);
401
402     @CalledByNative
403     public byte[] returnByteArray();
404
405     @CalledByNative
406     public boolean[] returnBooleanArray();
407
408     @CalledByNative
409     public char[] returnCharArray();
410
411     @CalledByNative
412     public short[] returnShortArray();
413
414     @CalledByNative
415     public int[] returnIntArray();
416
417     @CalledByNative
418     public long[] returnLongArray();
419
420     @CalledByNative
421     public double[] returnDoubleArray();
422
423     @CalledByNative
424     public Object[] returnObjectArray();
425
426     @CalledByNative
427     public byte[][] returnArrayOfByteArray();
428
429     @CalledByNative
430     public Bitmap.CompressFormat getCompressFormat();
431
432     @CalledByNative
433     public List<Bitmap.CompressFormat> getCompressFormatList();
434     """
435     jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo')
436     jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
437     called_by_natives = jni_generator.ExtractCalledByNatives(test_data)
438     golden_called_by_natives = [
439         CalledByNative(
440             return_type='InnerClass',
441             system_class=False,
442             static=False,
443             name='showConfirmInfoBar',
444             method_id_var_name='showConfirmInfoBar',
445             java_class_name='',
446             params=[Param(datatype='int', name='nativeInfoBar'),
447                     Param(datatype='String', name='buttonOk'),
448                     Param(datatype='String', name='buttonCancel'),
449                     Param(datatype='String', name='title'),
450                     Param(datatype='Bitmap', name='icon')],
451             env_call=('Object', ''),
452             unchecked=False,
453         ),
454         CalledByNative(
455             return_type='InnerClass',
456             system_class=False,
457             static=False,
458             name='showAutoLoginInfoBar',
459             method_id_var_name='showAutoLoginInfoBar',
460             java_class_name='',
461             params=[Param(datatype='int', name='nativeInfoBar'),
462                     Param(datatype='String', name='realm'),
463                     Param(datatype='String', name='account'),
464                     Param(datatype='String', name='args')],
465             env_call=('Object', ''),
466             unchecked=False,
467         ),
468         CalledByNative(
469             return_type='void',
470             system_class=False,
471             static=False,
472             name='dismiss',
473             method_id_var_name='dismiss',
474             java_class_name='InfoBar',
475             params=[],
476             env_call=('Void', ''),
477             unchecked=False,
478         ),
479         CalledByNative(
480             return_type='boolean',
481             system_class=False,
482             static=True,
483             name='shouldShowAutoLogin',
484             method_id_var_name='shouldShowAutoLogin',
485             java_class_name='',
486             params=[Param(datatype='View', name='view'),
487                     Param(datatype='String', name='realm'),
488                     Param(datatype='String', name='account'),
489                     Param(datatype='String', name='args')],
490             env_call=('Boolean', ''),
491             unchecked=False,
492         ),
493         CalledByNative(
494             return_type='InputStream',
495             system_class=False,
496             static=True,
497             name='openUrl',
498             method_id_var_name='openUrl',
499             java_class_name='',
500             params=[Param(datatype='String', name='url')],
501             env_call=('Object', ''),
502             unchecked=False,
503         ),
504         CalledByNative(
505             return_type='void',
506             system_class=False,
507             static=False,
508             name='activateHardwareAcceleration',
509             method_id_var_name='activateHardwareAcceleration',
510             java_class_name='',
511             params=[Param(datatype='boolean', name='activated'),
512                     Param(datatype='int', name='iPid'),
513                     Param(datatype='int', name='iType'),
514                     Param(datatype='int', name='iPrimaryID'),
515                     Param(datatype='int', name='iSecondaryID'),
516                    ],
517             env_call=('Void', ''),
518             unchecked=False,
519         ),
520         CalledByNative(
521             return_type='void',
522             system_class=False,
523             static=False,
524             name='uncheckedCall',
525             method_id_var_name='uncheckedCall',
526             java_class_name='',
527             params=[Param(datatype='int', name='iParam')],
528             env_call=('Void', ''),
529             unchecked=True,
530         ),
531         CalledByNative(
532             return_type='byte[]',
533             system_class=False,
534             static=False,
535             name='returnByteArray',
536             method_id_var_name='returnByteArray',
537             java_class_name='',
538             params=[],
539             env_call=('Void', ''),
540             unchecked=False,
541         ),
542         CalledByNative(
543             return_type='boolean[]',
544             system_class=False,
545             static=False,
546             name='returnBooleanArray',
547             method_id_var_name='returnBooleanArray',
548             java_class_name='',
549             params=[],
550             env_call=('Void', ''),
551             unchecked=False,
552         ),
553         CalledByNative(
554             return_type='char[]',
555             system_class=False,
556             static=False,
557             name='returnCharArray',
558             method_id_var_name='returnCharArray',
559             java_class_name='',
560             params=[],
561             env_call=('Void', ''),
562             unchecked=False,
563         ),
564         CalledByNative(
565             return_type='short[]',
566             system_class=False,
567             static=False,
568             name='returnShortArray',
569             method_id_var_name='returnShortArray',
570             java_class_name='',
571             params=[],
572             env_call=('Void', ''),
573             unchecked=False,
574         ),
575         CalledByNative(
576             return_type='int[]',
577             system_class=False,
578             static=False,
579             name='returnIntArray',
580             method_id_var_name='returnIntArray',
581             java_class_name='',
582             params=[],
583             env_call=('Void', ''),
584             unchecked=False,
585         ),
586         CalledByNative(
587             return_type='long[]',
588             system_class=False,
589             static=False,
590             name='returnLongArray',
591             method_id_var_name='returnLongArray',
592             java_class_name='',
593             params=[],
594             env_call=('Void', ''),
595             unchecked=False,
596         ),
597         CalledByNative(
598             return_type='double[]',
599             system_class=False,
600             static=False,
601             name='returnDoubleArray',
602             method_id_var_name='returnDoubleArray',
603             java_class_name='',
604             params=[],
605             env_call=('Void', ''),
606             unchecked=False,
607         ),
608         CalledByNative(
609             return_type='Object[]',
610             system_class=False,
611             static=False,
612             name='returnObjectArray',
613             method_id_var_name='returnObjectArray',
614             java_class_name='',
615             params=[],
616             env_call=('Void', ''),
617             unchecked=False,
618         ),
619         CalledByNative(
620             return_type='byte[][]',
621             system_class=False,
622             static=False,
623             name='returnArrayOfByteArray',
624             method_id_var_name='returnArrayOfByteArray',
625             java_class_name='',
626             params=[],
627             env_call=('Void', ''),
628             unchecked=False,
629         ),
630         CalledByNative(
631             return_type='Bitmap.CompressFormat',
632             system_class=False,
633             static=False,
634             name='getCompressFormat',
635             method_id_var_name='getCompressFormat',
636             java_class_name='',
637             params=[],
638             env_call=('Void', ''),
639             unchecked=False,
640         ),
641         CalledByNative(
642             return_type='List<Bitmap.CompressFormat>',
643             system_class=False,
644             static=False,
645             name='getCompressFormatList',
646             method_id_var_name='getCompressFormatList',
647             java_class_name='',
648             params=[],
649             env_call=('Void', ''),
650             unchecked=False,
651         ),
652     ]
653     self.assertListEquals(golden_called_by_natives, called_by_natives)
654     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
655                                              [], called_by_natives,
656                                              TestOptions())
657     self.assertGoldenTextEquals(h.GetContent())
658
659   def testCalledByNativeParseError(self):
660     try:
661       jni_generator.ExtractCalledByNatives("""
662 @CalledByNative
663 public static int foo(); // This one is fine
664
665 @CalledByNative
666 scooby doo
667 """)
668       self.fail('Expected a ParseError')
669     except jni_generator.ParseError, e:
670       self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines)
671
672   def testFullyQualifiedClassName(self):
673     contents = """
674 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
675 // Use of this source code is governed by a BSD-style license that can be
676 // found in the LICENSE file.
677
678 package org.chromium.content.browser;
679
680 import org.chromium.base.BuildInfo;
681 """
682     self.assertEquals('org/chromium/content/browser/Foo',
683                       jni_generator.ExtractFullyQualifiedJavaClassName(
684                           'org/chromium/content/browser/Foo.java', contents))
685     self.assertEquals('org/chromium/content/browser/Foo',
686                       jni_generator.ExtractFullyQualifiedJavaClassName(
687                           'frameworks/Foo.java', contents))
688     self.assertRaises(SyntaxError,
689                       jni_generator.ExtractFullyQualifiedJavaClassName,
690                       'com/foo/Bar', 'no PACKAGE line')
691
692   def testMethodNameMangling(self):
693     self.assertEquals('closeV',
694         jni_generator.GetMangledMethodName('close', [], 'void'))
695     self.assertEquals('readI_AB_I_I',
696         jni_generator.GetMangledMethodName('read',
697             [Param(name='p1',
698                    datatype='byte[]'),
699              Param(name='p2',
700                    datatype='int'),
701              Param(name='p3',
702                    datatype='int'),],
703              'int'))
704     self.assertEquals('openJIIS_JLS',
705         jni_generator.GetMangledMethodName('open',
706             [Param(name='p1',
707                    datatype='java/lang/String'),],
708              'java/io/InputStream'))
709
710   def testFromJavaPGenerics(self):
711     contents = """
712 public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
713       implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable {
714     public void dummy();
715   Signature: ()V
716 }
717 """
718     jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
719                                                 TestOptions())
720     self.assertEquals(1, len(jni_from_javap.called_by_natives))
721     self.assertGoldenTextEquals(jni_from_javap.GetContent())
722
723   def testSnippnetJavap6_7(self):
724     content_javap6 = """
725 public class java.util.HashSet {
726 public boolean add(java.lang.Object);
727  Signature: (Ljava/lang/Object;)Z
728 }
729 """
730
731     content_javap7 = """
732 public class java.util.HashSet {
733 public boolean add(E);
734   Signature: (Ljava/lang/Object;)Z
735 }
736 """
737     jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
738                                                  TestOptions())
739     jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
740                                                  TestOptions())
741     self.assertTrue(jni_from_javap6.GetContent())
742     self.assertTrue(jni_from_javap7.GetContent())
743     # Ensure the javap7 is correctly parsed and uses the Signature field rather
744     # than the "E" parameter.
745     self.assertTextEquals(jni_from_javap6.GetContent(),
746                           jni_from_javap7.GetContent())
747
748   def testFromJavaP(self):
749     contents = """
750 public abstract class java.io.InputStream extends
751   java.lang.Object implements java.io.Closeable{
752 public java.io.InputStream();
753   Signature: ()V
754 public int available()   throws java.io.IOException;
755   Signature: ()I
756 public void close()   throws java.io.IOException;
757   Signature: ()V
758 public void mark(int);
759   Signature: (I)V
760 public boolean markSupported();
761   Signature: ()Z
762 public abstract int read()   throws java.io.IOException;
763   Signature: ()I
764 public int read(byte[])   throws java.io.IOException;
765   Signature: ([B)I
766 public int read(byte[], int, int)   throws java.io.IOException;
767   Signature: ([BII)I
768 public synchronized void reset()   throws java.io.IOException;
769   Signature: ()V
770 public long skip(long)   throws java.io.IOException;
771   Signature: (J)J
772 }
773 """
774     jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
775                                                 TestOptions())
776     self.assertEquals(10, len(jni_from_javap.called_by_natives))
777     self.assertGoldenTextEquals(jni_from_javap.GetContent())
778
779   def testREForNatives(self):
780     # We should not match "native SyncSetupFlow" inside the comment.
781     test_data = """
782     /**
783      * Invoked when the setup process is complete so we can disconnect from the
784      * native-side SyncSetupFlowHandler.
785      */
786     public void destroy() {
787         Log.v(TAG, "Destroying native SyncSetupFlow");
788         if (mNativeSyncSetupFlow != 0) {
789             nativeSyncSetupEnded(mNativeSyncSetupFlow);
790             mNativeSyncSetupFlow = 0;
791         }
792     }
793     private native void nativeSyncSetupEnded(
794         int nativeAndroidSyncSetupFlowHandler);
795     """
796     jni_from_java = jni_generator.JNIFromJavaSource(
797         test_data, 'foo/bar', TestOptions())
798
799   def testRaisesOnNonJNIMethod(self):
800     test_data = """
801     class MyInnerClass {
802       private int Foo(int p0) {
803       }
804     }
805     """
806     self.assertRaises(SyntaxError,
807                       jni_generator.JNIFromJavaSource,
808                       test_data, 'foo/bar', TestOptions())
809
810   def testJniSelfDocumentingExample(self):
811     script_dir = os.path.dirname(sys.argv[0])
812     content = file(os.path.join(script_dir,
813         'java/src/org/chromium/example/jni_generator/SampleForTests.java')
814         ).read()
815     golden_file = os.path.join(script_dir, 'golden_sample_for_tests_jni.h')
816     golden_content = file(golden_file).read()
817     jni_from_java = jni_generator.JNIFromJavaSource(
818         content, 'org/chromium/example/jni_generator/SampleForTests',
819         TestOptions())
820     generated_text = jni_from_java.GetContent()
821     if not self.compareText(golden_content, generated_text):
822       if os.environ.get(REBASELINE_ENV):
823         with file(golden_file, 'w') as f:
824           f.write(generated_text)
825         return
826       self.fail('testJniSelfDocumentingExample')
827
828   def testNoWrappingPreprocessorLines(self):
829     test_data = """
830     package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday;
831
832     class ReallyLongClassNamesAreAllTheRage {
833         private static native int nativeTest();
834     }
835     """
836     jni_from_java = jni_generator.JNIFromJavaSource(
837         test_data, ('com/google/lookhowextremelylongiam/snarf/'
838                     'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
839         TestOptions())
840     jni_lines = jni_from_java.GetContent().split('\n')
841     line = filter(lambda line: line.lstrip().startswith('#ifndef'),
842                   jni_lines)[0]
843     self.assertTrue(len(line) > 80,
844                     ('Expected #ifndef line to be > 80 chars: ', line))
845
846   def testJarJarRemapping(self):
847     test_data = """
848     package org.chromium.example.jni_generator;
849
850     import org.chromium.example2.Test;
851
852     class Example {
853       private static native void nativeTest(Test t);
854     }
855     """
856     jni_generator.JniParams.SetJarJarMappings(
857         """rule org.chromium.example.** com.test.@1
858         rule org.chromium.example2.** org.test2.@0""")
859     jni_from_java = jni_generator.JNIFromJavaSource(
860         test_data, 'org/chromium/example/jni_generator/Example', TestOptions())
861     jni_generator.JniParams.SetJarJarMappings('')
862     self.assertGoldenTextEquals(jni_from_java.GetContent())
863
864   def testImports(self):
865     import_header = """
866 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
867 // Use of this source code is governed by a BSD-style license that can be
868 // found in the LICENSE file.
869
870 package org.chromium.content.app;
871
872 import android.app.Service;
873 import android.content.Context;
874 import android.content.Intent;
875 import android.graphics.SurfaceTexture;
876 import android.os.Bundle;
877 import android.os.IBinder;
878 import android.os.ParcelFileDescriptor;
879 import android.os.Process;
880 import android.os.RemoteException;
881 import android.util.Log;
882 import android.view.Surface;
883
884 import java.util.ArrayList;
885
886 import org.chromium.base.CalledByNative;
887 import org.chromium.base.JNINamespace;
888 import org.chromium.content.app.ContentMain;
889 import org.chromium.content.browser.SandboxedProcessConnection;
890 import org.chromium.content.common.ISandboxedProcessCallback;
891 import org.chromium.content.common.ISandboxedProcessService;
892 import org.chromium.content.common.WillNotRaise.AnException;
893 import org.chromium.content.common.WillRaise.AnException;
894
895 import static org.chromium.Bar.Zoo;
896
897 class Foo {
898   public static class BookmarkNode implements Parcelable {
899   }
900   public interface PasswordListObserver {
901   }
902 }
903     """
904     jni_generator.JniParams.SetFullyQualifiedClass(
905         'org/chromium/content/app/Foo')
906     jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header)
907     self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in
908                     jni_generator.JniParams._imports)
909     self.assertTrue('Lorg/chromium/Bar/Zoo' in
910                     jni_generator.JniParams._imports)
911     self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in
912                     jni_generator.JniParams._inner_classes)
913     self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in
914                     jni_generator.JniParams._inner_classes)
915     self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner;',
916                       jni_generator.JniParams.JavaToJni('ContentMain.Inner'))
917     self.assertRaises(SyntaxError,
918                       jni_generator.JniParams.JavaToJni,
919                       'AnException')
920
921   def testJniParamsJavaToJni(self):
922     self.assertTextEquals('I', JniParams.JavaToJni('int'))
923     self.assertTextEquals('[B', JniParams.JavaToJni('byte[]'))
924     self.assertTextEquals(
925         '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]'))
926
927   def testNativesLong(self):
928     test_options = TestOptions()
929     test_options.ptr_type = 'long'
930     test_data = """"
931     private native void nativeDestroy(long nativeChromeBrowserProvider);
932     """
933     jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
934     natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type)
935     golden_natives = [
936         NativeMethod(return_type='void', static=False, name='Destroy',
937                      params=[Param(datatype='long',
938                                    name='nativeChromeBrowserProvider')],
939                      java_class_name=None,
940                      type='method',
941                      p0_type='ChromeBrowserProvider',
942                      ptr_type=test_options.ptr_type),
943     ]
944     self.assertListEquals(golden_natives, natives)
945     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
946                                              natives, [], test_options)
947     self.assertGoldenTextEquals(h.GetContent())
948
949   def testPureNativeMethodsOption(self):
950     test_data = """
951     package org.chromium.example.jni_generator;
952
953     /** The pointer to the native Test. */
954     long nativeTest;
955
956     class Test {
957         private static native long nativeMethod(long nativeTest, int arg1);
958     }
959     """
960     options = TestOptions()
961     options.pure_native_methods = True
962     jni_from_java = jni_generator.JNIFromJavaSource(
963         test_data, 'org/chromium/example/jni_generator/Test', options)
964     self.assertGoldenTextEquals(jni_from_java.GetContent())
965
966   def testJNIInitNativeNameOption(self):
967     test_data = """
968     package org.chromium.example.jni_generator;
969
970     /** The pointer to the native Test. */
971     long nativeTest;
972
973     class Test {
974         private static native boolean nativeInitNativeClass();
975         private static native int nativeMethod(long nativeTest, int arg1);
976     }
977     """
978     options = TestOptions()
979     options.jni_init_native_name = 'nativeInitNativeClass'
980     jni_from_java = jni_generator.JNIFromJavaSource(
981         test_data, 'org/chromium/example/jni_generator/Test', options)
982     self.assertGoldenTextEquals(jni_from_java.GetContent())
983
984   def testEagerCalledByNativesOption(self):
985     test_data = """
986     package org.chromium.example.jni_generator;
987
988     /** The pointer to the native Test. */
989     long nativeTest;
990
991     class Test {
992         private static native boolean nativeInitNativeClass();
993         private static native int nativeMethod(long nativeTest, int arg1);
994         @CalledByNative
995         private void testMethodWithParam(int iParam);
996         @CalledByNative
997         private static int testStaticMethodWithParam(int iParam);
998         @CalledByNative
999         private static double testMethodWithNoParam();
1000         @CalledByNative
1001         private static String testStaticMethodWithNoParam();
1002     }
1003     """
1004     options = TestOptions()
1005     options.jni_init_native_name = 'nativeInitNativeClass'
1006     options.eager_called_by_natives = True
1007     jni_from_java = jni_generator.JNIFromJavaSource(
1008         test_data, 'org/chromium/example/jni_generator/Test', options)
1009     self.assertGoldenTextEquals(jni_from_java.GetContent())
1010
1011 if __name__ == '__main__':
1012   unittest.main()