| 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 |