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