Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
598 lines
17 KiB
598 lines
17 KiB
1 year ago
|
<?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()
|
||
|
{
|
||
|
$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;
|
||
|
}
|
||
|
}
|