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/string_util.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
11 #include "webkit/glue/cpp_variant.h"
13 using WebKit::WebBindings
;
14 using webkit_glue::CppVariant
;
16 // Creates a std::string from an NPVariant of string type. If the NPVariant
17 // is not a string, empties the std::string.
18 void MakeStdString(const NPVariant
& np
, std::string
* std_string
) {
19 if (np
.type
== NPVariantType_String
) {
21 reinterpret_cast<const char*>(np
.value
.stringValue
.UTF8Characters
);
22 (*std_string
).assign(chars
, np
.value
.stringValue
.UTF8Length
);
24 (*std_string
).clear();
28 // Verifies that the actual NPVariant is a string and that its value matches
30 void CheckString(const std::string
& expected_str
, const NPVariant
& actual
) {
31 EXPECT_EQ(NPVariantType_String
, actual
.type
);
32 std::string actual_str
;
33 MakeStdString(actual
, &actual_str
);
34 EXPECT_EQ(expected_str
, actual_str
);
37 // Verifies that both the actual and the expected NPVariants are strings and
38 // that their values match.
39 void CheckString(const NPVariant
& expected
, const NPVariant
& actual
) {
40 EXPECT_EQ(NPVariantType_String
, expected
.type
);
41 std::string expected_str
;
42 MakeStdString(expected
, &expected_str
);
43 CheckString(expected_str
, actual
);
46 int g_allocate_call_count
= 0;
47 int g_deallocate_call_count
= 0;
49 void CheckObject(const NPVariant
& actual
) {
50 EXPECT_EQ(NPVariantType_Object
, actual
.type
);
51 EXPECT_TRUE(actual
.value
.objectValue
);
52 EXPECT_EQ(1U, actual
.value
.objectValue
->referenceCount
);
53 EXPECT_EQ(1, g_allocate_call_count
);
54 EXPECT_EQ(0, g_deallocate_call_count
);
57 NPObject
* MockNPAllocate(NPP npp
, NPClass
* aClass
) {
58 // This is a mock allocate method that mimics the behavior
59 // of WebBindings::createObject when allocate() is NULL
61 ++g_allocate_call_count
;
62 // Ignore npp and NPClass
63 return reinterpret_cast<NPObject
*>(malloc(sizeof(NPObject
)));
66 void MockNPDeallocate(NPObject
* npobj
) {
67 // This is a mock deallocate method that mimics the behavior
68 // of NPN_DeallocateObject when deallocate() is NULL
70 ++g_deallocate_call_count
;
74 static NPClass void_class
= { NP_CLASS_STRUCT_VERSION
,
77 0, 0, 0, 0, 0, 0, 0, 0, 0 };
79 NPObject
* MakeVoidObject() {
80 g_allocate_call_count
= 0;
81 g_deallocate_call_count
= 0;
82 return WebBindings::createObject(NULL
, &void_class
);
85 TEST(CppVariantTest
, NewVariantHasNullType
) {
87 EXPECT_EQ(NPVariantType_Null
, value
.type
);
90 TEST(CppVariantTest
, SetNullSetsType
) {
94 EXPECT_EQ(NPVariantType_Null
, value
.type
);
97 TEST(CppVariantTest
, CopyConstructorDoesDeepCopy
) {
99 source
.Set("test string");
100 CppVariant dest
= source
;
101 EXPECT_EQ(NPVariantType_String
, dest
.type
);
102 EXPECT_EQ(NPVariantType_String
, source
.type
);
104 // Ensure that the string was copied, not just the pointer.
105 EXPECT_NE(source
.value
.stringValue
.UTF8Characters
,
106 dest
.value
.stringValue
.UTF8Characters
);
108 CheckString(source
, dest
);
111 TEST(CppVariantTest
, CopyConstructorIncrementsRefCount
) {
113 NPObject
*object
= MakeVoidObject();
115 // 2 references so far.
116 EXPECT_EQ(2U, source
.value
.objectValue
->referenceCount
);
118 CppVariant dest
= source
;
119 EXPECT_EQ(3U, dest
.value
.objectValue
->referenceCount
);
120 EXPECT_EQ(1, g_allocate_call_count
);
121 WebBindings::releaseObject(object
);
126 TEST(CppVariantTest
, AssignmentDoesDeepCopy
) {
128 source
.Set("test string");
131 EXPECT_EQ(NPVariantType_String
, dest
.type
);
132 EXPECT_EQ(NPVariantType_String
, source
.type
);
134 // Ensure that the string was copied, not just the pointer.
135 EXPECT_NE(source
.value
.stringValue
.UTF8Characters
,
136 dest
.value
.stringValue
.UTF8Characters
);
138 CheckString(source
, dest
);
141 TEST(CppVariantTest
, AssignmentIncrementsRefCount
) {
143 NPObject
*object
= MakeVoidObject();
145 // 2 references so far.
146 EXPECT_EQ(2U, source
.value
.objectValue
->referenceCount
);
150 EXPECT_EQ(3U, dest
.value
.objectValue
->referenceCount
);
151 EXPECT_EQ(1, g_allocate_call_count
);
153 WebBindings::releaseObject(object
);
158 TEST(CppVariantTest
, DestroyingCopyDoesNotCorruptSource
) {
160 source
.Set("test string");
162 MakeStdString(source
, &before
);
164 CppVariant dest
= source
;
166 CheckString(before
, source
);
168 NPObject
*object
= MakeVoidObject();
171 CppVariant dest2
= source
;
173 WebBindings::releaseObject(object
);
177 TEST(CppVariantTest
, CopiesTypeAndValueToNPVariant
) {
182 cpp
.CopyToNPVariant(&np
);
183 EXPECT_EQ(cpp
.type
, np
.type
);
184 EXPECT_EQ(cpp
.value
.boolValue
, np
.value
.boolValue
);
185 WebBindings::releaseVariantValue(&np
);
188 cpp
.CopyToNPVariant(&np
);
189 EXPECT_EQ(cpp
.type
, np
.type
);
190 EXPECT_EQ(cpp
.value
.intValue
, np
.value
.intValue
);
191 WebBindings::releaseVariantValue(&np
);
194 cpp
.CopyToNPVariant(&np
);
195 EXPECT_EQ(cpp
.type
, np
.type
);
196 EXPECT_EQ(cpp
.value
.doubleValue
, np
.value
.doubleValue
);
197 WebBindings::releaseVariantValue(&np
);
199 cpp
.Set("test value");
200 cpp
.CopyToNPVariant(&np
);
201 CheckString("test value", np
);
202 WebBindings::releaseVariantValue(&np
);
205 cpp
.CopyToNPVariant(&np
);
206 EXPECT_EQ(cpp
.type
, np
.type
);
207 WebBindings::releaseVariantValue(&np
);
209 NPObject
*object
= MakeVoidObject();
211 cpp
.CopyToNPVariant(&np
);
212 WebBindings::releaseObject(object
);
215 WebBindings::releaseVariantValue(&np
);
218 TEST(CppVariantTest
, SetsTypeAndValueFromNPVariant
) {
222 VOID_TO_NPVARIANT(np
);
224 EXPECT_EQ(np
.type
, cpp
.type
);
225 WebBindings::releaseVariantValue(&np
);
227 NULL_TO_NPVARIANT(np
);
229 EXPECT_EQ(np
.type
, cpp
.type
);
230 WebBindings::releaseVariantValue(&np
);
232 BOOLEAN_TO_NPVARIANT(true, np
);
234 EXPECT_EQ(np
.type
, cpp
.type
);
235 EXPECT_EQ(np
.value
.boolValue
, cpp
.value
.boolValue
);
236 WebBindings::releaseVariantValue(&np
);
238 INT32_TO_NPVARIANT(15, np
);
240 EXPECT_EQ(np
.type
, cpp
.type
);
241 EXPECT_EQ(np
.value
.intValue
, cpp
.value
.intValue
);
242 WebBindings::releaseVariantValue(&np
);
244 DOUBLE_TO_NPVARIANT(2.71828, np
);
246 EXPECT_EQ(np
.type
, cpp
.type
);
247 EXPECT_EQ(np
.value
.doubleValue
, cpp
.value
.doubleValue
);
248 WebBindings::releaseVariantValue(&np
);
250 NPString np_ascii_str
= { "1st test value",
251 static_cast<uint32_t>(strlen("1st test value")) };
252 WebBindings::initializeVariantWithStringCopy(&np
, &np_ascii_str
);
254 CheckString("1st test value", cpp
);
255 WebBindings::releaseVariantValue(&np
);
257 // Test characters represented in 2/3/4 bytes in UTF-8
258 // Greek alpha, Chinese number 1 (horizontal bar),
259 // Deseret letter (similar to 'O')
260 NPString np_intl_str
= { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
261 static_cast<uint32_t>(strlen(
262 "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
263 WebBindings::initializeVariantWithStringCopy(&np
, &np_intl_str
);
265 CheckString("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84", cpp
);
266 WebBindings::releaseVariantValue(&np
);
268 NPObject
*obj
= MakeVoidObject();
269 OBJECT_TO_NPVARIANT(obj
, np
); // Doesn't make a copy.
271 // Use this or WebBindings::releaseObject but NOT both.
272 WebBindings::releaseVariantValue(&np
);
276 TEST(CppVariantTest
, SetsSimpleTypesAndValues
) {
279 EXPECT_EQ(NPVariantType_Bool
, cpp
.type
);
280 EXPECT_TRUE(cpp
.value
.boolValue
);
283 EXPECT_EQ(NPVariantType_Int32
, cpp
.type
);
284 EXPECT_EQ(5, cpp
.value
.intValue
);
287 EXPECT_EQ(NPVariantType_Double
, cpp
.type
);
288 EXPECT_EQ(1.234, cpp
.value
.doubleValue
);
291 cpp
.Set("1st test string");
292 CheckString("1st test string", cpp
);
295 std::string
source("std test string");
297 CheckString("std test string", cpp
);
300 NPString np_ascii_str
= { "test NPString",
301 static_cast<uint32_t>(strlen("test NPString")) };
302 cpp
.Set(np_ascii_str
);
303 std::string
expected("test NPString");
304 CheckString(expected
, cpp
);
306 // Test characters represented in 2/3/4 bytes in UTF-8
307 // Greek alpha, Chinese number 1 (horizontal bar),
308 // Deseret letter (similar to 'O')
309 NPString np_intl_str
= { "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84",
310 static_cast<uint32_t>(strlen(
311 "\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84")) };
312 cpp
.Set(np_intl_str
);
313 expected
= std::string("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84");
314 CheckString(expected
, cpp
);
316 NPObject
* obj
= MakeVoidObject();
318 WebBindings::releaseObject(obj
);
322 TEST(CppVariantTest
, FreeDataSetsToVoid
) {
324 EXPECT_EQ(NPVariantType_Null
, cpp
.type
);
326 EXPECT_EQ(NPVariantType_Int32
, cpp
.type
);
328 EXPECT_EQ(NPVariantType_Void
, cpp
.type
);
331 TEST(CppVariantTest
, FreeDataReleasesObject
) {
333 NPObject
* object
= MakeVoidObject();
335 EXPECT_EQ(2U, object
->referenceCount
);
337 EXPECT_EQ(1U, object
->referenceCount
);
338 EXPECT_EQ(0, g_deallocate_call_count
);
341 WebBindings::releaseObject(object
);
342 EXPECT_EQ(0, g_deallocate_call_count
);
344 EXPECT_EQ(1, g_deallocate_call_count
);
347 TEST(CppVariantTest
, IsTypeFunctionsWork
) {
349 // These should not happen in practice, since voids are not supported
350 // This test must be first since it just clobbers internal data without
352 VOID_TO_NPVARIANT(cpp
);
353 EXPECT_FALSE(cpp
.isBool());
354 EXPECT_FALSE(cpp
.isInt32());
355 EXPECT_FALSE(cpp
.isDouble());
356 EXPECT_FALSE(cpp
.isNumber());
357 EXPECT_FALSE(cpp
.isString());
358 EXPECT_TRUE(cpp
.isVoid());
359 EXPECT_FALSE(cpp
.isNull());
360 EXPECT_TRUE(cpp
.isEmpty());
363 EXPECT_TRUE(cpp
.isBool());
364 EXPECT_FALSE(cpp
.isInt32());
365 EXPECT_FALSE(cpp
.isDouble());
366 EXPECT_FALSE(cpp
.isNumber());
367 EXPECT_FALSE(cpp
.isString());
368 EXPECT_FALSE(cpp
.isVoid());
369 EXPECT_FALSE(cpp
.isNull());
370 EXPECT_FALSE(cpp
.isEmpty());
371 EXPECT_FALSE(cpp
.isObject());
374 EXPECT_FALSE(cpp
.isBool());
375 EXPECT_TRUE(cpp
.isInt32());
376 EXPECT_FALSE(cpp
.isDouble());
377 EXPECT_TRUE(cpp
.isNumber());
378 EXPECT_FALSE(cpp
.isString());
379 EXPECT_FALSE(cpp
.isVoid());
380 EXPECT_FALSE(cpp
.isNull());
381 EXPECT_FALSE(cpp
.isEmpty());
382 EXPECT_FALSE(cpp
.isObject());
385 EXPECT_FALSE(cpp
.isBool());
386 EXPECT_FALSE(cpp
.isInt32());
387 EXPECT_TRUE(cpp
.isDouble());
388 EXPECT_TRUE(cpp
.isNumber());
389 EXPECT_FALSE(cpp
.isString());
390 EXPECT_FALSE(cpp
.isVoid());
391 EXPECT_FALSE(cpp
.isNull());
392 EXPECT_FALSE(cpp
.isEmpty());
393 EXPECT_FALSE(cpp
.isObject());
396 EXPECT_FALSE(cpp
.isBool());
397 EXPECT_FALSE(cpp
.isInt32());
398 EXPECT_FALSE(cpp
.isDouble());
399 EXPECT_FALSE(cpp
.isNumber());
400 EXPECT_TRUE(cpp
.isString());
401 EXPECT_FALSE(cpp
.isVoid());
402 EXPECT_FALSE(cpp
.isNull());
403 EXPECT_FALSE(cpp
.isEmpty());
404 EXPECT_FALSE(cpp
.isObject());
407 EXPECT_FALSE(cpp
.isBool());
408 EXPECT_FALSE(cpp
.isInt32());
409 EXPECT_FALSE(cpp
.isDouble());
410 EXPECT_FALSE(cpp
.isNumber());
411 EXPECT_FALSE(cpp
.isString());
412 EXPECT_FALSE(cpp
.isVoid());
413 EXPECT_TRUE(cpp
.isNull());
414 EXPECT_TRUE(cpp
.isEmpty());
415 EXPECT_FALSE(cpp
.isObject());
417 NPObject
*obj
= MakeVoidObject();
419 EXPECT_FALSE(cpp
.isBool());
420 EXPECT_FALSE(cpp
.isInt32());
421 EXPECT_FALSE(cpp
.isDouble());
422 EXPECT_FALSE(cpp
.isNumber());
423 EXPECT_FALSE(cpp
.isString());
424 EXPECT_FALSE(cpp
.isVoid());
425 EXPECT_FALSE(cpp
.isNull());
426 EXPECT_FALSE(cpp
.isEmpty());
427 EXPECT_TRUE(cpp
.isObject());
428 WebBindings::releaseObject(obj
);
432 bool MockNPHasPropertyFunction(NPObject
*npobj
, NPIdentifier name
) {
436 bool MockNPGetPropertyFunction(NPObject
*npobj
, NPIdentifier name
,
438 if (WebBindings::getStringIdentifier("length") == name
) {
439 DOUBLE_TO_NPVARIANT(4, *result
);
440 } else if (WebBindings::getIntIdentifier(0) == name
) {
441 DOUBLE_TO_NPVARIANT(0, *result
);
442 } else if (WebBindings::getIntIdentifier(1) == name
) {
443 BOOLEAN_TO_NPVARIANT(true, *result
);
444 } else if (WebBindings::getIntIdentifier(2) == name
) {
445 NULL_TO_NPVARIANT(*result
);
446 } else if (WebBindings::getIntIdentifier(3) == name
) {
447 const char* s
= "string";
448 size_t length
= strlen(s
);
449 char* mem
= static_cast<char*>(malloc(length
+ 1));
450 base::strlcpy(mem
, s
, length
+ 1);
451 STRINGZ_TO_NPVARIANT(mem
, *result
);
457 TEST(CppVariantTest
, ToVector
) {
458 NPClass array_like_class
= {
459 NP_CLASS_STRUCT_VERSION
,
460 0, // NPAllocateFunctionPtr allocate;
461 0, // NPDeallocateFunctionPtr deallocate;
462 0, // NPInvalidateFunctionPtr invalidate;
463 0, // NPHasMethodFunctionPtr hasMethod;
464 0, // NPInvokeFunctionPtr invoke;
465 0, // NPInvokeDefaultFunctionPtr invokeDefault;
466 MockNPHasPropertyFunction
, // NPHasPropertyFunctionPtr hasProperty;
467 MockNPGetPropertyFunction
, // NPGetPropertyFunctionPtr getProperty;
468 0, // NPSetPropertyFunctionPtr setProperty;
469 0, // NPRemovePropertyFunctionPtr removeProperty;
470 0, // NPEnumerationFunctionPtr enumerate;
471 0 // NPConstructFunctionPtr construct;
474 NPObject
* obj
= WebBindings::createObject(NULL
, &array_like_class
);
479 std::vector
<CppVariant
> cpp_vector
= cpp
.ToVector();
480 EXPECT_EQ(4u, cpp_vector
.size());
482 EXPECT_TRUE(cpp_vector
[0].isDouble());
483 EXPECT_EQ(0, cpp_vector
[0].ToDouble());
485 EXPECT_TRUE(cpp_vector
[1].isBool());
486 EXPECT_EQ(true, cpp_vector
[1].ToBoolean());
488 EXPECT_TRUE(cpp_vector
[2].isNull());
490 EXPECT_TRUE(cpp_vector
[3].isString());
491 CheckString("string", cpp_vector
[3]);
493 WebBindings::releaseObject(obj
);