aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog34
-rw-r--r--plugin/icedteanp/IcedTeaJavaRequestProcessor.cc7
-rw-r--r--plugin/icedteanp/IcedTeaNPPlugin.cc118
-rw-r--r--plugin/icedteanp/IcedTeaNPPlugin.h9
-rw-r--r--tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc416
-rw-r--r--tests/cpp-unit-tests/IcedTeaNPPluginTest.cc32
-rw-r--r--tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc4
-rw-r--r--tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc33
-rw-r--r--tests/cpp-unit-tests/MemoryLeakDetector.h2
-rw-r--r--tests/cpp-unit-tests/browser_mock.cc56
-rw-r--r--tests/cpp-unit-tests/browser_mock.h4
-rw-r--r--tests/cpp-unit-tests/browser_mock_npidentifier.cc117
-rw-r--r--tests/cpp-unit-tests/browser_mock_npidentifier.h57
-rw-r--r--tests/cpp-unit-tests/checked_allocations.h6
-rw-r--r--tests/cpp-unit-tests/main.cc27
15 files changed, 835 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index ab45517..2e020a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,39 @@
2013-08-23 Adam Domurad <[email protected]>
+ Spawn Java side during C++ unit tests. Many new tests.
+ * plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
+ (hasPackage): Minor cleanup.
+ * plugin/icedteanp/IcedTeaNPPlugin.cc
+ (initialize_data_directory): New, extracted function.
+ (NP_Initialize): Calls extracted function.
+ * plugin/icedteanp/IcedTeaNPPlugin.h: Expose more functions for
+ testing purposes.
+ * tests/cpp-unit-tests/IcedTeaNPPluginTest.cc
+ (get_scriptable_package_object): Test binding of java package
+ (get_scriptable_java_object): Test binding of java object
+ * tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
+ (NPIdentifierAsString): Update to create npidentifier properly.
+ * tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc
+ (getProperty): Test loading java.lang.Integer.MAX_VALUE from C++.
+ * tests/cpp-unit-tests/MemoryLeakDetector.h
+ (reset_global_state): Made public
+ * tests/cpp-unit-tests/checked_allocations.h
+ (SafeAllocator): New, typedef for allocator that avoids leak detection.
+ * tests/cpp-unit-tests/browser_mock.cc
+ (browsermock_setup_functions): Renamed to (browsermock_create_table).
+ (browsermock_create_table): Now returns browser table, additional
+ object release and identifier methods added.
+ * tests/cpp-unit-tests/browser_mock.h: Update for rename.
+ * tests/cpp-unit-tests/main.cc: Now clears state via
+ (reset_global_state)
+ * tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc: New,
+ contains unit tests that cover all of JavaRequestProcessor's methods.
+ * tests/cpp-unit-tests/browser_mock_npidentifier.cc: Allocation-safe
+ npidentifier mocking, adheres to NPAPI spec.
+ * tests/cpp-unit-tests/browser_mock_npidentifier.h: Same.
+
+2013-08-23 Adam Domurad <[email protected]>
+
* plugin/icedteanp/IcedTeaNPPlugin.cc: Refactor plugin data creation.
* plugin/icedteanp/IcedTeaNPPlugin.h: Same.
diff --git a/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc b/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
index f7b7332..0d65bd4 100644
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
+++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
@@ -1279,7 +1279,6 @@ JavaRequestProcessor::hasPackage(int plugin_instance_id,
{
JavaResultData* java_result;
JavaRequestProcessor* java_request = new JavaRequestProcessor();
- std::string message = std::string();
std::string plugin_instance_id_str = std::string();
IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
@@ -1288,11 +1287,9 @@ JavaRequestProcessor::hasPackage(int plugin_instance_id,
this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
this->reference = IcedTeaPluginUtilities::getReference();
+ std::string message;
IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
- message.append(" HasPackage ");
- message.append(plugin_instance_id_str);
- message.append(" ");
- message.append(java_result->return_string->c_str());
+ message += " HasPackage " + plugin_instance_id_str + " " + *java_result->return_string;
postAndWaitForResponse(message);
diff --git a/plugin/icedteanp/IcedTeaNPPlugin.cc b/plugin/icedteanp/IcedTeaNPPlugin.cc
index 7515f1b..bfce1ae 100644
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc
+++ b/plugin/icedteanp/IcedTeaNPPlugin.cc
@@ -190,8 +190,6 @@ static pthread_t plugin_request_processor_thread2;
static pthread_t plugin_request_processor_thread3;
// Static instance helper functions.
-// Have the browser allocate a new ITNPPluginData structure.
-static ITNPPluginData* plugin_data_new ();
// Retrieve the current document's documentbase.
static std::string plugin_get_documentbase (NPP instance);
// Callback used to monitor input pipe status.
@@ -202,16 +200,12 @@ static gboolean plugin_in_pipe_callback (GIOChannel* source,
static gboolean plugin_out_pipe_callback (GIOChannel* source,
GIOCondition condition,
gpointer plugin_data);
-static NPError plugin_start_appletviewer (ITNPPluginData* data);
std::string plugin_parameters_string (int argc, char* argn[], char* argv[]);
static void plugin_stop_appletviewer ();
-// Uninitialize ITNPPluginData structure
-static void plugin_data_destroy (NPP instance);
NPError get_cookie_info(const char* siteAddr, char** cookieString, uint32_t* len);
NPError get_proxy_info(const char* siteAddr, char** proxy, uint32_t* len);
void consume_message(gchar* message);
-void start_jvm_if_needed();
static void appletviewer_monitor(GPid pid, gint status, gpointer data);
void plugin_send_initialization_message(char* instance, gulong handle,
int width, int height,
@@ -922,7 +916,7 @@ set_cookie_info(const char* siteAddr, const char* cookieString, uint32_t len)
// HELPER FUNCTIONS
-static ITNPPluginData*
+ITNPPluginData*
plugin_data_new ()
{
PLUGIN_DEBUG ("plugin_data_new\n");
@@ -1366,7 +1360,7 @@ plugin_test_appletviewer ()
return error;
}
-static NPError
+NPError
plugin_start_appletviewer (ITNPPluginData* data)
{
PLUGIN_DEBUG ("plugin_start_appletviewer\n");
@@ -1707,7 +1701,7 @@ static void appletviewer_monitor(GPid pid, gint status, gpointer data)
PLUGIN_DEBUG ("appletviewer_monitor return\n");
}
-static void
+void
plugin_data_destroy (NPP instance)
{
PLUGIN_DEBUG ("plugin_data_destroy\n");
@@ -1792,6 +1786,61 @@ initialize_plugin_table(NPPluginFuncs* pluginTable)
return true;
}
+// Make sure the plugin data directory exists, creating it if necessary.
+NPError
+initialize_data_directory()
+{
+ const char* tmpdir_env = getenv("TMPDIR");
+ if (tmpdir_env != NULL && g_file_test (tmpdir_env,
+ (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ {
+ data_directory = tmpdir_env;
+ }
+ else if (g_file_test (P_tmpdir,
+ (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ {
+ data_directory = P_tmpdir;
+ }
+ else
+ {
+ // If TMPDIR and P_tmpdir do not exist, try /tmp directly
+ data_directory = "/tmp";
+ }
+
+ data_directory += "/icedteaplugin-";
+ if (getenv("USER") != NULL)
+ data_directory += getenv("USER");
+
+ // Now create a icedteaplugin subdir
+ if (!g_file_test (data_directory.c_str(),
+ (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ {
+ int file_error = 0;
+
+ file_error = g_mkdir (data_directory.c_str(), 0700);
+ if (file_error != 0)
+ {
+ PLUGIN_ERROR_THREE ("Failed to create data directory",
+ data_directory.c_str(),
+ strerror (errno));
+ return NPERR_GENERIC_ERROR;
+ }
+ }
+
+
+ // If data directory doesn't exist by this point, bail
+ if (!g_file_test (data_directory.c_str(),
+ (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ {
+ PLUGIN_ERROR_THREE ("Temp directory does not exist: ",
+ data_directory.c_str(),
+ strerror (errno));
+ return NPERR_GENERIC_ERROR;
+ }
+
+ return NPERR_NO_ERROR;
+}
+
// FACTORY FUNCTIONS
// Provides the browser with pointers to the plugin functions that we
@@ -1860,56 +1909,7 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable)
NPError np_error = NPERR_NO_ERROR;
- // Make sure the plugin data directory exists, creating it if
- // necessary.
-
- const char* tmpdir_env = getenv("TMPDIR");
- if (tmpdir_env != NULL && g_file_test (tmpdir_env,
- (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- {
- data_directory = tmpdir_env;
- }
- else if (g_file_test (P_tmpdir,
- (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- {
- data_directory = P_tmpdir;
- }
- else
- {
- // If TMPDIR and P_tmpdir do not exist, try /tmp directly
- data_directory = "/tmp";
- }
-
- data_directory += "/icedteaplugin-";
- if (getenv("USER") != NULL)
- data_directory += getenv("USER");
-
- // Now create a icedteaplugin subdir
- if (!g_file_test (data_directory.c_str(),
- (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- {
- int file_error = 0;
-
- file_error = g_mkdir (data_directory.c_str(), 0700);
- if (file_error != 0)
- {
- PLUGIN_ERROR_THREE ("Failed to create data directory",
- data_directory.c_str(),
- strerror (errno));
- return NPERR_GENERIC_ERROR;
- }
- }
-
-
- // If data directory doesn't exist by this point, bail
- if (!g_file_test (data_directory.c_str(),
- (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- {
- PLUGIN_ERROR_THREE ("Temp directory does not exist: ",
- data_directory.c_str(),
- strerror (errno));
- return NPERR_GENERIC_ERROR;
- }
+ initialize_data_directory();
// Set appletviewer_executable.
PLUGIN_DEBUG("Executing java at %s\n", get_plugin_executable().c_str());
diff --git a/plugin/icedteanp/IcedTeaNPPlugin.h b/plugin/icedteanp/IcedTeaNPPlugin.h
index ff5e1eb..db6c421 100644
--- a/plugin/icedteanp/IcedTeaNPPlugin.h
+++ b/plugin/icedteanp/IcedTeaNPPlugin.h
@@ -99,6 +99,13 @@ struct ITNPPluginData
}
};
+// Have the browser allocate a new ITNPPluginData structure.
+ITNPPluginData* plugin_data_new ();
+void plugin_data_destroy (NPP instance);
+
+NPError initialize_data_directory();
+void start_jvm_if_needed();
+
// Condition on which the queue processor waits
extern pthread_cond_t cond_message_available;
@@ -144,4 +151,6 @@ NPObject* get_scriptable_object(NPP instance);
/* Creates a new scriptable plugin object and returns it */
NPObject* allocate_scriptable_object(NPP npp, NPClass *aClass);
+NPError plugin_start_appletviewer (ITNPPluginData* data);
+
#endif /* __ICEDTEANPPLUGIN_H__ */
diff --git a/tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc b/tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc
new file mode 100644
index 0000000..517d5d0
--- /dev/null
+++ b/tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc
@@ -0,0 +1,416 @@
+/* Copyright (C) 2013 Red Hat
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ IcedTea is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+#include <cstdio>
+
+#include <vector>
+#include <string>
+
+#include <npapi.h>
+
+#include <UnitTest++.h>
+
+#include "MemoryLeakDetector.h"
+
+#include "IcedTeaJavaRequestProcessor.h"
+
+/******************************************************************************
+ * Simple helper methods to keep the tests clean. *
+ ******************************************************************************/
+
+static const char* TEST_SOURCE = "[System]";
+
+static std::string checked_return(JavaResultData* result) {
+ CHECK(!result->error_occurred);
+ return *result->return_string;
+}
+
+// Packages
+
+static bool jrp_has_package(std::string package_name) {
+ JavaRequestProcessor processor;
+ JavaResultData* result = processor.hasPackage(0, package_name);
+ CHECK(!result->error_occurred);
+ return (result->return_identifier != 0);
+}
+
+// Classes
+
+static std::string jrp_find_class(std::string name) {
+ return checked_return(
+ JavaRequestProcessor().findClass(0, name)
+ );
+}
+
+// Object creation
+
+static std::string jrp_new_object_with_constructor(std::string class_id,
+ std::string method_id,
+ std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().newObjectWithConstructor(TEST_SOURCE,
+ class_id, method_id, args)
+ );
+}
+
+static std::string jrp_new_array(std::string class_id, std::string len) {
+ return checked_return(
+ JavaRequestProcessor().newArray(class_id, len)
+ );
+}
+
+static std::string jrp_new_string(std::string str) {
+ return checked_return(
+ JavaRequestProcessor().newString(str)
+ );
+}
+
+static std::string jrp_new_object(std::string class_id,
+ std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().newObject(TEST_SOURCE, class_id, args)
+ );
+}
+
+static std::string jrp_get_value(std::string object_id) {
+ return checked_return(
+ JavaRequestProcessor().getValue(object_id)
+ );
+}
+
+// Inheritance
+
+static bool jrp_is_instance_of(std::string object_id, std::string class_id) {
+ JavaRequestProcessor processor;
+ JavaResultData* result = processor.isInstanceOf(object_id, class_id);
+
+ CHECK(!result->error_occurred);
+ return (result->return_identifier != 0);
+}
+
+
+// Java methods operations.
+
+static std::string jrp_get_method_id(std::string class_id,
+ std::string method_name,
+ std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().getMethodID(class_id,
+ browser_functions.getstringidentifier(method_name.c_str()), args)
+ );
+}
+
+static std::string jrp_get_static_method_id(std::string class_id,
+ std::string method_name,
+ std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().getStaticMethodID(class_id,
+ browser_functions.getstringidentifier(method_name.c_str()), args)
+ );
+}
+
+static std::string jrp_call_method(std::string object_id,
+ std::string method_name, std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().callMethod(TEST_SOURCE, object_id,
+ method_name, args)
+ );
+}
+
+static std::string jrp_call_static_method(std::string class_id,
+ std::string method_name, std::vector<std::string> args = std::vector<std::string>()) {
+ return checked_return(
+ JavaRequestProcessor().callStaticMethod(TEST_SOURCE, class_id,
+ method_name, args)
+ );
+}
+
+static std::string jrp_get_string(std::string object_id) {
+ return checked_return(
+ JavaRequestProcessor().getString(object_id)
+ );
+}
+
+static std::string jrp_get_class_id(std::string object_id) {
+ return checked_return(
+ JavaRequestProcessor().getClassID(object_id)
+ );
+}
+
+
+// Java field operations.
+
+static std::string jrp_get_field(std::string object_id,
+ std::string field_name) {
+ return checked_return(
+ JavaRequestProcessor().getField(TEST_SOURCE,
+ jrp_get_class_id(object_id), object_id, field_name)
+ );
+}
+
+static std::string jrp_get_field_id(std::string class_id,
+ std::string field_name) {
+ return checked_return(
+ JavaRequestProcessor().getFieldID(class_id, field_name)
+ );
+}
+
+static std::string jrp_get_static_field_id(std::string class_id,
+ std::string field_name) {
+ return checked_return(
+ JavaRequestProcessor().getStaticFieldID(class_id, field_name)
+ );
+}
+
+static std::string jrp_get_static_field(std::string class_id,
+ std::string field_name) {
+ return checked_return(
+ JavaRequestProcessor().getStaticField(TEST_SOURCE, class_id, field_name)
+ );
+}
+
+static std::string jrp_set_field(std::string object_id, std::string field_name,
+ std::string value_id) {
+ return checked_return(
+ JavaRequestProcessor().setField(TEST_SOURCE,
+ jrp_get_class_id(object_id), object_id, field_name, value_id)
+ );
+}
+
+static std::string jrp_set_static_field(std::string class_id, std::string field_name,
+ std::string value_id) {
+ return checked_return(
+ JavaRequestProcessor().setStaticField(TEST_SOURCE, class_id, field_name, value_id)
+ );
+}
+
+// Java array operations.
+
+static std::string jrp_set_slot(std::string object_id, std::string index,
+ std::string value_id) {
+ return checked_return(
+ JavaRequestProcessor().setSlot(object_id, index, value_id)
+ );
+}
+
+static std::string jrp_get_slot(std::string object_id, std::string index) {
+ return checked_return(
+ JavaRequestProcessor().getSlot(object_id, index)
+ );
+}
+
+static std::string jrp_get_array_length(std::string object_id) {
+ return checked_return(
+ JavaRequestProcessor().getArrayLength(object_id)
+ );
+}
+
+// Result of toString()
+
+static std::string jrp_get_to_string_value(std::string object_id) {
+ return checked_return(
+ JavaRequestProcessor().getToStringValue(object_id)
+ );
+}
+
+/******************************************************************************
+ * Compound helper methods. *
+ ******************************************************************************/
+
+static NPP_t dummy_npp = {0,0};
+
+static std::string create_java_integer(int value) {
+ // Prepare a java integer object with the value 1
+ NPVariant integer_variant;
+ std::string integer_id;
+ INT32_TO_NPVARIANT(value, integer_variant);
+ createJavaObjectFromVariant(&dummy_npp, integer_variant, &integer_id);
+ return integer_id;
+}
+
+static std::string create_null() {
+ // Prepare a null object
+ NPVariant null_variant;
+ std::string null_id;
+ NULL_TO_NPVARIANT(null_variant);
+ createJavaObjectFromVariant(&dummy_npp, null_variant, &null_id);
+ return null_id;
+}
+
+static NPVariant java_result_to_variant(std::string object_id) {
+ NPVariant variant;
+ IcedTeaPluginUtilities::javaResultToNPVariant(&dummy_npp, &object_id, &variant);
+ return variant;
+}
+
+/* Call the no-argument constructor of an object */
+static std::string jrp_noarg_construct(std::string classname) {
+ std::string class_id = jrp_find_class(classname);
+ std::string constructor_id = jrp_get_method_id(class_id, "<init>");
+ return jrp_new_object_with_constructor(class_id, constructor_id);
+}
+
+
+/******************************************************************************
+ * Test cases. Note that the tests exercise a variety of functions to first *
+ * create the appropriate conditions for the intended test. *
+ ******************************************************************************/
+
+SUITE(JavaRequestProcessor) {
+
+ TEST(callMethod) {
+ std::string object_id = jrp_noarg_construct("java.lang.Object");
+ std::string tostring_result = jrp_get_string(
+ jrp_call_method(object_id, "toString"));
+ const char substr[] = "java.lang.Object@";
+ // Check that the result of toString is as expected
+ CHECK(strncmp(tostring_result.c_str(), substr, strlen(substr)) == 0);
+ }
+
+ /* Create a java.awt.Point, since it is one of the few standard classes with public fields. */
+ TEST(getField_and_setField) {
+ std::string object_id = jrp_noarg_construct("java.awt.Point");
+
+ // Set the field 'x' to 1
+ jrp_set_field(object_id, "x", create_java_integer(1));
+
+ // Get the field 'x'
+ NPVariant field_value = java_result_to_variant(jrp_get_field(object_id, "x"));
+
+ // Ensure that the received field is 1
+ CHECK(NPVARIANT_IS_INT32(field_value) && NPVARIANT_TO_INT32(field_value) == 1);
+ }
+
+ TEST(getStaticField_and_setStaticField) {
+ // One of the few classes with a public & non-final static field that we can tinker with.
+ // If it moves, this test will fail, in which-case this test should be updated to another appropriate field.
+ std::string class_id = jrp_find_class("net.sourceforge.jnlp.controlpanel.DebuggingPanel");
+ std::string properties_id = jrp_get_static_field(class_id, "properties");
+
+ // Check that the field is initially a non-null object
+ NPVariant sh_variant = java_result_to_variant(properties_id);
+ CHECK(!NPVARIANT_IS_NULL(sh_variant) && NPVARIANT_IS_OBJECT(sh_variant));
+ browser_functions.releasevariantvalue(&sh_variant);
+
+ jrp_set_static_field(class_id, "properties", create_null());
+ sh_variant = java_result_to_variant(jrp_get_static_field(class_id, "properties"));
+ CHECK(NPVARIANT_IS_NULL(sh_variant));
+
+ // Reset the field to its original contents
+ jrp_set_static_field(class_id, "properties", properties_id);
+ sh_variant = java_result_to_variant(jrp_get_static_field(class_id, "properties"));
+ CHECK(!NPVARIANT_IS_NULL(sh_variant) && NPVARIANT_IS_OBJECT(sh_variant));
+ browser_functions.releasevariantvalue(&sh_variant);
+ }
+
+ TEST(arrayIndexing) {
+ const int ARRAY_LEN = 1;
+
+ // We will create an Integer array of ARRAY_LEN
+ std::vector<std::string> args;
+ args.push_back(jrp_find_class("java.lang.Integer"));
+ args.push_back(create_java_integer(ARRAY_LEN));
+
+ // Create an array 'the hard way' (ie not using 'newArray') to test more of the API
+ std::string array_id = jrp_call_static_method(jrp_find_class("java.lang.reflect.Array"), "newInstance", args);
+
+ // Attempt to set the first element to 1
+ jrp_set_slot(array_id, "0", create_java_integer(1));
+ // Note we get an integer _object_, not a plain int literal
+ std::string integer_id = jrp_get_slot(array_id, "0");
+ NPVariant unboxed_slot_value = java_result_to_variant(jrp_call_method(integer_id, "intValue"));
+
+ // Ensure that the received slot is 1
+ CHECK(NPVARIANT_IS_INT32(unboxed_slot_value) && NPVARIANT_TO_INT32(unboxed_slot_value) == 1);
+ }
+
+ // Also exercises 'getToStringValue'
+ TEST(newObject) {
+ std::string object_id = jrp_new_object(jrp_find_class("java.lang.Object"));
+ const char substr[] = "java.lang.Object@";
+ // Check that the result of toString is as expected
+ CHECK(strncmp(jrp_get_to_string_value(object_id).c_str(), substr, strlen(substr)) == 0);
+ }
+
+ TEST(hasPackage) {
+ CHECK(jrp_has_package("java.lang"));
+ CHECK(!jrp_has_package("not.an.icedtea_web.package"));
+ }
+
+ TEST(newArray) {
+ const char ARRAY_LEN[] = "10";
+ std::string array_id = jrp_new_array(jrp_find_class("java.lang.Integer"), ARRAY_LEN);
+ CHECK_EQUAL(ARRAY_LEN, jrp_get_array_length(array_id));
+ }
+
+ TEST(newString) {
+ const char TEST_STRING[] = "foobar";
+ std::string string_id = jrp_new_string(TEST_STRING);
+ CHECK_EQUAL(TEST_STRING, jrp_get_string(string_id));
+ CHECK_EQUAL(TEST_STRING, jrp_get_to_string_value(string_id));
+ }
+
+ // Can only really do sanity checks with given API
+ TEST(getFieldID_getStaticFieldID) {
+ CHECK(!jrp_get_field_id(jrp_find_class("java.awt.Point"), "x").empty());
+ CHECK(!jrp_get_static_field_id(jrp_find_class("java.lang.Integer"), "MAX_VALUE").empty());
+ }
+
+ // Can only really do sanity checks with given API
+ TEST(getStaticMethodID) {
+ std::string class_id = jrp_find_class("java.lang.Integer");
+
+ std::vector<std::string> argtypes;
+ argtypes.push_back("Ljava.lang.String;");
+
+ CHECK(!jrp_get_static_method_id(class_id, "valueOf", argtypes).empty());
+ }
+
+ TEST(isInstanceOf) {
+ std::string point_id = jrp_noarg_construct("java.awt.Point");
+ std::string object_class_id = jrp_find_class("java.lang.Object");
+ CHECK(jrp_is_instance_of(point_id, object_class_id));
+ }
+
+ // Wasn't sure what the point of this method is to be honest, but it is used.
+ // Here it simply returns back a passed string object.
+ TEST(getValue) {
+ const char TEST_STRING[] = "foobar";
+
+ std::string str = jrp_get_string(jrp_get_value(jrp_new_string(TEST_STRING)));
+ CHECK_EQUAL(TEST_STRING, str);
+ }
+}
diff --git a/tests/cpp-unit-tests/IcedTeaNPPluginTest.cc b/tests/cpp-unit-tests/IcedTeaNPPluginTest.cc
index 1633d6b..6fc0bf9 100644
--- a/tests/cpp-unit-tests/IcedTeaNPPluginTest.cc
+++ b/tests/cpp-unit-tests/IcedTeaNPPluginTest.cc
@@ -40,7 +40,10 @@
#include <UnitTest++.h>
+#include "MemoryLeakDetector.h"
+
#include "IcedTeaNPPlugin.h"
+#include "IcedTeaScriptablePluginObject.h"
#include "IcedTeaPluginUtils.h"
TEST(NP_GetMIMEDescription) {
@@ -51,19 +54,38 @@ TEST(NP_GetMIMEDescription) {
/* Not normally exposed */
std::vector<std::string*>* get_jvm_args();
-extern gchar* in_pipe_name;
-extern gchar* out_pipe_name;
TEST(get_jvm_args) {
- in_pipe_name = (gchar*)"inpipe";
- out_pipe_name = (gchar*)"outpipe";
-
std::vector<std::string*>* args = get_jvm_args();
CHECK(args != NULL);
IcedTeaPluginUtilities::freeStringPtrVector(args);
}
+
+static IcedTeaScriptableJavaPackageObject* get_scriptable_package_object() {
+ NPP_t instance = { /*Plugin data*/plugin_data_new(), /* Browser data*/0 };
+
+ /* Get the packages object (since instance.pdata->is_applet_instance == false) */
+ NPObject* obj = get_scriptable_object(&instance);
+
+ /* Make sure we got an IcedTeaScriptableJavaPackageObject */
+ CHECK(obj->_class->deallocate == IcedTeaScriptableJavaPackageObject::deAllocate);
+
+ plugin_data_destroy(&instance);
+ return (IcedTeaScriptableJavaPackageObject*)obj;
+}
+
+TEST(get_scriptable_object) {
+ MemoryLeakDetector leak_detector;
+ // We test without an applet context, pending mocking of applet instances.
+ IcedTeaScriptableJavaPackageObject* obj = get_scriptable_package_object(); // Calls get_scriptable_object
+
+ browser_functions.releaseobject(obj);
+
+ CHECK(leak_detector.memory_leaks() == 0);
+}
+
TEST(NP_GetValue) {
void* __unused = NULL;
gchar* char_value = NULL;
diff --git a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
index 7df0a1e..ac0e0d3 100644
--- a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
+++ b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
@@ -86,11 +86,11 @@ TEST(NPVariantStringCopy) {
}
TEST(NPIdentifierAsString) {
- // NB: Mocked definition of 'utf8fromidentifier' simply reads NPIdentifier as a char* string.
const char test_string[] = "foobar";
MemoryLeakDetector leak_detector;
/* Ensure destruction */{
- std::string str = IcedTeaPluginUtilities::NPIdentifierAsString((NPIdentifier)test_string);
+ std::string str = IcedTeaPluginUtilities::NPIdentifierAsString(
+ browser_functions.getstringidentifier(test_string));
CHECK_EQUAL(test_string, str);
}
CHECK_EQUAL(0, leak_detector.memory_leaks());
diff --git a/tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc b/tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc
index 9de0bbd..bb2b376 100644
--- a/tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc
+++ b/tests/cpp-unit-tests/IcedTeaScriptablePluginObjectTest.cc
@@ -95,4 +95,37 @@ SUITE(IcedTeaScriptableJavaPackageObject) {
browser_functions.releaseobject(obj);
CHECK(leak_detector.memory_leaks() == 0);
}
+
+ static NPVariant np_checked_get(NPObject* obj, const char* identifier) {
+ NPVariant result;
+ CHECK(browser_functions.getproperty(&dummy_npp, obj, browser_functions.getstringidentifier(identifier), &result));
+ return result;
+ }
+
+ /* NOTICE: Requires icedtea-web Java-side to be running!
+ * Loads java.lang.Integer.MAX_VALUE */
+ TEST(getProperty) {
+ MemoryLeakDetector leak_detector;
+ /* Ensure destruction */{
+ /* Get the 'root' package */
+ NPObject* obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_package_object(&dummy_npp, "");
+ // Look up java.lang.Integer.MAX_VALUE
+ NPVariant java_result = np_checked_get(obj, "java");
+ NPVariant lang_result = np_checked_get(NPVARIANT_TO_OBJECT(java_result), "lang");
+ NPVariant integer_result = np_checked_get(NPVARIANT_TO_OBJECT(lang_result), "Integer");
+ NPVariant max_value_result = np_checked_get(NPVARIANT_TO_OBJECT(integer_result), "MAX_VALUE");
+
+ // Check that it is indeed equal to 2147483647
+ CHECK(NPVARIANT_IS_INT32(max_value_result));
+ CHECK_EQUAL(2147483647, NPVARIANT_TO_INT32(max_value_result));
+
+ browser_functions.releasevariantvalue(&java_result);
+ browser_functions.releasevariantvalue(&lang_result);
+ browser_functions.releasevariantvalue(&integer_result);
+ browser_functions.releasevariantvalue(&max_value_result);
+
+ browser_functions.releaseobject(obj);
+ }
+ CHECK(leak_detector.memory_leaks() == 0);
+ }
}
diff --git a/tests/cpp-unit-tests/MemoryLeakDetector.h b/tests/cpp-unit-tests/MemoryLeakDetector.h
index 2bd5e9c..d457cb7 100644
--- a/tests/cpp-unit-tests/MemoryLeakDetector.h
+++ b/tests/cpp-unit-tests/MemoryLeakDetector.h
@@ -42,6 +42,7 @@
#define MEMORYLEAKDETECTOR_H_
#include <cstdio>
+#include "browser_mock.h"
#include "checked_allocations.h"
#include "IcedTeaPluginUtils.h"
@@ -69,7 +70,6 @@ public:
return cpp_leaks + npapi_leaks;
}
-private:
static void reset_global_state() {
/* Clears allocations caused by storeInstanceID */
IcedTeaPluginUtilities::clearInstanceIDs();
diff --git a/tests/cpp-unit-tests/browser_mock.cc b/tests/cpp-unit-tests/browser_mock.cc
index 8724687..32027f3 100644
--- a/tests/cpp-unit-tests/browser_mock.cc
+++ b/tests/cpp-unit-tests/browser_mock.cc
@@ -36,17 +36,26 @@
// Browser mock functions. Add more as needed.
+#include <new>
+#include <map>
#include <cstring>
+
+#include <npapi.h>
+
#include "checked_allocations.h"
#include "UnitTest++.h"
#include "browser_mock.h"
+#include "browser_mock_npidentifier.h"
-#include "IcedTeaNPPlugin.h"
+// 'Browser' global data
+// Stores NPAPI allocations
static AllocationSet __allocations;
+// Mocked functions
+
// It is expected that these will only run during a unit test
static void* mock_memalloc(uint32_t size) {
void* mem = malloc(size);
@@ -78,6 +87,15 @@ static void mock_releaseobject(NPObject* obj) {
}
}
+static void mock_releasevariantvalue(NPVariant* variant) {
+ if (variant->type == NPVariantType_String) {
+ /* Only string and object values require freeing */
+ mock_memfree((void*)variant->value.stringValue.UTF8Characters);
+ } else if (variant->type == NPVariantType_Object) {
+ mock_releaseobject(variant->value.objectValue);
+ }
+}
+
static NPObject* mock_createobject(NPP instance, NPClass* np_class) {
NPObject* obj;
if (np_class->allocate) {
@@ -90,17 +108,26 @@ static NPObject* mock_createobject(NPP instance, NPClass* np_class) {
return obj;
}
-static NPUTF8* mock_utf8fromidentifier(NPIdentifier id) {
- // Treat NPIdentifier (== void pointer) as a pointer to characters for simplicity
- const NPUTF8* str = (const NPUTF8*) id;
- // We expect this string to be freed with 'memfree'
- NPUTF8* copy = (NPUTF8*) mock_memalloc(strlen(str) + 1);
- memcpy(copy, str, strlen(str) + 1);
- return copy;
+static bool mock_getproperty(NPP npp, NPObject* obj, NPIdentifier property_name, NPVariant* result) {
+ if (obj->_class->getProperty) {
+ return obj->_class->getProperty(obj, property_name, result);
+ } else {
+ return false;
+ }
}
-void browsermock_setup_functions() {
+static bool mock_setproperty(NPP npp, NPObject* obj, NPIdentifier property_name, const NPVariant* value) {
+ if (obj->_class->setProperty) {
+ return obj->_class->setProperty(obj, property_name, value);
+ } else {
+ return false;
+ }
+}
+
+NPNetscapeFuncs browsermock_create_table() {
+ NPNetscapeFuncs browser_functions;
memset(&browser_functions, 0, sizeof(NPNetscapeFuncs));
+ browser_functions.size = sizeof(NPNetscapeFuncs);
browser_functions.memalloc = &mock_memalloc;
browser_functions.memfree = &mock_memfree;
@@ -108,7 +135,16 @@ void browsermock_setup_functions() {
browser_functions.createobject = &mock_createobject;
browser_functions.retainobject = &mock_retainobject;
browser_functions.releaseobject = &mock_releaseobject;
- browser_functions.utf8fromidentifier = &mock_utf8fromidentifier;
+ browser_functions.releasevariantvalue = &mock_releasevariantvalue;
+
+ browser_functions.setproperty = &mock_setproperty;
+ browser_functions.getproperty = &mock_getproperty;
+
+ browser_functions.utf8fromidentifier = &browsermock_utf8fromidentifier;
+ browser_functions.getstringidentifier = &browsermock_getstringidentifier;
+ browser_functions.identifierisstring = &browsermock_identifierisstring;
+
+ return browser_functions;
}
void browsermock_clear_state() {
diff --git a/tests/cpp-unit-tests/browser_mock.h b/tests/cpp-unit-tests/browser_mock.h
index d936215..ac38813 100644
--- a/tests/cpp-unit-tests/browser_mock.h
+++ b/tests/cpp-unit-tests/browser_mock.h
@@ -43,7 +43,9 @@
#ifndef __BROWSER_MOCK_H__
#define __BROWSER_MOCK_H__
-void browsermock_setup_functions();
+#include <npfunctions.h>
+
+NPNetscapeFuncs browsermock_create_table();
void browsermock_clear_state();
int browsermock_unfreed_allocations();
diff --git a/tests/cpp-unit-tests/browser_mock_npidentifier.cc b/tests/cpp-unit-tests/browser_mock_npidentifier.cc
new file mode 100644
index 0000000..736d9a5
--- /dev/null
+++ b/tests/cpp-unit-tests/browser_mock_npidentifier.cc
@@ -0,0 +1,117 @@
+/* Copyright (C) 2013 Red Hat
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ IcedTea is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+#include <cstdlib>
+
+#include <map>
+
+#include "IcedTeaNPPlugin.h"
+#include "checked_allocations.h"
+#include "browser_mock_npidentifier.h"
+
+struct MockedNPIdentifier_t; // foward declare
+typedef std::basic_string<char, std::char_traits<char>, SafeAllocator> SafeString;
+typedef std::map<int, MockedNPIdentifier_t*, std::less<int>, SafeAllocator> SafeIntToIDMap;
+typedef std::map<SafeString, MockedNPIdentifier_t*, std::less<SafeString>, SafeAllocator> SafeStringToIDMap;
+
+
+// Handles creation of NPIdentifier
+
+// Carefully avoids operator new so as not to interfere with leak detection.
+// This mimics browser internal state.
+struct MockedNPIdentifier_t {
+ SafeString string;
+ int integer;
+ bool is_integer; // If false, it is a string
+
+ // Carefully avoids operator new so as not to interfere with leak detection
+ static MockedNPIdentifier_t* safe_allocate(SafeString str) {
+ MockedNPIdentifier_t* mem = (MockedNPIdentifier_t*)malloc(sizeof(MockedNPIdentifier_t));
+ new (&mem->string) SafeString(str);
+ mem->integer = -1;
+ mem->is_integer = false;
+ return mem;
+ }
+
+ // Carefully avoids operator new so as not to interfere with leak detection
+ static MockedNPIdentifier_t* safe_allocate(int i) {
+ MockedNPIdentifier_t* mem = (MockedNPIdentifier_t*) malloc(
+ sizeof(MockedNPIdentifier_t));
+ new (&mem->string) SafeString();
+ mem->integer = i;
+ mem->is_integer = true;
+ return mem;
+ }
+};
+
+// Mimics global browser data. OK if not cleared in-between tests, does not change semantics.
+// Used to ensure NPIdentifiers are unique. Never freed.
+static SafeIntToIDMap __np_int_identifiers;
+static SafeStringToIDMap __np_string_identifiers;
+
+// Carefully avoids operator new so as not to interfere with leak detection
+NPIdentifier browsermock_getstringidentifier(const NPUTF8* name) {
+ SafeString safe_copy(name);
+ if (__np_string_identifiers.find(safe_copy) == __np_string_identifiers.end()) {
+ __np_string_identifiers[safe_copy] = MockedNPIdentifier_t::safe_allocate(safe_copy);
+ }
+ return __np_string_identifiers[safe_copy];
+}
+
+// Carefully avoids operator new so as not to interfere with leak detection
+NPIdentifier browsermock_getintidentifier(int i) {
+ if (__np_int_identifiers.find(i) == __np_int_identifiers.end()) {
+ __np_int_identifiers[i] = MockedNPIdentifier_t::safe_allocate(i);
+ }
+ return __np_int_identifiers[i];
+}
+
+bool browsermock_identifierisstring(NPIdentifier identifier) {
+ MockedNPIdentifier_t* contents = (MockedNPIdentifier_t*)identifier;
+ return !contents->is_integer;
+}
+
+NPUTF8* browsermock_utf8fromidentifier(NPIdentifier identifier) {
+ MockedNPIdentifier_t* contents = (MockedNPIdentifier_t*)identifier;
+ if (contents->is_integer) {
+ return NULL;
+ }
+
+ // We expect this string to be freed with 'memfree'
+ NPUTF8* copy = (NPUTF8*) browser_functions.memalloc(contents->string.size() + 1);
+ memcpy(copy, contents->string.c_str(), contents->string.size() + 1);
+ return copy;
+}
diff --git a/tests/cpp-unit-tests/browser_mock_npidentifier.h b/tests/cpp-unit-tests/browser_mock_npidentifier.h
new file mode 100644
index 0000000..d477fef
--- /dev/null
+++ b/tests/cpp-unit-tests/browser_mock_npidentifier.h
@@ -0,0 +1,57 @@
+/* Copyright (C) 2013 Red Hat
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ IcedTea is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+/*
+ * browser_mock_npidentifier.h:
+ * Handles NPAPI functions related to NPIdentifier, NPIdentifier has the following constraints:
+ * - Unique for each integer & string
+ * - Should not interfere with leak detection, so use malloc-based allocators (specified by templates) everywhere.
+ */
+
+#ifndef __BROWSER_MOCK_NPIDENTIFIER_H__
+#define __BROWSER_MOCK_NPIDENTIFIER_H__
+
+#include <string>
+#include <npfunctions.h>
+
+NPIdentifier browsermock_getstringidentifier(const NPUTF8* name);
+NPIdentifier browsermock_getintidentifier(int i);
+
+bool browsermock_identifierisstring(NPIdentifier identifier);
+
+NPUTF8* browsermock_utf8fromidentifier(NPIdentifier identifier);
+
+#endif // __BROWSER_MOCK_NPIDENTIFIER_H__
diff --git a/tests/cpp-unit-tests/checked_allocations.h b/tests/cpp-unit-tests/checked_allocations.h
index 0c9ce04..299c769 100644
--- a/tests/cpp-unit-tests/checked_allocations.h
+++ b/tests/cpp-unit-tests/checked_allocations.h
@@ -39,6 +39,7 @@
#ifndef CHECKED_ALLOCATIONS_H_
#define CHECKED_ALLOCATIONS_H_
+#include <string>
#include <set>
#include <cstdio>
#include <exception>
@@ -46,8 +47,9 @@
#include <cstdlib>
#include <ext/malloc_allocator.h> //GNU extension
-// Plays nice with custom-defined operator new
-typedef std::set<void*, std::less<void*>, __gnu_cxx::malloc_allocator<void*> > AllocationSet;
+// Classes that play nice with custom-defined operator new by using 'vanilla' malloc
+typedef __gnu_cxx::malloc_allocator<void*> SafeAllocator;
+typedef std::set<void*, std::less<void*>, SafeAllocator> AllocationSet;
int cpp_unfreed_allocations();
diff --git a/tests/cpp-unit-tests/main.cc b/tests/cpp-unit-tests/main.cc
index d7e71f6..c050bbb 100644
--- a/tests/cpp-unit-tests/main.cc
+++ b/tests/cpp-unit-tests/main.cc
@@ -42,7 +42,11 @@
#include <UnitTest++.h>
#include <TestReporter.h>
+#include <npfunctions.h>
+
+#include "IcedTeaNPPlugin.h"
#include "browser_mock.h"
+#include "MemoryLeakDetector.h"
#include "checked_allocations.h"
using namespace UnitTest;
@@ -56,6 +60,12 @@ static std::string full_testname(const TestDetails& details) {
}
}
+// Important for testing purposes of eg leaks between tests
+static void reset_global_state() {
+ browsermock_clear_state();
+ MemoryLeakDetector::reset_global_state();
+}
+
class IcedteaWebUnitTestReporter: public TestReporter {
public:
@@ -66,7 +76,7 @@ public:
}
virtual void ReportTestStart(const TestDetails& test) {
- browsermock_clear_state();
+ reset_global_state();
pretest_allocs = cpp_unfreed_allocations();
did_finish_correctly = true;
}
@@ -84,6 +94,7 @@ public:
virtual void ReportTestFinish(const TestDetails& details,
float secondsElapsed) {
+ reset_global_state();
int posttest_allocs = cpp_unfreed_allocations();
std::string testname = full_testname(details);
@@ -126,8 +137,20 @@ static int run_icedtea_web_unit_tests() {
True() /*All tests*/, 0 /*No time limit*/);
}
+/* Spawns the Java-side of the plugin, create request processing threads,
+ * and sets up a mocked 'browser' environment. */
+static void initialize_plugin_components() {
+ NPNetscapeFuncs mocked_browser_functions = browsermock_create_table();
+ NPPluginFuncs unused_plugin_functions;
+ memset(&unused_plugin_functions, 0, sizeof(NPPluginFuncs));
+ unused_plugin_functions.size = sizeof(NPPluginFuncs);
+
+ NP_Initialize (&mocked_browser_functions, &unused_plugin_functions);
+ start_jvm_if_needed();
+}
+
int main() {
- browsermock_setup_functions();
+ initialize_plugin_components();
int exitcode = run_icedtea_web_unit_tests();