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