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