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