| <?php | |
| require_once('test_base.php'); | |
| require_once('test_util.php'); | |
| use Google\Protobuf\Internal\RepeatedField; | |
| use Google\Protobuf\Internal\GPBType; | |
| use Foo\EmptyAnySerialization; | |
| use Foo\TestInt32Value; | |
| use Foo\TestStringValue; | |
| use Foo\TestAny; | |
| use Foo\TestEnum; | |
| use Foo\TestLargeFieldNumber; | |
| use Foo\TestMessage; | |
| use Foo\TestMessage\Sub; | |
| use Foo\TestPackedMessage; | |
| use Foo\TestRandomFieldOrder; | |
| use Foo\TestUnpackedMessage; | |
| use Google\Protobuf\Any; | |
| use Google\Protobuf\DoubleValue; | |
| use Google\Protobuf\FieldMask; | |
| use Google\Protobuf\FloatValue; | |
| use Google\Protobuf\Int32Value; | |
| use Google\Protobuf\UInt32Value; | |
| use Google\Protobuf\Int64Value; | |
| use Google\Protobuf\UInt64Value; | |
| use Google\Protobuf\BoolValue; | |
| use Google\Protobuf\StringValue; | |
| use Google\Protobuf\BytesValue; | |
| use Google\Protobuf\Value; | |
| use Google\Protobuf\ListValue; | |
| use Google\Protobuf\Struct; | |
| use Google\Protobuf\GPBEmpty; | |
| class DebugInfoTest extends TestBase | |
| { | |
| public function setUp(): void | |
| { | |
| if (extension_loaded('protobuf')) { | |
| $this->markTestSkipped('__debugInfo is not supported for the protobuf extension'); | |
| } | |
| } | |
| public function testVarDumpOutput() | |
| { | |
| if (extension_loaded('xdebug')) { | |
| $this->markTestSkipped('please disable the xdebug extension to run this test'); | |
| } | |
| $m = new DoubleValue(); | |
| $m->setValue(1.5); | |
| var_dump($m); | |
| $regex = <<<EOL | |
| object(Google\Protobuf\DoubleValue)#%s (1) { | |
| ["value"]=> | |
| float(1.5) | |
| } | |
| EOL; | |
| $this->expectOutputRegex('/' . sprintf(preg_quote($regex), '\d+') . '/'); | |
| } | |
| public function testTopLevelDoubleValue() | |
| { | |
| $m = new DoubleValue(); | |
| $m->setValue(1.5); | |
| $this->assertSame(['value' => 1.5], $m->__debugInfo()); | |
| } | |
| public function testTopLevelFloatValue() | |
| { | |
| $m = new FloatValue(); | |
| $m->setValue(1.5); | |
| $this->assertSame(['value' => 1.5], $m->__debugInfo()); | |
| } | |
| public function testTopLevelInt32Value() | |
| { | |
| $m = new Int32Value(); | |
| $m->setValue(1); | |
| $this->assertSame(['value' => 1], $m->__debugInfo()); | |
| } | |
| public function testTopLevelUInt32Value() | |
| { | |
| $m = new UInt32Value(); | |
| $m->setValue(1); | |
| $this->assertSame(['value' => 1], $m->__debugInfo()); | |
| } | |
| public function testTopLevelInt64Value() | |
| { | |
| $m = new Int64Value(); | |
| $m->setValue(1); | |
| $this->assertSame(['value' => '1'], $m->__debugInfo()); | |
| } | |
| public function testTopLevelUInt64Value() | |
| { | |
| $m = new UInt64Value(); | |
| $m->setValue(1); | |
| $this->assertSame(['value' => '1'], $m->__debugInfo()); | |
| } | |
| public function testTopLevelStringValue() | |
| { | |
| $m = new StringValue(); | |
| $m->setValue("a"); | |
| $this->assertSame(['value' => 'a'], $m->__debugInfo()); | |
| } | |
| public function testTopLevelBoolValue() | |
| { | |
| $m = new BoolValue(); | |
| $m->setValue(true); | |
| $this->assertSame(['value' => true], $m->__debugInfo()); | |
| } | |
| public function testTopLevelBytesValue() | |
| { | |
| $m = new BytesValue(); | |
| $m->setValue("a"); | |
| $this->assertSame(['value' => 'YQ=='], $m->__debugInfo()); | |
| } | |
| public function testTopLevelLongBytesValue() | |
| { | |
| $m = new BytesValue(); | |
| $data = $this->generateRandomString(12007); | |
| $m->setValue($data); | |
| $expected = base64_encode($data); | |
| $this->assertSame(['value' => $expected], $m->__debugInfo()); | |
| } | |
| public function testJsonEncodeNullSubMessage() | |
| { | |
| $from = new TestMessage(); | |
| $from->setOptionalMessage(null); | |
| $data = $from->__debugInfo(); | |
| $this->assertEquals([], $data); | |
| } | |
| public function testDuration() | |
| { | |
| $m = new Google\Protobuf\Duration(); | |
| $m->setSeconds(1234); | |
| $m->setNanos(999999999); | |
| $this->assertEquals([ | |
| 'seconds' => 1234, | |
| 'nanos' => 999999999, | |
| ], $m->__debugInfo()); | |
| } | |
| public function testTimestamp() | |
| { | |
| $m = new Google\Protobuf\Timestamp(); | |
| $m->setSeconds(946684800); | |
| $m->setNanos(123456789); | |
| $this->assertEquals([ | |
| 'seconds' => 946684800, | |
| 'nanos' => 123456789, | |
| ], $m->__debugInfo()); | |
| } | |
| public function testTopLevelValue() | |
| { | |
| $m = new Value(); | |
| $m->setStringValue("a"); | |
| $this->assertSame(['stringValue' => 'a'], $m->__debugInfo()); | |
| $m = new Value(); | |
| $m->setNumberValue(1.5); | |
| $this->assertSame(['numberValue' => 1.5], $m->__debugInfo()); | |
| $m = new Value(); | |
| $m->setBoolValue(true); | |
| $this->assertSame(['boolValue' => true], $m->__debugInfo()); | |
| $m = new Value(); | |
| $m->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE); | |
| $this->assertSame(['nullValue' => 0], $m->__debugInfo()); | |
| $m = new Value(); | |
| $struct = new Struct(); | |
| $map = $struct->getFields(); | |
| $sub = new Value(); | |
| $sub->setNumberValue(1.5); | |
| $map["a"] = $sub; | |
| $m->setStructValue($struct); | |
| $this->assertSame(['structValue' => ['a' => 1.5]], $m->__debugInfo()); | |
| $m = new Value(); | |
| $list = new ListValue(); | |
| $arr = $list->getValues(); | |
| $sub = new Value(); | |
| $sub->setNumberValue(1.5); | |
| $arr[] = $sub; | |
| $m->setListValue($list); | |
| $this->assertSame(['listValue' => [1.5]], $m->__debugInfo()); | |
| } | |
| public function testTopLevelListValue() | |
| { | |
| $m = new ListValue(); | |
| $arr = $m->getValues(); | |
| $sub = new Value(); | |
| $sub->setNumberValue(1.5); | |
| $arr[] = $sub; | |
| $this->assertSame([1.5], $m->__debugInfo()); | |
| } | |
| public function testEmptyListValue() | |
| { | |
| $m = new Struct(); | |
| $m->setFields(['test' => (new Value())->setListValue(new ListValue())]); | |
| $this->assertSame(['test' => []], $m->__debugInfo()); | |
| } | |
| public function testTopLevelStruct() | |
| { | |
| $m = new Struct(); | |
| $map = $m->getFields(); | |
| $sub = new Value(); | |
| $sub->setNumberValue(1.5); | |
| $map["a"] = $sub; | |
| $this->assertSame(['a' => 1.5], $m->__debugInfo()); | |
| } | |
| public function testEmptyStruct() | |
| { | |
| $m = new Struct(); | |
| $m->setFields(['test' => (new Value())->setStructValue(new Struct())]); | |
| $this->assertSame(['test' => []], $m->__debugInfo()); | |
| } | |
| public function testEmptyValue() | |
| { | |
| $m = new Value(); | |
| $this->assertSame([], $m->__debugInfo()); | |
| } | |
| public function testTopLevelAny() | |
| { | |
| // Test a normal message. | |
| $packed = new TestMessage(); | |
| $packed->setOptionalInt32(123); | |
| $packed->setOptionalString("abc"); | |
| $m = new Any(); | |
| $m->pack($packed); | |
| $expected = [ | |
| '@type' => 'type.googleapis.com/foo.TestMessage', | |
| 'optionalInt32' => 123, | |
| 'optionalString' => 'abc', | |
| ]; | |
| $result = $m->__debugInfo(); | |
| $this->assertSame($expected, $result); | |
| // Test a well known message. | |
| $packed = new Int32Value(); | |
| $packed->setValue(123); | |
| $m = new Any(); | |
| $m->pack($packed); | |
| $this->assertSame([ | |
| '@type' => 'type.googleapis.com/google.protobuf.Int32Value', | |
| 'value' => 123 | |
| ], $m->__debugInfo()); | |
| // Test an Any message. | |
| $outer = new Any(); | |
| $outer->pack($m); | |
| $this->assertSame([ | |
| '@type' => 'type.googleapis.com/google.protobuf.Any', | |
| 'value' => [ | |
| '@type' => 'type.googleapis.com/google.protobuf.Int32Value', | |
| 'value' => 123 | |
| ], | |
| ], $outer->__debugInfo()); | |
| // Test a Timestamp message. | |
| $packed = new Google\Protobuf\Timestamp(); | |
| $packed->setSeconds(946684800); | |
| $packed->setNanos(123456789); | |
| $m = new Any(); | |
| $m->pack($packed); | |
| $this->assertSame([ | |
| '@type' => 'type.googleapis.com/google.protobuf.Timestamp', | |
| 'value' => '2000-01-01T00:00:00.123456789Z', | |
| ], $m->__debugInfo()); | |
| } | |
| public function testAnyWithDefaultWrapperMessagePacked() | |
| { | |
| $any = new Any(); | |
| $any->pack(new TestInt32Value([ | |
| 'field' => new Int32Value(['value' => 0]), | |
| ])); | |
| $this->assertSame( | |
| ['@type' => 'type.googleapis.com/foo.TestInt32Value', 'field' => 0], | |
| $any->__debugInfo() | |
| ); | |
| } | |
| public function testTopLevelFieldMask() | |
| { | |
| $m = new FieldMask(); | |
| $m->setPaths(["foo.bar_baz", "qux"]); | |
| $this->assertSame(['paths' => ['foo.bar_baz', 'qux']], $m->__debugInfo()); | |
| } | |
| public function testEmptyAnySerialization() | |
| { | |
| $m = new EmptyAnySerialization(); | |
| $any = new Any(); | |
| $any->pack($m); | |
| $data = $any->__debugInfo(); | |
| $this->assertEquals(['@type' => 'type.googleapis.com/foo.EmptyAnySerialization'], $data); | |
| } | |
| public function testRepeatedStringValue() | |
| { | |
| $m = new TestStringValue(); | |
| $r = [new StringValue(['value' => 'a'])]; | |
| $m->setRepeatedField($r); | |
| $this->assertSame(['repeatedField' => ['a']], $m->__debugInfo()); | |
| } | |
| public function testMapStringValue() | |
| { | |
| $m = new TestStringValue(); | |
| $m->mergeFromJsonString("{\"map_field\":{\"1\": \"a\"}}"); | |
| $this->assertSame(['mapField' => [1 => 'a']], $m->__debugInfo()); | |
| } | |
| public function testNestedAny() | |
| { | |
| // Make sure packed message has been created at least once. | |
| $m = new TestAny(); | |
| $m->mergeFromJsonString( | |
| "{\"any\":{\"optionalInt32\": 1, " . | |
| "\"@type\":\"type.googleapis.com/foo.TestMessage\", " . | |
| "\"optionalInt64\": 2}}"); | |
| $this->assertSame([ | |
| 'any' => [ | |
| '@type' => 'type.googleapis.com/foo.TestMessage', | |
| 'optionalInt32' => 1, | |
| 'optionalInt64' => '2', | |
| ] | |
| ], $m->__debugInfo()); | |
| } | |
| public function testEnum() | |
| { | |
| $m = new TestMessage(); | |
| $m->setOneofEnum(TestEnum::ZERO); | |
| $this->assertSame(['oneofEnum' => 'ZERO'], $m->__debugInfo()); | |
| } | |
| public function testTopLevelRepeatedField() | |
| { | |
| $r1 = new RepeatedField(GPBType::class); | |
| $r1[] = 'a'; | |
| $this->assertSame(['a'], $r1->__debugInfo()); | |
| $r2 = new RepeatedField(TestMessage::class); | |
| $r2[] = new TestMessage(['optional_int32' => -42]); | |
| $r2[] = new TestMessage(['optional_int64' => 43]); | |
| $this->assertSame([ | |
| ['optionalInt32' => -42], | |
| ['optionalInt64' => '43'], | |
| ], $r2->__debugInfo()); | |
| $r3 = new RepeatedField(RepeatedField::class); | |
| $r3[] = $r1; | |
| $r3[] = $r2; | |
| $this->assertSame([ | |
| ['a'], | |
| [ | |
| ['optionalInt32' => -42], | |
| ['optionalInt64' => '43'], | |
| ], | |
| ], $r3->__debugInfo()); | |
| } | |
| public function testEverything() | |
| { | |
| $m = new TestMessage([ | |
| 'optional_int32' => -42, | |
| 'optional_int64' => -43, | |
| 'optional_uint32' => 42, | |
| 'optional_uint64' => 43, | |
| 'optional_sint32' => -44, | |
| 'optional_sint64' => -45, | |
| 'optional_fixed32' => 46, | |
| 'optional_fixed64' => 47, | |
| 'optional_sfixed32' => -46, | |
| 'optional_sfixed64' => -47, | |
| 'optional_float' => 1.5, | |
| 'optional_double' => 1.6, | |
| 'optional_bool' => true, | |
| 'optional_string' => 'a', | |
| 'optional_bytes' => 'bbbb', | |
| 'optional_enum' => TestEnum::ONE, | |
| 'optional_message' => new Sub([ | |
| 'a' => 33 | |
| ]), | |
| 'repeated_int32' => [-42, -52], | |
| 'repeated_int64' => [-43, -53], | |
| 'repeated_uint32' => [42, 52], | |
| 'repeated_uint64' => [43, 53], | |
| 'repeated_sint32' => [-44, -54], | |
| 'repeated_sint64' => [-45, -55], | |
| 'repeated_fixed32' => [46, 56], | |
| 'repeated_fixed64' => [47, 57], | |
| 'repeated_sfixed32' => [-46, -56], | |
| 'repeated_sfixed64' => [-47, -57], | |
| 'repeated_float' => [1.5, 2.5], | |
| 'repeated_double' => [1.6, 2.6], | |
| 'repeated_bool' => [true, false], | |
| 'repeated_string' => ['a', 'c'], | |
| 'repeated_bytes' => ['bbbb', 'dddd'], | |
| 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], | |
| 'repeated_message' => [new Sub(['a' => 34]), | |
| new Sub(['a' => 35])], | |
| 'map_int32_int32' => [-62 => -62], | |
| 'map_int64_int64' => [-63 => -63], | |
| 'map_uint32_uint32' => [62 => 62], | |
| 'map_uint64_uint64' => [63 => 63], | |
| 'map_sint32_sint32' => [-64 => -64], | |
| 'map_sint64_sint64' => [-65 => -65], | |
| 'map_fixed32_fixed32' => [66 => 66], | |
| 'map_fixed64_fixed64' => [67 => 67], | |
| 'map_sfixed32_sfixed32' => [-68 => -68], | |
| 'map_sfixed64_sfixed64' => [-69 => -69], | |
| 'map_int32_float' => [1 => 3.5], | |
| 'map_int32_double' => [1 => 3.6], | |
| 'map_bool_bool' => [true => true], | |
| 'map_string_string' => ['e' => 'e'], | |
| 'map_int32_bytes' => [1 => 'ffff'], | |
| 'map_int32_enum' => [1 => TestEnum::ONE], | |
| 'map_int32_message' => [1 => new Sub(['a' => 36])], | |
| ]); | |
| $this->assertSame([ | |
| 'optionalInt32' => -42, | |
| 'optionalInt64' => '-43', | |
| 'optionalUint32' => 42, | |
| 'optionalUint64' => '43', | |
| 'optionalSint32' => -44, | |
| 'optionalSint64' => '-45', | |
| 'optionalFixed32' => 46, | |
| 'optionalFixed64' => '47', | |
| 'optionalSfixed32' => -46, | |
| 'optionalSfixed64' => '-47', | |
| 'optionalFloat' => 1.5, | |
| 'optionalDouble' => 1.6, | |
| 'optionalBool' => true, | |
| 'optionalString' => 'a', | |
| 'optionalBytes' => 'YmJiYg==', | |
| 'optionalEnum' => 'ONE', | |
| 'optionalMessage' => [ | |
| 'a' => 33, | |
| ], | |
| 'repeatedInt32' => [ | |
| -42, | |
| -52, | |
| ], | |
| 'repeatedInt64' => [ | |
| '-43', | |
| '-53', | |
| ], | |
| 'repeatedUint32' => [ | |
| 42, | |
| 52, | |
| ], | |
| 'repeatedUint64' => [ | |
| '43', | |
| '53', | |
| ], | |
| 'repeatedSint32' => [ | |
| -44, | |
| -54, | |
| ], | |
| 'repeatedSint64' => [ | |
| '-45', | |
| '-55', | |
| ], | |
| 'repeatedFixed32' => [ | |
| 46, | |
| 56, | |
| ], | |
| 'repeatedFixed64' => [ | |
| '47', | |
| '57', | |
| ], | |
| 'repeatedSfixed32' => [ | |
| -46, | |
| -56, | |
| ], | |
| 'repeatedSfixed64' => [ | |
| '-47', | |
| '-57', | |
| ], | |
| 'repeatedFloat' => [ | |
| 1.5, | |
| 2.5, | |
| ], | |
| 'repeatedDouble' => [ | |
| 1.6, | |
| 2.6, | |
| ], | |
| 'repeatedBool' => [ | |
| true, | |
| false, | |
| ], | |
| 'repeatedString' => [ | |
| 'a', | |
| 'c', | |
| ], | |
| 'repeatedBytes' => [ | |
| 'YmJiYg==', | |
| 'ZGRkZA==', | |
| ], | |
| 'repeatedEnum' => [ | |
| 'ZERO', | |
| 'ONE', | |
| ], | |
| 'repeatedMessage' => [ | |
| [ | |
| 'a' => 34, | |
| ], | |
| [ | |
| 'a' => 35, | |
| ], | |
| ], | |
| 'mapInt32Int32' => [ | |
| -62 => -62, | |
| ], | |
| 'mapInt64Int64' => [ | |
| -63 => '-63', | |
| ], | |
| 'mapUint32Uint32' => [ | |
| 62 => 62, | |
| ], | |
| 'mapUint64Uint64' => [ | |
| 63 => '63', | |
| ], | |
| 'mapSint32Sint32' => [ | |
| -64 => -64, | |
| ], | |
| 'mapSint64Sint64' => [ | |
| -65 => '-65', | |
| ], | |
| 'mapFixed32Fixed32' => [ | |
| 66 => 66, | |
| ], | |
| 'mapFixed64Fixed64' => [ | |
| 67 => '67', | |
| ], | |
| 'mapSfixed32Sfixed32' => [ | |
| -68 => -68, | |
| ], | |
| 'mapSfixed64Sfixed64' => [ | |
| -69 => '-69', | |
| ], | |
| 'mapInt32Float' => [ | |
| 1 => 3.5, | |
| ], | |
| 'mapInt32Double' => [ | |
| 1 => 3.6, | |
| ], | |
| 'mapBoolBool' => [ | |
| 'true' => true, | |
| ], | |
| 'mapStringString' => [ | |
| 'e' => 'e', | |
| ], | |
| 'mapInt32Bytes' => [ | |
| 1 => 'ZmZmZg==', | |
| ], | |
| 'mapInt32Enum' => [ | |
| 1 => 'ONE', | |
| ], | |
| 'mapInt32Message' => [ | |
| 1 => ['a' => 36], | |
| ], | |
| ], $m->__debugInfo()); | |
| } | |
| private function generateRandomString($length = 10) | |
| { | |
| $randomString = str_repeat("+", $length); | |
| for ($i = 0; $i < $length; $i++) { | |
| $randomString[$i] = chr(rand(0, 255)); | |
| } | |
| return $randomString; | |
| } | |
| } |