/hg/icedtea-web: 2 new changesets
adomurad at icedtea.classpath.org
adomurad at icedtea.classpath.org
Fri Nov 30 10:09:23 PST 2012
changeset 0a968aa027ea in /hg/icedtea-web
details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=0a968aa027ea
author: Adam Domurad <adomurad at redhat.com>
date: Fri Nov 30 12:38:03 2012 -0500
C++ unit testing: Simple mocking of browser-table functions
changeset 172a5691e70d in /hg/icedtea-web
details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=172a5691e70d
author: Adam Domurad <adomurad at redhat.com>
date: Fri Nov 30 13:08:45 2012 -0500
Refactor IcedTeaPluginUtilities::javaResultToNPVariant into multiple functions
diffstat:
ChangeLog | 22 ++
plugin/icedteanp/IcedTeaPluginUtils.cc | 227 +++++++++++++-----------
plugin/icedteanp/IcedTeaPluginUtils.h | 8 +-
tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc | 36 +++
tests/cpp-unit-tests/browser_mock.cc | 79 ++++++++
tests/cpp-unit-tests/browser_mock.h | 50 +++++
tests/cpp-unit-tests/main.cc | 16 +-
7 files changed, 334 insertions(+), 104 deletions(-)
diffs (truncated from 542 to 500 lines):
diff -r 054a17dd19f6 -r 172a5691e70d ChangeLog
--- a/ChangeLog Tue Nov 27 09:20:50 2012 +0100
+++ b/ChangeLog Fri Nov 30 13:08:45 2012 -0500
@@ -1,3 +1,25 @@
+2012-11-30 Adam Domurad <adomurad at redhat.com>
+
+ Breaks up IcedTeaPluginUtilities::javaResultToNPVariant into multiple,
+ more manageable parts.
+ * plugin/icedteanp/IcedTeaPluginUtils.cc: Make three helper functions
+ for the different cases. Two new helper functions for converting from
+ std::string to NPString and NPVariant.
+ * plugin/icedteanp/IcedTeaPluginUtils.h: Two new helper functions.
+ * tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc: Tests for the new
+ NPString and NPVariant from std::string functions.
+
+2012-11-30 Adam Domurad <adomurad at redhat.com>
+
+ Added a simple mechanism for mocking functions in the browser function
+ table. Can be expanded as needed.
+ * tests/cpp-unit-tests/main.cc: Call setup function, warn on browser
+ function based memory leak.
+ * tests/cpp-unit-tests/browser_mock.cc: New, implements simple
+ error-checking mocks of browser callbacks.
+ * tests/cpp-unit-tests/browser_mock.h: New, interface to mocking
+ functions.
+
2012-11-27 Jiri Vanek <jvanek at redhat.com>
Better error reporting from applets
diff -r 054a17dd19f6 -r 172a5691e70d plugin/icedteanp/IcedTeaPluginUtils.cc
--- a/plugin/icedteanp/IcedTeaPluginUtils.cc Tue Nov 27 09:20:50 2012 +0100
+++ b/plugin/icedteanp/IcedTeaPluginUtils.cc Fri Nov 30 13:08:45 2012 -0500
@@ -715,116 +715,124 @@
}
}
+/**
+ * Convert either a void, boolean, or a number
+ */
+static void
+javaPrimitiveResultToNPVariant(const std::string& value, NPVariant* variant)
+{
+ if (value == "void")
+ {
+ PLUGIN_DEBUG("Method call returned void\n");
+ VOID_TO_NPVARIANT(*variant);
+ } else if (value == "null")
+ {
+ PLUGIN_DEBUG("Method call returned null\n");
+ NULL_TO_NPVARIANT(*variant);
+ } else if (value == "true")
+ {
+ PLUGIN_DEBUG("Method call returned a boolean (true)\n");
+ BOOLEAN_TO_NPVARIANT(true, *variant);
+ } else if (value == "false")
+ {
+ PLUGIN_DEBUG("Method call returned a boolean (false)\n");
+ BOOLEAN_TO_NPVARIANT(false, *variant);
+ } else
+ {
+ double d = strtod(value.c_str(), NULL);
+
+ // See if it is convertible to int
+ if (value.find(".") != std::string::npos || d < -(0x7fffffffL - 1L) || d > 0x7fffffffL)
+ {
+ PLUGIN_DEBUG("Method call returned a double %f\n", d);
+ DOUBLE_TO_NPVARIANT(d, *variant);
+ } else
+ {
+ int32_t i = (int32_t) d;
+ PLUGIN_DEBUG("Method call returned an int %d\n", i);
+ INT32_TO_NPVARIANT(i, *variant);
+ }
+ }
+}
+
+static bool
+javaStringResultToNPVariant(const std::string& jobject_id, NPVariant* variant)
+{
+ JavaRequestProcessor jrequest_processor;
+ JavaResultData* jstring_result = jrequest_processor.getString(jobject_id);
+
+ if (jstring_result->error_occurred)
+ {
+ return false;
+ }
+
+ std::string str = *jstring_result->return_string;
+
+ PLUGIN_DEBUG( "Method call returned a string:\"%s\"\n", str.c_str());
+
+ *variant = IcedTeaPluginUtilities::NPVariantStringCopy(str);
+
+ return true;
+}
+
+static bool
+javaObjectResultToNPVariant(NPP instance, const std::string& jobject_id, NPVariant* variant)
+{
+ // Reference the class object so we can construct an NPObject with it and the instance
+
+ JavaRequestProcessor jrequest_processor;
+ JavaResultData* jclass_result = jrequest_processor.getClassID(jobject_id);
+
+ if (jclass_result->error_occurred)
+ {
+ return false;
+ }
+
+ std::string jclass_id = *jclass_result->return_string;
+
+ NPObject* obj;
+ if (jclass_id.at(0) == '[') // array
+ {
+ obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, jclass_id,
+ jobject_id, true);
+ } else
+ {
+ obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, jclass_id,
+ jobject_id, false);
+ }
+
+ OBJECT_TO_NPVARIANT(obj, *variant);
+
+ return true;
+}
+
bool
IcedTeaPluginUtilities::javaResultToNPVariant(NPP instance,
- std::string* java_value,
- NPVariant* variant)
+ std::string* java_value, NPVariant* variant)
{
- JavaRequestProcessor java_request = JavaRequestProcessor();
- JavaResultData* java_result;
+ int literal_n = sizeof("literalreturn"); // Accounts for one space char
+ if (strncmp("literalreturn ", java_value->c_str(), literal_n) == 0)
+ {
+ javaPrimitiveResultToNPVariant(java_value->substr(literal_n), variant);
+ } else
+ {
+ std::string jobject_id = *java_value;
- if (java_value->find("literalreturn") == 0)
- {
- // 'literalreturn ' == 14 to skip
- std::string value = java_value->substr(14);
+ JavaRequestProcessor jrequest_processor;
+ JavaResultData* jclassname_result = jrequest_processor.getClassName(jobject_id);
- // VOID/BOOLEAN/NUMBER
-
- if (value == "void")
- {
- PLUGIN_DEBUG("Method call returned void\n");
- VOID_TO_NPVARIANT(*variant);
- } else if (value == "null")
- {
- PLUGIN_DEBUG("Method call returned null\n");
- NULL_TO_NPVARIANT(*variant);
- }else if (value == "true")
- {
- PLUGIN_DEBUG("Method call returned a boolean (true)\n");
- BOOLEAN_TO_NPVARIANT(true, *variant);
- } else if (value == "false")
- {
- PLUGIN_DEBUG("Method call returned a boolean (false)\n");
- BOOLEAN_TO_NPVARIANT(false, *variant);
- } else
- {
- double d = strtod(value.c_str(), NULL);
-
- // See if it is convertible to int
- if (value.find(".") != std::string::npos ||
- d < -(0x7fffffffL - 1L) ||
- d > 0x7fffffffL)
- {
- PLUGIN_DEBUG("Method call returned a double %f\n", d);
- DOUBLE_TO_NPVARIANT(d, *variant);
- } else
- {
- int32_t i = (int32_t) d;
- PLUGIN_DEBUG("Method call returned an int %d\n", i);
- INT32_TO_NPVARIANT(i, *variant);
- }
- }
- } else {
- // Else this is a complex java object
-
- // To keep code a little bit cleaner, we create variables with proper descriptive names
- std::string return_obj_instance_id = std::string();
- std::string return_obj_class_id = std::string();
- std::string return_obj_class_name = std::string();
- return_obj_instance_id.append(*java_value);
-
- // Find out the class name first, because string is a special case
- java_result = java_request.getClassName(return_obj_instance_id);
-
- if (java_result->error_occurred)
+ if (jclassname_result->error_occurred)
{
return false;
}
- return_obj_class_name.append(*(java_result->return_string));
-
- if (return_obj_class_name == "java.lang.String")
+ // Special-case for NPString if string
+ if (*jclassname_result->return_string == "java.lang.String")
{
- // String is a special case as NPVariant can handle it directly
- java_result = java_request.getString(return_obj_instance_id);
-
- if (java_result->error_occurred)
- {
- return false;
- }
-
- // needs to be on the heap
- NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
- strcpy(return_str, java_result->return_string->c_str());
-
- PLUGIN_DEBUG("Method call returned a string: \"%s\"\n", return_str);
- STRINGZ_TO_NPVARIANT(return_str, *variant);
-
- } else {
-
- // Else this is a regular class. Reference the class object so
- // we can construct an NPObject with it and the instance
- java_result = java_request.getClassID(return_obj_instance_id);
-
- if (java_result->error_occurred)
- {
- return false;
- }
-
- return_obj_class_id.append(*(java_result->return_string));
-
- NPObject* obj;
-
- if (return_obj_class_name.find('[') == 0) // array
- obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
- instance,
- return_obj_class_id, return_obj_instance_id, true);
- else
- obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
- instance,
- return_obj_class_id, return_obj_instance_id, false);
-
- OBJECT_TO_NPVARIANT(obj, *variant);
+ return javaStringResultToNPVariant(jobject_id, variant);
+ } else // Else this needs a java object wrapper
+ {
+ return javaObjectResultToNPVariant(instance, jobject_id, variant);
}
}
@@ -916,6 +924,25 @@
* @param func The function to post
* @param data Arguments to *func
*/
+NPString IcedTeaPluginUtilities::NPStringCopy(const std::string& result) {
+ char* utf8 = (char*)browser_functions.memalloc(result.size() + 1);
+ strncpy(utf8, result.c_str(), result.size() + 1);
+
+ NPString npstr = {utf8, result.size()};
+ return npstr;
+}
+
+NPVariant IcedTeaPluginUtilities::NPVariantStringCopy(const std::string& result) {
+ NPString npstr = NPStringCopy(result);
+ NPVariant npvar;
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+ STRINGN_TO_NPVARIANT(npstr.utf8characters, npstr.utf8length, npvar);
+#else
+ STRINGN_TO_NPVARIANT(npstr.UTF8Characters, npstr.UTF8Length, npvar);
+#endif
+ return npvar;
+}
+
void
IcedTeaPluginUtilities::callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data)
{
diff -r 054a17dd19f6 -r 172a5691e70d plugin/icedteanp/IcedTeaPluginUtils.h
--- a/plugin/icedteanp/IcedTeaPluginUtils.h Tue Nov 27 09:20:50 2012 +0100
+++ b/plugin/icedteanp/IcedTeaPluginUtils.h Fri Nov 30 13:08:45 2012 -0500
@@ -211,6 +211,12 @@
/* Copies a variant data type into a C++ string */
static std::string NPVariantAsString(NPVariant variant);
+ /* This must be freed with browserfunctions.memfree */
+ static NPString NPStringCopy(const std::string& result);
+
+ /* This must be freed with browserfunctions.releasevariantvalue */
+ static NPVariant NPVariantStringCopy(const std::string& result);
+
/* Frees the given vector and the strings that its contents point to */
static void freeStringPtrVector(std::vector<std::string*>* v);
@@ -242,7 +248,7 @@
static void printNPVariant(NPVariant variant);
- static void NPVariantToString(NPVariant variant, std::string* result);
+ static void NPVariantToString(NPVariant variant, std::string* result);
static bool javaResultToNPVariant(NPP instance,
std::string* java_result,
diff -r 054a17dd19f6 -r 172a5691e70d tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
--- a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc Tue Nov 27 09:20:50 2012 +0100
+++ b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc Fri Nov 30 13:08:45 2012 -0500
@@ -37,7 +37,11 @@
#include <UnitTest++.h>
#include <npapi.h>
+
+#include "browser_mock.h"
+
#include "IcedTeaPluginUtils.h"
+#include "IcedTeaNPPlugin.h"
TEST(NPVariantAsString) {
NPVariant var;
@@ -45,4 +49,36 @@
std::string cppstr = IcedTeaPluginUtilities::NPVariantAsString(var);
CHECK(cppstr == "test");
+
}
+
+TEST(NPStringCopy) {
+ std::string cppstr = "test";
+ NPString npstr = IcedTeaPluginUtilities::NPStringCopy(cppstr);
+
+ CHECK_EQUAL(4, npstr.UTF8Length);
+ CHECK_EQUAL("test", npstr.UTF8Characters);
+
+ // NPAPI states that browser allocation function should be used for NPString/NPVariant
+ CHECK_EQUAL(1, browsermock_unfreed_allocations());
+
+ browser_functions.memfree((void*) npstr.UTF8Characters);
+
+ CHECK_EQUAL(0, browsermock_unfreed_allocations());
+}
+
+TEST(NPVariantStringCopy) {
+ std::string cppstr = "test";
+ NPVariant npvar = IcedTeaPluginUtilities::NPVariantStringCopy(cppstr);
+
+ CHECK_EQUAL(NPVariantType_String, npvar.type);
+
+ CHECK_EQUAL(4, npvar.value.stringValue.UTF8Length);
+ CHECK_EQUAL("test", npvar.value.stringValue.UTF8Characters);
+
+ CHECK_EQUAL(1, browsermock_unfreed_allocations());
+
+ browser_functions.memfree((void*) npvar.value.stringValue.UTF8Characters);
+
+ CHECK_EQUAL(0, browsermock_unfreed_allocations());
+}
diff -r 054a17dd19f6 -r 172a5691e70d tests/cpp-unit-tests/browser_mock.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cpp-unit-tests/browser_mock.cc Fri Nov 30 13:08:45 2012 -0500
@@ -0,0 +1,79 @@
+/* Copyright (C) 2012 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 functions. Add more as needed.
+
+#include <cstring>
+#include <set>
+
+#include "UnitTest++.h"
+
+#include "browser_mock.h"
+
+#include "IcedTeaNPPlugin.h"
+
+static std::set<void*> __allocations;
+
+// It is expected that these will only run during a unit test
+static void* mock_memalloc(uint32_t size) {
+ void* mem = malloc(size);
+ __allocations.insert(mem);
+ return mem;
+}
+
+static void mock_memfree(void* ptr) {
+ if (__allocations.erase(ptr)) {
+ free(ptr);
+ } else {
+ printf("Attempt to free memory with browserfunctions.memfree that was not allocated by the browser!\n");
+ CHECK(false);
+ }
+}
+
+void browsermock_setup_functions() {
+ memset(&browser_functions, 0, sizeof(NPNetscapeFuncs));
+
+ browser_functions.memalloc = &mock_memalloc;
+ browser_functions.memfree = &mock_memfree;
+}
+
+void browsermock_clear_state() {
+ __allocations.clear();
+}
+
+int browsermock_unfreed_allocations() {
+ return __allocations.size();
+}
diff -r 054a17dd19f6 -r 172a5691e70d tests/cpp-unit-tests/browser_mock.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cpp-unit-tests/browser_mock.h Fri Nov 30 13:08:45 2012 -0500
@@ -0,0 +1,50 @@
+/* Copyright (C) 2012 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 functions.
+// This sets up a mock for unit testing purposes that puts simple
+// functions in the 'browserfunctions' table. This enables unit testing
+// of some functions that would otherwise not be possible.
+// Add additional mock functions in browser_mock.cc as needed
+
+#ifndef __BROWSER_MOCK_H__
+#define __BROWSER_MOCK_H__
+
+void browsermock_setup_functions();
+void browsermock_clear_state();
+int browsermock_unfreed_allocations();
+
+#endif // __BROWSER_MOCK_H__
diff -r 054a17dd19f6 -r 172a5691e70d tests/cpp-unit-tests/main.cc
--- a/tests/cpp-unit-tests/main.cc Tue Nov 27 09:20:50 2012 +0100
+++ b/tests/cpp-unit-tests/main.cc Fri Nov 30 13:08:45 2012 -0500
More information about the distro-pkg-dev
mailing list