OJI API Test Analysis. Interfaces implemented by OJI module. JNIEnv.

Important note concerning JNI testing (from JNI specification):

Reporting Programming Errors

The JNI does not check for programming errors such as passing in NULL pointers or illegal argument types. Illegal argument
types includes such things as using a normal Java object instead of a Java class object. The JNI does not check for these
programming errors for the following reasons:

      Forcing JNI functions to check for all possible error conditions degrades the performance of normal (correct) native
      methods.
      In many cases, there is not enough runtime type information to perform such checking.

Most C library functions do not guard against programming errors. The printf() function, for example, usually causes a
runtime error, rather than returning an error code, when it receives an invalid address. Forcing C library functions to check for
all possible error conditions would likely result in such checks to be duplicated--once in the user code, and then again in the
library.

The programmer must not pass illegal pointers or arguments of the wrong type to JNI functions. Doing so could result in
arbitrary consequences, including a corrupted system state or VM crash.

So the purposes of  testing OJI JNI implementation are next:
- checking on correctnesses in "normal" cases
- checking that this implementation (that is really wrapper  on implementation provided by Java Plugin) is not degrading the provided implementation in "negative" cases
 

Testcases description:

jint GetVersion();
Test cases number: 1

jclass DefineClass(jobject loader, const jbyte *buf, jsize bufLen);
Combinations:
 
loader buf bufLen Expected result
NON NULL correctly formed correct Class correctly defined
- incorrectly formed - NULL
- NULL - NULL
NULL correctly formed - NULL

Test cases number: 4

jclass FindClass(const char *name);
Combinations:
 
name Expected result
Name of existing class Correct class is found
With array signature character ("[") Correct class is found
Name of existing interface Correct class is found
Name of existing abstract class Correct class is found
Name of non-existing class NULL
Empty string NULL
NULL NULL

Test cases number: 7

jclass GetSuperclass(jclass clazz);
Combinations:
 
clazz Expected result
Any class (not java.lang.Object) superclass
java.lang.Object NULL
interface NULL
NULL NULL

Test cases number: 4

jboolean IsAssignableFrom(jclass clazz1, jclass clazz2);
Combinations:
 
clazz1 clazz2 Expected result
Any class the same class JNI_TRUE
Subclass of the clazz2 Any class JNI_TRUE
Implements the clazz2 Any interface JNI_TRUE
Any class Any class that isn't the superclass of clazz1 JNI_FALSE
NULL NULL JNI_FALSE

Test cases number: 5

jint Throw(jthrowable obj);
Combinations:
 
obj Expected result
Instance of any subclass of throwable 0, should be really thrown
NULL negative, should not be thrown

Test cases number: 2

jint ThrowNew(jclass clazz, const char *message);
Combinations:
 
clazz message Expected result
Any subclass of throwable some non-empty message 0, should be really thrown
- empty message 0, should be really thrown
- NULL 0, should be really thrown
Isn't subclass of throwable some non-empty message negative, should not be thrown
NULL NULL negative, should not be thrown

Test cases number: 5

jthrowable ExceptionOccurred();
Combinations:
 
Expected result
there exception is being thrown the being thrown object
no exception is currently being thrown NULL

Test cases number: 2

void ExceptionDescribe();
Combinations:
 
Expected result
there exception is being thrown the exception is printed
no exception is currently being thrown no effect

Test cases number: 2

void ExceptionClear();
Combinations:
 
Expected result
there exception is being thrown the exception is cleared
no exception is currently being thrown no effect

Test cases number: 2

void FatalError(const char *msg);
Combinations:
 
msg Expected result
the non-empty message the function doesn't return, crash
the empty message the function doesn't return, crash
NULL the function doesn't return, crash

Test cases number: 3

jobject NewGlobalRef(jobject obj);
Combinations:
 
obj Expected result
some jobject new global ref
NULL ?(NULL)

Test cases number: 2

void DeleteGlobalRef(jobject globalRef);
Combinations:
 
globalRef Expected result
Some jobject  returned as new global ref global ref is deleted
NULL no effect

Test cases number: 2

void DeleteLocalRef(jobject localRef);
Combinations:
 
localRef Expected result
some jobject local ref is deleted
NULL no effect

Test cases number: 2

