## 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.