1<?php 2 3require_once('test_base.php'); 4require_once('test_util.php'); 5 6use Google\Protobuf\Internal\GPBType; 7use Google\Protobuf\Internal\MapField; 8use Foo\TestMessage; 9use Foo\TestMessage\Sub; 10 11class MapFieldTest extends TestBase { 12 13 ######################################################### 14 # Test int32 field. 15 ######################################################### 16 17 public function testInt32() { 18 $arr = new MapField(GPBType::INT32, GPBType::INT32); 19 20 // Test integer argument. 21 $arr[MAX_INT32] = MAX_INT32; 22 $this->assertSame(MAX_INT32, $arr[MAX_INT32]); 23 $arr[MIN_INT32] = MIN_INT32; 24 $this->assertSame(MIN_INT32, $arr[MIN_INT32]); 25 $this->assertEquals(2, count($arr)); 26 $this->assertTrue(isset($arr[MAX_INT32])); 27 $this->assertTrue(isset($arr[MIN_INT32])); 28 unset($arr[MAX_INT32]); 29 unset($arr[MIN_INT32]); 30 $this->assertEquals(0, count($arr)); 31 32 // Test float argument. 33 $arr[1.9] = 1.9; 34 $arr[2.1] = 2.1; 35 $this->assertSame(1, $arr[1]); 36 $this->assertSame(2, $arr[2]); 37 $arr[MAX_INT32_FLOAT] = MAX_INT32_FLOAT; 38 $this->assertSame(MAX_INT32, $arr[MAX_INT32]); 39 $arr[MIN_INT32_FLOAT] = MIN_INT32_FLOAT; 40 $this->assertSame(MIN_INT32, $arr[MIN_INT32]); 41 $this->assertEquals(4, count($arr)); 42 unset($arr[1.9]); 43 unset($arr[2.9]); 44 unset($arr[MAX_INT32_FLOAT]); 45 unset($arr[MIN_INT32_FLOAT]); 46 $this->assertEquals(0, count($arr)); 47 48 // Test string argument. 49 $arr['2'] = '2'; 50 $this->assertSame(2, $arr[2]); 51 $arr['3.1'] = '3.1'; 52 $this->assertSame(3, $arr[3]); 53 $arr[MAX_INT32_STRING] = MAX_INT32_STRING; 54 $this->assertSame(MAX_INT32, $arr[MAX_INT32]); 55 $this->assertEquals(3, count($arr)); 56 unset($arr['2']); 57 unset($arr['3.1']); 58 unset($arr[MAX_INT32_STRING]); 59 $this->assertEquals(0, count($arr)); 60 61 // Test foreach. 62 $arr = new MapField(GPBType::INT32, GPBType::INT32); 63 for ($i = 0; $i < 3; $i++) { 64 $arr[$i] = $i; 65 } 66 $i = 0; 67 $arr_test = []; 68 foreach ($arr as $key => $val) { 69 $this->assertSame($key, $val); 70 $arr_test[] = $key; 71 $i++; 72 } 73 $this->assertTrue(isset($arr_test[0])); 74 $this->assertTrue(isset($arr_test[1])); 75 $this->assertTrue(isset($arr_test[2])); 76 $this->assertSame(3, $i); 77 } 78 79 ######################################################### 80 # Test uint32 field. 81 ######################################################### 82 83 public function testUint32() { 84 $arr = new MapField(GPBType::UINT32, GPBType::UINT32); 85 86 // Test integer argument. 87 $arr[MAX_UINT32] = MAX_UINT32; 88 $this->assertSame(-1, $arr[-1]); 89 $this->assertEquals(1, count($arr)); 90 unset($arr[MAX_UINT32]); 91 $this->assertEquals(0, count($arr)); 92 93 $arr[-1] = -1; 94 $this->assertSame(-1, $arr[-1]); 95 $arr[MIN_UINT32] = MIN_UINT32; 96 $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); 97 $this->assertEquals(2, count($arr)); 98 unset($arr[-1]); 99 unset($arr[MIN_UINT32]); 100 $this->assertEquals(0, count($arr)); 101 102 // Test float argument. 103 $arr[MAX_UINT32_FLOAT] = MAX_UINT32_FLOAT; 104 $this->assertSame(-1, $arr[-1]); 105 $this->assertEquals(1, count($arr)); 106 unset($arr[MAX_UINT32_FLOAT]); 107 $this->assertEquals(0, count($arr)); 108 109 $arr[3.1] = 3.1; 110 $this->assertSame(3, $arr[3]); 111 $arr[-1.0] = -1.0; 112 $this->assertSame(-1, $arr[-1]); 113 $arr[MIN_UINT32_FLOAT] = MIN_UINT32_FLOAT; 114 $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); 115 $this->assertEquals(3, count($arr)); 116 unset($arr[3.1]); 117 unset($arr[-1.0]); 118 unset($arr[MIN_UINT32_FLOAT]); 119 $this->assertEquals(0, count($arr)); 120 121 // Test string argument. 122 $arr[MAX_UINT32_STRING] = MAX_UINT32_STRING; 123 $this->assertSame(-1, $arr[-1]); 124 $this->assertEquals(1, count($arr)); 125 unset($arr[MAX_UINT32_STRING]); 126 $this->assertEquals(0, count($arr)); 127 128 $arr['7'] = '7'; 129 $this->assertSame(7, $arr[7]); 130 $arr['3.1'] = '3.1'; 131 $this->assertSame(3, $arr[3]); 132 $arr['-1.0'] = '-1.0'; 133 $this->assertSame(-1, $arr[-1]); 134 $arr[MIN_UINT32_STRING] = MIN_UINT32_STRING; 135 $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); 136 $this->assertEquals(4, count($arr)); 137 unset($arr['7']); 138 unset($arr['3.1']); 139 unset($arr['-1.0']); 140 unset($arr[MIN_UINT32_STRING]); 141 $this->assertEquals(0, count($arr)); 142 } 143 144 ######################################################### 145 # Test int64 field. 146 ######################################################### 147 148 public function testInt64() { 149 $arr = new MapField(GPBType::INT64, GPBType::INT64); 150 151 // Test integer argument. 152 $arr[MAX_INT64] = MAX_INT64; 153 $arr[MIN_INT64] = MIN_INT64; 154 if (PHP_INT_SIZE == 4) { 155 $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); 156 $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); 157 } else { 158 $this->assertSame(MAX_INT64, $arr[MAX_INT64]); 159 $this->assertSame(MIN_INT64, $arr[MIN_INT64]); 160 } 161 $this->assertEquals(2, count($arr)); 162 unset($arr[MAX_INT64]); 163 unset($arr[MIN_INT64]); 164 $this->assertEquals(0, count($arr)); 165 166 // Test float argument. 167 $arr[1.1] = 1.1; 168 if (PHP_INT_SIZE == 4) { 169 $this->assertSame('1', $arr['1']); 170 } else { 171 $this->assertSame(1, $arr[1]); 172 } 173 $this->assertEquals(1, count($arr)); 174 unset($arr[1.1]); 175 $this->assertEquals(0, count($arr)); 176 177 // Test string argument. 178 $arr['2'] = '2'; 179 $arr['3.1'] = '3.1'; 180 $arr[MAX_INT64_STRING] = MAX_INT64_STRING; 181 $arr[MIN_INT64_STRING] = MIN_INT64_STRING; 182 if (PHP_INT_SIZE == 4) { 183 $this->assertSame('2', $arr['2']); 184 $this->assertSame('3', $arr['3']); 185 $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); 186 $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); 187 } else { 188 $this->assertSame(2, $arr[2]); 189 $this->assertSame(3, $arr[3]); 190 $this->assertSame(MAX_INT64, $arr[MAX_INT64]); 191 $this->assertSame(MIN_INT64, $arr[MIN_INT64]); 192 } 193 $this->assertEquals(4, count($arr)); 194 unset($arr['2']); 195 unset($arr['3.1']); 196 unset($arr[MAX_INT64_STRING]); 197 unset($arr[MIN_INT64_STRING]); 198 $this->assertEquals(0, count($arr)); 199 } 200 201 ######################################################### 202 # Test uint64 field. 203 ######################################################### 204 205 public function testUint64() { 206 $arr = new MapField(GPBType::UINT64, GPBType::UINT64); 207 208 // Test integer argument. 209 $arr[MAX_UINT64] = MAX_UINT64; 210 if (PHP_INT_SIZE == 4) { 211 $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); 212 } else { 213 $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); 214 } 215 $this->assertEquals(1, count($arr)); 216 unset($arr[MAX_UINT64]); 217 $this->assertEquals(0, count($arr)); 218 219 // Test float argument. 220 $arr[1.1] = 1.1; 221 if (PHP_INT_SIZE == 4) { 222 $this->assertSame('1', $arr['1']); 223 } else { 224 $this->assertSame(1, $arr[1]); 225 } 226 $this->assertEquals(1, count($arr)); 227 unset($arr[1.1]); 228 $this->assertEquals(0, count($arr)); 229 230 // Test string argument. 231 $arr['2'] = '2'; 232 $arr['3.1'] = '3.1'; 233 $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING; 234 235 if (PHP_INT_SIZE == 4) { 236 $this->assertSame('2', $arr['2']); 237 $this->assertSame('3', $arr['3']); 238 $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); 239 } else { 240 $this->assertSame(2, $arr[2]); 241 $this->assertSame(3, $arr[3]); 242 $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); 243 } 244 245 $this->assertEquals(3, count($arr)); 246 unset($arr['2']); 247 unset($arr['3.1']); 248 unset($arr[MAX_UINT64_STRING]); 249 $this->assertEquals(0, count($arr)); 250 } 251 252 ######################################################### 253 # Test float field. 254 ######################################################### 255 256 public function testFloat() { 257 $arr = new MapField(GPBType::INT32, GPBType::FLOAT); 258 259 // Test set. 260 $arr[0] = 1; 261 $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); 262 263 $arr[1] = 1.1; 264 $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); 265 266 $arr[2] = '2'; 267 $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); 268 $arr[3] = '3.1'; 269 $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); 270 271 $this->assertEquals(4, count($arr)); 272 } 273 274 ######################################################### 275 # Test double field. 276 ######################################################### 277 278 public function testDouble() { 279 $arr = new MapField(GPBType::INT32, GPBType::DOUBLE); 280 281 // Test set. 282 $arr[0] = 1; 283 $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); 284 285 $arr[1] = 1.1; 286 $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); 287 288 $arr[2] = '2'; 289 $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); 290 $arr[3] = '3.1'; 291 $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); 292 293 $this->assertEquals(4, count($arr)); 294 } 295 296 ######################################################### 297 # Test bool field. 298 ######################################################### 299 300 public function testBool() { 301 $arr = new MapField(GPBType::BOOL, GPBType::BOOL); 302 303 // Test boolean. 304 $arr[True] = True; 305 $this->assertSame(True, $arr[True]); 306 $this->assertEquals(1, count($arr)); 307 unset($arr[True]); 308 $this->assertEquals(0, count($arr)); 309 310 $arr[False] = False; 311 $this->assertSame(False, $arr[False]); 312 $this->assertEquals(1, count($arr)); 313 unset($arr[False]); 314 $this->assertEquals(0, count($arr)); 315 316 // Test integer. 317 $arr[-1] = -1; 318 $this->assertSame(True, $arr[True]); 319 $this->assertEquals(1, count($arr)); 320 unset($arr[-1]); 321 $this->assertEquals(0, count($arr)); 322 323 $arr[0] = 0; 324 $this->assertSame(False, $arr[False]); 325 $this->assertEquals(1, count($arr)); 326 unset($arr[0]); 327 $this->assertEquals(0, count($arr)); 328 329 // Test float. 330 $arr[1.1] = 1.1; 331 $this->assertSame(True, $arr[True]); 332 $this->assertEquals(1, count($arr)); 333 unset($arr[1.1]); 334 $this->assertEquals(0, count($arr)); 335 336 $arr[0.0] = 0.0; 337 $this->assertSame(False, $arr[False]); 338 $this->assertEquals(1, count($arr)); 339 unset($arr[0.0]); 340 $this->assertEquals(0, count($arr)); 341 342 // Test string. 343 $arr['a'] = 'a'; 344 $this->assertSame(True, $arr[True]); 345 $this->assertEquals(1, count($arr)); 346 unset($arr['a']); 347 $this->assertEquals(0, count($arr)); 348 349 $arr[''] = ''; 350 $this->assertSame(False, $arr[False]); 351 $this->assertEquals(1, count($arr)); 352 unset($arr['']); 353 $this->assertEquals(0, count($arr)); 354 } 355 356 ######################################################### 357 # Test string field. 358 ######################################################### 359 360 public function testString() { 361 $arr = new MapField(GPBType::STRING, GPBType::STRING); 362 363 // Test set. 364 $arr['abc'] = 'abc'; 365 $this->assertSame('abc', $arr['abc']); 366 $this->assertEquals(1, count($arr)); 367 unset($arr['abc']); 368 $this->assertEquals(0, count($arr)); 369 370 $arr[1] = 1; 371 $this->assertSame('1', $arr['1']); 372 $this->assertEquals(1, count($arr)); 373 unset($arr[1]); 374 $this->assertEquals(0, count($arr)); 375 376 $arr[1.1] = 1.1; 377 $this->assertSame('1.1', $arr['1.1']); 378 $this->assertEquals(1, count($arr)); 379 unset($arr[1.1]); 380 $this->assertEquals(0, count($arr)); 381 382 $arr[True] = True; 383 $this->assertSame('1', $arr['1']); 384 $this->assertEquals(1, count($arr)); 385 unset($arr[True]); 386 $this->assertEquals(0, count($arr)); 387 388 // Test foreach. 389 $arr = new MapField(GPBType::STRING, GPBType::STRING); 390 for ($i = 0; $i < 3; $i++) { 391 $arr[$i] = $i; 392 } 393 $i = 0; 394 $arr_test = []; 395 foreach ($arr as $key => $val) { 396 $this->assertSame($key, $val); 397 $arr_test[] = $key; 398 $i++; 399 } 400 $this->assertTrue(isset($arr_test['0'])); 401 $this->assertTrue(isset($arr_test['1'])); 402 $this->assertTrue(isset($arr_test['2'])); 403 $this->assertSame(3, $i); 404 } 405 406 ######################################################### 407 # Test message field. 408 ######################################################### 409 410 public function testMessage() { 411 $arr = new MapField(GPBType::INT32, 412 GPBType::MESSAGE, Sub::class); 413 414 // Test append. 415 $sub_m = new Sub(); 416 $sub_m->setA(1); 417 $arr[0] = $sub_m; 418 $this->assertSame(1, $arr[0]->getA()); 419 420 $this->assertEquals(1, count($arr)); 421 422 // Test foreach. 423 $arr = new MapField(GPBType::INT32, 424 GPBType::MESSAGE, Sub::class); 425 for ($i = 0; $i < 3; $i++) { 426 $arr[$i] = new Sub();; 427 $arr[$i]->setA($i); 428 } 429 $i = 0; 430 $key_test = []; 431 $value_test = []; 432 foreach ($arr as $key => $val) { 433 $key_test[] = $key; 434 $value_test[] = $val->getA(); 435 $i++; 436 } 437 $this->assertTrue(isset($key_test['0'])); 438 $this->assertTrue(isset($key_test['1'])); 439 $this->assertTrue(isset($key_test['2'])); 440 $this->assertTrue(isset($value_test['0'])); 441 $this->assertTrue(isset($value_test['1'])); 442 $this->assertTrue(isset($value_test['2'])); 443 $this->assertSame(3, $i); 444 } 445 446 ######################################################### 447 # Test reference in map 448 ######################################################### 449 450 public function testMapElementIsReference() 451 { 452 // Bool elements 453 $values = [true => true]; 454 array_walk($values, function (&$value) {}); 455 $m = new TestMessage(); 456 $m->setMapBoolBool($values); 457 458 // Int32 elements 459 $values = [1 => 1]; 460 array_walk($values, function (&$value) {}); 461 $m = new TestMessage(); 462 $m->setMapInt32Int32($values); 463 464 // Double elements 465 $values = [1 => 1.0]; 466 array_walk($values, function (&$value) {}); 467 $m = new TestMessage(); 468 $m->setMapInt32Double($values); 469 470 // String elements 471 $values = ['a' => 'a']; 472 array_walk($values, function (&$value) {}); 473 $m = new TestMessage(); 474 $m->setMapStringString($values); 475 476 // Message elements 477 $values = [1 => new Sub()]; 478 array_walk($values, function (&$value) {}); 479 $m = new TestMessage(); 480 $m->setMapInt32Message($values); 481 482 $this->assertTrue(true); 483 } 484 485 ######################################################### 486 # Test equality 487 ######################################################### 488 489 public function testEquality() 490 { 491 $map = new MapField(GPBType::INT32, GPBType::INT32); 492 $map2 = new MapField(GPBType::INT32, GPBType::INT32); 493 494 $this->assertTrue($map == $map2); 495 496 $map[1] = 2; 497 498 $this->assertFalse($map == $map2); 499 500 $map2[1] = 2; 501 502 $this->assertTrue($map == $map2); 503 504 // Arrays of different types always compare false. 505 $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) == 506 new MapField(GPBType::INT32, GPBType::INT64)); 507 $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) == 508 new MapField(GPBType::INT64, GPBType::INT32)); 509 $this->assertFalse( 510 new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class) == 511 new MapField(GPBType::INT32, GPBType::MESSAGE, Sub::class)); 512 } 513 514 ######################################################### 515 # Test clone 516 ######################################################### 517 518 public function testClone() 519 { 520 $map = new MapField(GPBType::INT32, 521 GPBType::MESSAGE, Sub::class); 522 523 // Test append. 524 $sub_m = new Sub(); 525 $sub_m->setA(1); 526 $map[0] = $sub_m; 527 528 $map2 = clone $map; 529 $this->assertSame($map[0], $map2[0]); 530 } 531 532 ######################################################### 533 # Test memory leak 534 ######################################################### 535 536 // TODO(teboring): Add it back. 537 // public function testCycleLeak() 538 // { 539 // $arr = new MapField(GPBType::INT32, 540 // GPBType::MESSAGE, TestMessage::class); 541 // $arr[0] = new TestMessage; 542 // $arr[0]->SetMapRecursive($arr); 543 544 // // Clean up memory before test. 545 // gc_collect_cycles(); 546 // $start = memory_get_usage(); 547 // unset($arr); 548 549 // // Explicitly trigger garbage collection. 550 // gc_collect_cycles(); 551 552 // $end = memory_get_usage(); 553 // $this->assertLessThan($start, $end); 554 // } 555} 556