jobject AllocObject(jclass clazz);
Combinations:
 
clazz Expected result
Any non-abstract class reference on newly constructed java object
abstract class NULL, InstantiationException is thrown
interface NULL, InstantiationException is thrown
NULL NULL

Test cases number: 4

jobject NewObject(jclass clazz, jmethodID methodID, ...);

jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue *args);

jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args);

Combinations:
 
clazz methodID args Expected result
Any non-abstract class ID of public, private, package visible or protected constructor with no args No arguments reference on new object
- ID of public constructor that throws exception - reference on new object, exception is thrown
- ID of public with args (all primitive and Object) required args reference on new object
- non-constructor method ID - NULL
Abstract class - - NULL, InstantiationException is thrown
NULL - - NULL

Test cases number for every method: 9
Test cases number: 27

jclass GetObjectClass(jobject obj);
Combinations:
 
obj Expected result
Some jobject  it's class 

Test cases number: 1

jboolean IsInstanceOf(jobject obj, jclass clazz);
Combinations:
 
obj clazz Expected result
some jobject it's class JNI_TRUE
- it's superclass JNI_TRUE
- class that isn't it's class or superclass JNI_FALSE
NULL any class JNI_TRUE
NULL NULL ?(JNI_TRUE)

Test cases number: 5

jboolean IsSameObject(jobject ref1, jobject ref2);
Combinations:
 
ref1 ref2 Expected result
some reference on the Java object reference on the same object JNI_TRUE
- reference on other object JNI_FALSE
- NULL JNI_FALSE
NULL NULL JNI_TRUE

Test cases number: 4

jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);
Combinations (based on next variations):
Field types:
boolean
byte
char
short
int
long
float
double
object(non-array)
array

Access modifiers:
public
protected
no modifier - package
private

Other modifiers:
no-modifier
final
transient
volatile

Inherited from:
not inherited
superclass

So the <selected> combinations for variable will be (note: the {other modifiers} will not be combined
one with another):
 
Number
{Field types} public no-modifier not inherited 10
{int, object} {access modifiers} no-modifier {inherited from} 16
{int, object} public {other modifiers} not inherited 8
Total: 34 - 4(intersection)=30
 
clazz name sig Expected result
some class <selected> existing variable  appropriate field ID, except the cases of private in superclass - 
NULL will be in such cases
- non-existing  some sig NULL
- existing some incorrect sig NULL
- NULL some sig NULL
- existing NULL NULL
NULL some name some sig NULL

Test cases number: 35

NativeType Get<type>Field(jobject obj, jfieldID fieldID);

The test cases for these methods are the testcases of GetFieldID method where correct field ID should be returned with varying on field values. Concerning the "negative" cases: it is explicitly specified what parameters should be valid.
Values variations:
jboolean: JNI_TRUE, JNI_FALSE
jbyte: min, max
jchar: some of ASCII (only 1st byte is significant), some character  with 2 significant bytes
jshort: min, max
jint: min, max
jlong: min, max
jfloat: min, max
jdouble: min, max
jobject(non-array): NULL, NON-NULL
jarray: NULL, NON-NULL

Test cases number: 58
 

void Set<type>Field(jobject obj, jfieldID fieldID, NativeType value);

In addition to the possible variations of the variable the next variations can be used for values of
different types:
Values variations:
jboolean: JNI_TRUE, JNI_FALSE
jbyte: min, max
jchar: some of ASCII (only 1st byte is significant), some character  with 2 significant bytes
jshort: min, max
jint: min, max
jlong: min, max
jfloat: min, max
jdouble: min, max
jobject(non-array): NULL, NON-NULL
jarray: NULL, NON-NULL
 
 
obj fieldID value Expected result
some obj valid fieldID for variable from <selected> (where it possible, i.e. except the cases of private in superclass )  corresponding to variable type from   {values variations} The value will be correctly set, except the cases of final.

Note concerning the "negative" cases with obj and fieldID parameters: it is specified what this parameters should be valid.

Test cases number: 58

jmethodID GetMethodID(jclass clazz, const char *name, const char *sig);
Combinations (based on next variations):
Class:
non-abstract
abstract
interface

Access modifiers:
public
protected
no modifier - package
private

Other modifiers:
no-modifier
final
synchronized
native
abstract

