OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <vector> | |
6 | |
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" | |
12 | |
13 using WebKit::WebBindings; | |
14 using webkit_glue::CppVariant; | |
15 | |
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) { | |
20 const char* chars = | |
21 reinterpret_cast<const char*>(np.value.stringValue.UTF8Characters); | |
22 (*std_string).assign(chars, np.value.stringValue.UTF8Length); | |
23 } else { | |
24 (*std_string).clear(); | |
25 } | |
26 } | |
27 | |
28 // Verifies that the actual NPVariant is a string and that its value matches | |
29 // the expected_str. | |
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); | |
35 } | |
36 | |
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); | |
44 } | |
45 | |
46 int g_allocate_call_count = 0; | |
47 int g_deallocate_call_count = 0; | |
48 | |
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); | |
55 } | |
56 | |
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 | |
60 | |
61 ++g_allocate_call_count; | |
62 // Ignore npp and NPClass | |
63 return reinterpret_cast<NPObject*>(malloc(sizeof(NPObject))); | |
64 } | |
65 | |
66 void MockNPDeallocate(NPObject* npobj) { | |
67 // This is a mock deallocate method that mimics the behavior | |
68 // of NPN_DeallocateObject when deallocate() is NULL | |
69 | |
70 ++g_deallocate_call_count; | |
71 free(npobj); | |
72 } | |
73 | |
74 static NPClass void_class = { NP_CLASS_STRUCT_VERSION, | |
75 MockNPAllocate, | |
76 MockNPDeallocate, | |
77 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
78 | |
79 NPObject* MakeVoidObject() { | |
80 g_allocate_call_count = 0; | |
81 g_deallocate_call_count = 0; | |
82 return WebBindings::createObject(NULL, &void_class); | |
83 } | |
84 | |
85 TEST(CppVariantTest, NewVariantHasNullType) { | |
86 CppVariant value; | |
87 EXPECT_EQ(NPVariantType_Null, value.type); | |
88 } | |
89 | |
90 TEST(CppVariantTest, SetNullSetsType) { | |
91 CppVariant value; | |
92 value.Set(17); | |
93 value.SetNull(); | |
94 EXPECT_EQ(NPVariantType_Null, value.type); | |
95 } | |
96 | |
97 TEST(CppVariantTest, CopyConstructorDoesDeepCopy) { | |
98 CppVariant source; | |
99 source.Set("test string"); | |
100 CppVariant dest = source; | |
101 EXPECT_EQ(NPVariantType_String, dest.type); | |
102 EXPECT_EQ(NPVariantType_String, source.type); | |
103 | |
104 // Ensure that the string was copied, not just the pointer. | |
105 EXPECT_NE(source.value.stringValue.UTF8Characters, | |
106 dest.value.stringValue.UTF8Characters); | |
107 | |
108 CheckString(source, dest); | |
109 } | |
110 | |
111 TEST(CppVariantTest, CopyConstructorIncrementsRefCount) { | |
112 CppVariant source; | |
113 NPObject *object = MakeVoidObject(); | |
114 source.Set(object); | |
115 // 2 references so far. | |
116 EXPECT_EQ(2U, source.value.objectValue->referenceCount); | |
117 | |
118 CppVariant dest = source; | |
119 EXPECT_EQ(3U, dest.value.objectValue->referenceCount); | |
120 EXPECT_EQ(1, g_allocate_call_count); | |
121 WebBindings::releaseObject(object); | |
122 source.SetNull(); | |
123 CheckObject(dest); | |
124 } | |
125 | |
126 TEST(CppVariantTest, AssignmentDoesDeepCopy) { | |
127 CppVariant source; | |
128 source.Set("test string"); | |
129 CppVariant dest; | |
130 dest = source; | |
131 EXPECT_EQ(NPVariantType_String, dest.type); | |
132 EXPECT_EQ(NPVariantType_String, source.type); | |
133 | |
134 // Ensure that the string was copied, not just the pointer. | |
135 EXPECT_NE(source.value.stringValue.UTF8Characters, | |
136 dest.value.stringValue.UTF8Characters); | |
137 | |
138 CheckString(source, dest); | |
139 } | |
140 | |
141 TEST(CppVariantTest, AssignmentIncrementsRefCount) { | |
142 CppVariant source; | |
143 NPObject *object = MakeVoidObject(); | |
144 source.Set(object); | |
145 // 2 references so far. | |
146 EXPECT_EQ(2U, source.value.objectValue->referenceCount); | |
147 | |
148 CppVariant dest; | |
149 dest = source; | |
150 EXPECT_EQ(3U, dest.value.objectValue->referenceCount); | |
151 EXPECT_EQ(1, g_allocate_call_count); | |
152 | |
153 WebBindings::releaseObject(object); | |
154 source.SetNull(); | |
155 CheckObject(dest); | |
156 } | |
157 | |
158 TEST(CppVariantTest, DestroyingCopyDoesNotCorruptSource) { | |
159 CppVariant source; | |
160 source.Set("test string"); | |
161 std::string before; | |
162 MakeStdString(source, &before); | |
163 { | |
164 CppVariant dest = source; | |
165 } | |
166 CheckString(before, source); | |
167 | |
168 NPObject *object = MakeVoidObject(); | |
169 source.Set(object); | |
170 { | |
171 CppVariant dest2 = source; | |
172 } | |
173 WebBindings::releaseObject(object); | |
174 CheckObject(source); | |
175 } | |
176 | |
177 TEST(CppVariantTest, CopiesTypeAndValueToNPVariant) { | |
178 NPVariant np; | |
179 CppVariant cpp; | |
180 | |
181 cpp.Set(true); | |
182 cpp.CopyToNPVariant(&np); | |
183 EXPECT_EQ(cpp.type, np.type); | |
184 EXPECT_EQ(cpp.value.boolValue, np.value.boolValue); | |
185 WebBindings::releaseVariantValue(&np); | |
186 | |
187 cpp.Set(17); | |
188 cpp.CopyToNPVariant(&np); | |
189 EXPECT_EQ(cpp.type, np.type); | |
190 EXPECT_EQ(cpp.value.intValue, np.value.intValue); | |
191 WebBindings::releaseVariantValue(&np); | |
192 | |
193 cpp.Set(3.1415); | |
194 cpp.CopyToNPVariant(&np); | |
195 EXPECT_EQ(cpp.type, np.type); | |
196 EXPECT_EQ(cpp.value.doubleValue, np.value.doubleValue); | |
197 WebBindings::releaseVariantValue(&np); | |
198 | |
199 cpp.Set("test value"); | |
200 cpp.CopyToNPVariant(&np); | |
201 CheckString("test value", np); | |
202 WebBindings::releaseVariantValue(&np); | |
203 | |
204 cpp.SetNull(); | |
205 cpp.CopyToNPVariant(&np); | |
206 EXPECT_EQ(cpp.type, np.type); | |
207 WebBindings::releaseVariantValue(&np); | |
208 | |
209 NPObject *object = MakeVoidObject(); | |
210 cpp.Set(object); | |
211 cpp.CopyToNPVariant(&np); | |
212 WebBindings::releaseObject(object); | |
213 cpp.SetNull(); | |
214 CheckObject(np); | |
215 WebBindings::releaseVariantValue(&np); | |
216 } | |
217 | |
218 TEST(CppVariantTest, SetsTypeAndValueFromNPVariant) { | |
219 NPVariant np; | |
220 CppVariant cpp; | |
221 | |
222 VOID_TO_NPVARIANT(np); | |
223 cpp.Set(np); | |
224 EXPECT_EQ(np.type, cpp.type); | |
225 WebBindings::releaseVariantValue(&np); | |
226 | |
227 NULL_TO_NPVARIANT(np); | |
228 cpp.Set(np); | |
229 EXPECT_EQ(np.type, cpp.type); | |
230 WebBindings::releaseVariantValue(&np); | |
231 | |
232 BOOLEAN_TO_NPVARIANT(true, np); | |
233 cpp.Set(np); | |
234 EXPECT_EQ(np.type, cpp.type); | |
235 EXPECT_EQ(np.value.boolValue, cpp.value.boolValue); | |
236 WebBindings::releaseVariantValue(&np); | |
237 | |
238 INT32_TO_NPVARIANT(15, np); | |
239 cpp.Set(np); | |
240 EXPECT_EQ(np.type, cpp.type); | |
241 EXPECT_EQ(np.value.intValue, cpp.value.intValue); | |
242 WebBindings::releaseVariantValue(&np); | |
243 | |
244 DOUBLE_TO_NPVARIANT(2.71828, np); | |
245 cpp.Set(np); | |
246 EXPECT_EQ(np.type, cpp.type); | |
247 EXPECT_EQ(np.value.doubleValue, cpp.value.doubleValue); | |
248 WebBindings::releaseVariantValue(&np); | |
249 | |
250 NPString np_ascii_str = { "1st test value", | |
251 static_cast<uint32_t>(strlen("1st test value")) }; | |
252 WebBindings::initializeVariantWithStringCopy(&np, &np_ascii_str); | |
253 cpp.Set(np); | |
254 CheckString("1st test value", cpp); | |
255 WebBindings::releaseVariantValue(&np); | |
256 | |
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); | |
264 cpp.Set(np); | |
265 CheckString("\xce\xb1\xe4\xb8\x80\xf0\x90\x90\x84", cpp); | |
266 WebBindings::releaseVariantValue(&np); | |
267 | |
268 NPObject *obj = MakeVoidObject(); | |
269 OBJECT_TO_NPVARIANT(obj, np); // Doesn't make a copy. | |
270 cpp.Set(np); | |
271 // Use this or WebBindings::releaseObject but NOT both. | |
272 WebBindings::releaseVariantValue(&np); | |
273 CheckObject(cpp); | |
274 } | |
275 | |
276 TEST(CppVariantTest, SetsSimpleTypesAndValues) { | |
277 CppVariant cpp; | |
278 cpp.Set(true); | |
279 EXPECT_EQ(NPVariantType_Bool, cpp.type); | |
280 EXPECT_TRUE(cpp.value.boolValue); | |
281 | |
282 cpp.Set(5); | |
283 EXPECT_EQ(NPVariantType_Int32, cpp.type); | |
284 EXPECT_EQ(5, cpp.value.intValue); | |
285 | |
286 cpp.Set(1.234); | |
287 EXPECT_EQ(NPVariantType_Double, cpp.type); | |
288 EXPECT_EQ(1.234, cpp.value.doubleValue); | |
289 | |
290 // C string | |
291 cpp.Set("1st test string"); | |
292 CheckString("1st test string", cpp); | |
293 | |
294 // std::string | |
295 std::string source("std test string"); | |
296 cpp.Set(source); | |
297 CheckString("std test string", cpp); | |
298 | |
299 // NPString | |
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); | |
305 | |
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); | |
315 | |
316 NPObject* obj = MakeVoidObject(); | |
317 cpp.Set(obj); | |
318 WebBindings::releaseObject(obj); | |
319 CheckObject(cpp); | |
320 } | |
321 | |
322 TEST(CppVariantTest, FreeDataSetsToVoid) { | |
323 CppVariant cpp; | |
324 EXPECT_EQ(NPVariantType_Null, cpp.type); | |
325 cpp.Set(12); | |
326 EXPECT_EQ(NPVariantType_Int32, cpp.type); | |
327 cpp.FreeData(); | |
328 EXPECT_EQ(NPVariantType_Void, cpp.type); | |
329 } | |
330 | |
331 TEST(CppVariantTest, FreeDataReleasesObject) { | |
332 CppVariant cpp; | |
333 NPObject* object = MakeVoidObject(); | |
334 cpp.Set(object); | |
335 EXPECT_EQ(2U, object->referenceCount); | |
336 cpp.FreeData(); | |
337 EXPECT_EQ(1U, object->referenceCount); | |
338 EXPECT_EQ(0, g_deallocate_call_count); | |
339 | |
340 cpp.Set(object); | |
341 WebBindings::releaseObject(object); | |
342 EXPECT_EQ(0, g_deallocate_call_count); | |
343 cpp.FreeData(); | |
344 EXPECT_EQ(1, g_deallocate_call_count); | |
345 } | |
346 | |
347 TEST(CppVariantTest, IsTypeFunctionsWork) { | |
348 CppVariant cpp; | |
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 | |
351 // releasing. | |
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()); | |
361 | |
362 cpp.Set(true); | |
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()); | |
372 | |
373 cpp.Set(12); | |
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()); | |
383 | |
384 cpp.Set(3.1415); | |
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()); | |
394 | |
395 cpp.Set("a string"); | |
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()); | |
405 | |
406 cpp.SetNull(); | |
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()); | |
416 | |
417 NPObject *obj = MakeVoidObject(); | |
418 cpp.Set(obj); | |
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); | |
429 CheckObject(cpp); | |
430 } | |
431 | |
432 bool MockNPHasPropertyFunction(NPObject *npobj, NPIdentifier name) { | |
433 return true; | |
434 } | |
435 | |
436 bool MockNPGetPropertyFunction(NPObject *npobj, NPIdentifier name, | |
437 NPVariant *result) { | |
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); | |
452 } | |
453 | |
454 return true; | |
455 } | |
456 | |
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; | |
472 }; | |
473 | |
474 NPObject* obj = WebBindings::createObject(NULL, &array_like_class); | |
475 | |
476 CppVariant cpp; | |
477 cpp.Set(obj); | |
478 | |
479 std::vector<CppVariant> cpp_vector = cpp.ToVector(); | |
480 EXPECT_EQ(4u, cpp_vector.size()); | |
481 | |
482 EXPECT_TRUE(cpp_vector[0].isDouble()); | |
483 EXPECT_EQ(0, cpp_vector[0].ToDouble()); | |
484 | |
485 EXPECT_TRUE(cpp_vector[1].isBool()); | |
486 EXPECT_EQ(true, cpp_vector[1].ToBoolean()); | |
487 | |
488 EXPECT_TRUE(cpp_vector[2].isNull()); | |
489 | |
490 EXPECT_TRUE(cpp_vector[3].isString()); | |
491 CheckString("string", cpp_vector[3]); | |
492 | |
493 WebBindings::releaseObject(obj); | |
494 } | |
OLD | NEW |