- Added unit test facilities for the dll
git-svn-id: https://svn.code.sf.net/p/libusbjava/code/trunk@298 94ad28fe-ef68-46b1-9651-e7ae4fcf1c4c
This commit is contained in:
234
LibusbJava/test/LibusbJavaTest.cpp
Normal file
234
LibusbJava/test/LibusbJavaTest.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
#include <stdio.h>
|
||||
#include <jni.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
# include <windows.h>
|
||||
|
||||
typedef HINSTANCE tLibHandle;
|
||||
typedef FARPROC tCallbackPtr;
|
||||
#else
|
||||
# error "Unit-Tests are not available on this platform"
|
||||
#endif
|
||||
|
||||
#include "CuTest.h"
|
||||
|
||||
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
|
||||
#define USER_CLASSPATH "../java/bin" /* where Prog.class is */
|
||||
|
||||
extern CuSuite* CuGetLibusbJavaSuite(JNIEnv *env);
|
||||
|
||||
const char *lib_paths[] = {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
"server\\jvm.dll",
|
||||
"client\\jvm.dll",
|
||||
"..\\jre\\bin\\server\\jvm.dll",
|
||||
"..\\jre\\bin\\client\\jvm.dll",
|
||||
#else
|
||||
# error "Library names are unknown for this platform"
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/*! \brief Signature of the JNI call for creating a new VM */
|
||||
typedef jint (CALLBACK *tJavaVMcreate)(JavaVM** jvm, void** env, JavaVMInitArgs* args);
|
||||
|
||||
/*! \brief Structure holding the data for the created JVM */
|
||||
typedef struct JVM {
|
||||
JavaVM *jvm; /*!< Pointer to the JVM the tests run in */
|
||||
JNIEnv *env; /*!< Pointer to the environment received while creating the
|
||||
JVM */
|
||||
}tJVM;
|
||||
|
||||
/*! \brief Contains Environment data for the test program */
|
||||
static struct
|
||||
{
|
||||
struct {
|
||||
tLibHandle lib; /*!< Contains the handle for the loaded JVM-Library */
|
||||
tJavaVMcreate VMcreate; /*!< Holds the pointer to the call for creating a JVM
|
||||
instance. */
|
||||
}jni;
|
||||
|
||||
tJVM jvm; /*!< Contains the data for the created JVM used
|
||||
for tests. */
|
||||
|
||||
JNIEnv* thread_env; /*!< Holds the pointer to the environment that can be
|
||||
used for the tests. (after the thread has been
|
||||
attached) */
|
||||
}globals = { { NULL, NULL }, { NULL, NULL }, NULL };
|
||||
|
||||
static inline int CreateVM(tJVM *vmdata);
|
||||
static inline tCallbackPtr JvmLibraryFunctionGet(const char *name);
|
||||
static inline void JvmLibraryFree(void);
|
||||
static inline tLibHandle JvmLibraryLoad(void);
|
||||
static inline long int JvmLibraryLastErrorGet(void);
|
||||
static inline int RunAllTests(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int test_fail_count = -1;
|
||||
|
||||
#if TEST_USING_JVM
|
||||
jint result = -1;
|
||||
|
||||
globals.jni.lib = JvmLibraryLoad();
|
||||
if (globals.jni.lib == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error loading library (%ld)\n", JvmLibraryLastErrorGet());
|
||||
goto end_no_jvm_lib;
|
||||
}
|
||||
|
||||
// get the address of the JNI call to create the VM from the loaded library.
|
||||
globals.jni.VMcreate = (tJavaVMcreate)JvmLibraryFunctionGet("JNI_CreateJavaVM");
|
||||
if (globals.jni.VMcreate == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error getting JNI_CreateJavaVM (%ld)", JvmLibraryLastErrorGet());
|
||||
goto end_no_CreateJavaVM;
|
||||
}
|
||||
|
||||
// Create the VM the tests should be done within
|
||||
result = CreateVM(&globals.jvm);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Can't create Java VM (%ld)\n", result);
|
||||
goto end_no_java_vm;
|
||||
}
|
||||
|
||||
// In order to be able to interact with the VM we have to attach our thread to the VM
|
||||
result = globals.jvm.jvm->AttachCurrentThread((void**)&globals.thread_env, NULL);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Can't attach thread to Java VM (%ld)\n", result);
|
||||
goto end_no_attach;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
test_fail_count = RunAllTests();
|
||||
|
||||
#if TEST_USING_JVM
|
||||
/* Check if there is still a pending exception. Usually all the tests should clear the
|
||||
* exceptions if any have been expected. If this is not the case something went wrong... */
|
||||
if (globals.jvm.env->ExceptionOccurred()) {
|
||||
globals.jvm.env->ExceptionDescribe();
|
||||
test_fail_count++;
|
||||
}
|
||||
|
||||
/* After cleaning up the java environment we can safely detach our thread from the JVM */
|
||||
globals.jvm.jvm->DetachCurrentThread();
|
||||
|
||||
end_no_attach:
|
||||
globals.jvm.jvm->DestroyJavaVM();
|
||||
|
||||
end_no_java_vm:
|
||||
end_no_CreateJavaVM:
|
||||
/* Unload the JNI Library */
|
||||
JvmLibraryFree();
|
||||
|
||||
end_no_jvm_lib:
|
||||
#endif
|
||||
return test_fail_count;
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Executes all the tests and returns the number of failed tests */
|
||||
static int RunAllTests(void)
|
||||
{
|
||||
CuSuite *suite = CuGetLibusbJavaSuite(globals.thread_env);
|
||||
CuString *output = CuStringNew();
|
||||
|
||||
|
||||
CuSuiteRun(suite);
|
||||
CuSuiteSummary(suite, output);
|
||||
CuSuiteDetails(suite, output);
|
||||
|
||||
printf("%s\n", output->buffer);
|
||||
|
||||
return suite->failCount;
|
||||
}
|
||||
|
||||
/*! \brief Creates a java virtual machine and places all the received handles into
|
||||
* the given structure
|
||||
*
|
||||
* \param vmdata Pointer to the structure that should hold all the handles
|
||||
* of the VM created.
|
||||
*
|
||||
* \return
|
||||
* - JNI_OK on success
|
||||
* - <0 on failure (see jni.h)
|
||||
*/
|
||||
static inline int CreateVM(tJVM *vmdata)
|
||||
{
|
||||
JavaVMInitArgs vm_args;
|
||||
JavaVMOption options[1];
|
||||
|
||||
options[0].optionString = "-Djava.class.path=" USER_CLASSPATH;
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.options = options;
|
||||
vm_args.nOptions = 1;
|
||||
vm_args.ignoreUnrecognized = JNI_TRUE;
|
||||
|
||||
/* Create the Java VM for unit tests */
|
||||
return globals.jni.VMcreate(&vmdata->jvm, (void**) &vmdata->env, &vm_args);
|
||||
}
|
||||
|
||||
/*! \brief Searches and tries to load the JVM library
|
||||
*
|
||||
* As there are some issues to find the appropriate library in the given path
|
||||
* this function searches a several options for loading a library.
|
||||
*
|
||||
* \return
|
||||
* - Handle for the loaded library
|
||||
* - NULL if the library could not be loaded. Use GetLastError() to determine
|
||||
* the reason.
|
||||
*/
|
||||
static tLibHandle JvmLibraryLoad(void)
|
||||
{
|
||||
unsigned int pos = 0;
|
||||
tLibHandle result = NULL;
|
||||
|
||||
while ((result == NULL) && (lib_paths[pos] != NULL))
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
result = LoadLibrary(lib_paths[pos++]);
|
||||
#else
|
||||
# error "Unable to load the jvm library for this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*! \brief Wrapper for freeing a loaded JVM library */
|
||||
static void JvmLibraryFree(void)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
FreeLibrary(globals.jni.lib);
|
||||
#else
|
||||
# error "Unable to unload the jvm library for this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! \brief Wrapper for getting a specific function pointer from the loaded JVM library
|
||||
*
|
||||
* \param name Name of the function to be retrieved.
|
||||
*
|
||||
* \return Function pointer to the given function or NULL if the function could not be found
|
||||
*/
|
||||
static tCallbackPtr JvmLibraryFunctionGet(const char *name)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
return GetProcAddress(globals.jni.lib, name);
|
||||
#else
|
||||
# error "Unable to get library function pointer for this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! \brief Wrapper for getting the reason why the last JvmLibrary*-Call failed
|
||||
*
|
||||
* \return Errorcode describing the error that happened. */
|
||||
static inline long int JvmLibraryLastErrorGet(void)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
return GetLastError();
|
||||
#else
|
||||
# error "Unable to determine last error for this platform"
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user