| #!/usr/bin/env python |
| # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Tests for jni_generator.py. |
| |
| This test suite contains various tests for the JNI generator. |
| It exercises the low-level parser all the way up to the |
| code generator and ensures the output matches a golden |
| file. |
| """ |
| |
| import difflib |
| import os |
| import sys |
| import unittest |
| import jni_generator |
| from jni_generator import CalledByNative, NativeMethod, Param |
| |
| |
| class TestGenerator(unittest.TestCase): |
| def assertObjEquals(self, first, second): |
| dict_first = first.__dict__ |
| dict_second = second.__dict__ |
| self.assertEquals(dict_first.keys(), dict_second.keys()) |
| for key, value in dict_first.iteritems(): |
| if (type(value) is list and len(value) and |
| isinstance(type(value[0]), object)): |
| self.assertListEquals(value, second.__getattribute__(key)) |
| else: |
| actual = second.__getattribute__(key) |
| self.assertEquals(value, actual, |
| 'Key ' + key + ': ' + str(value) + '!=' + str(actual)) |
| |
| def assertListEquals(self, first, second): |
| self.assertEquals(len(first), len(second)) |
| for i in xrange(len(first)): |
| if isinstance(first[i], object): |
| self.assertObjEquals(first[i], second[i]) |
| else: |
| self.assertEquals(first[i], second[i]) |
| |
| def assertTextEquals(self, golden_text, generated_text): |
| stripped_golden = [l.strip() for l in golden_text.split('\n')] |
| stripped_generated = [l.strip() for l in generated_text.split('\n')] |
| if stripped_golden != stripped_generated: |
| print self.id() |
| for line in difflib.context_diff(stripped_golden, stripped_generated): |
| print line |
| print '\n\nGenerated' |
| print '=' * 80 |
| print generated_text |
| print '=' * 80 |
| self.fail('Golden text mismatch') |
| |
| def testNatives(self): |
| test_data = """" |
| interface OnFrameAvailableListener {} |
| private native int nativeInit(); |
| private native void nativeDestroy(int nativeChromeBrowserProvider); |
| private native long nativeAddBookmark( |
| int nativeChromeBrowserProvider, |
| String url, String title, boolean isFolder, long parentId); |
| private static native String nativeGetDomainAndRegistry(String url); |
| private static native void nativeCreateHistoricalTabFromState( |
| byte[] state, int tab_index); |
| private native byte[] nativeGetStateAsByteArray(View view); |
| private static native String[] nativeGetAutofillProfileGUIDs(); |
| private native void nativeSetRecognitionResults( |
| int sessionId, String[] results); |
| private native long nativeAddBookmarkFromAPI( |
| int nativeChromeBrowserProvider, |
| String url, Long created, Boolean isBookmark, |
| Long date, byte[] favicon, String title, Integer visits); |
| native int nativeFindAll(String find); |
| private static native OnFrameAvailableListener nativeGetInnerClass(); |
| private native Bitmap nativeQueryBitmap( |
| int nativeChromeBrowserProvider, |
| String[] projection, String selection, |
| String[] selectionArgs, String sortOrder); |
| private native void nativeGotOrientation( |
| int nativeDataFetcherImplAndroid, |
| double alpha, double beta, double gamma); |
| """ |
| jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) |
| natives = jni_generator.ExtractNatives(test_data) |
| golden_natives = [ |
| NativeMethod(return_type='int', static=False, |
| name='Init', |
| params=[], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='void', static=False, name='Destroy', |
| params=[Param(datatype='int', |
| name='nativeChromeBrowserProvider')], |
| java_class_name=None, |
| type='method', |
| p0_type='ChromeBrowserProvider'), |
| NativeMethod(return_type='long', static=False, name='AddBookmark', |
| params=[Param(datatype='int', |
| name='nativeChromeBrowserProvider'), |
| Param(datatype='String', |
| name='url'), |
| Param(datatype='String', |
| name='title'), |
| Param(datatype='boolean', |
| name='isFolder'), |
| Param(datatype='long', |
| name='parentId')], |
| java_class_name=None, |
| type='method', |
| p0_type='ChromeBrowserProvider'), |
| NativeMethod(return_type='String', static=True, |
| name='GetDomainAndRegistry', |
| params=[Param(datatype='String', |
| name='url')], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='void', static=True, |
| name='CreateHistoricalTabFromState', |
| params=[Param(datatype='byte[]', |
| name='state'), |
| Param(datatype='int', |
| name='tab_index')], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='byte[]', static=False, |
| name='GetStateAsByteArray', |
| params=[Param(datatype='View', name='view')], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='String[]', static=True, |
| name='GetAutofillProfileGUIDs', params=[], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='void', static=False, |
| name='SetRecognitionResults', |
| params=[Param(datatype='int', name='sessionId'), |
| Param(datatype='String[]', name='results')], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='long', static=False, |
| name='AddBookmarkFromAPI', |
| params=[Param(datatype='int', |
| name='nativeChromeBrowserProvider'), |
| Param(datatype='String', |
| name='url'), |
| Param(datatype='Long', |
| name='created'), |
| Param(datatype='Boolean', |
| name='isBookmark'), |
| Param(datatype='Long', |
| name='date'), |
| Param(datatype='byte[]', |
| name='favicon'), |
| Param(datatype='String', |
| name='title'), |
| Param(datatype='Integer', |
| name='visits')], |
| java_class_name=None, |
| type='method', |
| p0_type='ChromeBrowserProvider'), |
| NativeMethod(return_type='int', static=False, |
| name='FindAll', |
| params=[Param(datatype='String', |
| name='find')], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='OnFrameAvailableListener', static=True, |
| name='GetInnerClass', |
| params=[], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='Bitmap', |
| static=False, |
| name='QueryBitmap', |
| params=[Param(datatype='int', |
| name='nativeChromeBrowserProvider'), |
| Param(datatype='String[]', |
| name='projection'), |
| Param(datatype='String', |
| name='selection'), |
| Param(datatype='String[]', |
| name='selectionArgs'), |
| Param(datatype='String', |
| name='sortOrder'), |
| ], |
| java_class_name=None, |
| type='method', |
| p0_type='ChromeBrowserProvider'), |
| NativeMethod(return_type='void', static=False, |
| name='GotOrientation', |
| params=[Param(datatype='int', |
| name='nativeDataFetcherImplAndroid'), |
| Param(datatype='double', |
| name='alpha'), |
| Param(datatype='double', |
| name='beta'), |
| Param(datatype='double', |
| name='gamma'), |
| ], |
| java_class_name=None, |
| type='method', |
| p0_type='content::DataFetcherImplAndroid'), |
| ] |
| self.assertListEquals(golden_natives, natives) |
| h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', |
| natives, []) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // org/chromium/TestJni |
| |
| #ifndef org_chromium_TestJni_JNI |
| #define org_chromium_TestJni_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kTestJniClassPath[] = "org/chromium/TestJni"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_TestJni_clazz = NULL; |
| } // namespace |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| static jstring GetDomainAndRegistry(JNIEnv* env, jclass clazz, |
| jstring url); |
| |
| static void CreateHistoricalTabFromState(JNIEnv* env, jclass clazz, |
| jbyteArray state, |
| jint tab_index); |
| |
| static jbyteArray GetStateAsByteArray(JNIEnv* env, jobject obj, |
| jobject view); |
| |
| static jobjectArray GetAutofillProfileGUIDs(JNIEnv* env, jclass clazz); |
| |
| static void SetRecognitionResults(JNIEnv* env, jobject obj, |
| jint sessionId, |
| jobjectArray results); |
| |
| static jint FindAll(JNIEnv* env, jobject obj, |
| jstring find); |
| |
| static jobject GetInnerClass(JNIEnv* env, jclass clazz); |
| |
| // Step 2: method stubs. |
| static void Destroy(JNIEnv* env, jobject obj, |
| jint nativeChromeBrowserProvider) { |
| DCHECK(nativeChromeBrowserProvider) << "Destroy"; |
| ChromeBrowserProvider* native = |
| reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); |
| return native->Destroy(env, obj); |
| } |
| |
| static jlong AddBookmark(JNIEnv* env, jobject obj, |
| jint nativeChromeBrowserProvider, |
| jstring url, |
| jstring title, |
| jboolean isFolder, |
| jlong parentId) { |
| DCHECK(nativeChromeBrowserProvider) << "AddBookmark"; |
| ChromeBrowserProvider* native = |
| reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); |
| return native->AddBookmark(env, obj, url, title, isFolder, parentId); |
| } |
| |
| static jlong AddBookmarkFromAPI(JNIEnv* env, jobject obj, |
| jint nativeChromeBrowserProvider, |
| jstring url, |
| jobject created, |
| jobject isBookmark, |
| jobject date, |
| jbyteArray favicon, |
| jstring title, |
| jobject visits) { |
| DCHECK(nativeChromeBrowserProvider) << "AddBookmarkFromAPI"; |
| ChromeBrowserProvider* native = |
| reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); |
| return native->AddBookmarkFromAPI(env, obj, url, created, isBookmark, date, |
| favicon, title, visits); |
| } |
| |
| static jobject QueryBitmap(JNIEnv* env, jobject obj, |
| jint nativeChromeBrowserProvider, |
| jobjectArray projection, |
| jstring selection, |
| jobjectArray selectionArgs, |
| jstring sortOrder) { |
| DCHECK(nativeChromeBrowserProvider) << "QueryBitmap"; |
| ChromeBrowserProvider* native = |
| reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); |
| return native->QueryBitmap(env, obj, projection, selection, selectionArgs, |
| sortOrder).Release(); |
| } |
| |
| static void GotOrientation(JNIEnv* env, jobject obj, |
| jint nativeDataFetcherImplAndroid, |
| jdouble alpha, |
| jdouble beta, |
| jdouble gamma) { |
| DCHECK(nativeDataFetcherImplAndroid) << "GotOrientation"; |
| DataFetcherImplAndroid* native = |
| reinterpret_cast<DataFetcherImplAndroid*>(nativeDataFetcherImplAndroid); |
| return native->GotOrientation(env, obj, alpha, beta, gamma); |
| } |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kTestJniClassPath))); |
| static const JNINativeMethod kMethodsTestJni[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| { "nativeDestroy", |
| "(" |
| "I" |
| ")" |
| "V", reinterpret_cast<void*>(Destroy) }, |
| { "nativeAddBookmark", |
| "(" |
| "I" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "Z" |
| "J" |
| ")" |
| "J", reinterpret_cast<void*>(AddBookmark) }, |
| { "nativeGetDomainAndRegistry", |
| "(" |
| "Ljava/lang/String;" |
| ")" |
| "Ljava/lang/String;", reinterpret_cast<void*>(GetDomainAndRegistry) }, |
| { "nativeCreateHistoricalTabFromState", |
| "(" |
| "[B" |
| "I" |
| ")" |
| "V", reinterpret_cast<void*>(CreateHistoricalTabFromState) }, |
| { "nativeGetStateAsByteArray", |
| "(" |
| "Landroid/view/View;" |
| ")" |
| "[B", reinterpret_cast<void*>(GetStateAsByteArray) }, |
| { "nativeGetAutofillProfileGUIDs", |
| "(" |
| ")" |
| "[Ljava/lang/String;", reinterpret_cast<void*>(GetAutofillProfileGUIDs) }, |
| { "nativeSetRecognitionResults", |
| "(" |
| "I" |
| "[Ljava/lang/String;" |
| ")" |
| "V", reinterpret_cast<void*>(SetRecognitionResults) }, |
| { "nativeAddBookmarkFromAPI", |
| "(" |
| "I" |
| "Ljava/lang/String;" |
| "Ljava/lang/Long;" |
| "Ljava/lang/Boolean;" |
| "Ljava/lang/Long;" |
| "[B" |
| "Ljava/lang/String;" |
| "Ljava/lang/Integer;" |
| ")" |
| "J", reinterpret_cast<void*>(AddBookmarkFromAPI) }, |
| { "nativeFindAll", |
| "(" |
| "Ljava/lang/String;" |
| ")" |
| "I", reinterpret_cast<void*>(FindAll) }, |
| { "nativeGetInnerClass", |
| "(" |
| ")" |
| "Lorg/chromium/example/jni_generator/SampleForTests$OnFrameAvailableListener;", |
| reinterpret_cast<void*>(GetInnerClass) }, |
| { "nativeQueryBitmap", |
| "(" |
| "I" |
| "[Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "[Ljava/lang/String;" |
| "Ljava/lang/String;" |
| ")" |
| "Landroid/graphics/Bitmap;", reinterpret_cast<void*>(QueryBitmap) }, |
| { "nativeGotOrientation", |
| "(" |
| "I" |
| "D" |
| "D" |
| "D" |
| ")" |
| "V", reinterpret_cast<void*>(GotOrientation) }, |
| }; |
| const int kMethodsTestJniSize = arraysize(kMethodsTestJni); |
| |
| if (env->RegisterNatives(g_TestJni_clazz, |
| kMethodsTestJni, |
| kMethodsTestJniSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| #endif // org_chromium_TestJni_JNI |
| """ |
| self.assertTextEquals(golden_content, h.GetContent()) |
| |
| def testInnerClassNatives(self): |
| test_data = """ |
| class MyInnerClass { |
| @NativeCall("MyInnerClass") |
| private native int nativeInit(); |
| } |
| """ |
| natives = jni_generator.ExtractNatives(test_data) |
| golden_natives = [ |
| NativeMethod(return_type='int', static=False, |
| name='Init', params=[], |
| java_class_name='MyInnerClass', |
| type='function') |
| ] |
| self.assertListEquals(golden_natives, natives) |
| h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', |
| natives, []) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // org/chromium/TestJni |
| |
| #ifndef org_chromium_TestJni_JNI |
| #define org_chromium_TestJni_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kTestJniClassPath[] = "org/chromium/TestJni"; |
| const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_TestJni_clazz = NULL; |
| } // namespace |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| // Step 2: method stubs. |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kTestJniClassPath))); |
| static const JNINativeMethod kMethodsMyInnerClass[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| }; |
| const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass); |
| |
| if (env->RegisterNatives(g_MyInnerClass_clazz, |
| kMethodsMyInnerClass, |
| kMethodsMyInnerClassSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| #endif // org_chromium_TestJni_JNI |
| """ |
| self.assertTextEquals(golden_content, h.GetContent()) |
| |
| def testInnerClassNativesMultiple(self): |
| test_data = """ |
| class MyInnerClass { |
| @NativeCall("MyInnerClass") |
| private native int nativeInit(); |
| } |
| class MyOtherInnerClass { |
| @NativeCall("MyOtherInnerClass") |
| private native int nativeInit(); |
| } |
| """ |
| natives = jni_generator.ExtractNatives(test_data) |
| golden_natives = [ |
| NativeMethod(return_type='int', static=False, |
| name='Init', params=[], |
| java_class_name='MyInnerClass', |
| type='function'), |
| NativeMethod(return_type='int', static=False, |
| name='Init', params=[], |
| java_class_name='MyOtherInnerClass', |
| type='function') |
| ] |
| self.assertListEquals(golden_natives, natives) |
| h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', |
| natives, []) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // org/chromium/TestJni |
| |
| #ifndef org_chromium_TestJni_JNI |
| #define org_chromium_TestJni_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kMyOtherInnerClassClassPath[] = |
| "org/chromium/TestJni$MyOtherInnerClass"; |
| const char kTestJniClassPath[] = "org/chromium/TestJni"; |
| const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_TestJni_clazz = NULL; |
| } // namespace |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| // Step 2: method stubs. |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kTestJniClassPath))); |
| static const JNINativeMethod kMethodsMyOtherInnerClass[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| }; |
| const int kMethodsMyOtherInnerClassSize = |
| arraysize(kMethodsMyOtherInnerClass); |
| |
| if (env->RegisterNatives(g_MyOtherInnerClass_clazz, |
| kMethodsMyOtherInnerClass, |
| kMethodsMyOtherInnerClassSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| static const JNINativeMethod kMethodsMyInnerClass[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| }; |
| const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass); |
| |
| if (env->RegisterNatives(g_MyInnerClass_clazz, |
| kMethodsMyInnerClass, |
| kMethodsMyInnerClassSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| #endif // org_chromium_TestJni_JNI |
| """ |
| self.assertTextEquals(golden_content, h.GetContent()) |
| |
| def testInnerClassNativesBothInnerAndOuter(self): |
| test_data = """ |
| class MyOuterClass { |
| private native int nativeInit(); |
| class MyOtherInnerClass { |
| @NativeCall("MyOtherInnerClass") |
| private native int nativeInit(); |
| } |
| } |
| """ |
| natives = jni_generator.ExtractNatives(test_data) |
| golden_natives = [ |
| NativeMethod(return_type='int', static=False, |
| name='Init', params=[], |
| java_class_name=None, |
| type='function'), |
| NativeMethod(return_type='int', static=False, |
| name='Init', params=[], |
| java_class_name='MyOtherInnerClass', |
| type='function') |
| ] |
| self.assertListEquals(golden_natives, natives) |
| h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', |
| natives, []) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // org/chromium/TestJni |
| |
| #ifndef org_chromium_TestJni_JNI |
| #define org_chromium_TestJni_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kMyOtherInnerClassClassPath[] = |
| "org/chromium/TestJni$MyOtherInnerClass"; |
| const char kTestJniClassPath[] = "org/chromium/TestJni"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_TestJni_clazz = NULL; |
| } // namespace |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| static jint Init(JNIEnv* env, jobject obj); |
| |
| // Step 2: method stubs. |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kTestJniClassPath))); |
| static const JNINativeMethod kMethodsMyOtherInnerClass[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| }; |
| const int kMethodsMyOtherInnerClassSize = |
| arraysize(kMethodsMyOtherInnerClass); |
| |
| if (env->RegisterNatives(g_MyOtherInnerClass_clazz, |
| kMethodsMyOtherInnerClass, |
| kMethodsMyOtherInnerClassSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| static const JNINativeMethod kMethodsTestJni[] = { |
| { "nativeInit", |
| "(" |
| ")" |
| "I", reinterpret_cast<void*>(Init) }, |
| }; |
| const int kMethodsTestJniSize = arraysize(kMethodsTestJni); |
| |
| if (env->RegisterNatives(g_TestJni_clazz, |
| kMethodsTestJni, |
| kMethodsTestJniSize) < 0) { |
| LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| #endif // org_chromium_TestJni_JNI |
| """ |
| self.assertTextEquals(golden_content, h.GetContent()) |
| |
| def testCalledByNatives(self): |
| test_data = """" |
| import android.graphics.Bitmap; |
| import android.view.View; |
| import java.io.InputStream; |
| |
| class InnerClass {} |
| |
| @CalledByNative |
| InnerClass showConfirmInfoBar(int nativeInfoBar, |
| String buttonOk, String buttonCancel, String title, Bitmap icon) { |
| InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext, |
| buttonOk, buttonCancel, |
| title, icon); |
| return infobar; |
| } |
| @CalledByNative |
| InnerClass showAutoLoginInfoBar(int nativeInfoBar, |
| String realm, String account, String args) { |
| AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext, |
| realm, account, args); |
| if (infobar.displayedAccountCount() == 0) |
| infobar = null; |
| return infobar; |
| } |
| @CalledByNative("InfoBar") |
| void dismiss(); |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private static boolean shouldShowAutoLogin(View view, |
| String realm, String account, String args) { |
| AccountManagerContainer accountManagerContainer = |
| new AccountManagerContainer((Activity)contentView.getContext(), |
| realm, account, args); |
| String[] logins = accountManagerContainer.getAccountLogins(null); |
| return logins.length != 0; |
| } |
| @CalledByNative |
| static InputStream openUrl(String url) { |
| return null; |
| } |
| @CalledByNative |
| private void activateHardwareAcceleration(final boolean activated, |
| final int iPid, final int iType, |
| final int iPrimaryID, final int iSecondaryID) { |
| if (!activated) { |
| return |
| } |
| } |
| @CalledByNativeUnchecked |
| private void uncheckedCall(int iParam); |
| """ |
| jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo') |
| jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) |
| called_by_natives = jni_generator.ExtractCalledByNatives(test_data) |
| golden_called_by_natives = [ |
| CalledByNative( |
| return_type='InnerClass', |
| system_class=False, |
| static=False, |
| name='showConfirmInfoBar', |
| method_id_var_name='showConfirmInfoBar', |
| java_class_name='', |
| params=[Param(datatype='int', name='nativeInfoBar'), |
| Param(datatype='String', name='buttonOk'), |
| Param(datatype='String', name='buttonCancel'), |
| Param(datatype='String', name='title'), |
| Param(datatype='Bitmap', name='icon')], |
| env_call=('Object', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='InnerClass', |
| system_class=False, |
| static=False, |
| name='showAutoLoginInfoBar', |
| method_id_var_name='showAutoLoginInfoBar', |
| java_class_name='', |
| params=[Param(datatype='int', name='nativeInfoBar'), |
| Param(datatype='String', name='realm'), |
| Param(datatype='String', name='account'), |
| Param(datatype='String', name='args')], |
| env_call=('Object', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='void', |
| system_class=False, |
| static=False, |
| name='dismiss', |
| method_id_var_name='dismiss', |
| java_class_name='InfoBar', |
| params=[], |
| env_call=('Void', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='boolean', |
| system_class=False, |
| static=True, |
| name='shouldShowAutoLogin', |
| method_id_var_name='shouldShowAutoLogin', |
| java_class_name='', |
| params=[Param(datatype='View', name='view'), |
| Param(datatype='String', name='realm'), |
| Param(datatype='String', name='account'), |
| Param(datatype='String', name='args')], |
| env_call=('Boolean', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='InputStream', |
| system_class=False, |
| static=True, |
| name='openUrl', |
| method_id_var_name='openUrl', |
| java_class_name='', |
| params=[Param(datatype='String', name='url')], |
| env_call=('Object', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='void', |
| system_class=False, |
| static=False, |
| name='activateHardwareAcceleration', |
| method_id_var_name='activateHardwareAcceleration', |
| java_class_name='', |
| params=[Param(datatype='boolean', name='activated'), |
| Param(datatype='int', name='iPid'), |
| Param(datatype='int', name='iType'), |
| Param(datatype='int', name='iPrimaryID'), |
| Param(datatype='int', name='iSecondaryID'), |
| ], |
| env_call=('Void', ''), |
| unchecked=False, |
| ), |
| CalledByNative( |
| return_type='void', |
| system_class=False, |
| static=False, |
| name='uncheckedCall', |
| method_id_var_name='uncheckedCall', |
| java_class_name='', |
| params=[Param(datatype='int', name='iParam')], |
| env_call=('Void', ''), |
| unchecked=True, |
| ), |
| ] |
| self.assertListEquals(golden_called_by_natives, called_by_natives) |
| h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', |
| [], called_by_natives) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // org/chromium/TestJni |
| |
| #ifndef org_chromium_TestJni_JNI |
| #define org_chromium_TestJni_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kTestJniClassPath[] = "org/chromium/TestJni"; |
| const char kInfoBarClassPath[] = "org/chromium/TestJni$InfoBar"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_TestJni_clazz = NULL; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_InfoBar_clazz = NULL; |
| } // namespace |
| |
| // Step 2: method stubs. |
| |
| static base::subtle::AtomicWord g_TestJni_showConfirmInfoBar = 0; |
| static ScopedJavaLocalRef<jobject> Java_TestJni_showConfirmInfoBar(JNIEnv* env, |
| jobject obj, jint nativeInfoBar, |
| jstring buttonOk, |
| jstring buttonCancel, |
| jstring title, |
| jobject icon) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_TestJni_clazz, |
| "showConfirmInfoBar", |
| |
| "(" |
| "I" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "Landroid/graphics/Bitmap;" |
| ")" |
| "Lorg/chromium/Foo$InnerClass;", |
| &g_TestJni_showConfirmInfoBar); |
| |
| jobject ret = |
| env->CallObjectMethod(obj, |
| method_id, nativeInfoBar, buttonOk, buttonCancel, title, icon); |
| base::android::CheckException(env); |
| return ScopedJavaLocalRef<jobject>(env, ret); |
| } |
| |
| static base::subtle::AtomicWord g_TestJni_showAutoLoginInfoBar = 0; |
| static ScopedJavaLocalRef<jobject> Java_TestJni_showAutoLoginInfoBar(JNIEnv* |
| env, jobject obj, jint nativeInfoBar, |
| jstring realm, |
| jstring account, |
| jstring args) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_TestJni_clazz, |
| "showAutoLoginInfoBar", |
| |
| "(" |
| "I" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| ")" |
| "Lorg/chromium/Foo$InnerClass;", |
| &g_TestJni_showAutoLoginInfoBar); |
| |
| jobject ret = |
| env->CallObjectMethod(obj, |
| method_id, nativeInfoBar, realm, account, args); |
| base::android::CheckException(env); |
| return ScopedJavaLocalRef<jobject>(env, ret); |
| } |
| |
| static base::subtle::AtomicWord g_InfoBar_dismiss = 0; |
| static void Java_InfoBar_dismiss(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InfoBar_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InfoBar_clazz, |
| "dismiss", |
| |
| "(" |
| ")" |
| "V", |
| &g_InfoBar_dismiss); |
| |
| env->CallVoidMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| |
| } |
| |
| static base::subtle::AtomicWord g_TestJni_shouldShowAutoLogin = 0; |
| static jboolean Java_TestJni_shouldShowAutoLogin(JNIEnv* env, jobject view, |
| jstring realm, |
| jstring account, |
| jstring args) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_STATIC>( |
| env, g_TestJni_clazz, |
| "shouldShowAutoLogin", |
| |
| "(" |
| "Landroid/view/View;" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| "Ljava/lang/String;" |
| ")" |
| "Z", |
| &g_TestJni_shouldShowAutoLogin); |
| |
| jboolean ret = |
| env->CallStaticBooleanMethod(g_TestJni_clazz, |
| method_id, view, realm, account, args); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_TestJni_openUrl = 0; |
| static ScopedJavaLocalRef<jobject> Java_TestJni_openUrl(JNIEnv* env, jstring |
| url) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_STATIC>( |
| env, g_TestJni_clazz, |
| "openUrl", |
| |
| "(" |
| "Ljava/lang/String;" |
| ")" |
| "Ljava/io/InputStream;", |
| &g_TestJni_openUrl); |
| |
| jobject ret = |
| env->CallStaticObjectMethod(g_TestJni_clazz, |
| method_id, url); |
| base::android::CheckException(env); |
| return ScopedJavaLocalRef<jobject>(env, ret); |
| } |
| |
| static base::subtle::AtomicWord g_TestJni_activateHardwareAcceleration = 0; |
| static void Java_TestJni_activateHardwareAcceleration(JNIEnv* env, jobject obj, |
| jboolean activated, |
| jint iPid, |
| jint iType, |
| jint iPrimaryID, |
| jint iSecondaryID) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_TestJni_clazz, |
| "activateHardwareAcceleration", |
| |
| "(" |
| "Z" |
| "I" |
| "I" |
| "I" |
| "I" |
| ")" |
| "V", |
| &g_TestJni_activateHardwareAcceleration); |
| |
| env->CallVoidMethod(obj, |
| method_id, activated, iPid, iType, iPrimaryID, iSecondaryID); |
| base::android::CheckException(env); |
| |
| } |
| |
| static base::subtle::AtomicWord g_TestJni_uncheckedCall = 0; |
| static void Java_TestJni_uncheckedCall(JNIEnv* env, jobject obj, jint iParam) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_TestJni_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_TestJni_clazz, |
| "uncheckedCall", |
| |
| "(" |
| "I" |
| ")" |
| "V", |
| &g_TestJni_uncheckedCall); |
| |
| env->CallVoidMethod(obj, |
| method_id, iParam); |
| |
| } |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kTestJniClassPath))); |
| g_InfoBar_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kInfoBarClassPath))); |
| return true; |
| } |
| |
| #endif // org_chromium_TestJni_JNI |
| """ |
| self.assertTextEquals(golden_content, h.GetContent()) |
| |
| def testCalledByNativeParseError(self): |
| try: |
| jni_generator.ExtractCalledByNatives(""" |
| @CalledByNative |
| public static int foo(); // This one is fine |
| |
| @CalledByNative |
| scooby doo |
| """) |
| self.fail('Expected a ParseError') |
| except jni_generator.ParseError, e: |
| self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines) |
| |
| def testFullyQualifiedClassName(self): |
| contents = """ |
| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.content.browser; |
| |
| import org.chromium.base.BuildInfo; |
| """ |
| self.assertEquals('org/chromium/content/browser/Foo', |
| jni_generator.ExtractFullyQualifiedJavaClassName( |
| 'org/chromium/content/browser/Foo.java', contents)) |
| self.assertEquals('org/chromium/content/browser/Foo', |
| jni_generator.ExtractFullyQualifiedJavaClassName( |
| 'frameworks/Foo.java', contents)) |
| self.assertRaises(SyntaxError, |
| jni_generator.ExtractFullyQualifiedJavaClassName, |
| 'com/foo/Bar', 'no PACKAGE line') |
| |
| def testMethodNameMangling(self): |
| self.assertEquals('closeV', |
| jni_generator.GetMangledMethodName('close', [], 'void')) |
| self.assertEquals('readI_AB_I_I', |
| jni_generator.GetMangledMethodName('read', |
| [Param(name='p1', |
| datatype='byte[]'), |
| Param(name='p2', |
| datatype='int'), |
| Param(name='p3', |
| datatype='int'),], |
| 'int')) |
| self.assertEquals('openJIIS_JLS', |
| jni_generator.GetMangledMethodName('open', |
| [Param(name='p1', |
| datatype='java/lang/String'),], |
| 'java/io/InputStream')) |
| |
| def testFromJavaP(self): |
| contents = """ |
| public abstract class java.io.InputStream extends java.lang.Object |
| implements java.io.Closeable{ |
| public java.io.InputStream(); |
| public int available() throws java.io.IOException; |
| public void close() throws java.io.IOException; |
| public void mark(int); |
| public boolean markSupported(); |
| public abstract int read() throws java.io.IOException; |
| public int read(byte[]) throws java.io.IOException; |
| public int read(byte[], int, int) throws java.io.IOException; |
| public synchronized void reset() throws java.io.IOException; |
| public long skip(long) throws java.io.IOException; |
| } |
| """ |
| jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), None) |
| self.assertEquals(10, len(jni_from_javap.called_by_natives)) |
| golden_content = """\ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file is autogenerated by |
| // base/android/jni_generator/jni_generator_tests.py |
| // For |
| // java/io/InputStream |
| |
| #ifndef java_io_InputStream_JNI |
| #define java_io_InputStream_JNI |
| |
| #include <jni.h> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| |
| using base::android::ScopedJavaLocalRef; |
| |
| // Step 1: forward declarations. |
| namespace { |
| const char kInputStreamClassPath[] = "java/io/InputStream"; |
| // Leaking this jclass as we cannot use LazyInstance from some threads. |
| jclass g_InputStream_clazz = NULL; |
| } // namespace |
| |
| namespace JNI_InputStream { |
| |
| // Step 2: method stubs. |
| |
| static base::subtle::AtomicWord g_InputStream_available = 0; |
| static jint Java_InputStream_available(JNIEnv* env, jobject obj) __attribute__ |
| ((unused)); |
| static jint Java_InputStream_available(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "available", |
| |
| "(" |
| ")" |
| "I", |
| &g_InputStream_available); |
| |
| jint ret = |
| env->CallIntMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_close = 0; |
| static void Java_InputStream_close(JNIEnv* env, jobject obj) __attribute__ |
| ((unused)); |
| static void Java_InputStream_close(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "close", |
| |
| "(" |
| ")" |
| "V", |
| &g_InputStream_close); |
| |
| env->CallVoidMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_mark = 0; |
| static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) |
| __attribute__ ((unused)); |
| static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "mark", |
| |
| "(" |
| "I" |
| ")" |
| "V", |
| &g_InputStream_mark); |
| |
| env->CallVoidMethod(obj, |
| method_id, p0); |
| base::android::CheckException(env); |
| |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_markSupported = 0; |
| static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) |
| __attribute__ ((unused)); |
| static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "markSupported", |
| |
| "(" |
| ")" |
| "Z", |
| &g_InputStream_markSupported); |
| |
| jboolean ret = |
| env->CallBooleanMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_readI = 0; |
| static jint Java_InputStream_readI(JNIEnv* env, jobject obj) __attribute__ |
| ((unused)); |
| static jint Java_InputStream_readI(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "read", |
| |
| "(" |
| ")" |
| "I", |
| &g_InputStream_readI); |
| |
| jint ret = |
| env->CallIntMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_readI_AB = 0; |
| static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) |
| __attribute__ ((unused)); |
| static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "read", |
| |
| "(" |
| "[B" |
| ")" |
| "I", |
| &g_InputStream_readI_AB); |
| |
| jint ret = |
| env->CallIntMethod(obj, |
| method_id, p0); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_readI_AB_I_I = 0; |
| static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray |
| p0, |
| jint p1, |
| jint p2) __attribute__ ((unused)); |
| static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray |
| p0, |
| jint p1, |
| jint p2) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "read", |
| |
| "(" |
| "[B" |
| "I" |
| "I" |
| ")" |
| "I", |
| &g_InputStream_readI_AB_I_I); |
| |
| jint ret = |
| env->CallIntMethod(obj, |
| method_id, p0, p1, p2); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_reset = 0; |
| static void Java_InputStream_reset(JNIEnv* env, jobject obj) __attribute__ |
| ((unused)); |
| static void Java_InputStream_reset(JNIEnv* env, jobject obj) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "reset", |
| |
| "(" |
| ")" |
| "V", |
| &g_InputStream_reset); |
| |
| env->CallVoidMethod(obj, |
| method_id); |
| base::android::CheckException(env); |
| |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_skip = 0; |
| static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) |
| __attribute__ ((unused)); |
| static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "skip", |
| |
| "(" |
| "J" |
| ")" |
| "J", |
| &g_InputStream_skip); |
| |
| jlong ret = |
| env->CallLongMethod(obj, |
| method_id, p0); |
| base::android::CheckException(env); |
| return ret; |
| } |
| |
| static base::subtle::AtomicWord g_InputStream_Constructor = 0; |
| static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) |
| __attribute__ ((unused)); |
| static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) { |
| /* Must call RegisterNativesImpl() */ |
| DCHECK(g_InputStream_clazz); |
| jmethodID method_id = |
| base::android::MethodID::LazyGet< |
| base::android::MethodID::TYPE_INSTANCE>( |
| env, g_InputStream_clazz, |
| "<init>", |
| |
| "(" |
| ")" |
| "V", |
| &g_InputStream_Constructor); |
| |
| jobject ret = |
| env->NewObject(g_InputStream_clazz, |
| method_id); |
| base::android::CheckException(env); |
| return ScopedJavaLocalRef<jobject>(env, ret); |
| } |
| |
| // Step 3: RegisterNatives. |
| |
| static bool RegisterNativesImpl(JNIEnv* env) { |
| |
| g_InputStream_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| base::android::GetUnscopedClass(env, kInputStreamClassPath))); |
| return true; |
| } |
| } // namespace JNI_InputStream |
| |
| #endif // java_io_InputStream_JNI |
| """ |
| self.assertTextEquals(golden_content, jni_from_javap.GetContent()) |
| |
| def testREForNatives(self): |
| # We should not match "native SyncSetupFlow" inside the comment. |
| test_data = """ |
| /** |
| * Invoked when the setup process is complete so we can disconnect from the |
| * native-side SyncSetupFlowHandler. |
| */ |
| public void destroy() { |
| Log.v(TAG, "Destroying native SyncSetupFlow"); |
| if (mNativeSyncSetupFlow != 0) { |
| nativeSyncSetupEnded(mNativeSyncSetupFlow); |
| mNativeSyncSetupFlow = 0; |
| } |
| } |
| private native void nativeSyncSetupEnded( |
| int nativeAndroidSyncSetupFlowHandler); |
| """ |
| jni_from_java = jni_generator.JNIFromJavaSource(test_data, 'foo/bar') |
| |
| def testRaisesOnNonJNIMethod(self): |
| test_data = """ |
| class MyInnerClass { |
| private int Foo(int p0) { |
| } |
| } |
| """ |
| self.assertRaises(SyntaxError, |
| jni_generator.JNIFromJavaSource, |
| test_data, 'foo/bar') |
| |
| def testJniSelfDocumentingExample(self): |
| script_dir = os.path.dirname(sys.argv[0]) |
| content = file(os.path.join(script_dir, 'SampleForTests.java')).read() |
| golden_content = file(os.path.join(script_dir, |
| 'golden_sample_for_tests_jni.h')).read() |
| jni_from_java = jni_generator.JNIFromJavaSource( |
| content, 'org/chromium/example/jni_generator/SampleForTests') |
| self.assertTextEquals(golden_content, jni_from_java.GetContent()) |
| |
| def testNoWrappingPreprocessorLines(self): |
| test_data = """ |
| package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday; |
| |
| class ReallyLongClassNamesAreAllTheRage { |
| private static native int nativeTest(); |
| } |
| """ |
| jni_from_java = jni_generator.JNIFromJavaSource( |
| test_data, ('com/google/lookhowextremelylongiam/snarf/' |
| 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage')) |
| jni_lines = jni_from_java.GetContent().split('\n') |
| line = filter(lambda line: line.lstrip().startswith('#ifndef'), |
| jni_lines)[0] |
| self.assertTrue(len(line) > 80, |
| ('Expected #ifndef line to be > 80 chars: ', line)) |
| |
| def testImports(self): |
| import_header = """ |
| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.content.app; |
| |
| import android.app.Service; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.graphics.SurfaceTexture; |
| import android.os.Bundle; |
| import android.os.IBinder; |
| import android.os.ParcelFileDescriptor; |
| import android.os.Process; |
| import android.os.RemoteException; |
| import android.util.Log; |
| import android.view.Surface; |
| |
| import java.util.ArrayList; |
| |
| import org.chromium.base.CalledByNative; |
| import org.chromium.base.JNINamespace; |
| import org.chromium.content.app.ContentMain; |
| import org.chromium.content.browser.SandboxedProcessConnection; |
| import org.chromium.content.common.ISandboxedProcessCallback; |
| import org.chromium.content.common.ISandboxedProcessService; |
| import org.chromium.content.common.SurfaceCallback; |
| import org.chromium.content.common.WillNotRaise.AnException; |
| import org.chromium.content.common.WillRaise.AnException; |
| |
| import static org.chromium.Bar.Zoo; |
| |
| class Foo { |
| public static class BookmarkNode implements Parcelable { |
| } |
| public interface PasswordListObserver { |
| } |
| } |
| """ |
| jni_generator.JniParams.SetFullyQualifiedClass( |
| 'org/chromium/content/app/Foo') |
| jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header) |
| self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in |
| jni_generator.JniParams._imports) |
| self.assertTrue('Lorg/chromium/Bar/Zoo' in |
| jni_generator.JniParams._imports) |
| self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in |
| jni_generator.JniParams._inner_classes) |
| self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in |
| jni_generator.JniParams._inner_classes) |
| self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner', |
| jni_generator.JniParams.JavaToJni('ContentMain.Inner')) |
| self.assertRaises(SyntaxError, |
| jni_generator.JniParams.JavaToJni, |
| 'AnException') |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |