@@ -480,6 +480,57 @@ public <G> void testDeclareConstructor() throws Exception {
480480 assertEquals (0xabcd , a .get (instance ));
481481 }
482482
483+ @ Test
484+ public void testDeclareNativeMethod () throws Exception {
485+ /*
486+ * class Generated {
487+ * public Generated() {
488+ * }
489+ * public native void nativeMethod();
490+ * }
491+ */
492+
493+ addDefaultConstructor ();
494+ String nativeMethodName = "nativeMethod" ;
495+ MethodId <?, Void > nativeMethodToGenerate = GENERATED .getMethod (TypeId .VOID , nativeMethodName );
496+ dexMaker .declare (nativeMethodToGenerate , java .lang .reflect .Modifier .PUBLIC | java .lang .reflect .Modifier .NATIVE );
497+
498+ Class <?> generatedClass = generateAndLoad ();
499+ Object instance = generatedClass .getConstructor ().newInstance ();
500+ Method nativeMethod = instance .getClass ().getMethod (nativeMethodName );
501+
502+ assertTrue ((nativeMethod .getModifiers () & NATIVE ) != 0 );
503+ assertTrue ((nativeMethod .getModifiers () & PUBLIC ) != 0 );
504+ assertEquals (void .class , nativeMethod .getReturnType ());
505+ assertEquals (nativeMethodName , nativeMethod .getName ());
506+ assertEquals (nativeMethod .getParameterTypes ().length , 0 );
507+ }
508+
509+ @ Test
510+ public void testDeclareAbstractClassWithAbstractMethod () throws Exception {
511+ /*
512+ * public abstract class AbstractClass {
513+ * public abstract void abstractMethod();
514+ * }
515+ */
516+
517+ dexMaker .declare (GENERATED , "AbstractClass.java" , PUBLIC , TypeId .OBJECT );
518+
519+ String abstractMethodName = "abstractMethod" ;
520+ MethodId <?, Void > nativeMethodToGenerate = GENERATED .getMethod (TypeId .VOID , abstractMethodName );
521+ dexMaker .declare (nativeMethodToGenerate , java .lang .reflect .Modifier .PUBLIC | ABSTRACT );
522+
523+ Class <?> generatedClass = generateAndLoad ();
524+ Method nativeMethod = generatedClass .getMethod (abstractMethodName );
525+
526+ assertTrue ((nativeMethod .getModifiers () & ABSTRACT ) != 0 );
527+ assertTrue ((nativeMethod .getModifiers () & PUBLIC ) != 0 );
528+ assertEquals (void .class , nativeMethod .getReturnType ());
529+ assertEquals (abstractMethodName , nativeMethod .getName ());
530+ assertEquals (nativeMethod .getParameterTypes ().length , 0 );
531+
532+ }
533+
483534 @ Test
484535 public void testReturnType () throws Exception {
485536 testReturnType (boolean .class , true );
@@ -1955,26 +2006,6 @@ public void testPrivateClassesAreUnsupported() {
19552006 }
19562007 }
19572008
1958- @ Test
1959- public void testAbstractMethodsAreUnsupported () {
1960- MethodId <?, Void > methodId = GENERATED .getMethod (TypeId .VOID , "call" );
1961- try {
1962- dexMaker .declare (methodId , ABSTRACT );
1963- fail ();
1964- } catch (IllegalArgumentException expected ) {
1965- }
1966- }
1967-
1968- @ Test
1969- public void testNativeMethodsAreUnsupported () {
1970- MethodId <?, Void > methodId = GENERATED .getMethod (TypeId .VOID , "call" );
1971- try {
1972- dexMaker .declare (methodId , NATIVE );
1973- fail ();
1974- } catch (IllegalArgumentException expected ) {
1975- }
1976- }
1977-
19782009 @ Test
19792010 public void testSynchronizedFieldsAreUnsupported () {
19802011 try {
@@ -2005,7 +2036,6 @@ public void testInitialValueWithNonStaticField() {
20052036 // TODO: don't generate multiple times (?)
20062037 // TODO: test array types
20072038 // TODO: test generating an interface
2008- // TODO: declare native method or abstract method
20092039 // TODO: get a thrown exception 'e' into a local
20102040 // TODO: move a primitive or reference
20112041
0 commit comments