summaryrefslogtreecommitdiffstats
path: root/webkit/glue/cpp_variant_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue/cpp_variant_unittest.cc')
-rw-r--r--webkit/glue/cpp_variant_unittest.cc426
1 files changed, 426 insertions, 0 deletions
diff --git a/webkit/glue/cpp_variant_unittest.cc b/webkit/glue/cpp_variant_unittest.cc
new file mode 100644
index 0000000..43c78de
--- /dev/null
+++ b/webkit/glue/cpp_variant_unittest.cc
@@ -0,0 +1,426 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/compiler_specific.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "webkit/glue/cpp_variant.h"
+
+using WebKit::WebBindings;
+
+// Creates a std::string from an NPVariant of string type. If the NPVariant
+// is not a string, empties the std::string.
+void MakeStdString(const NPVariant& np, std::string* std_string) {
+ if (np.type == NPVariantType_String) {
+ const char* chars =
+ reinterpret_cast<const char*>(np.value.stringValue.UTF8Characters);
+ (*std_string).assign(chars, np.value.stringValue.UTF8Length);
+ } else {
+ (*std_string).clear();
+ }
+}
+
+// Verifies that the actual NPVariant is a string and that its value matches
+// the expected_str.
+void CheckString(const std::string& expected_str, const NPVariant& actual) {
+ EXPECT_EQ(NPVariantType_String, actual.type);
+ std::string actual_str;
+ MakeStdString(actual, &actual_str);
+ EXPECT_EQ(expected_str, actual_str);
+}
+
+// Verifies that both the actual and the expected NPVariants are strings and
+// that their values match.
+void CheckString(const NPVariant& expected, const NPVariant& actual) {
+ EXPECT_EQ(NPVariantType_String, expected.type);
+ std::string expected_str;
+ MakeStdString(expected, &expected_str);
+ CheckString(expected_str, actual);
+}
+
+int g_allocate_call_count = 0;
+int g_deallocate_call_count = 0;
+
+void CheckObject(const NPVariant& actual) {
+ EXPECT_EQ(NPVariantType_Object, actual.type);
+ EXPECT_TRUE(actual.value.objectValue);
+ EXPECT_EQ(1U, actual.value.objectValue->referenceCount);
+ EXPECT_EQ(1, g_allocate_call_count);
+ EXPECT_EQ(0, g_deallocate_call_count);
+}
+
+NPObject* MockNPAllocate(NPP npp, NPClass* aClass) {
+ // This is a mock allocate method that mimics the behavior
+ // of WebBindings::createObject when allocate() is NULL
+
+ ++g_allocate_call_count;
+ // Ignore npp and NPClass
+ return reinterpret_cast<NPObject*>(malloc(sizeof(NPObject)));
+}
+
+void MockNPDeallocate(NPObject* npobj) {
+ // This is a mock deallocate method that mimics the behavior
+ // of NPN_DeallocateObject when deallocate() is NULL
+
+ ++g_deallocate_call_count;
+ free(npobj);
+}
+
+static NPClass void_class = { NP_CLASS_STRUCT_VERSION,
+ MockNPAllocate,
+ MockNPDeallocate,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+NPObject* MakeVoidObject() {
+ g_allocate_call_count = 0;
+ g_deallocate_call_count = 0;
+ return WebBindings::createObject(NULL, &void_class);
+}
+
+TEST(CppVariantTest, NewVariantHasNullType) {
+ CppVariant value;
+ EXPECT_EQ(NPVariantType_Null, value.type);
+}
+
+TEST(CppVariantTest, SetNullSetsType) {
+ CppVariant value;
+ value.Set(17);
+ value.SetNull();
+ EXPECT_EQ(NPVariantType_Null, value.type);
+}
+
+TEST(CppVariantTest, CopyConstructorDoesDeepCopy) {
+ CppVariant source;
+ source.Set("test string");
+ CppVariant dest = source;
+ EXPECT_EQ(NPVariantType_String, dest.type);
+ EXPECT_EQ(NPVariantType_String, source.type);
+
+ // Ensure that the string was copied, not just the pointer.
+ EXPECT_NE(source.value.stringValue.UTF8Characters,
+ dest.value.stringValue.UTF8Characters);
+
+ CheckString(source, dest);
+}
+
+TEST(CppVariantTest, CopyConstructorIncrementsRefCount) {
+ CppVariant source;
+ NPObject *object = MakeVoidObject();
+ source.Set(object);
+ // 2 references so far.
+ EXPECT_EQ(2U, source.value.objectValue->referenceCount);
+
+ CppVariant dest = source;
+ EXPECT_EQ(3U, dest.value.objectValue->referenceCount);
+ EXPECT_EQ(1, g_allocate_call_count);
+ WebBindings::releaseObject(object);
+ source.SetNull();
+ CheckObject(dest);
+}
+
+TEST(CppVariantTest, AssignmentDoesDeepCopy) {
+ CppVariant source;
+ source.Set("test string");
+ CppVariant dest;
+ dest = source;
+ EXPECT_EQ(NPVariantType_String, dest.type);
+ EXPECT_EQ(NPVariantType_String, source.type);
+
+ // Ensure that the string was copied, not just the pointer.
+ EXPECT_NE(source.value.stringValue.UTF8Characters,
+ dest.value.stringValue.UTF8Characters);
+
+ CheckString(source, dest);
+}
+
+TEST(CppVariantTest, AssignmentIncrementsRefCount) {
+ CppVariant source;
+ NPObject *object = MakeVoidObject();
+ source.Set(object);
+ // 2 references so far.
+ EXPECT_EQ(2U, source.value.objectValue->referenceCount);
+
+ CppVariant dest;
+ dest = source;
+ EXPECT_EQ(3U, dest.value.objectValue->referenceCount);
+ EXPECT_EQ(1, g_allocate_call_count);
+
+ WebBindings::releaseObject(object);
+ source.SetNull();
+ CheckObject(dest);
+}
+
+TEST(CppVariantTest, DestroyingCopyDoesNotCorruptSource) {
+ CppVariant source;
+ source.Set("test string");
+ std::string before;
+ MakeStdString(source, &before);
+ {
+ CppVariant dest = source;
+ }
+ CheckString(before, source);
+
+ NPObject *object = MakeVoidObject();
+ source.Set(object);
+ {
+ CppVariant dest2 = source;
+ }
+ WebBindings::releaseObject(object);
+ CheckObject(source);
+}
+
+TEST(CppVariantTest, CopiesTypeAndValueToNPVariant) {
+ NPVariant np;
+ CppVariant cpp;
+
+ cpp.Set(true);
+ cpp.CopyToNPVariant(&np);
+ EXPECT_EQ(cpp.type, np.type);
+ EXPECT_EQ(cpp.value.boolValue, np.value.boolValue);
+ WebBindings::releaseVariantValue(&np);
+
+ cpp.Set(17);
+ cpp.CopyToNPVariant(&np);
+ EXPECT_EQ(cpp.type, np.type);
+ EXPECT_EQ(cpp.value.intValue, np.value.intValue);
+ WebBindings::releaseVariantValue(&np);
+
+ cpp.Set(3.1415);
+ cpp.CopyToNPVariant(&np);
+ EXPECT_EQ(cpp.type, np.type);
+ EXPECT_EQ(cpp.value.doubleValue, np.value.doubleValue);
+ WebBindings::releaseVariantValue(&np);
+
+ cpp.Set("test value");
+ cpp.CopyToNPVariant(&np);
+ CheckString("test value", np);
+ WebBindings::releaseVariantValue(&np);
+
+ cpp.SetNull();
+ cpp.CopyToNPVariant(&np);
+ EXPECT_EQ(cpp.type, np.type);
+ WebBindings::releaseVariantValue(&np);
+
+ NPObject *object = MakeVoidObject();
+ cpp.Set(object);
+ cpp.CopyToNPVariant(&np);
+ WebBindings::releaseObject(object);
+ cpp.SetNull();
+ CheckObject(np);
+ WebBindings::releaseVariantValue(&np);
+}
+
+TEST(CppVariantTest, SetsTypeAndValueFromNPVariant) {
+ NPVariant np;
+ CppVariant cpp;
+
+ VOID_TO_NPVARIANT(np);
+ cpp.Set(np);
+ EXPECT_EQ(np.type, cpp.type);
+ WebBindings::releaseVariantValue(&np);
+
+ NULL_TO_NPVARIANT(np);
+ cpp.Set(np);
+ EXPECT_EQ(np.type, cpp.type);
+ WebBindings::releaseVariantValue(&np);
+
+ BOOLEAN_TO_NPVARIANT(true, np);
+ cpp.Set(np);
+ EXPECT_EQ(np.type, cpp.type);
+ EXPECT_EQ(np.value.boolValue, cpp.value.boolValue);
+ WebBindings::releaseVariantValue(&np);
+
+ INT32_TO_NPVARIANT(15, np);
+ cpp.Set(np);
+ EXPECT_EQ(np.type, cpp.type);
+ EXPECT_EQ(np.value.intValue, cpp.value.intValue);
+ WebBindings::releaseVariantValue(&np);
+
+ DOUBLE_TO_NPVARIANT(2.71828, np);
+ cpp.Set(np);
+ EXPECT_EQ(np.type, cpp.type);
+ EXPECT_EQ(np.value.doubleValue, cpp.value.doubleValue);
+ WebBindings::releaseVariantValue(&np);
+
+ NPString np_ascii_str = { "1st test value",
+ static_cast<uint32_t>(strlen("1st test value")) };
+ WebBindings::initializeVariantWithStringCopy(&np, &np_ascii_str);
+ cpp.Set(np);
+ CheckString("1st test value", cpp);
+ WebBindings::releaseVariantValue(&np);
+
+ // Test characters represented in 2/3/4 bytes in UTF-8
+ // Greek alpha, Chinese number 1 (horizontal bar),
+ // Deseret letter (similar to 'O')
+ NPString np_intl_str = { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
+ static_cast<uint32_t>(strlen(
+ "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
+ WebBindings::initializeVariantWithStringCopy(&np, &np_intl_str);
+ cpp.Set(np);
+ CheckString("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84", cpp);
+ WebBindings::releaseVariantValue(&np);
+
+ NPObject *obj = MakeVoidObject();
+ OBJECT_TO_NPVARIANT(obj, np); // Doesn't make a copy.
+ cpp.Set(np);
+ // Use this or WebBindings::releaseObject but NOT both.
+ WebBindings::releaseVariantValue(&np);
+ CheckObject(cpp);
+}
+
+TEST(CppVariantTest, SetsSimpleTypesAndValues) {
+ CppVariant cpp;
+ cpp.Set(true);
+ EXPECT_EQ(NPVariantType_Bool, cpp.type);
+ EXPECT_EQ(true, cpp.value.boolValue);
+
+ cpp.Set(5);
+ EXPECT_EQ(NPVariantType_Int32, cpp.type);
+ EXPECT_EQ(5, cpp.value.intValue);
+
+ cpp.Set(1.234);
+ EXPECT_EQ(NPVariantType_Double, cpp.type);
+ EXPECT_EQ(1.234, cpp.value.doubleValue);
+
+ // C string
+ cpp.Set("1st test string");
+ CheckString("1st test string", cpp);
+
+ // std::string
+ std::string source("std test string");
+ cpp.Set(source);
+ CheckString("std test string", cpp);
+
+ // NPString
+ NPString np_ascii_str = { "test NPString",
+ static_cast<uint32_t>(strlen("test NPString")) };
+ cpp.Set(np_ascii_str);
+ std::string expected("test NPString");
+ CheckString(expected, cpp);
+
+ // Test characters represented in 2/3/4 bytes in UTF-8
+ // Greek alpha, Chinese number 1 (horizontal bar),
+ // Deseret letter (similar to 'O')
+ NPString np_intl_str = { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
+ static_cast<uint32_t>(strlen(
+ "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
+ cpp.Set(np_intl_str);
+ expected = std::string("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84");
+ CheckString(expected, cpp);
+
+ NPObject* obj = MakeVoidObject();
+ cpp.Set(obj);
+ WebBindings::releaseObject(obj);
+ CheckObject(cpp);
+}
+
+TEST(CppVariantTest, FreeDataSetsToVoid) {
+ CppVariant cpp;
+ EXPECT_EQ(NPVariantType_Null, cpp.type);
+ cpp.Set(12);
+ EXPECT_EQ(NPVariantType_Int32, cpp.type);
+ cpp.FreeData();
+ EXPECT_EQ(NPVariantType_Void, cpp.type);
+}
+
+TEST(CppVariantTest, FreeDataReleasesObject) {
+ CppVariant cpp;
+ NPObject* object = MakeVoidObject();
+ cpp.Set(object);
+ EXPECT_EQ(2U, object->referenceCount);
+ cpp.FreeData();
+ EXPECT_EQ(1U, object->referenceCount);
+ EXPECT_EQ(0, g_deallocate_call_count);
+
+ cpp.Set(object);
+ WebBindings::releaseObject(object);
+ EXPECT_EQ(0, g_deallocate_call_count);
+ cpp.FreeData();
+ EXPECT_EQ(1, g_deallocate_call_count);
+}
+
+TEST(CppVariantTest, IsTypeFunctionsWork) {
+ CppVariant cpp;
+ // These should not happen in practice, since voids are not supported
+ // This test must be first since it just clobbers internal data without
+ // releasing.
+ VOID_TO_NPVARIANT(cpp);
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_FALSE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_TRUE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_TRUE(cpp.isEmpty());
+
+ cpp.Set(true);
+ EXPECT_TRUE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_FALSE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_FALSE(cpp.isEmpty());
+ EXPECT_FALSE(cpp.isObject());
+
+ cpp.Set(12);
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_TRUE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_TRUE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_FALSE(cpp.isEmpty());
+ EXPECT_FALSE(cpp.isObject());
+
+ cpp.Set(3.1415);
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_TRUE(cpp.isDouble());
+ EXPECT_TRUE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_FALSE(cpp.isEmpty());
+ EXPECT_FALSE(cpp.isObject());
+
+ cpp.Set("a string");
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_FALSE(cpp.isNumber());
+ EXPECT_TRUE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_FALSE(cpp.isEmpty());
+ EXPECT_FALSE(cpp.isObject());
+
+ cpp.SetNull();
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_FALSE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_TRUE(cpp.isNull());
+ EXPECT_TRUE(cpp.isEmpty());
+ EXPECT_FALSE(cpp.isObject());
+
+ NPObject *obj = MakeVoidObject();
+ cpp.Set(obj);
+ EXPECT_FALSE(cpp.isBool());
+ EXPECT_FALSE(cpp.isInt32());
+ EXPECT_FALSE(cpp.isDouble());
+ EXPECT_FALSE(cpp.isNumber());
+ EXPECT_FALSE(cpp.isString());
+ EXPECT_FALSE(cpp.isVoid());
+ EXPECT_FALSE(cpp.isNull());
+ EXPECT_FALSE(cpp.isEmpty());
+ EXPECT_TRUE(cpp.isObject());
+ WebBindings::releaseObject(obj);
+ CheckObject(cpp);
+}