aboutsummaryrefslogtreecommitdiffstats
path: root/tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc')
-rw-r--r--tests/cpp-unit-tests/IcedTeaJavaRequestProcessorTest.cc416
1 files changed, 416 insertions, 0 deletions
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);
+ }
+}