Files
jlibusb/LibusbJava/test/LibusbJavaTest.cpp
uniederer 4e116ce35c - Reorganization of the build script to make it more portable
- Removed the conditional code that decided whether to use JVM for unit tests or not
- Changed the unit test code so the test code is now imported by using the DLL function
- Introduced mechanisms to concentrate the loading of classes to specific methods instead of putting them into another function

git-svn-id: https://svn.code.sf.net/p/libusbjava/code/trunk@301 94ad28fe-ef68-46b1-9651-e7ae4fcf1c4c
2012-11-29 17:10:26 +00:00

261 lines
6.9 KiB
C++

#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 */
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;
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);
/*! \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 };
int main(void)
{
int test_fail_count = -1;
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;
}
test_fail_count = RunAllTests();
/* 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:
return test_fail_count;
}
typedef CuSuite* (*tSuiteNew)(void);
typedef CuSuite* (*tGetDLLtests)(tSuiteNew SuiteNew, JNIEnv *env);
/*! \brief Executes all the tests
*
* \return Number of tests that failed */
static inline int RunAllTests(void)
{
int result = 0;
tGetDLLtests getTestSuite = NULL;
tLibHandle libusb = LoadLibrary("LibusbJava-1_0.dll");
if (libusb == NULL) {
printf("Failed to load LibusbJava-1_0.dll: %lu", GetLastError());
goto no_lib;
}
getTestSuite = (tGetDLLtests)GetProcAddress(libusb, "GetLibusbJavaSuite");
if (getTestSuite == NULL)
{
printf("Failed to get unit tests: %lu", GetLastError());
goto no_suite_new;
}
/* Run the test procedures */
{
CuSuite *suite = getTestSuite(&CuSuiteNew, globals.thread_env);
CuString *output = CuStringNew();
CuSuiteRun(suite);
CuSuiteSummary(suite, output);
CuSuiteDetails(suite, output);
printf("%s\n", output->buffer);
result = suite->failCount;
}
FreeLibrary(libusb);
return result;
no_suite_new:
FreeLibrary(libusb);
no_lib:
return -1;
}
/*! \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 inline 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 inline 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 inline 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
}