[7392] fix conformance test in PHP JSON parser (#19376)

# Motivation

This PR fixes failing JSON conformance tests for php with name `IgnoreUnknownEnumStringValue*`.

The JSON parsing spec was discussed in https://github.com/protocolbuffers/protobuf/issues/7392.

Recent similar changes in other languages:
- Python: 86abf35ef5
- Swift: https://github.com/apple/swift-protobuf/pull/1345
- C#: https://github.com/protocolbuffers/protobuf/pull/15758
- C++: https://github.com/protocolbuffers/protobuf/pull/16479

Note: this PR is equivalent to https://github.com/protocolbuffers/protobuf/pull/16743. I had to create a new one since I lost access to noom/protobuf in the meantime (switched companies recently).

Closes #19376

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/19376 from antongrbin:anton--7392--php-newbranch 641a28a2b8
PiperOrigin-RevId: 699989555
pull/19388/head
Anton Grbin 3 months ago committed by Copybara-Service
parent a02ec0f353
commit 1c98b5ba47
  1. 4
      conformance/failure_list_php.txt
  2. 22
      php/src/Google/Protobuf/Internal/Message.php
  3. 62
      php/tests/EncodeDecodeTest.php

@ -4,10 +4,6 @@ Recommended.*.FieldMaskTooManyUnderscore.JsonOutput
Recommended.*.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.*.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.*.JsonInput.FieldMaskInvalidCharacter
Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput
Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput
Recommended.*.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Recommended.*.ValueRejectInfNumberValue.JsonOutput # Should have failed to serialize, but didn't.
Recommended.*.ValueRejectNanNumberValue.JsonOutput # Should have failed to serialize, but didn't.

@ -1255,6 +1255,18 @@ class Message
$tmp_value,
$value_field,
$ignore_unknown);
// Mapped unknown enum string values should be silently
// ignored if ignore_unknown is set.
if ($value_field->getType() == GPBType::ENUM &&
is_string($tmp_value) &&
is_null(
$value_field->getEnumType()->getValueByName($tmp_value)
) &&
$ignore_unknown) {
continue;
}
self::kvUpdateHelper($field, $proto_key, $proto_value);
}
} else if ($field->isRepeated()) {
@ -1270,6 +1282,16 @@ class Message
$tmp,
$field,
$ignore_unknown);
// Repeated unknown enum string values should be silently
// ignored if ignore_unknown is set.
if ($field->getType() == GPBType::ENUM &&
is_string($tmp) &&
is_null($field->getEnumType()->getValueByName($tmp)) &&
$ignore_unknown) {
continue;
}
self::appendHelper($field, $proto_value);
}
} else {

@ -205,6 +205,68 @@ class EncodeDecodeTest extends TestBase
$this->assertSame("a", $m->getRepeatedField()[0]->getValue());
}
public function testDecodeEnumMapWithUnknownStringValueThrows()
{
$this->expectException(Exception::class);
$m = new TestMessage();
$m->mergeFromJsonString(
"{\"map_int32_enum\":{
\"1\": \"ONE\",
\"2\": \"UNKNOWN_ENUM\",
\"3\": \"ZERO\"
}}"
);
}
public function testDecodeEnumMapWithUnknownStringValueIgnored()
{
$m = new TestMessage();
$m->mergeFromJsonString(
"{\"map_int32_enum\":{
\"1\": \"ONE\",
\"2\": \"UNKNOWN_ENUM\",
\"3\": \"ZERO\"
}}",
true
);
$this->assertSame(TestEnum::ONE, $m->getMapInt32Enum()["1"]);
$this->assertSame(TestEnum::ZERO, $m->getMapInt32Enum()["3"]);
$this->assertFalse($m->getMapInt32Enum()->offsetExists(2));
}
public function testDecodeRepeatedEnumWithUnknownStringValueThrows()
{
$this->expectException(Exception::class);
$m = new TestMessage();
$m->mergeFromJsonString(
"{\"repeated_enum\":[
\"ONE\",
\"UNKNOWN_ENUM\",
\"ZERO\"
]}"
);
}
public function testDecodeRepeatedEnumWithUnknownStringValueIgnored()
{
$m = new TestMessage();
$m->mergeFromJsonString(
"{\"repeated_enum\":[
\"ONE\",
\"UNKNOWN_ENUM\",
\"ZERO\"
]}",
true
);
$this->assertSame(2, count($m->getRepeatedEnum()));
$this->assertSame(TestEnum::ONE, $m->getRepeatedEnum()[0]);
$this->assertSame(TestEnum::ZERO, $m->getRepeatedEnum()[1]);
}
public function testDecodeMapStringValue()
{
$m = new TestStringValue();

Loading…
Cancel
Save