Inherited from:
not inherited
superclass
interface

So the <selected> methods will be:
Number
interface not inherited and 
inherited from superinterface
2
abstract class inherited from interface 1
abstract class except private abstract not inherited and 
inherited from superclass
6
non-abstract {access modifiers} no-modifier not inherited and 
inherited from superclass
8
non-abstract public except abstract not inherited 4
non-abstract public no-modifier override 1
constructor in abstract and non-abstract {access modifiers} no-modifier not inherited 8
Total: 30-1(intersection)=29

Varying on signatures:
"()V"
"(ZBCLSIJFDL<some class>;[L<some class>;)V"
"(ZBCLSIJFDL<some class>;[L<some class>;)I"
"(ZBCLSIJFDL<some class>;[L<some class>;)L<some class>;"
"(ZBCLSIJFDL<some class>;[L<some class>;)[L<some class>;"
So in <selected> set will be added these varying for public non-inherited method of non-abstract class.
Total: +5
 
clazz name sig Expected result
some class name of the existing method from <selected> correct signature Method ID, except the cases of private in superclass - NULL should be returned in these cases
name of non-existing method some sig NULL
name of existing method incorrect sig NULL
NULL some sig NULL
name of existing method NULL NULL
NULL some name some sig NULL
Test cases number:  39
 

NativeType Call<type>Method(jobject obj, jmethodID methodID, ...);

NativeType Call<type>MethodA(jobject obj, jmethodID methodID, jvalue *args);

NativeType Call<type>MethodV(jobject obj, jmethodID methodID, va_list args);

Combinations:
Note: The implementation under testing wrapes the nsISecureEnv that  exports the only one CallMethod which accepts the arguments in the form of jvalue* and is used for implementation of all these methods. So the <selected> combinations (based on modifiers/inheritance) from GetMethodID method will be used only with one method - CallIntMethod. The combinations based on varying on values will be used for all 3 set of methods.
<selected> combinations (based on modifiers/inheritance)
 
Number
non-abstract {access modifiers} no-modifier not inherited and 
inherited from superclass
8
non-abstract public except abstract not inherited 4
non-abstract public no-modifier override 1

Values variations:
 
Combination 1 Combination 2
jboolean JNI_TRUE JNI_FALSE
jbyte min max
jchar some of ASCII (only 1st byte is significant) some character  with 2 significant bytes
jshort min max
jint min max
jlong min max
jfloat min max
jdouble min max
jobject(non-array) NULL NON-NULL
jarray NULL NON-NULL
Return values for methods
<type> is Boolean JNI_TRUE JNI_FALSE
<type> is Byte min max
<type> is Char some of ASCII (only 1st byte is significant) some character  with 2 significant bytes
<type> is Short min max
<type> is Int min max
<type> is Long min max
<type> is Float min max
<type> is Double min max
<type> is Object NULL NON-NULL
<type> is Object NULL jarray NON-NULL jarray
<type> is Void - -

 
obj jmethodID args Expected result Number
some obj CallIntMethod ID of <selected> method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)I" some args corresponding result 12
some obj Call<type>Method
Call<type>MethodA
Call<type>MethodV
ID of public non-inherited method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)?" where ? is run on the all set of possibilities  Combination 1 and 2 corresponding result 66
some obj CallIntMethod
CallIntMethodA
CallIntMethodV
ID of public non-inherited method with signature "()I"  corresponding result 3
some obj CallIntMethod
CallIntMethodA
CallIntMethodV
ID of public non-inherited method that throws exception Exception should be thrown 3
some obj CallIntMethod ID of public inherited method which was received using superclass corresponding result 1

Number of test cases: 84
 

NativeType CallNonvirtual<type>Method(jobject obj, jclass clazz, jmethodID methodID, ...);

NativeType CallNonvirtual<type>MethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);

NativeType CallNonvirtual<type>MethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);

Combinations:
Note: things concerning inheritance are pointed out for clazz parameter (for example if it is said "non-inherited method" then it means that this method is defined in clazz)
 
