1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/compiler_specific.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/WebKit/public/web/WebBindings.h"
12 #include "webkit/renderer/cpp_variant.h"
14 using WebKit::WebBindings
;
15 using webkit_glue::CppVariant
;
17 // Creates a std::string from an NPVariant of string type. If the NPVariant
18 // is not a string, empties the std::string.
19 void MakeStdString(const NPVariant
& np
, std::string
* std_string
) {
20 if (np
.type
== NPVariantType_String
) {
22 reinterpret_cast<const char*>(np
.value
.stringValue
.UTF8Characters
);
23 (*std_string
).assign(chars
, np
.value
.stringValue
.UTF8Length
);
25 (*std_string
).clear();
29 // Verifies that the actual NPVariant is a string and that its value matches
31 void CheckString(const std::string
& expected_str
, const NPVariant
& actual
) {
32 EXPECT_EQ(NPVariantType_String
, actual
.type
);
33 std::string actual_str
;
34 MakeStdString(actual
, &actual_str
);
35 EXPECT_EQ(expected_str
, actual_str
);
38 // Verifies that both the actual and the expected NPVariants are strings and
39 // that their values match.
40 void CheckString(const NPVariant
& expected
, const NPVariant
& actual
) {
41 EXPECT_EQ(NPVariantType_String
, expected
.type
);
42 std::string expected_str
;
43 MakeStdString(expected
, &expected_str
);
44 CheckString(expected_str
, actual
);
47 int g_allocate_call_count
= 0;
48 int g_deallocate_call_count
= 0;
50 void CheckObject(const NPVariant
& actual
) {
51 EXPECT_EQ(NPVariantType_Object
, actual
.type
);
52 EXPECT_TRUE(actual
.value
.objectValue
);
53 EXPECT_EQ(1U, actual
.value
.objectValue
->referenceCount
);
54 EXPECT_EQ(1, g_allocate_call_count
);
55 EXPECT_EQ(0, g_deallocate_call_count
);
58 NPObject
* MockNPAllocate(NPP npp
, NPClass
* aClass
) {
59 // This is a mock allocate method that mimics the behavior
60 // of WebBindings::createObject when allocate() is NULL
62 ++g_allocate_call_count
;
63 // Ignore npp and NPClass
64 return reinterpret_cast<NPObject
*>(malloc(sizeof(NPObject
)));
67 void MockNPDeallocate(NPObject
* npobj
) {
68 // This is a mock deallocate method that mimics the behavior
69 // of NPN_DeallocateObject when deallocate() is NULL
71 ++g_deallocate_call_count
;
75 static NPClass void_class
= { NP_CLASS_STRUCT_VERSION
,
78 0, 0, 0, 0, 0, 0, 0, 0, 0 };
80 class CppVariantTest
: public testing::Test
{
82 CppVariantTest() : npp_(new struct _NPP
) {}
83 virtual ~CppVariantTest() {}
85 virtual void SetUp() OVERRIDE
{
86 WebBindings::registerObjectOwner(npp_
.get());
89 virtual void TearDown() OVERRIDE
{
90 WebBindings::unregisterObjectOwner(npp_
.get());
93 struct _NPP
* npp() { return npp_
.get(); }
95 NPObject
* MakeVoidObject() {
96 g_allocate_call_count
= 0;
97 g_deallocate_call_count
= 0;
98 return WebBindings::createObject(npp_
.get(), &void_class
);
102 scoped_ptr
<struct _NPP
> npp_
;
105 TEST_F(CppVariantTest
, NewVariantHasNullType
) {
107 EXPECT_EQ(NPVariantType_Null
, value
.type
);
110 TEST_F(CppVariantTest
, SetNullSetsType
) {
114 EXPECT_EQ(NPVariantType_Null
, value
.type
);
117 TEST_F(CppVariantTest
, CopyConstructorDoesDeepCopy
) {
119 source
.Set("test string");
120 CppVariant dest
= source
;
121 EXPECT_EQ(NPVariantType_String
, dest
.type
);
122 EXPECT_EQ(NPVariantType_String
, source
.type
);
124 // Ensure that the string was copied, not just the pointer.
125 EXPECT_NE(source
.value
.stringValue
.UTF8Characters
,
126 dest
.value
.stringValue
.UTF8Characters
);
128 CheckString(source
, dest
);
131 TEST_F(CppVariantTest
, CopyConstructorIncrementsRefCount
) {
133 NPObject
*object
= MakeVoidObject();
135 // 2 references so far.
136 EXPECT_EQ(2U, source
.value
.objectValue
->referenceCount
);
138 CppVariant dest
= source
;
139 EXPECT_EQ(3U, dest
.value
.objectValue
->referenceCount
);
140 EXPECT_EQ(1, g_allocate_call_count
);
141 WebBindings::releaseObject(object
);
146 TEST_F(CppVariantTest
, AssignmentDoesDeepCopy
) {
148 source
.Set("test string");
151 EXPECT_EQ(NPVariantType_String
, dest
.type
);
152 EXPECT_EQ(NPVariantType_String
, source
.type
);
154 // Ensure that the string was copied, not just the pointer.
155 EXPECT_NE(source
.value
.stringValue
.UTF8Characters
,
156 dest
.value
.stringValue
.UTF8Characters
);
158 CheckString(source
, dest
);
161 TEST_F(CppVariantTest
, AssignmentIncrementsRefCount
) {
163 NPObject
*object
= MakeVoidObject();
165 // 2 references so far.
166 EXPECT_EQ(2U, source
.value
.objectValue
->referenceCount
);
170 EXPECT_EQ(3U, dest
.value
.objectValue
->referenceCount
);
171 EXPECT_EQ(1, g_allocate_call_count
);
173 WebBindings::releaseObject(object
);
178 TEST_F(CppVariantTest
, DestroyingCopyDoesNotCorruptSource
) {
180 source
.Set("test string");
182 MakeStdString(source
, &before
);
184 CppVariant dest
= source
;
186 CheckString(before
, source
);
188 NPObject
*object
= MakeVoidObject();
191 CppVariant dest2
= source
;
193 WebBindings::releaseObject(object
);
197 TEST_F(CppVariantTest
, CopiesTypeAndValueToNPVariant
) {
202 cpp
.CopyToNPVariant(&np
);
203 EXPECT_EQ(cpp
.type
, np
.type
);
204 EXPECT_EQ(cpp
.value
.boolValue
, np
.value
.boolValue
);
205 WebBindings::releaseVariantValue(&np
);
208 cpp
.CopyToNPVariant(&np
);
209 EXPECT_EQ(cpp
.type
, np
.type
);
210 EXPECT_EQ(cpp
.value
.intValue
, np
.value
.intValue
);
211 WebBindings::releaseVariantValue(&np
);
214 cpp
.CopyToNPVariant(&np
);
215 EXPECT_EQ(cpp
.type
, np
.type
);
216 EXPECT_EQ(cpp
.value
.doubleValue
, np
.value
.doubleValue
);
217 WebBindings::releaseVariantValue(&np
);
219 cpp
.Set("test value");
220 cpp
.CopyToNPVariant(&np
);
221 CheckString("test value", np
);
222 WebBindings::releaseVariantValue(&np
);
225 cpp
.CopyToNPVariant(&np
);
226 EXPECT_EQ(cpp
.type
, np
.type
);
227 WebBindings::releaseVariantValue(&np
);
229 NPObject
*object
= MakeVoidObject();
231 cpp
.CopyToNPVariant(&np
);
232 WebBindings::releaseObject(object
);
235 WebBindings::releaseVariantValue(&np
);
238 TEST_F(CppVariantTest
, SetsTypeAndValueFromNPVariant
) {
242 VOID_TO_NPVARIANT(np
);
244 EXPECT_EQ(np
.type
, cpp
.type
);
245 WebBindings::releaseVariantValue(&np
);
247 NULL_TO_NPVARIANT(np
);
249 EXPECT_EQ(np
.type
, cpp
.type
);
250 WebBindings::releaseVariantValue(&np
);
252 BOOLEAN_TO_NPVARIANT(true, np
);
254 EXPECT_EQ(np
.type
, cpp
.type
);
255 EXPECT_EQ(np
.value
.boolValue
, cpp
.value
.boolValue
);
256 WebBindings::releaseVariantValue(&np
);
258 INT32_TO_NPVARIANT(15, np
);
260 EXPECT_EQ(np
.type
, cpp
.type
);
261 EXPECT_EQ(np
.value
.intValue
, cpp
.value
.intValue
);
262 WebBindings::releaseVariantValue(&np
);
264 DOUBLE_TO_NPVARIANT(2.71828, np
);
266 EXPECT_EQ(np
.type
, cpp
.type
);
267 EXPECT_EQ(np
.value
.doubleValue
, cpp
.value
.doubleValue
);
268 WebBindings::releaseVariantValue(&np
);
270 NPString np_ascii_str
= { "1st test value",
271 static_cast<uint32_t>(strlen("1st test value")) };
272 WebBindings::initializeVariantWithStringCopy(&np
, &np_ascii_str
);
274 CheckString("1st test value", cpp
);
275 WebBindings::releaseVariantValue(&np
);
277 // Test characters represented in 2/3/4 bytes in UTF-8
278 // Greek alpha, Chinese number 1 (horizontal bar),
279 // Deseret letter (similar to 'O')
280 NPString np_intl_str
= { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
281 static_cast<uint32_t>(strlen(
282 "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
283 WebBindings::initializeVariantWithStringCopy(&np
, &np_intl_str
);
285 CheckString("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84", cpp
);
286 WebBindings::releaseVariantValue(&np
);
288 NPObject
*obj
= MakeVoidObject();
289 OBJECT_TO_NPVARIANT(obj
, np
); // Doesn't make a copy.
291 // Use this or WebBindings::releaseObject but NOT both.
292 WebBindings::releaseVariantValue(&np
);
296 TEST_F(CppVariantTest
, SetsSimpleTypesAndValues
) {
299 EXPECT_EQ(NPVariantType_Bool
, cpp
.type
);
300 EXPECT_TRUE(cpp
.value
.boolValue
);
303 EXPECT_EQ(NPVariantType_Int32
, cpp
.type
);
304 EXPECT_EQ(5, cpp
.value
.intValue
);
307 EXPECT_EQ(NPVariantType_Double
, cpp
.type
);
308 EXPECT_EQ(1.234, cpp
.value
.doubleValue
);
311 cpp
.Set("1st test string");
312 CheckString("1st test string", cpp
);
315 std::string
source("std test string");
317 CheckString("std test string", cpp
);
320 NPString np_ascii_str
= { "test NPString",
321 static_cast<uint32_t>(strlen("test NPString")) };
322 cpp
.Set(np_ascii_str
);
323 std::string
expected("test NPString");
324 CheckString(expected
, cpp
);
326 // Test characters represented in 2/3/4 bytes in UTF-8
327 // Greek alpha, Chinese number 1 (horizontal bar),
328 // Deseret letter (similar to 'O')
329 NPString np_intl_str
= { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
330 static_cast<uint32_t>(strlen(
331 "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
332 cpp
.Set(np_intl_str
);
333 expected
= std::string("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84");
334 CheckString(expected
, cpp
);
336 NPObject
* obj
= MakeVoidObject();
338 WebBindings::releaseObject(obj
);
342 TEST_F(CppVariantTest
, FreeDataSetsToVoid
) {
344 EXPECT_EQ(NPVariantType_Null
, cpp
.type
);
346 EXPECT_EQ(NPVariantType_Int32
, cpp
.type
);
348 EXPECT_EQ(NPVariantType_Void
, cpp
.type
);
351 TEST_F(CppVariantTest
, FreeDataReleasesObject
) {
353 NPObject
* object
= MakeVoidObject();
355 EXPECT_EQ(2U, object
->referenceCount
);
357 EXPECT_EQ(1U, object
->referenceCount
);
358 EXPECT_EQ(0, g_deallocate_call_count
);
361 WebBindings::releaseObject(object
);
362 EXPECT_EQ(0, g_deallocate_call_count
);
364 EXPECT_EQ(1, g_deallocate_call_count
);
367 TEST_F(CppVariantTest
, IsTypeFunctionsWork
) {
369 // These should not happen in practice, since voids are not supported
370 // This test must be first since it just clobbers internal data without
372 VOID_TO_NPVARIANT(cpp
);
373 EXPECT_FALSE(cpp
.isBool());
374 EXPECT_FALSE(cpp
.isInt32());
375 EXPECT_FALSE(cpp
.isDouble());
376 EXPECT_FALSE(cpp
.isNumber());
377 EXPECT_FALSE(cpp
.isString());
378 EXPECT_TRUE(cpp
.isVoid());
379 EXPECT_FALSE(cpp
.isNull());
380 EXPECT_TRUE(cpp
.isEmpty());
383 EXPECT_TRUE(cpp
.isBool());
384 EXPECT_FALSE(cpp
.isInt32());
385 EXPECT_FALSE(cpp
.isDouble());
386 EXPECT_FALSE(cpp
.isNumber());
387 EXPECT_FALSE(cpp
.isString());
388 EXPECT_FALSE(cpp
.isVoid());
389 EXPECT_FALSE(cpp
.isNull());
390 EXPECT_FALSE(cpp
.isEmpty());
391 EXPECT_FALSE(cpp
.isObject());
394 EXPECT_FALSE(cpp
.isBool());
395 EXPECT_TRUE(cpp
.isInt32());
396 EXPECT_FALSE(cpp
.isDouble());
397 EXPECT_TRUE(cpp
.isNumber());
398 EXPECT_FALSE(cpp
.isString());
399 EXPECT_FALSE(cpp
.isVoid());
400 EXPECT_FALSE(cpp
.isNull());
401 EXPECT_FALSE(cpp
.isEmpty());
402 EXPECT_FALSE(cpp
.isObject());
405 EXPECT_FALSE(cpp
.isBool());
406 EXPECT_FALSE(cpp
.isInt32());
407 EXPECT_TRUE(cpp
.isDouble());
408 EXPECT_TRUE(cpp
.isNumber());
409 EXPECT_FALSE(cpp
.isString());
410 EXPECT_FALSE(cpp
.isVoid());
411 EXPECT_FALSE(cpp
.isNull());
412 EXPECT_FALSE(cpp
.isEmpty());
413 EXPECT_FALSE(cpp
.isObject());
416 EXPECT_FALSE(cpp
.isBool());
417 EXPECT_FALSE(cpp
.isInt32());
418 EXPECT_FALSE(cpp
.isDouble());
419 EXPECT_FALSE(cpp
.isNumber());
420 EXPECT_TRUE(cpp
.isString());
421 EXPECT_FALSE(cpp
.isVoid());
422 EXPECT_FALSE(cpp
.isNull());
423 EXPECT_FALSE(cpp
.isEmpty());
424 EXPECT_FALSE(cpp
.isObject());
427 EXPECT_FALSE(cpp
.isBool());
428 EXPECT_FALSE(cpp
.isInt32());
429 EXPECT_FALSE(cpp
.isDouble());
430 EXPECT_FALSE(cpp
.isNumber());
431 EXPECT_FALSE(cpp
.isString());
432 EXPECT_FALSE(cpp
.isVoid());
433 EXPECT_TRUE(cpp
.isNull());
434 EXPECT_TRUE(cpp
.isEmpty());
435 EXPECT_FALSE(cpp
.isObject());
437 NPObject
*obj
= MakeVoidObject();
439 EXPECT_FALSE(cpp
.isBool());
440 EXPECT_FALSE(cpp
.isInt32());
441 EXPECT_FALSE(cpp
.isDouble());
442 EXPECT_FALSE(cpp
.isNumber());
443 EXPECT_FALSE(cpp
.isString());
444 EXPECT_FALSE(cpp
.isVoid());
445 EXPECT_FALSE(cpp
.isNull());
446 EXPECT_FALSE(cpp
.isEmpty());
447 EXPECT_TRUE(cpp
.isObject());
448 WebBindings::releaseObject(obj
);
452 bool MockNPHasPropertyFunction(NPObject
*npobj
, NPIdentifier name
) {
456 bool MockNPGetPropertyFunction(NPObject
*npobj
, NPIdentifier name
,
458 if (WebBindings::getStringIdentifier("length") == name
) {
459 DOUBLE_TO_NPVARIANT(4, *result
);
460 } else if (WebBindings::getIntIdentifier(0) == name
) {
461 DOUBLE_TO_NPVARIANT(0, *result
);
462 } else if (WebBindings::getIntIdentifier(1) == name
) {
463 BOOLEAN_TO_NPVARIANT(true, *result
);
464 } else if (WebBindings::getIntIdentifier(2) == name
) {
465 NULL_TO_NPVARIANT(*result
);
466 } else if (WebBindings::getIntIdentifier(3) == name
) {
467 const char* s
= "string";
468 size_t length
= strlen(s
);
469 char* mem
= static_cast<char*>(malloc(length
+ 1));
470 base::strlcpy(mem
, s
, length
+ 1);
471 STRINGZ_TO_NPVARIANT(mem
, *result
);
477 TEST_F(CppVariantTest
, ToVector
) {
478 NPClass array_like_class
= {
479 NP_CLASS_STRUCT_VERSION
,
480 0, // NPAllocateFunctionPtr allocate;
481 0, // NPDeallocateFunctionPtr deallocate;
482 0, // NPInvalidateFunctionPtr invalidate;
483 0, // NPHasMethodFunctionPtr hasMethod;
484 0, // NPInvokeFunctionPtr invoke;
485 0, // NPInvokeDefaultFunctionPtr invokeDefault;
486 MockNPHasPropertyFunction
, // NPHasPropertyFunctionPtr hasProperty;
487 MockNPGetPropertyFunction
, // NPGetPropertyFunctionPtr getProperty;
488 0, // NPSetPropertyFunctionPtr setProperty;
489 0, // NPRemovePropertyFunctionPtr removeProperty;
490 0, // NPEnumerationFunctionPtr enumerate;
491 0 // NPConstructFunctionPtr construct;
494 NPObject
* obj
= WebBindings::createObject(npp(), &array_like_class
);
499 std::vector
<CppVariant
> cpp_vector
= cpp
.ToVector();
500 EXPECT_EQ(4u, cpp_vector
.size());
502 EXPECT_TRUE(cpp_vector
[0].isDouble());
503 EXPECT_EQ(0, cpp_vector
[0].ToDouble());
505 EXPECT_TRUE(cpp_vector
[1].isBool());
506 EXPECT_EQ(true, cpp_vector
[1].ToBoolean());
508 EXPECT_TRUE(cpp_vector
[2].isNull());
510 EXPECT_TRUE(cpp_vector
[3].isString());
511 CheckString("string", cpp_vector
[3]);
513 WebBindings::releaseObject(obj
);