• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?php
2
3require_once('test_base.php');
4require_once('test_util.php');
5
6use Google\Protobuf\Internal\RepeatedField;
7use Google\Protobuf\Internal\GPBType;
8use Foo\EmptyAnySerialization;
9use Foo\TestInt32Value;
10use Foo\TestStringValue;
11use Foo\TestAny;
12use Foo\TestEnum;
13use Foo\TestLargeFieldNumber;
14use Foo\TestMessage;
15use Foo\TestMessage\Sub;
16use Foo\TestPackedMessage;
17use Foo\TestRandomFieldOrder;
18use Foo\TestUnpackedMessage;
19use Google\Protobuf\Any;
20use Google\Protobuf\DoubleValue;
21use Google\Protobuf\FieldMask;
22use Google\Protobuf\FloatValue;
23use Google\Protobuf\Int32Value;
24use Google\Protobuf\UInt32Value;
25use Google\Protobuf\Int64Value;
26use Google\Protobuf\UInt64Value;
27use Google\Protobuf\BoolValue;
28use Google\Protobuf\StringValue;
29use Google\Protobuf\BytesValue;
30use Google\Protobuf\Value;
31use Google\Protobuf\ListValue;
32use Google\Protobuf\Struct;
33use Google\Protobuf\GPBEmpty;
34
35class DebugInfoTest extends TestBase
36{
37    public function setUp(): void
38    {
39        if (extension_loaded('protobuf')) {
40            $this->markTestSkipped('__debugInfo is not supported for the protobuf extension');
41        }
42    }
43
44    public function testVarDumpOutput()
45    {
46        $m = new DoubleValue();
47        $m->setValue(1.5);
48        var_dump($m);
49        $regex = <<<EOL
50object(Google\Protobuf\DoubleValue)#%s (1) {
51  ["value"]=>
52  float(1.5)
53}
54EOL;
55        $this->expectOutputRegex('/' . sprintf(preg_quote($regex), '\d+') . '/');
56    }
57
58    public function testTopLevelDoubleValue()
59    {
60        $m = new DoubleValue();
61        $m->setValue(1.5);
62        $this->assertSame(['value' => 1.5], $m->__debugInfo());
63    }
64
65    public function testTopLevelFloatValue()
66    {
67        $m = new FloatValue();
68        $m->setValue(1.5);
69        $this->assertSame(['value' => 1.5], $m->__debugInfo());
70    }
71
72    public function testTopLevelInt32Value()
73    {
74        $m = new Int32Value();
75        $m->setValue(1);
76        $this->assertSame(['value' => 1], $m->__debugInfo());
77    }
78
79    public function testTopLevelUInt32Value()
80    {
81        $m = new UInt32Value();
82        $m->setValue(1);
83        $this->assertSame(['value' => 1], $m->__debugInfo());
84    }
85
86    public function testTopLevelInt64Value()
87    {
88        $m = new Int64Value();
89        $m->setValue(1);
90        $this->assertSame(['value' => '1'], $m->__debugInfo());
91    }
92
93    public function testTopLevelUInt64Value()
94    {
95        $m = new UInt64Value();
96        $m->setValue(1);
97        $this->assertSame(['value' => '1'], $m->__debugInfo());
98    }
99
100    public function testTopLevelStringValue()
101    {
102        $m = new StringValue();
103        $m->setValue("a");
104        $this->assertSame(['value' => 'a'], $m->__debugInfo());
105    }
106
107    public function testTopLevelBoolValue()
108    {
109        $m = new BoolValue();
110        $m->setValue(true);
111        $this->assertSame(['value' => true], $m->__debugInfo());
112    }
113
114    public function testTopLevelBytesValue()
115    {
116        $m = new BytesValue();
117        $m->setValue("a");
118        $this->assertSame(['value' => 'YQ=='], $m->__debugInfo());
119    }
120
121    public function testTopLevelLongBytesValue()
122    {
123        $m = new BytesValue();
124        $data = $this->generateRandomString(12007);
125        $m->setValue($data);
126        $expected = base64_encode($data);
127        $this->assertSame(['value' => $expected], $m->__debugInfo());
128    }
129
130    public function testJsonEncodeNullSubMessage()
131    {
132        $from = new TestMessage();
133        $from->setOptionalMessage(null);
134        $data = $from->__debugInfo();
135        $this->assertEquals([], $data);
136    }
137
138    public function testDuration()
139    {
140        $m = new Google\Protobuf\Duration();
141        $m->setSeconds(1234);
142        $m->setNanos(999999999);
143        $this->assertEquals([
144            'seconds' => 1234,
145            'nanos' => 999999999,
146        ], $m->__debugInfo());
147    }
148
149    public function testTimestamp()
150    {
151        $m = new Google\Protobuf\Timestamp();
152        $m->setSeconds(946684800);
153        $m->setNanos(123456789);
154        $this->assertEquals([
155            'seconds' => 946684800,
156            'nanos' => 123456789,
157        ], $m->__debugInfo());
158    }
159
160    public function testTopLevelValue()
161    {
162        $m = new Value();
163        $m->setStringValue("a");
164        $this->assertSame(['stringValue' => 'a'], $m->__debugInfo());
165
166        $m = new Value();
167        $m->setNumberValue(1.5);
168        $this->assertSame(['numberValue' => 1.5], $m->__debugInfo());
169
170        $m = new Value();
171        $m->setBoolValue(true);
172        $this->assertSame(['boolValue' => true], $m->__debugInfo());
173
174        $m = new Value();
175        $m->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE);
176        $this->assertSame(['nullValue' => 0], $m->__debugInfo());
177
178        $m = new Value();
179        $struct = new Struct();
180        $map = $struct->getFields();
181        $sub = new Value();
182        $sub->setNumberValue(1.5);
183        $map["a"] = $sub;
184        $m->setStructValue($struct);
185        $this->assertSame(['structValue' => ['a' => 1.5]], $m->__debugInfo());
186
187        $m = new Value();
188        $list = new ListValue();
189        $arr = $list->getValues();
190        $sub = new Value();
191        $sub->setNumberValue(1.5);
192        $arr[] = $sub;
193        $m->setListValue($list);
194        $this->assertSame(['listValue' => [1.5]], $m->__debugInfo());
195    }
196
197    public function testTopLevelListValue()
198    {
199        $m = new ListValue();
200        $arr = $m->getValues();
201        $sub = new Value();
202        $sub->setNumberValue(1.5);
203        $arr[] = $sub;
204        $this->assertSame([1.5], $m->__debugInfo());
205    }
206
207    public function testEmptyListValue()
208    {
209        $m = new Struct();
210        $m->setFields(['test' => (new Value())->setListValue(new ListValue())]);
211        $this->assertSame(['test' => []], $m->__debugInfo());
212    }
213
214    public function testTopLevelStruct()
215    {
216        $m = new Struct();
217        $map = $m->getFields();
218        $sub = new Value();
219        $sub->setNumberValue(1.5);
220        $map["a"] = $sub;
221        $this->assertSame(['a' => 1.5], $m->__debugInfo());
222    }
223
224    public function testEmptyStruct()
225    {
226        $m = new Struct();
227        $m->setFields(['test' => (new Value())->setStructValue(new Struct())]);
228        $this->assertSame(['test' => []], $m->__debugInfo());
229    }
230
231    public function testEmptyValue()
232    {
233        $m = new Value();
234        $this->assertSame([], $m->__debugInfo());
235    }
236
237    public function testTopLevelAny()
238    {
239        // Test a normal message.
240        $packed = new TestMessage();
241        $packed->setOptionalInt32(123);
242        $packed->setOptionalString("abc");
243
244        $m = new Any();
245        $m->pack($packed);
246        $expected = [
247            '@type' => 'type.googleapis.com/foo.TestMessage',
248            'optionalInt32' => 123,
249            'optionalString' => 'abc',
250        ];
251        $result = $m->__debugInfo();
252        $this->assertSame($expected, $result);
253
254        // Test a well known message.
255        $packed = new Int32Value();
256        $packed->setValue(123);
257
258        $m = new Any();
259        $m->pack($packed);
260        $this->assertSame([
261            '@type' => 'type.googleapis.com/google.protobuf.Int32Value',
262            'value' =>  123
263        ], $m->__debugInfo());
264
265        // Test an Any message.
266        $outer = new Any();
267        $outer->pack($m);
268        $this->assertSame([
269            '@type' => 'type.googleapis.com/google.protobuf.Any',
270            'value' =>  [
271                '@type' => 'type.googleapis.com/google.protobuf.Int32Value',
272                'value' => 123
273            ],
274        ], $outer->__debugInfo());
275
276        // Test a Timestamp message.
277        $packed = new Google\Protobuf\Timestamp();
278        $packed->setSeconds(946684800);
279        $packed->setNanos(123456789);
280        $m = new Any();
281        $m->pack($packed);
282        $this->assertSame([
283            '@type' => 'type.googleapis.com/google.protobuf.Timestamp',
284            'value' =>  '2000-01-01T00:00:00.123456789Z',
285        ], $m->__debugInfo());
286    }
287
288    public function testAnyWithDefaultWrapperMessagePacked()
289    {
290        $any = new Any();
291        $any->pack(new TestInt32Value([
292            'field' => new Int32Value(['value' => 0]),
293        ]));
294        $this->assertSame(
295            ['@type' => 'type.googleapis.com/foo.TestInt32Value', 'field' => 0],
296            $any->__debugInfo()
297        );
298    }
299
300    public function testTopLevelFieldMask()
301    {
302        $m = new FieldMask();
303        $m->setPaths(["foo.bar_baz", "qux"]);
304        $this->assertSame(['paths' => ['foo.bar_baz', 'qux']], $m->__debugInfo());
305    }
306
307    public function testEmptyAnySerialization()
308    {
309        $m = new EmptyAnySerialization();
310
311        $any = new Any();
312        $any->pack($m);
313
314        $data = $any->__debugInfo();
315        $this->assertEquals(['@type' => 'type.googleapis.com/foo.EmptyAnySerialization'], $data);
316    }
317
318    public function testRepeatedStringValue()
319    {
320        $m = new TestStringValue();
321        $r = [new StringValue(['value' => 'a'])];
322        $m->setRepeatedField($r);
323        $this->assertSame(['repeatedField' => ['a']], $m->__debugInfo());
324    }
325
326    public function testMapStringValue()
327    {
328        $m = new TestStringValue();
329        $m->mergeFromJsonString("{\"map_field\":{\"1\": \"a\"}}");
330        $this->assertSame(['mapField' => [1 => 'a']], $m->__debugInfo());
331    }
332
333    public function testNestedAny()
334    {
335        // Make sure packed message has been created at least once.
336        $m = new TestAny();
337        $m->mergeFromJsonString(
338            "{\"any\":{\"optionalInt32\": 1, " .
339            "\"@type\":\"type.googleapis.com/foo.TestMessage\", " .
340            "\"optionalInt64\": 2}}");
341        $this->assertSame([
342            'any' => [
343                '@type' => 'type.googleapis.com/foo.TestMessage',
344                'optionalInt32' => 1,
345                'optionalInt64' => '2',
346            ]
347        ], $m->__debugInfo());
348    }
349
350    public function testEnum()
351    {
352        $m = new TestMessage();
353        $m->setOneofEnum(TestEnum::ZERO);
354        $this->assertSame(['oneofEnum' => 'ZERO'], $m->__debugInfo());
355    }
356
357    public function testTopLevelRepeatedField()
358    {
359        $r1 = new RepeatedField(GPBType::class);
360        $r1[] = 'a';
361        $this->assertSame(['a'], $r1->__debugInfo());
362
363        $r2 = new RepeatedField(TestMessage::class);
364        $r2[] = new TestMessage(['optional_int32' => -42]);
365        $r2[] = new TestMessage(['optional_int64' => 43]);
366        $this->assertSame([
367            ['optionalInt32' => -42],
368            ['optionalInt64' => '43'],
369        ], $r2->__debugInfo());
370
371        $r3 = new RepeatedField(RepeatedField::class);
372        $r3[] = $r1;
373        $r3[] = $r2;
374
375        $this->assertSame([
376            ['a'],
377            [
378                ['optionalInt32' => -42],
379                ['optionalInt64' => '43'],
380            ],
381        ], $r3->__debugInfo());
382    }
383
384    public function testEverything()
385    {
386        $m = new TestMessage([
387            'optional_int32' => -42,
388            'optional_int64' => -43,
389            'optional_uint32' => 42,
390            'optional_uint64' => 43,
391            'optional_sint32' => -44,
392            'optional_sint64' => -45,
393            'optional_fixed32' => 46,
394            'optional_fixed64' => 47,
395            'optional_sfixed32' => -46,
396            'optional_sfixed64' => -47,
397            'optional_float' => 1.5,
398            'optional_double' => 1.6,
399            'optional_bool' => true,
400            'optional_string' => 'a',
401            'optional_bytes' => 'bbbb',
402            'optional_enum' => TestEnum::ONE,
403            'optional_message' => new Sub([
404                'a' => 33
405            ]),
406            'repeated_int32' => [-42, -52],
407            'repeated_int64' => [-43, -53],
408            'repeated_uint32' => [42, 52],
409            'repeated_uint64' => [43, 53],
410            'repeated_sint32' => [-44, -54],
411            'repeated_sint64' => [-45, -55],
412            'repeated_fixed32' => [46, 56],
413            'repeated_fixed64' => [47, 57],
414            'repeated_sfixed32' => [-46, -56],
415            'repeated_sfixed64' => [-47, -57],
416            'repeated_float' => [1.5, 2.5],
417            'repeated_double' => [1.6, 2.6],
418            'repeated_bool' => [true, false],
419            'repeated_string' => ['a', 'c'],
420            'repeated_bytes' => ['bbbb', 'dddd'],
421            'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
422            'repeated_message' => [new Sub(['a' => 34]),
423                                   new Sub(['a' => 35])],
424            'map_int32_int32' => [-62 => -62],
425            'map_int64_int64' => [-63 => -63],
426            'map_uint32_uint32' => [62 => 62],
427            'map_uint64_uint64' => [63 => 63],
428            'map_sint32_sint32' => [-64 => -64],
429            'map_sint64_sint64' => [-65 => -65],
430            'map_fixed32_fixed32' => [66 => 66],
431            'map_fixed64_fixed64' => [67 => 67],
432            'map_sfixed32_sfixed32' => [-68 => -68],
433            'map_sfixed64_sfixed64' => [-69 => -69],
434            'map_int32_float' => [1 => 3.5],
435            'map_int32_double' => [1 => 3.6],
436            'map_bool_bool' => [true => true],
437            'map_string_string' => ['e' => 'e'],
438            'map_int32_bytes' => [1 => 'ffff'],
439            'map_int32_enum' => [1 => TestEnum::ONE],
440            'map_int32_message' => [1 => new Sub(['a' => 36])],
441        ]);
442
443        $this->assertSame([
444            'optionalInt32' => -42,
445            'optionalInt64' => '-43',
446            'optionalUint32' => 42,
447            'optionalUint64' => '43',
448            'optionalSint32' => -44,
449            'optionalSint64' => '-45',
450            'optionalFixed32' => 46,
451            'optionalFixed64' => '47',
452            'optionalSfixed32' => -46,
453            'optionalSfixed64' => '-47',
454            'optionalFloat' => 1.5,
455            'optionalDouble' => 1.6,
456            'optionalBool' => true,
457            'optionalString' => 'a',
458            'optionalBytes' => 'YmJiYg==',
459            'optionalEnum' => 'ONE',
460            'optionalMessage' => [
461                'a' => 33,
462            ],
463            'repeatedInt32' => [
464                -42,
465                -52,
466            ],
467            'repeatedInt64' => [
468                '-43',
469                '-53',
470            ],
471            'repeatedUint32' => [
472                42,
473                52,
474            ],
475            'repeatedUint64' => [
476                '43',
477                '53',
478            ],
479            'repeatedSint32' => [
480                -44,
481                -54,
482            ],
483            'repeatedSint64' => [
484                '-45',
485                '-55',
486            ],
487            'repeatedFixed32' => [
488                46,
489                56,
490            ],
491            'repeatedFixed64' => [
492                '47',
493                '57',
494            ],
495            'repeatedSfixed32' => [
496                -46,
497                -56,
498            ],
499            'repeatedSfixed64' => [
500                '-47',
501                '-57',
502            ],
503            'repeatedFloat' => [
504                1.5,
505                2.5,
506            ],
507            'repeatedDouble' => [
508                1.6,
509                2.6,
510            ],
511            'repeatedBool' => [
512                true,
513                false,
514            ],
515            'repeatedString' => [
516                'a',
517                'c',
518            ],
519            'repeatedBytes' => [
520                'YmJiYg==',
521                'ZGRkZA==',
522            ],
523            'repeatedEnum' => [
524                'ZERO',
525                'ONE',
526            ],
527            'repeatedMessage' => [
528                [
529                    'a' => 34,
530                ],
531                [
532                    'a' => 35,
533                ],
534            ],
535            'mapInt32Int32' => [
536                -62 => -62,
537            ],
538            'mapInt64Int64' => [
539                -63 => '-63',
540            ],
541            'mapUint32Uint32' => [
542                62 => 62,
543            ],
544            'mapUint64Uint64' => [
545                63 => '63',
546            ],
547            'mapSint32Sint32' => [
548                -64 => -64,
549            ],
550            'mapSint64Sint64' => [
551                -65 => '-65',
552            ],
553            'mapFixed32Fixed32' => [
554                66 => 66,
555            ],
556            'mapFixed64Fixed64' => [
557                67 => '67',
558            ],
559            'mapSfixed32Sfixed32' => [
560                -68 => -68,
561            ],
562            'mapSfixed64Sfixed64' => [
563                -69 => '-69',
564            ],
565            'mapInt32Float' => [
566                1 => 3.5,
567            ],
568            'mapInt32Double' => [
569                1 => 3.6,
570            ],
571            'mapBoolBool' => [
572                'true' => true,
573            ],
574            'mapStringString' => [
575                'e' => 'e',
576            ],
577            'mapInt32Bytes' => [
578                1 => 'ZmZmZg==',
579            ],
580            'mapInt32Enum' => [
581                1 => 'ONE',
582            ],
583            'mapInt32Message' => [
584                1 => ['a' => 36],
585            ],
586        ], $m->__debugInfo());
587    }
588
589    private function generateRandomString($length = 10)
590    {
591        $randomString = str_repeat("+", $length);
592        for ($i = 0; $i < $length; $i++) {
593            $randomString[$i] = chr(rand(0, 255));
594        }
595        return $randomString;
596    }
597}
598