obj clazz jmethodID args Expected result Number
some obj superclass,
overriding methods exist in the class of the obj
CallNonvirtualIntMethod ID of <selected> method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)I" some args corresponding result 12
some obj the  class of the object CallNonvirtualIntMethod ID of the overriding methods  in the previous row of this table some args corresponding result 12
some obj superclass CallNonvirtual<type>Method
CallNonvirtual<type>MethodA
CallNonvirtual<type>MethodV
ID of public non-inherited method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)?" where ? is run on the all set of possibilities  Combination 1 and 2 corresponding result 66
some obj superclass CallNonvirtualIntMethod
CallNonvirtualIntMethodA
CallNonvirtualIntMethodV
ID of public non-inherited method with signature "()I"  corresponding result 3
some obj superclass CallNonvirtualIntMethod
CallNonvirtualIntMethodA
CallNonvirtualIntMethodV
ID of public non-inherited method that throws exception Exception should be thrown 3

Number of test cases: 96

jfieldID GetStaticFieldID(jclass clazz, const char *name, const char *sig);
Combinations (based on next variations):
Field types:
boolean
byte
char
short
int
long
float
double
object(non-array)
array

Access modifiers:
public
protected
no modifier - package
private

Other modifiers:
no-modifier
final
transient
volatile

Inherited from:
not inherited
superclass
interface

So the <selected> combinations for static variable will be (note: the {other modifiers} will not be combined
one with another):
For classes:
Number
{Field types} public no-modifier not inherited 10
{int, object} {access modifiers} no-modifier inherited from superclass and not inherited 16
{int, object} inherited from interface 2
{int, object} public {other modifiers} not inherited 8
Total: 36 - 4(intersection)=32
For interfaces will be considered 4 cases: {int, object} inherited and not-inherited from superinterface
 
clazz name sig Expected result
some class <selected> existing variable  appropriate field ID, except the cases of private in superclass - 
NULL will be in such cases
- non-existing  some sig NULL
- existing some incorrect sig NULL
- NULL some sig NULL
- existing NULL NULL
NULL some name some sig NULL

Note: to check the correctnesses of received field ID the GetStatic<type>Field methods will be used. So it will also be  the tests on these methods.

Test cases number: 41
 

NativeType GetStatic<type>Field(jclass clazz, jfieldID fieldID);

The test cases for these methods are the testcases of GetStaticFieldID method where correct field ID should be returned with varying on field values. Concerning the "negative" cases: it is fully undefined cases.

Test cases number: 70

void SetStatic<type>Field(jclass clazz, jfieldID fieldID, NativeType value);

In addition to the possible variations of the variable based on its type/modifiers/inheritance the next variations can be used for values of
different types:
Values variations:
jboolean: JNI_TRUE, JNI_FALSE
jbyte: min, max
jchar: some of ASCII (only 1st byte is significant), some character  with 2 significant bytes
jshort: min, max
jint: min, max
jlong: min, max
jfloat: min, max
jdouble: min, max
jobject(non-array): NULL, NON-NULL
jarray: NULL, NON-NULL
 
 
obj fieldID value Expected result
some obj valid fieldID for variable from <selected> (where it possible, i.e. except the cases of private in superclass )  corresponding to variable type from   {values variations} The value will be correctly set, except the cases of final (including interface cases).

Note concerning the "negative" cases with obj and fieldID parameters:  it is fully undefined cases.

Test cases number: 58

jmethodID GetStaticMethodID(jclass clazz, const char *name, const char *sig);

Access modifiers:
public
protected
no modifier - package
private

Other modifiers:
no-modifier
final
synchronized
native

Inherited from:
not inherited
superclass
 

So the <selected> methods will be:
Number
{access modifiers} no-modifier not inherited and 
inherited from superclass
8
public {other modifiers} not inherited 4
public no-modifier override 1
Total: 12

Varying on signatures:
"()V"
"(ZBCLSIJFDL<some class>;[L<some class>;)V"
"(ZBCLSIJFDL<some class>;[L<some class>;)I"
"(ZBCLSIJFDL<some class>;[L<some class>;)L<some class>;"
"(ZBCLSIJFDL<some class>;[L<some class>;)[L<some class>;"
So in <selected> set will be added these varying for public non-inherited method.
Total: +5
 
clazz name sig Expected result
some class name of the existing method from <selected> correct signature Method ID, except the cases of private in superclass - NULL should be returned in these cases
name of non-existing method some sig NULL
name of existing method incorrect sig NULL
NULL some sig NULL
name of existing method NULL NULL
NULL some name some sig NULL
Test cases number:  22

