- add sources.
[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 os
16 import sys
17 import unittest
18 import jni_generator
19 from jni_generator import CalledByNative, JniParams, NativeMethod, Param
20
21
22 SCRIPT_NAME = 'base/android/jni_generator/jni_generator.py'
23
24
25 class TestOptions(object):
26   """The mock options object which is passed to the jni_generator.py script."""
27
28   def __init__(self):
29     self.namespace = None
30     self.script_name = SCRIPT_NAME
31     self.ptr_type = 'int'
32
33
34 class TestGenerator(unittest.TestCase):
35   def assertObjEquals(self, first, second):
36     dict_first = first.__dict__
37     dict_second = second.__dict__
38     self.assertEquals(dict_first.keys(), dict_second.keys())
39     for key, value in dict_first.iteritems():
40       if (type(value) is list and len(value) and
41           isinstance(type(value[0]), object)):
42         self.assertListEquals(value, second.__getattribute__(key))
43       else:
44         actual = second.__getattribute__(key)
45         self.assertEquals(value, actual,
46                           'Key ' + key + ': ' + str(value) + '!=' + str(actual))
47
48   def assertListEquals(self, first, second):
49     self.assertEquals(len(first), len(second))
50     for i in xrange(len(first)):
51       if isinstance(first[i], object):
52         self.assertObjEquals(first[i], second[i])
53       else:
54         self.assertEquals(first[i], second[i])
55
56   def assertTextEquals(self, golden_text, generated_text):
57     stripped_golden = [l.strip() for l in golden_text.split('\n')]
58     stripped_generated = [l.strip() for l in generated_text.split('\n')]
59     if stripped_golden != stripped_generated:
60       print self.id()
61       for line in difflib.context_diff(stripped_golden, stripped_generated):
62         print line
63       print '\n\nGenerated'
64       print '=' * 80
65       print generated_text
66       print '=' * 80
67       self.fail('Golden text mismatch')
68
69   def testNatives(self):
70     test_data = """"
71     interface OnFrameAvailableListener {}
72     private native int nativeInit();
73     private native void nativeDestroy(int nativeChromeBrowserProvider);
74     private native long nativeAddBookmark(
75             int nativeChromeBrowserProvider,
76             String url, String title, boolean isFolder, long parentId);
77     private static native String nativeGetDomainAndRegistry(String url);
78     private static native void nativeCreateHistoricalTabFromState(
79             byte[] state, int tab_index);
80     private native byte[] nativeGetStateAsByteArray(View view);
81     private static native String[] nativeGetAutofillProfileGUIDs();
82     private native void nativeSetRecognitionResults(
83             int sessionId, String[] results);
84     private native long nativeAddBookmarkFromAPI(
85             int nativeChromeBrowserProvider,
86             String url, Long created, Boolean isBookmark,
87             Long date, byte[] favicon, String title, Integer visits);
88     native int nativeFindAll(String find);
89     private static native OnFrameAvailableListener nativeGetInnerClass();
90     private native Bitmap nativeQueryBitmap(
91             int nativeChromeBrowserProvider,
92             String[] projection, String selection,
93             String[] selectionArgs, String sortOrder);
94     private native void nativeGotOrientation(
95             int nativeDataFetcherImplAndroid,
96             double alpha, double beta, double gamma);
97     """
98     jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
99     natives = jni_generator.ExtractNatives(test_data, 'int')
100     golden_natives = [
101         NativeMethod(return_type='int', static=False,
102                      name='Init',
103                      params=[],
104                      java_class_name=None,
105                      type='function'),
106         NativeMethod(return_type='void', static=False, name='Destroy',
107                      params=[Param(datatype='int',
108                                    name='nativeChromeBrowserProvider')],
109                      java_class_name=None,
110                      type='method',
111                      p0_type='ChromeBrowserProvider'),
112         NativeMethod(return_type='long', static=False, name='AddBookmark',
113                      params=[Param(datatype='int',
114                                    name='nativeChromeBrowserProvider'),
115                              Param(datatype='String',
116                                    name='url'),
117                              Param(datatype='String',
118                                    name='title'),
119                              Param(datatype='boolean',
120                                    name='isFolder'),
121                              Param(datatype='long',
122                                    name='parentId')],
123                      java_class_name=None,
124                      type='method',
125                      p0_type='ChromeBrowserProvider'),
126         NativeMethod(return_type='String', static=True,
127                      name='GetDomainAndRegistry',
128                      params=[Param(datatype='String',
129                                    name='url')],
130                      java_class_name=None,
131                      type='function'),
132         NativeMethod(return_type='void', static=True,
133                      name='CreateHistoricalTabFromState',
134                      params=[Param(datatype='byte[]',
135                                    name='state'),
136                              Param(datatype='int',
137                                    name='tab_index')],
138                      java_class_name=None,
139                      type='function'),
140         NativeMethod(return_type='byte[]', static=False,
141                      name='GetStateAsByteArray',
142                      params=[Param(datatype='View', name='view')],
143                      java_class_name=None,
144                      type='function'),
145         NativeMethod(return_type='String[]', static=True,
146                      name='GetAutofillProfileGUIDs', params=[],
147                      java_class_name=None,
148                      type='function'),
149         NativeMethod(return_type='void', static=False,
150                      name='SetRecognitionResults',
151                      params=[Param(datatype='int', name='sessionId'),
152                              Param(datatype='String[]', name='results')],
153                      java_class_name=None,
154                      type='function'),
155         NativeMethod(return_type='long', static=False,
156                      name='AddBookmarkFromAPI',
157                      params=[Param(datatype='int',
158                                    name='nativeChromeBrowserProvider'),
159                              Param(datatype='String',
160                                    name='url'),
161                              Param(datatype='Long',
162                                    name='created'),
163                              Param(datatype='Boolean',
164                                    name='isBookmark'),
165                              Param(datatype='Long',
166                                    name='date'),
167                              Param(datatype='byte[]',
168                                    name='favicon'),
169                              Param(datatype='String',
170                                    name='title'),
171                              Param(datatype='Integer',
172                                    name='visits')],
173                      java_class_name=None,
174                      type='method',
175                      p0_type='ChromeBrowserProvider'),
176         NativeMethod(return_type='int', static=False,
177                      name='FindAll',
178                      params=[Param(datatype='String',
179                                    name='find')],
180                      java_class_name=None,
181                      type='function'),
182         NativeMethod(return_type='OnFrameAvailableListener', static=True,
183                      name='GetInnerClass',
184                      params=[],
185                      java_class_name=None,
186                      type='function'),
187         NativeMethod(return_type='Bitmap',
188                      static=False,
189                      name='QueryBitmap',
190                      params=[Param(datatype='int',
191                                    name='nativeChromeBrowserProvider'),
192                              Param(datatype='String[]',
193                                    name='projection'),
194                              Param(datatype='String',
195                                    name='selection'),
196                              Param(datatype='String[]',
197                                    name='selectionArgs'),
198                              Param(datatype='String',
199                                    name='sortOrder'),
200                             ],
201                      java_class_name=None,
202                      type='method',
203                      p0_type='ChromeBrowserProvider'),
204         NativeMethod(return_type='void', static=False,
205                      name='GotOrientation',
206                      params=[Param(datatype='int',
207                                    name='nativeDataFetcherImplAndroid'),
208                              Param(datatype='double',
209                                    name='alpha'),
210                              Param(datatype='double',
211                                    name='beta'),
212                              Param(datatype='double',
213                                    name='gamma'),
214                             ],
215                      java_class_name=None,
216                      type='method',
217                      p0_type='content::DataFetcherImplAndroid'),
218     ]
219     self.assertListEquals(golden_natives, natives)
220     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
221                                              natives, [], TestOptions())
222     golden_content = """\
223 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
224 // Use of this source code is governed by a BSD-style license that can be
225 // found in the LICENSE file.
226
227 // This file is autogenerated by
228 //     base/android/jni_generator/jni_generator.py
229 // For
230 //     org/chromium/TestJni
231
232 #ifndef org_chromium_TestJni_JNI
233 #define org_chromium_TestJni_JNI
234
235 #include <jni.h>
236
237 #include "base/android/jni_android.h"
238 #include "base/android/scoped_java_ref.h"
239 #include "base/basictypes.h"
240 #include "base/logging.h"
241
242 using base::android::ScopedJavaLocalRef;
243
244 // Step 1: forward declarations.
245 namespace {
246 const char kTestJniClassPath[] = "org/chromium/TestJni";
247 // Leaking this jclass as we cannot use LazyInstance from some threads.
248 jclass g_TestJni_clazz = NULL;
249 }  // namespace
250
251 static jint Init(JNIEnv* env, jobject obj);
252
253 static jstring GetDomainAndRegistry(JNIEnv* env, jclass clazz,
254     jstring url);
255
256 static void CreateHistoricalTabFromState(JNIEnv* env, jclass clazz,
257     jbyteArray state,
258     jint tab_index);
259
260 static jbyteArray GetStateAsByteArray(JNIEnv* env, jobject obj,
261     jobject view);
262
263 static jobjectArray GetAutofillProfileGUIDs(JNIEnv* env, jclass clazz);
264
265 static void SetRecognitionResults(JNIEnv* env, jobject obj,
266     jint sessionId,
267     jobjectArray results);
268
269 static jint FindAll(JNIEnv* env, jobject obj,
270     jstring find);
271
272 static jobject GetInnerClass(JNIEnv* env, jclass clazz);
273
274 // Step 2: method stubs.
275 static void Destroy(JNIEnv* env, jobject obj,
276     jint nativeChromeBrowserProvider) {
277   DCHECK(nativeChromeBrowserProvider) << "Destroy";
278   ChromeBrowserProvider* native =
279       reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
280   return native->Destroy(env, obj);
281 }
282
283 static jlong AddBookmark(JNIEnv* env, jobject obj,
284     jint nativeChromeBrowserProvider,
285     jstring url,
286     jstring title,
287     jboolean isFolder,
288     jlong parentId) {
289   DCHECK(nativeChromeBrowserProvider) << "AddBookmark";
290   ChromeBrowserProvider* native =
291       reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
292   return native->AddBookmark(env, obj, url, title, isFolder, parentId);
293 }
294
295 static jlong AddBookmarkFromAPI(JNIEnv* env, jobject obj,
296     jint nativeChromeBrowserProvider,
297     jstring url,
298     jobject created,
299     jobject isBookmark,
300     jobject date,
301     jbyteArray favicon,
302     jstring title,
303     jobject visits) {
304   DCHECK(nativeChromeBrowserProvider) << "AddBookmarkFromAPI";
305   ChromeBrowserProvider* native =
306       reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
307   return native->AddBookmarkFromAPI(env, obj, url, created, isBookmark, date,
308       favicon, title, visits);
309 }
310
311 static jobject QueryBitmap(JNIEnv* env, jobject obj,
312     jint nativeChromeBrowserProvider,
313     jobjectArray projection,
314     jstring selection,
315     jobjectArray selectionArgs,
316     jstring sortOrder) {
317   DCHECK(nativeChromeBrowserProvider) << "QueryBitmap";
318   ChromeBrowserProvider* native =
319       reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
320   return native->QueryBitmap(env, obj, projection, selection, selectionArgs,
321       sortOrder).Release();
322 }
323
324 static void GotOrientation(JNIEnv* env, jobject obj,
325     jint nativeDataFetcherImplAndroid,
326     jdouble alpha,
327     jdouble beta,
328     jdouble gamma) {
329   DCHECK(nativeDataFetcherImplAndroid) << "GotOrientation";
330   DataFetcherImplAndroid* native =
331       reinterpret_cast<DataFetcherImplAndroid*>(nativeDataFetcherImplAndroid);
332   return native->GotOrientation(env, obj, alpha, beta, gamma);
333 }
334
335 // Step 3: RegisterNatives.
336
337 static bool RegisterNativesImpl(JNIEnv* env) {
338
339   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
340       base::android::GetClass(env, kTestJniClassPath).obj()));
341   static const JNINativeMethod kMethodsTestJni[] = {
342     { "nativeInit",
343 "("
344 ")"
345 "I", reinterpret_cast<void*>(Init) },
346     { "nativeDestroy",
347 "("
348 "I"
349 ")"
350 "V", reinterpret_cast<void*>(Destroy) },
351     { "nativeAddBookmark",
352 "("
353 "I"
354 "Ljava/lang/String;"
355 "Ljava/lang/String;"
356 "Z"
357 "J"
358 ")"
359 "J", reinterpret_cast<void*>(AddBookmark) },
360     { "nativeGetDomainAndRegistry",
361 "("
362 "Ljava/lang/String;"
363 ")"
364 "Ljava/lang/String;", reinterpret_cast<void*>(GetDomainAndRegistry) },
365     { "nativeCreateHistoricalTabFromState",
366 "("
367 "[B"
368 "I"
369 ")"
370 "V", reinterpret_cast<void*>(CreateHistoricalTabFromState) },
371     { "nativeGetStateAsByteArray",
372 "("
373 "Landroid/view/View;"
374 ")"
375 "[B", reinterpret_cast<void*>(GetStateAsByteArray) },
376     { "nativeGetAutofillProfileGUIDs",
377 "("
378 ")"
379 "[Ljava/lang/String;", reinterpret_cast<void*>(GetAutofillProfileGUIDs) },
380     { "nativeSetRecognitionResults",
381 "("
382 "I"
383 "[Ljava/lang/String;"
384 ")"
385 "V", reinterpret_cast<void*>(SetRecognitionResults) },
386     { "nativeAddBookmarkFromAPI",
387 "("
388 "I"
389 "Ljava/lang/String;"
390 "Ljava/lang/Long;"
391 "Ljava/lang/Boolean;"
392 "Ljava/lang/Long;"
393 "[B"
394 "Ljava/lang/String;"
395 "Ljava/lang/Integer;"
396 ")"
397 "J", reinterpret_cast<void*>(AddBookmarkFromAPI) },
398     { "nativeFindAll",
399 "("
400 "Ljava/lang/String;"
401 ")"
402 "I", reinterpret_cast<void*>(FindAll) },
403     { "nativeGetInnerClass",
404 "("
405 ")"
406 "Lorg/chromium/example/jni_generator/SampleForTests$OnFrameAvailableListener;",
407     reinterpret_cast<void*>(GetInnerClass) },
408     { "nativeQueryBitmap",
409 "("
410 "I"
411 "[Ljava/lang/String;"
412 "Ljava/lang/String;"
413 "[Ljava/lang/String;"
414 "Ljava/lang/String;"
415 ")"
416 "Landroid/graphics/Bitmap;", reinterpret_cast<void*>(QueryBitmap) },
417     { "nativeGotOrientation",
418 "("
419 "I"
420 "D"
421 "D"
422 "D"
423 ")"
424 "V", reinterpret_cast<void*>(GotOrientation) },
425   };
426   const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
427
428   if (env->RegisterNatives(g_TestJni_clazz,
429                            kMethodsTestJni,
430                            kMethodsTestJniSize) < 0) {
431     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
432     return false;
433   }
434
435   return true;
436 }
437
438 #endif  // org_chromium_TestJni_JNI
439 """
440     self.assertTextEquals(golden_content, h.GetContent())
441
442   def testInnerClassNatives(self):
443     test_data = """
444     class MyInnerClass {
445       @NativeCall("MyInnerClass")
446       private native int nativeInit();
447     }
448     """
449     natives = jni_generator.ExtractNatives(test_data, 'int')
450     golden_natives = [
451         NativeMethod(return_type='int', static=False,
452                      name='Init', params=[],
453                      java_class_name='MyInnerClass',
454                      type='function')
455     ]
456     self.assertListEquals(golden_natives, natives)
457     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
458                                              natives, [], TestOptions())
459     golden_content = """\
460 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
461 // Use of this source code is governed by a BSD-style license that can be
462 // found in the LICENSE file.
463
464 // This file is autogenerated by
465 //     base/android/jni_generator/jni_generator.py
466 // For
467 //     org/chromium/TestJni
468
469 #ifndef org_chromium_TestJni_JNI
470 #define org_chromium_TestJni_JNI
471
472 #include <jni.h>
473
474 #include "base/android/jni_android.h"
475 #include "base/android/scoped_java_ref.h"
476 #include "base/basictypes.h"
477 #include "base/logging.h"
478
479 using base::android::ScopedJavaLocalRef;
480
481 // Step 1: forward declarations.
482 namespace {
483 const char kTestJniClassPath[] = "org/chromium/TestJni";
484 const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass";
485 // Leaking this jclass as we cannot use LazyInstance from some threads.
486 jclass g_TestJni_clazz = NULL;
487 }  // namespace
488
489 static jint Init(JNIEnv* env, jobject obj);
490
491 // Step 2: method stubs.
492
493 // Step 3: RegisterNatives.
494
495 static bool RegisterNativesImpl(JNIEnv* env) {
496
497   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
498       base::android::GetClass(env, kTestJniClassPath).obj()));
499   static const JNINativeMethod kMethodsMyInnerClass[] = {
500     { "nativeInit",
501 "("
502 ")"
503 "I", reinterpret_cast<void*>(Init) },
504   };
505   const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass);
506
507   if (env->RegisterNatives(g_MyInnerClass_clazz,
508                            kMethodsMyInnerClass,
509                            kMethodsMyInnerClassSize) < 0) {
510     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
511     return false;
512   }
513
514   return true;
515 }
516
517 #endif  // org_chromium_TestJni_JNI
518 """
519     self.assertTextEquals(golden_content, h.GetContent())
520
521   def testInnerClassNativesMultiple(self):
522     test_data = """
523     class MyInnerClass {
524       @NativeCall("MyInnerClass")
525       private native int nativeInit();
526     }
527     class MyOtherInnerClass {
528       @NativeCall("MyOtherInnerClass")
529       private native int nativeInit();
530     }
531     """
532     natives = jni_generator.ExtractNatives(test_data, 'int')
533     golden_natives = [
534         NativeMethod(return_type='int', static=False,
535                      name='Init', params=[],
536                      java_class_name='MyInnerClass',
537                      type='function'),
538         NativeMethod(return_type='int', static=False,
539                      name='Init', params=[],
540                      java_class_name='MyOtherInnerClass',
541                      type='function')
542     ]
543     self.assertListEquals(golden_natives, natives)
544     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
545                                              natives, [], TestOptions())
546     golden_content = """\
547 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
548 // Use of this source code is governed by a BSD-style license that can be
549 // found in the LICENSE file.
550
551 // This file is autogenerated by
552 //     base/android/jni_generator/jni_generator.py
553 // For
554 //     org/chromium/TestJni
555
556 #ifndef org_chromium_TestJni_JNI
557 #define org_chromium_TestJni_JNI
558
559 #include <jni.h>
560
561 #include "base/android/jni_android.h"
562 #include "base/android/scoped_java_ref.h"
563 #include "base/basictypes.h"
564 #include "base/logging.h"
565
566 using base::android::ScopedJavaLocalRef;
567
568 // Step 1: forward declarations.
569 namespace {
570 const char kMyOtherInnerClassClassPath[] =
571     "org/chromium/TestJni$MyOtherInnerClass";
572 const char kTestJniClassPath[] = "org/chromium/TestJni";
573 const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass";
574 // Leaking this jclass as we cannot use LazyInstance from some threads.
575 jclass g_TestJni_clazz = NULL;
576 }  // namespace
577
578 static jint Init(JNIEnv* env, jobject obj);
579
580 static jint Init(JNIEnv* env, jobject obj);
581
582 // Step 2: method stubs.
583
584 // Step 3: RegisterNatives.
585
586 static bool RegisterNativesImpl(JNIEnv* env) {
587
588   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
589       base::android::GetClass(env, kTestJniClassPath).obj()));
590   static const JNINativeMethod kMethodsMyOtherInnerClass[] = {
591     { "nativeInit",
592 "("
593 ")"
594 "I", reinterpret_cast<void*>(Init) },
595   };
596   const int kMethodsMyOtherInnerClassSize =
597       arraysize(kMethodsMyOtherInnerClass);
598
599   if (env->RegisterNatives(g_MyOtherInnerClass_clazz,
600                            kMethodsMyOtherInnerClass,
601                            kMethodsMyOtherInnerClassSize) < 0) {
602     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
603     return false;
604   }
605
606   static const JNINativeMethod kMethodsMyInnerClass[] = {
607     { "nativeInit",
608 "("
609 ")"
610 "I", reinterpret_cast<void*>(Init) },
611   };
612   const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass);
613
614   if (env->RegisterNatives(g_MyInnerClass_clazz,
615                            kMethodsMyInnerClass,
616                            kMethodsMyInnerClassSize) < 0) {
617     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
618     return false;
619   }
620
621   return true;
622 }
623
624 #endif  // org_chromium_TestJni_JNI
625 """
626     self.assertTextEquals(golden_content, h.GetContent())
627
628   def testInnerClassNativesBothInnerAndOuter(self):
629     test_data = """
630     class MyOuterClass {
631       private native int nativeInit();
632       class MyOtherInnerClass {
633         @NativeCall("MyOtherInnerClass")
634         private native int nativeInit();
635       }
636     }
637     """
638     natives = jni_generator.ExtractNatives(test_data, 'int')
639     golden_natives = [
640         NativeMethod(return_type='int', static=False,
641                      name='Init', params=[],
642                      java_class_name=None,
643                      type='function'),
644         NativeMethod(return_type='int', static=False,
645                      name='Init', params=[],
646                      java_class_name='MyOtherInnerClass',
647                      type='function')
648     ]
649     self.assertListEquals(golden_natives, natives)
650     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
651                                              natives, [], TestOptions())
652     golden_content = """\
653 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
654 // Use of this source code is governed by a BSD-style license that can be
655 // found in the LICENSE file.
656
657 // This file is autogenerated by
658 //     base/android/jni_generator/jni_generator.py
659 // For
660 //     org/chromium/TestJni
661
662 #ifndef org_chromium_TestJni_JNI
663 #define org_chromium_TestJni_JNI
664
665 #include <jni.h>
666
667 #include "base/android/jni_android.h"
668 #include "base/android/scoped_java_ref.h"
669 #include "base/basictypes.h"
670 #include "base/logging.h"
671
672 using base::android::ScopedJavaLocalRef;
673
674 // Step 1: forward declarations.
675 namespace {
676 const char kMyOtherInnerClassClassPath[] =
677     "org/chromium/TestJni$MyOtherInnerClass";
678 const char kTestJniClassPath[] = "org/chromium/TestJni";
679 // Leaking this jclass as we cannot use LazyInstance from some threads.
680 jclass g_TestJni_clazz = NULL;
681 }  // namespace
682
683 static jint Init(JNIEnv* env, jobject obj);
684
685 static jint Init(JNIEnv* env, jobject obj);
686
687 // Step 2: method stubs.
688
689 // Step 3: RegisterNatives.
690
691 static bool RegisterNativesImpl(JNIEnv* env) {
692
693   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
694       base::android::GetClass(env, kTestJniClassPath).obj()));
695   static const JNINativeMethod kMethodsMyOtherInnerClass[] = {
696     { "nativeInit",
697 "("
698 ")"
699 "I", reinterpret_cast<void*>(Init) },
700   };
701   const int kMethodsMyOtherInnerClassSize =
702       arraysize(kMethodsMyOtherInnerClass);
703
704   if (env->RegisterNatives(g_MyOtherInnerClass_clazz,
705                            kMethodsMyOtherInnerClass,
706                            kMethodsMyOtherInnerClassSize) < 0) {
707     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
708     return false;
709   }
710
711   static const JNINativeMethod kMethodsTestJni[] = {
712     { "nativeInit",
713 "("
714 ")"
715 "I", reinterpret_cast<void*>(Init) },
716   };
717   const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
718
719   if (env->RegisterNatives(g_TestJni_clazz,
720                            kMethodsTestJni,
721                            kMethodsTestJniSize) < 0) {
722     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
723     return false;
724   }
725
726   return true;
727 }
728
729 #endif  // org_chromium_TestJni_JNI
730 """
731     self.assertTextEquals(golden_content, h.GetContent())
732
733   def testCalledByNatives(self):
734     test_data = """"
735     import android.graphics.Bitmap;
736     import android.view.View;
737     import java.io.InputStream;
738     import java.util.List;
739
740     class InnerClass {}
741
742     @CalledByNative
743     InnerClass showConfirmInfoBar(int nativeInfoBar,
744             String buttonOk, String buttonCancel, String title, Bitmap icon) {
745         InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext,
746                                              buttonOk, buttonCancel,
747                                              title, icon);
748         return infobar;
749     }
750     @CalledByNative
751     InnerClass showAutoLoginInfoBar(int nativeInfoBar,
752             String realm, String account, String args) {
753         AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext,
754                 realm, account, args);
755         if (infobar.displayedAccountCount() == 0)
756             infobar = null;
757         return infobar;
758     }
759     @CalledByNative("InfoBar")
760     void dismiss();
761     @SuppressWarnings("unused")
762     @CalledByNative
763     private static boolean shouldShowAutoLogin(View view,
764             String realm, String account, String args) {
765         AccountManagerContainer accountManagerContainer =
766             new AccountManagerContainer((Activity)contentView.getContext(),
767             realm, account, args);
768         String[] logins = accountManagerContainer.getAccountLogins(null);
769         return logins.length != 0;
770     }
771     @CalledByNative
772     static InputStream openUrl(String url) {
773         return null;
774     }
775     @CalledByNative
776     private void activateHardwareAcceleration(final boolean activated,
777             final int iPid, final int iType,
778             final int iPrimaryID, final int iSecondaryID) {
779       if (!activated) {
780           return
781       }
782     }
783     @CalledByNativeUnchecked
784     private void uncheckedCall(int iParam);
785
786     @CalledByNative
787     public byte[] returnByteArray();
788
789     @CalledByNative
790     public boolean[] returnBooleanArray();
791
792     @CalledByNative
793     public char[] returnCharArray();
794
795     @CalledByNative
796     public short[] returnShortArray();
797
798     @CalledByNative
799     public int[] returnIntArray();
800
801     @CalledByNative
802     public long[] returnLongArray();
803
804     @CalledByNative
805     public double[] returnDoubleArray();
806
807     @CalledByNative
808     public Object[] returnObjectArray();
809
810     @CalledByNative
811     public byte[][] returnArrayOfByteArray();
812
813     @CalledByNative
814     public Bitmap.CompressFormat getCompressFormat();
815
816     @CalledByNative
817     public List<Bitmap.CompressFormat> getCompressFormatList();
818     """
819     jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo')
820     jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
821     called_by_natives = jni_generator.ExtractCalledByNatives(test_data)
822     golden_called_by_natives = [
823         CalledByNative(
824             return_type='InnerClass',
825             system_class=False,
826             static=False,
827             name='showConfirmInfoBar',
828             method_id_var_name='showConfirmInfoBar',
829             java_class_name='',
830             params=[Param(datatype='int', name='nativeInfoBar'),
831                     Param(datatype='String', name='buttonOk'),
832                     Param(datatype='String', name='buttonCancel'),
833                     Param(datatype='String', name='title'),
834                     Param(datatype='Bitmap', name='icon')],
835             env_call=('Object', ''),
836             unchecked=False,
837         ),
838         CalledByNative(
839             return_type='InnerClass',
840             system_class=False,
841             static=False,
842             name='showAutoLoginInfoBar',
843             method_id_var_name='showAutoLoginInfoBar',
844             java_class_name='',
845             params=[Param(datatype='int', name='nativeInfoBar'),
846                     Param(datatype='String', name='realm'),
847                     Param(datatype='String', name='account'),
848                     Param(datatype='String', name='args')],
849             env_call=('Object', ''),
850             unchecked=False,
851         ),
852         CalledByNative(
853             return_type='void',
854             system_class=False,
855             static=False,
856             name='dismiss',
857             method_id_var_name='dismiss',
858             java_class_name='InfoBar',
859             params=[],
860             env_call=('Void', ''),
861             unchecked=False,
862         ),
863         CalledByNative(
864             return_type='boolean',
865             system_class=False,
866             static=True,
867             name='shouldShowAutoLogin',
868             method_id_var_name='shouldShowAutoLogin',
869             java_class_name='',
870             params=[Param(datatype='View', name='view'),
871                     Param(datatype='String', name='realm'),
872                     Param(datatype='String', name='account'),
873                     Param(datatype='String', name='args')],
874             env_call=('Boolean', ''),
875             unchecked=False,
876         ),
877         CalledByNative(
878             return_type='InputStream',
879             system_class=False,
880             static=True,
881             name='openUrl',
882             method_id_var_name='openUrl',
883             java_class_name='',
884             params=[Param(datatype='String', name='url')],
885             env_call=('Object', ''),
886             unchecked=False,
887         ),
888         CalledByNative(
889             return_type='void',
890             system_class=False,
891             static=False,
892             name='activateHardwareAcceleration',
893             method_id_var_name='activateHardwareAcceleration',
894             java_class_name='',
895             params=[Param(datatype='boolean', name='activated'),
896                     Param(datatype='int', name='iPid'),
897                     Param(datatype='int', name='iType'),
898                     Param(datatype='int', name='iPrimaryID'),
899                     Param(datatype='int', name='iSecondaryID'),
900                    ],
901             env_call=('Void', ''),
902             unchecked=False,
903         ),
904         CalledByNative(
905             return_type='void',
906             system_class=False,
907             static=False,
908             name='uncheckedCall',
909             method_id_var_name='uncheckedCall',
910             java_class_name='',
911             params=[Param(datatype='int', name='iParam')],
912             env_call=('Void', ''),
913             unchecked=True,
914         ),
915         CalledByNative(
916             return_type='byte[]',
917             system_class=False,
918             static=False,
919             name='returnByteArray',
920             method_id_var_name='returnByteArray',
921             java_class_name='',
922             params=[],
923             env_call=('Void', ''),
924             unchecked=False,
925         ),
926         CalledByNative(
927             return_type='boolean[]',
928             system_class=False,
929             static=False,
930             name='returnBooleanArray',
931             method_id_var_name='returnBooleanArray',
932             java_class_name='',
933             params=[],
934             env_call=('Void', ''),
935             unchecked=False,
936         ),
937         CalledByNative(
938             return_type='char[]',
939             system_class=False,
940             static=False,
941             name='returnCharArray',
942             method_id_var_name='returnCharArray',
943             java_class_name='',
944             params=[],
945             env_call=('Void', ''),
946             unchecked=False,
947         ),
948         CalledByNative(
949             return_type='short[]',
950             system_class=False,
951             static=False,
952             name='returnShortArray',
953             method_id_var_name='returnShortArray',
954             java_class_name='',
955             params=[],
956             env_call=('Void', ''),
957             unchecked=False,
958         ),
959         CalledByNative(
960             return_type='int[]',
961             system_class=False,
962             static=False,
963             name='returnIntArray',
964             method_id_var_name='returnIntArray',
965             java_class_name='',
966             params=[],
967             env_call=('Void', ''),
968             unchecked=False,
969         ),
970         CalledByNative(
971             return_type='long[]',
972             system_class=False,
973             static=False,
974             name='returnLongArray',
975             method_id_var_name='returnLongArray',
976             java_class_name='',
977             params=[],
978             env_call=('Void', ''),
979             unchecked=False,
980         ),
981         CalledByNative(
982             return_type='double[]',
983             system_class=False,
984             static=False,
985             name='returnDoubleArray',
986             method_id_var_name='returnDoubleArray',
987             java_class_name='',
988             params=[],
989             env_call=('Void', ''),
990             unchecked=False,
991         ),
992         CalledByNative(
993             return_type='Object[]',
994             system_class=False,
995             static=False,
996             name='returnObjectArray',
997             method_id_var_name='returnObjectArray',
998             java_class_name='',
999             params=[],
1000             env_call=('Void', ''),
1001             unchecked=False,
1002         ),
1003         CalledByNative(
1004             return_type='byte[][]',
1005             system_class=False,
1006             static=False,
1007             name='returnArrayOfByteArray',
1008             method_id_var_name='returnArrayOfByteArray',
1009             java_class_name='',
1010             params=[],
1011             env_call=('Void', ''),
1012             unchecked=False,
1013         ),
1014         CalledByNative(
1015             return_type='Bitmap.CompressFormat',
1016             system_class=False,
1017             static=False,
1018             name='getCompressFormat',
1019             method_id_var_name='getCompressFormat',
1020             java_class_name='',
1021             params=[],
1022             env_call=('Void', ''),
1023             unchecked=False,
1024         ),
1025         CalledByNative(
1026             return_type='List<Bitmap.CompressFormat>',
1027             system_class=False,
1028             static=False,
1029             name='getCompressFormatList',
1030             method_id_var_name='getCompressFormatList',
1031             java_class_name='',
1032             params=[],
1033             env_call=('Void', ''),
1034             unchecked=False,
1035         ),
1036     ]
1037     self.assertListEquals(golden_called_by_natives, called_by_natives)
1038     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
1039                                              [], called_by_natives,
1040                                              TestOptions())
1041     golden_content = """\
1042 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
1043 // Use of this source code is governed by a BSD-style license that can be
1044 // found in the LICENSE file.
1045
1046 // This file is autogenerated by
1047 //     base/android/jni_generator/jni_generator.py
1048 // For
1049 //     org/chromium/TestJni
1050
1051 #ifndef org_chromium_TestJni_JNI
1052 #define org_chromium_TestJni_JNI
1053
1054 #include <jni.h>
1055
1056 #include "base/android/jni_android.h"
1057 #include "base/android/scoped_java_ref.h"
1058 #include "base/basictypes.h"
1059 #include "base/logging.h"
1060
1061 using base::android::ScopedJavaLocalRef;
1062
1063 // Step 1: forward declarations.
1064 namespace {
1065 const char kTestJniClassPath[] = "org/chromium/TestJni";
1066 const char kInfoBarClassPath[] = "org/chromium/TestJni$InfoBar";
1067 // Leaking this jclass as we cannot use LazyInstance from some threads.
1068 jclass g_TestJni_clazz = NULL;
1069 // Leaking this jclass as we cannot use LazyInstance from some threads.
1070 jclass g_InfoBar_clazz = NULL;
1071 }  // namespace
1072
1073 // Step 2: method stubs.
1074
1075 static base::subtle::AtomicWord g_TestJni_showConfirmInfoBar = 0;
1076 static ScopedJavaLocalRef<jobject> Java_TestJni_showConfirmInfoBar(JNIEnv* env,
1077     jobject obj, jint nativeInfoBar,
1078     jstring buttonOk,
1079     jstring buttonCancel,
1080     jstring title,
1081     jobject icon) {
1082   /* Must call RegisterNativesImpl()  */
1083   DCHECK(g_TestJni_clazz);
1084   jmethodID method_id =
1085       base::android::MethodID::LazyGet<
1086       base::android::MethodID::TYPE_INSTANCE>(
1087       env, g_TestJni_clazz,
1088       "showConfirmInfoBar",
1089
1090 "("
1091 "I"
1092 "Ljava/lang/String;"
1093 "Ljava/lang/String;"
1094 "Ljava/lang/String;"
1095 "Landroid/graphics/Bitmap;"
1096 ")"
1097 "Lorg/chromium/Foo$InnerClass;",
1098       &g_TestJni_showConfirmInfoBar);
1099
1100   jobject ret =
1101     env->CallObjectMethod(obj,
1102       method_id, nativeInfoBar, buttonOk, buttonCancel, title, icon);
1103   base::android::CheckException(env);
1104   return ScopedJavaLocalRef<jobject>(env, ret);
1105 }
1106
1107 static base::subtle::AtomicWord g_TestJni_showAutoLoginInfoBar = 0;
1108 static ScopedJavaLocalRef<jobject> Java_TestJni_showAutoLoginInfoBar(JNIEnv*
1109     env, jobject obj, jint nativeInfoBar,
1110     jstring realm,
1111     jstring account,
1112     jstring args) {
1113   /* Must call RegisterNativesImpl()  */
1114   DCHECK(g_TestJni_clazz);
1115   jmethodID method_id =
1116       base::android::MethodID::LazyGet<
1117       base::android::MethodID::TYPE_INSTANCE>(
1118       env, g_TestJni_clazz,
1119       "showAutoLoginInfoBar",
1120
1121 "("
1122 "I"
1123 "Ljava/lang/String;"
1124 "Ljava/lang/String;"
1125 "Ljava/lang/String;"
1126 ")"
1127 "Lorg/chromium/Foo$InnerClass;",
1128       &g_TestJni_showAutoLoginInfoBar);
1129
1130   jobject ret =
1131     env->CallObjectMethod(obj,
1132       method_id, nativeInfoBar, realm, account, args);
1133   base::android::CheckException(env);
1134   return ScopedJavaLocalRef<jobject>(env, ret);
1135 }
1136
1137 static base::subtle::AtomicWord g_InfoBar_dismiss = 0;
1138 static void Java_InfoBar_dismiss(JNIEnv* env, jobject obj) {
1139   /* Must call RegisterNativesImpl()  */
1140   DCHECK(g_InfoBar_clazz);
1141   jmethodID method_id =
1142       base::android::MethodID::LazyGet<
1143       base::android::MethodID::TYPE_INSTANCE>(
1144       env, g_InfoBar_clazz,
1145       "dismiss",
1146
1147 "("
1148 ")"
1149 "V",
1150       &g_InfoBar_dismiss);
1151
1152   env->CallVoidMethod(obj,
1153       method_id);
1154   base::android::CheckException(env);
1155
1156 }
1157
1158 static base::subtle::AtomicWord g_TestJni_shouldShowAutoLogin = 0;
1159 static jboolean Java_TestJni_shouldShowAutoLogin(JNIEnv* env, jobject view,
1160     jstring realm,
1161     jstring account,
1162     jstring args) {
1163   /* Must call RegisterNativesImpl()  */
1164   DCHECK(g_TestJni_clazz);
1165   jmethodID method_id =
1166       base::android::MethodID::LazyGet<
1167       base::android::MethodID::TYPE_STATIC>(
1168       env, g_TestJni_clazz,
1169       "shouldShowAutoLogin",
1170
1171 "("
1172 "Landroid/view/View;"
1173 "Ljava/lang/String;"
1174 "Ljava/lang/String;"
1175 "Ljava/lang/String;"
1176 ")"
1177 "Z",
1178       &g_TestJni_shouldShowAutoLogin);
1179
1180   jboolean ret =
1181     env->CallStaticBooleanMethod(g_TestJni_clazz,
1182       method_id, view, realm, account, args);
1183   base::android::CheckException(env);
1184   return ret;
1185 }
1186
1187 static base::subtle::AtomicWord g_TestJni_openUrl = 0;
1188 static ScopedJavaLocalRef<jobject> Java_TestJni_openUrl(JNIEnv* env, jstring
1189     url) {
1190   /* Must call RegisterNativesImpl()  */
1191   DCHECK(g_TestJni_clazz);
1192   jmethodID method_id =
1193       base::android::MethodID::LazyGet<
1194       base::android::MethodID::TYPE_STATIC>(
1195       env, g_TestJni_clazz,
1196       "openUrl",
1197
1198 "("
1199 "Ljava/lang/String;"
1200 ")"
1201 "Ljava/io/InputStream;",
1202       &g_TestJni_openUrl);
1203
1204   jobject ret =
1205     env->CallStaticObjectMethod(g_TestJni_clazz,
1206       method_id, url);
1207   base::android::CheckException(env);
1208   return ScopedJavaLocalRef<jobject>(env, ret);
1209 }
1210
1211 static base::subtle::AtomicWord g_TestJni_activateHardwareAcceleration = 0;
1212 static void Java_TestJni_activateHardwareAcceleration(JNIEnv* env, jobject obj,
1213     jboolean activated,
1214     jint iPid,
1215     jint iType,
1216     jint iPrimaryID,
1217     jint iSecondaryID) {
1218   /* Must call RegisterNativesImpl()  */
1219   DCHECK(g_TestJni_clazz);
1220   jmethodID method_id =
1221       base::android::MethodID::LazyGet<
1222       base::android::MethodID::TYPE_INSTANCE>(
1223       env, g_TestJni_clazz,
1224       "activateHardwareAcceleration",
1225
1226 "("
1227 "Z"
1228 "I"
1229 "I"
1230 "I"
1231 "I"
1232 ")"
1233 "V",
1234       &g_TestJni_activateHardwareAcceleration);
1235
1236   env->CallVoidMethod(obj,
1237       method_id, activated, iPid, iType, iPrimaryID, iSecondaryID);
1238   base::android::CheckException(env);
1239
1240 }
1241
1242 static base::subtle::AtomicWord g_TestJni_uncheckedCall = 0;
1243 static void Java_TestJni_uncheckedCall(JNIEnv* env, jobject obj, jint iParam) {
1244   /* Must call RegisterNativesImpl()  */
1245   DCHECK(g_TestJni_clazz);
1246   jmethodID method_id =
1247       base::android::MethodID::LazyGet<
1248       base::android::MethodID::TYPE_INSTANCE>(
1249       env, g_TestJni_clazz,
1250       "uncheckedCall",
1251
1252 "("
1253 "I"
1254 ")"
1255 "V",
1256       &g_TestJni_uncheckedCall);
1257
1258   env->CallVoidMethod(obj,
1259       method_id, iParam);
1260
1261 }
1262
1263 static base::subtle::AtomicWord g_TestJni_returnByteArray = 0;
1264 static ScopedJavaLocalRef<jbyteArray> Java_TestJni_returnByteArray(JNIEnv* env,
1265     jobject obj) {
1266   /* Must call RegisterNativesImpl()  */
1267   DCHECK(g_TestJni_clazz);
1268   jmethodID method_id =
1269       base::android::MethodID::LazyGet<
1270       base::android::MethodID::TYPE_INSTANCE>(
1271       env, g_TestJni_clazz,
1272       "returnByteArray",
1273
1274 "("
1275 ")"
1276 "[B",
1277       &g_TestJni_returnByteArray);
1278
1279   jbyteArray ret =
1280     static_cast<jbyteArray>(env->CallObjectMethod(obj,
1281       method_id));
1282   base::android::CheckException(env);
1283   return ScopedJavaLocalRef<jbyteArray>(env, ret);
1284 }
1285
1286 static base::subtle::AtomicWord g_TestJni_returnBooleanArray = 0;
1287 static ScopedJavaLocalRef<jbooleanArray> Java_TestJni_returnBooleanArray(JNIEnv*
1288     env, jobject obj) {
1289   /* Must call RegisterNativesImpl()  */
1290   DCHECK(g_TestJni_clazz);
1291   jmethodID method_id =
1292       base::android::MethodID::LazyGet<
1293       base::android::MethodID::TYPE_INSTANCE>(
1294       env, g_TestJni_clazz,
1295       "returnBooleanArray",
1296
1297 "("
1298 ")"
1299 "[Z",
1300       &g_TestJni_returnBooleanArray);
1301
1302   jbooleanArray ret =
1303     static_cast<jbooleanArray>(env->CallObjectMethod(obj,
1304       method_id));
1305   base::android::CheckException(env);
1306   return ScopedJavaLocalRef<jbooleanArray>(env, ret);
1307 }
1308
1309 static base::subtle::AtomicWord g_TestJni_returnCharArray = 0;
1310 static ScopedJavaLocalRef<jcharArray> Java_TestJni_returnCharArray(JNIEnv* env,
1311     jobject obj) {
1312   /* Must call RegisterNativesImpl()  */
1313   DCHECK(g_TestJni_clazz);
1314   jmethodID method_id =
1315       base::android::MethodID::LazyGet<
1316       base::android::MethodID::TYPE_INSTANCE>(
1317       env, g_TestJni_clazz,
1318       "returnCharArray",
1319
1320 "("
1321 ")"
1322 "[C",
1323       &g_TestJni_returnCharArray);
1324
1325   jcharArray ret =
1326     static_cast<jcharArray>(env->CallObjectMethod(obj,
1327       method_id));
1328   base::android::CheckException(env);
1329   return ScopedJavaLocalRef<jcharArray>(env, ret);
1330 }
1331
1332 static base::subtle::AtomicWord g_TestJni_returnShortArray = 0;
1333 static ScopedJavaLocalRef<jshortArray> Java_TestJni_returnShortArray(JNIEnv*
1334     env, jobject obj) {
1335   /* Must call RegisterNativesImpl()  */
1336   DCHECK(g_TestJni_clazz);
1337   jmethodID method_id =
1338       base::android::MethodID::LazyGet<
1339       base::android::MethodID::TYPE_INSTANCE>(
1340       env, g_TestJni_clazz,
1341       "returnShortArray",
1342
1343 "("
1344 ")"
1345 "[S",
1346       &g_TestJni_returnShortArray);
1347
1348   jshortArray ret =
1349     static_cast<jshortArray>(env->CallObjectMethod(obj,
1350       method_id));
1351   base::android::CheckException(env);
1352   return ScopedJavaLocalRef<jshortArray>(env, ret);
1353 }
1354
1355 static base::subtle::AtomicWord g_TestJni_returnIntArray = 0;
1356 static ScopedJavaLocalRef<jintArray> Java_TestJni_returnIntArray(JNIEnv* env,
1357     jobject obj) {
1358   /* Must call RegisterNativesImpl()  */
1359   DCHECK(g_TestJni_clazz);
1360   jmethodID method_id =
1361       base::android::MethodID::LazyGet<
1362       base::android::MethodID::TYPE_INSTANCE>(
1363       env, g_TestJni_clazz,
1364       "returnIntArray",
1365
1366 "("
1367 ")"
1368 "[I",
1369       &g_TestJni_returnIntArray);
1370
1371   jintArray ret =
1372     static_cast<jintArray>(env->CallObjectMethod(obj,
1373       method_id));
1374   base::android::CheckException(env);
1375   return ScopedJavaLocalRef<jintArray>(env, ret);
1376 }
1377
1378 static base::subtle::AtomicWord g_TestJni_returnLongArray = 0;
1379 static ScopedJavaLocalRef<jlongArray> Java_TestJni_returnLongArray(JNIEnv* env,
1380     jobject obj) {
1381   /* Must call RegisterNativesImpl()  */
1382   DCHECK(g_TestJni_clazz);
1383   jmethodID method_id =
1384       base::android::MethodID::LazyGet<
1385       base::android::MethodID::TYPE_INSTANCE>(
1386       env, g_TestJni_clazz,
1387       "returnLongArray",
1388
1389 "("
1390 ")"
1391 "[J",
1392       &g_TestJni_returnLongArray);
1393
1394   jlongArray ret =
1395     static_cast<jlongArray>(env->CallObjectMethod(obj,
1396       method_id));
1397   base::android::CheckException(env);
1398   return ScopedJavaLocalRef<jlongArray>(env, ret);
1399 }
1400
1401 static base::subtle::AtomicWord g_TestJni_returnDoubleArray = 0;
1402 static ScopedJavaLocalRef<jdoubleArray> Java_TestJni_returnDoubleArray(JNIEnv*
1403     env, jobject obj) {
1404   /* Must call RegisterNativesImpl()  */
1405   DCHECK(g_TestJni_clazz);
1406   jmethodID method_id =
1407       base::android::MethodID::LazyGet<
1408       base::android::MethodID::TYPE_INSTANCE>(
1409       env, g_TestJni_clazz,
1410       "returnDoubleArray",
1411
1412 "("
1413 ")"
1414 "[D",
1415       &g_TestJni_returnDoubleArray);
1416
1417   jdoubleArray ret =
1418     static_cast<jdoubleArray>(env->CallObjectMethod(obj,
1419       method_id));
1420   base::android::CheckException(env);
1421   return ScopedJavaLocalRef<jdoubleArray>(env, ret);
1422 }
1423
1424 static base::subtle::AtomicWord g_TestJni_returnObjectArray = 0;
1425 static ScopedJavaLocalRef<jobjectArray> Java_TestJni_returnObjectArray(JNIEnv*
1426     env, jobject obj) {
1427   /* Must call RegisterNativesImpl()  */
1428   DCHECK(g_TestJni_clazz);
1429   jmethodID method_id =
1430       base::android::MethodID::LazyGet<
1431       base::android::MethodID::TYPE_INSTANCE>(
1432       env, g_TestJni_clazz,
1433       "returnObjectArray",
1434
1435 "("
1436 ")"
1437 "[Ljava/lang/Object;",
1438       &g_TestJni_returnObjectArray);
1439
1440   jobjectArray ret =
1441     static_cast<jobjectArray>(env->CallObjectMethod(obj,
1442       method_id));
1443   base::android::CheckException(env);
1444   return ScopedJavaLocalRef<jobjectArray>(env, ret);
1445 }
1446
1447 static base::subtle::AtomicWord g_TestJni_returnArrayOfByteArray = 0;
1448 static ScopedJavaLocalRef<jobjectArray>
1449     Java_TestJni_returnArrayOfByteArray(JNIEnv* env, jobject obj) {
1450   /* Must call RegisterNativesImpl()  */
1451   DCHECK(g_TestJni_clazz);
1452   jmethodID method_id =
1453       base::android::MethodID::LazyGet<
1454       base::android::MethodID::TYPE_INSTANCE>(
1455       env, g_TestJni_clazz,
1456       "returnArrayOfByteArray",
1457
1458 "("
1459 ")"
1460 "[[B",
1461       &g_TestJni_returnArrayOfByteArray);
1462
1463   jobjectArray ret =
1464     static_cast<jobjectArray>(env->CallObjectMethod(obj,
1465       method_id));
1466   base::android::CheckException(env);
1467   return ScopedJavaLocalRef<jobjectArray>(env, ret);
1468 }
1469
1470 static base::subtle::AtomicWord g_TestJni_getCompressFormat = 0;
1471 static ScopedJavaLocalRef<jobject> Java_TestJni_getCompressFormat(JNIEnv* env,
1472     jobject obj) {
1473   /* Must call RegisterNativesImpl()  */
1474   DCHECK(g_TestJni_clazz);
1475   jmethodID method_id =
1476       base::android::MethodID::LazyGet<
1477       base::android::MethodID::TYPE_INSTANCE>(
1478       env, g_TestJni_clazz,
1479       "getCompressFormat",
1480
1481 "("
1482 ")"
1483 "Landroid/graphics/Bitmap$CompressFormat;",
1484       &g_TestJni_getCompressFormat);
1485
1486   jobject ret =
1487     env->CallObjectMethod(obj,
1488       method_id);
1489   base::android::CheckException(env);
1490   return ScopedJavaLocalRef<jobject>(env, ret);
1491 }
1492
1493 static base::subtle::AtomicWord g_TestJni_getCompressFormatList = 0;
1494 static ScopedJavaLocalRef<jobject> Java_TestJni_getCompressFormatList(JNIEnv*
1495     env, jobject obj) {
1496   /* Must call RegisterNativesImpl()  */
1497   DCHECK(g_TestJni_clazz);
1498   jmethodID method_id =
1499       base::android::MethodID::LazyGet<
1500       base::android::MethodID::TYPE_INSTANCE>(
1501       env, g_TestJni_clazz,
1502       "getCompressFormatList",
1503
1504 "("
1505 ")"
1506 "Ljava/util/List;",
1507       &g_TestJni_getCompressFormatList);
1508
1509   jobject ret =
1510     env->CallObjectMethod(obj,
1511       method_id);
1512   base::android::CheckException(env);
1513   return ScopedJavaLocalRef<jobject>(env, ret);
1514 }
1515
1516 // Step 3: RegisterNatives.
1517
1518 static bool RegisterNativesImpl(JNIEnv* env) {
1519
1520   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1521       base::android::GetClass(env, kTestJniClassPath).obj()));
1522   g_InfoBar_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1523       base::android::GetClass(env, kInfoBarClassPath).obj()));
1524   return true;
1525 }
1526
1527 #endif  // org_chromium_TestJni_JNI
1528 """
1529     self.assertTextEquals(golden_content, h.GetContent())
1530
1531   def testCalledByNativeParseError(self):
1532     try:
1533       jni_generator.ExtractCalledByNatives("""
1534 @CalledByNative
1535 public static int foo(); // This one is fine
1536
1537 @CalledByNative
1538 scooby doo
1539 """)
1540       self.fail('Expected a ParseError')
1541     except jni_generator.ParseError, e:
1542       self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines)
1543
1544   def testFullyQualifiedClassName(self):
1545     contents = """
1546 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
1547 // Use of this source code is governed by a BSD-style license that can be
1548 // found in the LICENSE file.
1549
1550 package org.chromium.content.browser;
1551
1552 import org.chromium.base.BuildInfo;
1553 """
1554     self.assertEquals('org/chromium/content/browser/Foo',
1555                       jni_generator.ExtractFullyQualifiedJavaClassName(
1556                           'org/chromium/content/browser/Foo.java', contents))
1557     self.assertEquals('org/chromium/content/browser/Foo',
1558                       jni_generator.ExtractFullyQualifiedJavaClassName(
1559                           'frameworks/Foo.java', contents))
1560     self.assertRaises(SyntaxError,
1561                       jni_generator.ExtractFullyQualifiedJavaClassName,
1562                       'com/foo/Bar', 'no PACKAGE line')
1563
1564   def testMethodNameMangling(self):
1565     self.assertEquals('closeV',
1566         jni_generator.GetMangledMethodName('close', [], 'void'))
1567     self.assertEquals('readI_AB_I_I',
1568         jni_generator.GetMangledMethodName('read',
1569             [Param(name='p1',
1570                    datatype='byte[]'),
1571              Param(name='p2',
1572                    datatype='int'),
1573              Param(name='p3',
1574                    datatype='int'),],
1575              'int'))
1576     self.assertEquals('openJIIS_JLS',
1577         jni_generator.GetMangledMethodName('open',
1578             [Param(name='p1',
1579                    datatype='java/lang/String'),],
1580              'java/io/InputStream'))
1581
1582   def testFromJavaPGenerics(self):
1583     contents = """
1584 public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
1585       implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable {
1586     public void dummy();
1587   Signature: ()V
1588 }
1589 """
1590     jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
1591                                                 TestOptions())
1592     self.assertEquals(1, len(jni_from_javap.called_by_natives))
1593     golden_content = """\
1594 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
1595 // Use of this source code is governed by a BSD-style license that can be
1596 // found in the LICENSE file.
1597
1598 // This file is autogenerated by
1599 //     base/android/jni_generator/jni_generator.py
1600 // For
1601 //     java/util/HashSet
1602
1603 #ifndef java_util_HashSet_JNI
1604 #define java_util_HashSet_JNI
1605
1606 #include <jni.h>
1607
1608 #include "base/android/jni_android.h"
1609 #include "base/android/scoped_java_ref.h"
1610 #include "base/basictypes.h"
1611 #include "base/logging.h"
1612
1613 using base::android::ScopedJavaLocalRef;
1614
1615 // Step 1: forward declarations.
1616 namespace {
1617 const char kHashSetClassPath[] = "java/util/HashSet";
1618 // Leaking this jclass as we cannot use LazyInstance from some threads.
1619 jclass g_HashSet_clazz = NULL;
1620 }  // namespace
1621
1622 namespace JNI_HashSet {
1623
1624 // Step 2: method stubs.
1625
1626 static base::subtle::AtomicWord g_HashSet_dummy = 0;
1627 static void Java_HashSet_dummy(JNIEnv* env, jobject obj) __attribute__
1628     ((unused));
1629 static void Java_HashSet_dummy(JNIEnv* env, jobject obj) {
1630   /* Must call RegisterNativesImpl()  */
1631   DCHECK(g_HashSet_clazz);
1632   jmethodID method_id =
1633       base::android::MethodID::LazyGet<
1634       base::android::MethodID::TYPE_INSTANCE>(
1635       env, g_HashSet_clazz,
1636       "dummy",
1637 "()V",
1638       &g_HashSet_dummy);
1639
1640   env->CallVoidMethod(obj,
1641       method_id);
1642   base::android::CheckException(env);
1643
1644 }
1645
1646 // Step 3: RegisterNatives.
1647
1648 static bool RegisterNativesImpl(JNIEnv* env) {
1649
1650   g_HashSet_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1651       base::android::GetClass(env, kHashSetClassPath).obj()));
1652   return true;
1653 }
1654 }  // namespace JNI_HashSet
1655
1656 #endif  // java_util_HashSet_JNI
1657 """
1658     self.assertTextEquals(golden_content, jni_from_javap.GetContent())
1659
1660   def testSnippnetJavap6_7(self):
1661     content_javap6 = """
1662 public class java.util.HashSet {
1663 public boolean add(java.lang.Object);
1664  Signature: (Ljava/lang/Object;)Z
1665 }
1666 """
1667
1668     content_javap7 = """
1669 public class java.util.HashSet {
1670 public boolean add(E);
1671   Signature: (Ljava/lang/Object;)Z
1672 }
1673 """
1674     jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
1675                                                  TestOptions())
1676     jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
1677                                                  TestOptions())
1678     self.assertTrue(jni_from_javap6.GetContent())
1679     self.assertTrue(jni_from_javap7.GetContent())
1680     # Ensure the javap7 is correctly parsed and uses the Signature field rather
1681     # than the "E" parameter.
1682     self.assertTextEquals(jni_from_javap6.GetContent(),
1683                           jni_from_javap7.GetContent())
1684
1685   def testFromJavaP(self):
1686     contents = """
1687 public abstract class java.io.InputStream extends
1688   java.lang.Object implements java.io.Closeable{
1689 public java.io.InputStream();
1690   Signature: ()V
1691 public int available()   throws java.io.IOException;
1692   Signature: ()I
1693 public void close()   throws java.io.IOException;
1694   Signature: ()V
1695 public void mark(int);
1696   Signature: (I)V
1697 public boolean markSupported();
1698   Signature: ()Z
1699 public abstract int read()   throws java.io.IOException;
1700   Signature: ()I
1701 public int read(byte[])   throws java.io.IOException;
1702   Signature: ([B)I
1703 public int read(byte[], int, int)   throws java.io.IOException;
1704   Signature: ([BII)I
1705 public synchronized void reset()   throws java.io.IOException;
1706   Signature: ()V
1707 public long skip(long)   throws java.io.IOException;
1708   Signature: (J)J
1709 }
1710 """
1711     jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
1712                                                 TestOptions())
1713     self.assertEquals(10, len(jni_from_javap.called_by_natives))
1714     golden_content = """\
1715 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
1716 // Use of this source code is governed by a BSD-style license that can be
1717 // found in the LICENSE file.
1718
1719 // This file is autogenerated by
1720 //     base/android/jni_generator/jni_generator.py
1721 // For
1722 //     java/io/InputStream
1723
1724 #ifndef java_io_InputStream_JNI
1725 #define java_io_InputStream_JNI
1726
1727 #include <jni.h>
1728
1729 #include "base/android/jni_android.h"
1730 #include "base/android/scoped_java_ref.h"
1731 #include "base/basictypes.h"
1732 #include "base/logging.h"
1733
1734 using base::android::ScopedJavaLocalRef;
1735
1736 // Step 1: forward declarations.
1737 namespace {
1738 const char kInputStreamClassPath[] = "java/io/InputStream";
1739 // Leaking this jclass as we cannot use LazyInstance from some threads.
1740 jclass g_InputStream_clazz = NULL;
1741 }  // namespace
1742
1743 namespace JNI_InputStream {
1744
1745 // Step 2: method stubs.
1746
1747 static base::subtle::AtomicWord g_InputStream_available = 0;
1748 static jint Java_InputStream_available(JNIEnv* env, jobject obj) __attribute__
1749     ((unused));
1750 static jint Java_InputStream_available(JNIEnv* env, jobject obj) {
1751   /* Must call RegisterNativesImpl()  */
1752   DCHECK(g_InputStream_clazz);
1753   jmethodID method_id =
1754   base::android::MethodID::LazyGet<
1755       base::android::MethodID::TYPE_INSTANCE>(
1756       env, g_InputStream_clazz,
1757       "available",
1758 "()I",
1759       &g_InputStream_available);
1760
1761   jint ret =
1762     env->CallIntMethod(obj,
1763       method_id);
1764   base::android::CheckException(env);
1765   return ret;
1766 }
1767
1768 static base::subtle::AtomicWord g_InputStream_close = 0;
1769 static void Java_InputStream_close(JNIEnv* env, jobject obj) __attribute__
1770     ((unused));
1771 static void Java_InputStream_close(JNIEnv* env, jobject obj) {
1772   /* Must call RegisterNativesImpl()  */
1773   DCHECK(g_InputStream_clazz);
1774   jmethodID method_id =
1775   base::android::MethodID::LazyGet<
1776       base::android::MethodID::TYPE_INSTANCE>(
1777       env, g_InputStream_clazz,
1778       "close",
1779 "()V",
1780       &g_InputStream_close);
1781
1782   env->CallVoidMethod(obj,
1783       method_id);
1784   base::android::CheckException(env);
1785
1786 }
1787
1788 static base::subtle::AtomicWord g_InputStream_mark = 0;
1789 static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0)
1790     __attribute__ ((unused));
1791 static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) {
1792   /* Must call RegisterNativesImpl()  */
1793   DCHECK(g_InputStream_clazz);
1794   jmethodID method_id =
1795   base::android::MethodID::LazyGet<
1796       base::android::MethodID::TYPE_INSTANCE>(
1797       env, g_InputStream_clazz,
1798       "mark",
1799 "(I)V",
1800       &g_InputStream_mark);
1801
1802   env->CallVoidMethod(obj,
1803       method_id, p0);
1804   base::android::CheckException(env);
1805
1806 }
1807
1808 static base::subtle::AtomicWord g_InputStream_markSupported = 0;
1809 static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj)
1810     __attribute__ ((unused));
1811 static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) {
1812   /* Must call RegisterNativesImpl()  */
1813   DCHECK(g_InputStream_clazz);
1814   jmethodID method_id =
1815   base::android::MethodID::LazyGet<
1816       base::android::MethodID::TYPE_INSTANCE>(
1817       env, g_InputStream_clazz,
1818       "markSupported",
1819 "()Z",
1820       &g_InputStream_markSupported);
1821
1822   jboolean ret =
1823     env->CallBooleanMethod(obj,
1824       method_id);
1825   base::android::CheckException(env);
1826   return ret;
1827 }
1828
1829 static base::subtle::AtomicWord g_InputStream_readI = 0;
1830 static jint Java_InputStream_readI(JNIEnv* env, jobject obj) __attribute__
1831     ((unused));
1832 static jint Java_InputStream_readI(JNIEnv* env, jobject obj) {
1833   /* Must call RegisterNativesImpl()  */
1834   DCHECK(g_InputStream_clazz);
1835   jmethodID method_id =
1836   base::android::MethodID::LazyGet<
1837       base::android::MethodID::TYPE_INSTANCE>(
1838       env, g_InputStream_clazz,
1839       "read",
1840 "()I",
1841       &g_InputStream_readI);
1842
1843   jint ret =
1844     env->CallIntMethod(obj,
1845       method_id);
1846   base::android::CheckException(env);
1847   return ret;
1848 }
1849
1850 static base::subtle::AtomicWord g_InputStream_readI_AB = 0;
1851 static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0)
1852     __attribute__ ((unused));
1853 static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) {
1854   /* Must call RegisterNativesImpl()  */
1855   DCHECK(g_InputStream_clazz);
1856   jmethodID method_id =
1857   base::android::MethodID::LazyGet<
1858       base::android::MethodID::TYPE_INSTANCE>(
1859       env, g_InputStream_clazz,
1860       "read",
1861 "([B)I",
1862       &g_InputStream_readI_AB);
1863
1864   jint ret =
1865     env->CallIntMethod(obj,
1866       method_id, p0);
1867   base::android::CheckException(env);
1868   return ret;
1869 }
1870
1871 static base::subtle::AtomicWord g_InputStream_readI_AB_I_I = 0;
1872 static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray
1873     p0,
1874     jint p1,
1875     jint p2) __attribute__ ((unused));
1876 static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray
1877     p0,
1878     jint p1,
1879     jint p2) {
1880   /* Must call RegisterNativesImpl()  */
1881   DCHECK(g_InputStream_clazz);
1882   jmethodID method_id =
1883   base::android::MethodID::LazyGet<
1884       base::android::MethodID::TYPE_INSTANCE>(
1885       env, g_InputStream_clazz,
1886       "read",
1887 "([BII)I",
1888       &g_InputStream_readI_AB_I_I);
1889
1890   jint ret =
1891     env->CallIntMethod(obj,
1892       method_id, p0, p1, p2);
1893   base::android::CheckException(env);
1894   return ret;
1895 }
1896
1897 static base::subtle::AtomicWord g_InputStream_reset = 0;
1898 static void Java_InputStream_reset(JNIEnv* env, jobject obj) __attribute__
1899     ((unused));
1900 static void Java_InputStream_reset(JNIEnv* env, jobject obj) {
1901   /* Must call RegisterNativesImpl()  */
1902   DCHECK(g_InputStream_clazz);
1903   jmethodID method_id =
1904   base::android::MethodID::LazyGet<
1905       base::android::MethodID::TYPE_INSTANCE>(
1906       env, g_InputStream_clazz,
1907       "reset",
1908 "()V",
1909       &g_InputStream_reset);
1910
1911   env->CallVoidMethod(obj,
1912       method_id);
1913   base::android::CheckException(env);
1914
1915 }
1916
1917 static base::subtle::AtomicWord g_InputStream_skip = 0;
1918 static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0)
1919     __attribute__ ((unused));
1920 static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) {
1921   /* Must call RegisterNativesImpl()  */
1922   DCHECK(g_InputStream_clazz);
1923   jmethodID method_id =
1924   base::android::MethodID::LazyGet<
1925       base::android::MethodID::TYPE_INSTANCE>(
1926       env, g_InputStream_clazz,
1927       "skip",
1928 "(J)J",
1929       &g_InputStream_skip);
1930
1931   jlong ret =
1932     env->CallLongMethod(obj,
1933       method_id, p0);
1934   base::android::CheckException(env);
1935   return ret;
1936 }
1937
1938 static base::subtle::AtomicWord g_InputStream_Constructor = 0;
1939 static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env)
1940     __attribute__ ((unused));
1941 static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) {
1942   /* Must call RegisterNativesImpl()  */
1943   DCHECK(g_InputStream_clazz);
1944   jmethodID method_id =
1945   base::android::MethodID::LazyGet<
1946       base::android::MethodID::TYPE_INSTANCE>(
1947       env, g_InputStream_clazz,
1948       "<init>",
1949 "()V",
1950       &g_InputStream_Constructor);
1951
1952   jobject ret =
1953     env->NewObject(g_InputStream_clazz,
1954       method_id);
1955   base::android::CheckException(env);
1956   return ScopedJavaLocalRef<jobject>(env, ret);
1957 }
1958
1959 // Step 3: RegisterNatives.
1960
1961 static bool RegisterNativesImpl(JNIEnv* env) {
1962
1963   g_InputStream_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1964       base::android::GetClass(env, kInputStreamClassPath).obj()));
1965   return true;
1966 }
1967 }  // namespace JNI_InputStream
1968
1969 #endif  // java_io_InputStream_JNI
1970 """
1971     self.assertTextEquals(golden_content, jni_from_javap.GetContent())
1972
1973   def testREForNatives(self):
1974     # We should not match "native SyncSetupFlow" inside the comment.
1975     test_data = """
1976     /**
1977      * Invoked when the setup process is complete so we can disconnect from the
1978      * native-side SyncSetupFlowHandler.
1979      */
1980     public void destroy() {
1981         Log.v(TAG, "Destroying native SyncSetupFlow");
1982         if (mNativeSyncSetupFlow != 0) {
1983             nativeSyncSetupEnded(mNativeSyncSetupFlow);
1984             mNativeSyncSetupFlow = 0;
1985         }
1986     }
1987     private native void nativeSyncSetupEnded(
1988         int nativeAndroidSyncSetupFlowHandler);
1989     """
1990     jni_from_java = jni_generator.JNIFromJavaSource(
1991         test_data, 'foo/bar', TestOptions())
1992
1993   def testRaisesOnNonJNIMethod(self):
1994     test_data = """
1995     class MyInnerClass {
1996       private int Foo(int p0) {
1997       }
1998     }
1999     """
2000     self.assertRaises(SyntaxError,
2001                       jni_generator.JNIFromJavaSource,
2002                       test_data, 'foo/bar', TestOptions())
2003
2004   def testJniSelfDocumentingExample(self):
2005     script_dir = os.path.dirname(sys.argv[0])
2006     content = file(os.path.join(script_dir,
2007         'java/src/org/chromium/example/jni_generator/SampleForTests.java')
2008         ).read()
2009     golden_content = file(os.path.join(script_dir,
2010                                        'golden_sample_for_tests_jni.h')).read()
2011     jni_from_java = jni_generator.JNIFromJavaSource(
2012         content, 'org/chromium/example/jni_generator/SampleForTests',
2013         TestOptions())
2014     self.assertTextEquals(golden_content, jni_from_java.GetContent())
2015
2016   def testNoWrappingPreprocessorLines(self):
2017     test_data = """
2018     package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday;
2019
2020     class ReallyLongClassNamesAreAllTheRage {
2021         private static native int nativeTest();
2022     }
2023     """
2024     jni_from_java = jni_generator.JNIFromJavaSource(
2025         test_data, ('com/google/lookhowextremelylongiam/snarf/'
2026                     'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
2027         TestOptions())
2028     jni_lines = jni_from_java.GetContent().split('\n')
2029     line = filter(lambda line: line.lstrip().startswith('#ifndef'),
2030                   jni_lines)[0]
2031     self.assertTrue(len(line) > 80,
2032                     ('Expected #ifndef line to be > 80 chars: ', line))
2033
2034   def testJarJarRemapping(self):
2035     test_data = """
2036     package org.chromium.example.jni_generator;
2037
2038     import org.chromium.example2.Test;
2039
2040     class Example {
2041       private static native void nativeTest(Test t);
2042     }
2043     """
2044     jni_generator.JniParams.SetJarJarMappings(
2045         """rule org.chromium.example.** com.test.@1
2046         rule org.chromium.example2.** org.test2.@0""")
2047     jni_from_java = jni_generator.JNIFromJavaSource(
2048         test_data, 'org/chromium/example/jni_generator/Example', TestOptions())
2049     jni_generator.JniParams.SetJarJarMappings('')
2050     golden_content = """\
2051 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2052 // Use of this source code is governed by a BSD-style license that can be
2053 // found in the LICENSE file.
2054
2055 // This file is autogenerated by
2056 //     base/android/jni_generator/jni_generator.py
2057 // For
2058 //     org/chromium/example/jni_generator/Example
2059
2060 #ifndef org_chromium_example_jni_generator_Example_JNI
2061 #define org_chromium_example_jni_generator_Example_JNI
2062
2063 #include <jni.h>
2064
2065 #include "base/android/jni_android.h"
2066 #include "base/android/scoped_java_ref.h"
2067 #include "base/basictypes.h"
2068 #include "base/logging.h"
2069
2070 using base::android::ScopedJavaLocalRef;
2071
2072 // Step 1: forward declarations.
2073 namespace {
2074 const char kExampleClassPath[] = "com/test/jni_generator/Example";
2075 // Leaking this jclass as we cannot use LazyInstance from some threads.
2076 jclass g_Example_clazz = NULL;
2077 }  // namespace
2078
2079 static void Test(JNIEnv* env, jclass clazz,
2080     jobject t);
2081
2082 // Step 2: method stubs.
2083
2084 // Step 3: RegisterNatives.
2085
2086 static bool RegisterNativesImpl(JNIEnv* env) {
2087
2088   g_Example_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
2089       base::android::GetClass(env, kExampleClassPath).obj()));
2090   static const JNINativeMethod kMethodsExample[] = {
2091     { "nativeTest",
2092 "("
2093 "Lorg/test2/org/chromium/example2/Test;"
2094 ")"
2095 "V", reinterpret_cast<void*>(Test) },
2096   };
2097   const int kMethodsExampleSize = arraysize(kMethodsExample);
2098
2099   if (env->RegisterNatives(g_Example_clazz,
2100                            kMethodsExample,
2101                            kMethodsExampleSize) < 0) {
2102     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
2103     return false;
2104   }
2105
2106   return true;
2107 }
2108
2109 #endif  // org_chromium_example_jni_generator_Example_JNI
2110 """
2111     self.assertTextEquals(golden_content, jni_from_java.GetContent())
2112
2113   def testImports(self):
2114     import_header = """
2115 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2116 // Use of this source code is governed by a BSD-style license that can be
2117 // found in the LICENSE file.
2118
2119 package org.chromium.content.app;
2120
2121 import android.app.Service;
2122 import android.content.Context;
2123 import android.content.Intent;
2124 import android.graphics.SurfaceTexture;
2125 import android.os.Bundle;
2126 import android.os.IBinder;
2127 import android.os.ParcelFileDescriptor;
2128 import android.os.Process;
2129 import android.os.RemoteException;
2130 import android.util.Log;
2131 import android.view.Surface;
2132
2133 import java.util.ArrayList;
2134
2135 import org.chromium.base.CalledByNative;
2136 import org.chromium.base.JNINamespace;
2137 import org.chromium.content.app.ContentMain;
2138 import org.chromium.content.browser.SandboxedProcessConnection;
2139 import org.chromium.content.common.ISandboxedProcessCallback;
2140 import org.chromium.content.common.ISandboxedProcessService;
2141 import org.chromium.content.common.WillNotRaise.AnException;
2142 import org.chromium.content.common.WillRaise.AnException;
2143
2144 import static org.chromium.Bar.Zoo;
2145
2146 class Foo {
2147   public static class BookmarkNode implements Parcelable {
2148   }
2149   public interface PasswordListObserver {
2150   }
2151 }
2152     """
2153     jni_generator.JniParams.SetFullyQualifiedClass(
2154         'org/chromium/content/app/Foo')
2155     jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header)
2156     self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in
2157                     jni_generator.JniParams._imports)
2158     self.assertTrue('Lorg/chromium/Bar/Zoo' in
2159                     jni_generator.JniParams._imports)
2160     self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in
2161                     jni_generator.JniParams._inner_classes)
2162     self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in
2163                     jni_generator.JniParams._inner_classes)
2164     self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner;',
2165                       jni_generator.JniParams.JavaToJni('ContentMain.Inner'))
2166     self.assertRaises(SyntaxError,
2167                       jni_generator.JniParams.JavaToJni,
2168                       'AnException')
2169
2170   def testJniParamsJavaToJni(self):
2171     self.assertTextEquals('I', JniParams.JavaToJni('int'))
2172     self.assertTextEquals('[B', JniParams.JavaToJni('byte[]'))
2173     self.assertTextEquals(
2174         '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]'))
2175
2176   def testNativesLong(self):
2177     test_options = TestOptions()
2178     test_options.ptr_type = 'long'
2179     test_data = """"
2180     private native void nativeDestroy(long nativeChromeBrowserProvider);
2181     """
2182     jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
2183     natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type)
2184     golden_natives = [
2185         NativeMethod(return_type='void', static=False, name='Destroy',
2186                      params=[Param(datatype='long',
2187                                    name='nativeChromeBrowserProvider')],
2188                      java_class_name=None,
2189                      type='method',
2190                      p0_type='ChromeBrowserProvider',
2191                      ptr_type=test_options.ptr_type),
2192     ]
2193     self.assertListEquals(golden_natives, natives)
2194     h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
2195                                              natives, [], test_options)
2196     golden_content = """\
2197 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2198 // Use of this source code is governed by a BSD-style license that can be
2199 // found in the LICENSE file.
2200
2201 // This file is autogenerated by
2202 //     base/android/jni_generator/jni_generator.py
2203 // For
2204 //     org/chromium/TestJni
2205
2206 #ifndef org_chromium_TestJni_JNI
2207 #define org_chromium_TestJni_JNI
2208
2209 #include <jni.h>
2210
2211 #include "base/android/jni_android.h"
2212 #include "base/android/scoped_java_ref.h"
2213 #include "base/basictypes.h"
2214 #include "base/logging.h"
2215
2216 using base::android::ScopedJavaLocalRef;
2217
2218 // Step 1: forward declarations.
2219 namespace {
2220 const char kTestJniClassPath[] = "org/chromium/TestJni";
2221 // Leaking this jclass as we cannot use LazyInstance from some threads.
2222 jclass g_TestJni_clazz = NULL;
2223 }  // namespace
2224
2225 // Step 2: method stubs.
2226 static void Destroy(JNIEnv* env, jobject obj,
2227     jlong nativeChromeBrowserProvider) {
2228   DCHECK(nativeChromeBrowserProvider) << "Destroy";
2229   ChromeBrowserProvider* native =
2230       reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
2231   return native->Destroy(env, obj);
2232 }
2233
2234 // Step 3: RegisterNatives.
2235
2236 static bool RegisterNativesImpl(JNIEnv* env) {
2237
2238   g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
2239       base::android::GetClass(env, kTestJniClassPath).obj()));
2240   static const JNINativeMethod kMethodsTestJni[] = {
2241     { "nativeDestroy",
2242 "("
2243 "J"
2244 ")"
2245 "V", reinterpret_cast<void*>(Destroy) },
2246   };
2247   const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
2248
2249   if (env->RegisterNatives(g_TestJni_clazz,
2250                            kMethodsTestJni,
2251                            kMethodsTestJniSize) < 0) {
2252     LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
2253     return false;
2254   }
2255
2256   return true;
2257 }
2258
2259 #endif  // org_chromium_TestJni_JNI
2260 """
2261     self.assertTextEquals(golden_content, h.GetContent())
2262
2263
2264 if __name__ == '__main__':
2265   unittest.main()