NativeType CallStatic<type>Method(jclass clazz, jmethodID methodID, ...);

NativeType CallStatic<type>MethodA(jclass clazz, jmethodID methodID, jvalue *args);

NativeType CallStatic<type>MethodV(jclass clazz, jmethodID methodID, va_list args);

Note: The implementation under testing wrapes the nsISecureEnv that  exports the only one CallStaticMethod which accepts the arguments in the form of jvalue* and is used for implementation of all these methods. So the <selected> combinations (based on modifiers/inheritance) from GetStaticMethodID method will be used only with one method - CallStaticIntMethod. The combinations based on varying on values will be used for all 3 set of methods.
<selected> combinations (based on modifiers/inheritance)
Number
{access modifiers} no-modifier not inherited and 
inherited from superclass
8
public {other modifiers} not inherited 4
public no-modifier override 1

Values variations:
 
Combination 1 Combination 2
jboolean JNI_TRUE JNI_FALSE
jbyte min max
jchar some of ASCII (only 1st byte is significant) some character  with 2 significant bytes
jshort min max
jint min max
jlong min max
jfloat min max
jdouble min max
jobject(non-array) NULL NON-NULL
jarray NULL NON-NULL
Return values for methods
<type> is Boolean JNI_TRUE JNI_FALSE
<type> is Byte min max
<type> is Char some of ASCII (only 1st byte is significant) some character  with 2 significant bytes
<type> is Short min max
<type> is Int min max
<type> is Long min max
<type> is Float min max
<type> is Double min max
<type> is Object NULL NON-NULL
<type> is Object NULL jarray NON-NULL jarray
<type> is Void - -

 
clazz jmethodID args Expected result Number
some class CallStaticIntMethod ID of <selected> method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)I" some args corresponding result 12
some class CallStatic<type>Method
CallStatic<type>MethodA
CallStatic<type>MethodV
ID of public non-inherited method with signature "(ZBCLSIJFDL<some class>;[L<some class>;)?" where ? is run on the all set of possibilities  Combination 1 and 2 corresponding result 66
some class CallStaticIntMethod
CallStaticIntMethodA
CallStaticIntMethodV
ID of public non-inherited method with signature "()I"  corresponding result 3
some class CallStaticIntMethod
CallStaticIntMethodA
CallStaticIntMethodV
ID of public non-inherited method that throws exception Exception should be thrown 3

Number of test cases: 84

jstring NewString(const jchar *unicodeChars, jsize len);

Combinations:
 
unicodeChars len Expected result
NULL 0 NULL
correct pointer 0 empty string
correct pointer correct length correct string

Number of test cases: 3

jsize GetStringLength(jstring string);

Combinations:
 
string Expected result
non-empty string object correct length
empty string object 0
NULL 0

Number of test cases: 3

const jchar * GetStringChars(jstring string, jboolean *isCopy);

Combinations:
 
string isCopy Expected result
non-empty string object NON-NULL correct pointer, some value in isCopy
empty string object NON-NULL correct pointer, some value in isCopy
NULL NON-NULL NULL
non-empty string object NULL correct pointer

Number of test cases: 4

void ReleaseStringChars(jstring string, const jchar *chars);

Combinations:
 
string chars Expected result
string object correct pointer
NULL NULL ?(no crash)

Number of test cases: 2

jstring NewStringUTF(const char *bytes);

Combinations:
bytes Expected result
non-empty string correct string object
empty string correct empty string object
NULL NULL

Number of test cases: 3

jsize GetStringUTFLength(jstring string);

Combinations:
string Expected result
non-empty string correct length
empty string correct length
NULL 0

Number of test cases: 3

const char* GetStringUTFChars(jstring string, jboolean *isCopy);

Combinations:
string isCopy Expected result
non-empty string object NON-NULL correct pointer, some value in isCopy
empty string object NON-NULL correct pointer, some value in isCopy
NULL NON-NULL NULL
non-empty string object NULL correct pointer

Number of test cases: 4

void ReleaseStringUTFChars(jstring string, const char *utf);

Combinations
string utf Expected result
string object correct pointer
NULL NULL ?(no crash)

Number of test cases: 2

jsize GetArrayLength(jarray array);

Combinations:
array Expected result
non-empty array length
empty 0
NULL 0

Number of test cases: 3

jarray NewObjectArray(jsize length, jclass elementClass, jobject initialElement);

Combinations:
 
length elementClass initialElement Expected result
0 some class some object of class empty array
> 0  some class some object of class correct array
>0 some class NULL correct array
<0 some class some object of class NULL
> 0 some class  some object of inconsistent class NULL
>0 NULL some object NULL

Number of test cases: 6

jobject GetObjectArrayElement(jobjectArray array, jsize index);

Combinations:
array index Expected result
some array inside bounds correct element in cases NULL and NON-NULL
some array <0 and => length ArrayIndexOutOfBoundsException should be thrown
NULL some value NULL

Number of test cases: 5

void SetObjectArrayElement(jobjectArray array, jsize index, jobject value);

Combinations:
array index value Expected result
some array inside bounds some value of correct class element will be set
some array inside bounds NULL element will be set
some array <0 and => length some value of correct class ArrayIndexOutOfBoundsException should be thrown
some array inside bounds some value of incorrect class ArrayStoreException should be thrown

Number of test cases: 5
 

ArrayType New<PrimitiveType>Array(jsize length);

Combinations:
length Expected result
<0 NULL
0 0-length array
>0  correct array

Number of test cases: 24

NativeType *Get<PrimitiveType>ArrayElements(ArrayType array, jboolean *isCopy);

Combinations:
array isCopy Expected result
some non-empty array NON-NULL correct array of native types, isCopy value is set
some non-empty array NULL correct array of native types
NULL NON-NULL NULL

Number of test cases: 24

void Release<PrimitiveType>ArrayElements(ArrayType array, NativeType *elems, jint mode);

Combinations:
array elems mode Expected result
some array correct pointer  0 changes reflected, buffer freed
some array correct pointer JNI_COMMIT changes reflected, buffer isn't freed if was a copy
some array correct pointer JNI_ABORT only buffer freed if was a copy

Number of test cases: 24

void Get<PrimitiveType>ArrayRegion(ArrayType array, jsize start, jsize len, NativeType *buf);

Combinations:
array start len buf Expected result
some array inside bounds start+len inside bounds correct correct elements are copied
some array of Int type <0 or start+len=>length correct ArrayIndexOutOfBoundsException should be thrown
NULL for Int method nothing should be copied
some array of Int type inside bounds start+len inside bounds NULL nothing should be copied

Number of test cases: 8+3=10

void Set<PrimitiveType>ArrayRegion(ArrayType array, jsize start, jsize len, NativeType *buf);

Combinations:
array start len buf Expected result
some array inside bounds start+len inside bounds correct correct elements are copied
some array of Int type <0 or start+len=>length correct ArrayIndexOutOfBoundsException should be thrown
NULL for Int method nothing should be copied
some array of Int type inside bounds start+len inside bounds NULL nothing should be copied

Number of test cases: 8+3=10

jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);

Combinations:
clazz methods nMethods Expected result
some class 2-3 correct method structures correct 0, methods should be bound
some class incorrect method structure:
unexistent name,
incorrect signature
correct negative value, NoSuchMethodError should be thrown
some class NULL 0 ?(0, nothing to bound)

Number of test cases: 4

jint UnregisterNatives(jclass clazz);

Combinations:
clazz Expected result
class with native methods 0, methods shoud be unbound
class w/o native methods ?(0, nothing to unbound)
NULL ?(0, nothing to unbound)

Number of test cases: 3

jint MonitorEnter(jobject obj);

Combinations:
object Expected result
NON-NULL, one thread takes and repeats 0, should be owned by thread
NON_NULL, 2 threads one owns, second doesn't
NULL negative value

Number of test cases: 3

jint MonitorExit(jobject obj);

Combinations:
object Expected result
NON_NULL, thread owns the monitor 0 returned, second thread can get the monitor 
NON_NULL, thread doesn't own the monitor negative value
NULL negative value

Number of test cases: 3

jint GetJavaVM(JavaVM **vm);

Combinations:
vm Expected result
NON-NULL 0, pointer should be placed
NULL negative value

Number of test cases: 2

Grand total: 877.