aboutsummaryrefslogtreecommitdiff
path: root/conformance
diff options
context:
space:
mode:
Diffstat (limited to 'conformance')
-rw-r--r--conformance/ConformanceJava.java197
-rw-r--r--conformance/Makefile.am136
-rw-r--r--conformance/README.md32
-rw-r--r--conformance/autoload.php21
-rw-r--r--conformance/conformance.proto190
-rw-r--r--conformance/conformance_cpp.cc34
-rwxr-xr-xconformance/conformance_nodejs.js182
-rw-r--r--conformance/conformance_objc.m15
-rwxr-xr-xconformance/conformance_php.php105
-rwxr-xr-xconformance/conformance_python.py30
-rwxr-xr-xconformance/conformance_ruby.rb23
-rw-r--r--conformance/conformance_test.cc1181
-rw-r--r--conformance/conformance_test.h111
-rw-r--r--conformance/conformance_test_runner.cc19
-rw-r--r--conformance/failure_list_cpp.txt92
-rw-r--r--conformance/failure_list_csharp.txt6
-rw-r--r--conformance/failure_list_java.txt86
-rw-r--r--conformance/failure_list_js.txt13
-rw-r--r--conformance/failure_list_objc.txt2
-rw-r--r--conformance/failure_list_php.txt20
-rw-r--r--conformance/failure_list_php_c.txt182
-rw-r--r--conformance/failure_list_php_zts_c.txt225
-rw-r--r--conformance/failure_list_python.txt67
-rw-r--r--conformance/failure_list_python_cpp.txt107
-rw-r--r--conformance/failure_list_ruby.txt350
-rwxr-xr-xconformance/update_failure_list.py6
26 files changed, 2330 insertions, 1102 deletions
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java
index 43787ffc..596d113a 100644
--- a/conformance/ConformanceJava.java
+++ b/conformance/ConformanceJava.java
@@ -1,8 +1,18 @@
-
+import com.google.protobuf.ByteString;
+import com.google.protobuf.AbstractMessage;
+import com.google.protobuf.Parser;
+import com.google.protobuf.CodedInputStream;
import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
+import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
-import com.google.protobuf.InvalidProtocolBufferException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
class ConformanceJava {
private int testCount = 0;
@@ -46,22 +56,185 @@ class ConformanceJava {
buf[3] = (byte)(val >> 24);
writeToStdout(buf);
}
+
+ private enum BinaryDecoderType {
+ BTYE_STRING_DECODER,
+ BYTE_ARRAY_DECODER,
+ ARRAY_BYTE_BUFFER_DECODER,
+ READONLY_ARRAY_BYTE_BUFFER_DECODER,
+ DIRECT_BYTE_BUFFER_DECODER,
+ READONLY_DIRECT_BYTE_BUFFER_DECODER,
+ INPUT_STREAM_DECODER;
+ }
+
+ private static class BinaryDecoder <MessageType extends AbstractMessage> {
+ public MessageType decode (ByteString bytes, BinaryDecoderType type,
+ Parser <MessageType> parser, ExtensionRegistry extensions)
+ throws InvalidProtocolBufferException {
+ switch (type) {
+ case BTYE_STRING_DECODER:
+ return parser.parseFrom(bytes, extensions);
+ case BYTE_ARRAY_DECODER:
+ return parser.parseFrom(bytes.toByteArray(), extensions);
+ case ARRAY_BYTE_BUFFER_DECODER: {
+ ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ try {
+ return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+ case READONLY_ARRAY_BYTE_BUFFER_DECODER: {
+ try {
+ return parser.parseFrom(
+ CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+ case DIRECT_BYTE_BUFFER_DECODER: {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ try {
+ return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+ case READONLY_DIRECT_BYTE_BUFFER_DECODER: {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+ bytes.copyTo(buffer);
+ buffer.flip();
+ try {
+ return parser.parseFrom(
+ CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+ case INPUT_STREAM_DECODER: {
+ try {
+ return parser.parseFrom(bytes.newInput(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+ default :
+ return null;
+ }
+ }
+ }
+
+ private <MessageType extends AbstractMessage> MessageType parseBinary(
+ ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions)
+ throws InvalidProtocolBufferException {
+ ArrayList <MessageType> messages = new ArrayList <MessageType> ();
+ ArrayList <InvalidProtocolBufferException> exceptions =
+ new ArrayList <InvalidProtocolBufferException>();
+
+ for (int i = 0; i < BinaryDecoderType.values().length; i++) {
+ messages.add(null);
+ exceptions.add(null);
+ }
+ BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> ();
+
+ boolean hasMessage = false;
+ boolean hasException = false;
+ for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+ try {
+ //= BinaryDecoderType.values()[i].parseProto3(bytes);
+ messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
+ hasMessage = true;
+ } catch (InvalidProtocolBufferException e) {
+ exceptions.set(i, e);
+ hasException = true;
+ }
+ }
+
+ if (hasMessage && hasException) {
+ StringBuilder sb =
+ new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
+ for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+ sb.append(BinaryDecoderType.values()[i].name());
+ if (messages.get(i) != null) {
+ sb.append(" accepted the payload.\n");
+ } else {
+ sb.append(" rejected the payload.\n");
+ }
+ }
+ throw new RuntimeException(sb.toString());
+ }
+
+ if (hasException) {
+ // We do not check if exceptions are equal. Different implementations may return different
+ // exception messages. Throw an arbitrary one out instead.
+ throw exceptions.get(0);
+ }
+
+ // Fast path comparing all the messages with the first message, assuming equality being
+ // symmetric and transitive.
+ boolean allEqual = true;
+ for (int i = 1; i < messages.size(); ++i) {
+ if (!messages.get(0).equals(messages.get(i))) {
+ allEqual = false;
+ break;
+ }
+ }
+
+ // Slow path: compare and find out all unequal pairs.
+ if (!allEqual) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < messages.size() - 1; ++i) {
+ for (int j = i + 1; j < messages.size(); ++j) {
+ if (!messages.get(i).equals(messages.get(j))) {
+ sb.append(BinaryDecoderType.values()[i].name())
+ .append(" and ")
+ .append(BinaryDecoderType.values()[j].name())
+ .append(" parsed the payload differently.\n");
+ }
+ }
+ }
+ throw new RuntimeException(sb.toString());
+ }
+
+ return messages.get(0);
+ }
private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
- Conformance.TestAllTypes testMessage;
+ com.google.protobuf.AbstractMessage testMessage;
+ boolean isProto3 = request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
+ boolean isProto2 = request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
switch (request.getPayloadCase()) {
case PROTOBUF_PAYLOAD: {
- try {
- testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
- } catch (InvalidProtocolBufferException e) {
- return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ if (isProto3) {
+ try {
+ ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+ TestMessagesProto3.registerAllExtensions(extensions);
+ testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ }
+ } else if (isProto2) {
+ try {
+ ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+ TestMessagesProto2.registerAllExtensions(extensions);
+ testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ }
+ } else {
+ throw new RuntimeException("Protobuf request doesn't have specific payload type.");
}
break;
}
case JSON_PAYLOAD: {
try {
- Conformance.TestAllTypes.Builder builder = Conformance.TestAllTypes.newBuilder();
+ TestMessagesProto3.TestAllTypesProto3.Builder builder =
+ TestMessagesProto3.TestAllTypesProto3.newBuilder();
JsonFormat.parser().usingTypeRegistry(typeRegistry)
.merge(request.getJsonPayload(), builder);
testMessage = builder.build();
@@ -83,8 +256,10 @@ class ConformanceJava {
case UNSPECIFIED:
throw new RuntimeException("Unspecified output format.");
- case PROTOBUF:
- return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+ case PROTOBUF: {
+ ByteString MessageString = testMessage.toByteString();
+ return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build();
+ }
case JSON:
try {
@@ -127,7 +302,7 @@ class ConformanceJava {
public void run() throws Exception {
typeRegistry = TypeRegistry.newBuilder().add(
- Conformance.TestAllTypes.getDescriptor()).build();
+ TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build();
while (doTestIo()) {
this.testCount++;
}
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 28ac3c8a..765f3588 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -1,7 +1,13 @@
## Process this file with automake to produce Makefile.in
conformance_protoc_inputs = \
- conformance.proto
+ conformance.proto \
+ $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto
+
+# proto2 input files, should be separated with proto3, as we
+# can't generate proto2 files for ruby, php and objc
+conformance_proto2_protoc_inputs = \
+ $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto
well_known_type_protoc_inputs = \
$(top_srcdir)/src/google/protobuf/any.proto \
@@ -20,6 +26,7 @@ other_language_protoc_outputs = \
conformance_pb2.py \
Conformance.pbobjc.h \
Conformance.pbobjc.m \
+ conformance_pb.js \
conformance_pb.rb \
com/google/protobuf/Any.java \
com/google/protobuf/AnyOrBuilder.java \
@@ -61,6 +68,8 @@ other_language_protoc_outputs = \
com/google/protobuf/Value.java \
com/google/protobuf/ValueOrBuilder.java \
com/google/protobuf/WrappersProto.java \
+ com/google/protobuf_test_messages/proto3/TestMessagesProto3.java \
+ com/google/protobuf_test_messages/proto2/TestMessagesProto2.java \
google/protobuf/any.pb.cc \
google/protobuf/any.pb.h \
google/protobuf/any.rb \
@@ -77,6 +86,17 @@ other_language_protoc_outputs = \
google/protobuf/struct.pb.h \
google/protobuf/struct.rb \
google/protobuf/struct_pb2.py \
+ google/protobuf/TestMessagesProto2.pbobjc.h \
+ google/protobuf/TestMessagesProto2.pbobjc.m \
+ google/protobuf/TestMessagesProto3.pbobjc.h \
+ google/protobuf/TestMessagesProto3.pbobjc.m \
+ google/protobuf/test_messages_proto3.pb.cc \
+ google/protobuf/test_messages_proto3.pb.h \
+ google/protobuf/test_messages_proto2.pb.cc \
+ google/protobuf/test_messages_proto2.pb.h \
+ google/protobuf/test_messages_proto3_pb.rb \
+ google/protobuf/test_messages_proto3_pb2.py \
+ google/protobuf/test_messages_proto2_pb2.py \
google/protobuf/timestamp.pb.cc \
google/protobuf/timestamp.pb.h \
google/protobuf/timestamp.rb \
@@ -84,7 +104,40 @@ other_language_protoc_outputs = \
google/protobuf/wrappers.pb.cc \
google/protobuf/wrappers.pb.h \
google/protobuf/wrappers.rb \
- google/protobuf/wrappers_pb2.py
+ google/protobuf/wrappers_pb2.py \
+ Conformance/ConformanceRequest.php \
+ Conformance/ConformanceResponse.php \
+ Conformance/WireFormat.php \
+ GPBMetadata/Conformance.php \
+ GPBMetadata/Google/Protobuf/Any.php \
+ GPBMetadata/Google/Protobuf/Duration.php \
+ GPBMetadata/Google/Protobuf/FieldMask.php \
+ GPBMetadata/Google/Protobuf/Struct.php \
+ GPBMetadata/Google/Protobuf/TestMessagesProto3.php \
+ GPBMetadata/Google/Protobuf/Timestamp.php \
+ GPBMetadata/Google/Protobuf/Wrappers.php \
+ Google/Protobuf/Any.php \
+ Google/Protobuf/BoolValue.php \
+ Google/Protobuf/BytesValue.php \
+ Google/Protobuf/DoubleValue.php \
+ Google/Protobuf/Duration.php \
+ Google/Protobuf/FieldMask.php \
+ Google/Protobuf/FloatValue.php \
+ Google/Protobuf/Int32Value.php \
+ Google/Protobuf/Int64Value.php \
+ Google/Protobuf/ListValue.php \
+ Google/Protobuf/NullValue.php \
+ Google/Protobuf/StringValue.php \
+ Google/Protobuf/Struct.php \
+ Google/Protobuf/Timestamp.php \
+ Google/Protobuf/UInt32Value.php \
+ Google/Protobuf/UInt64Value.php \
+ Google/Protobuf/Value.php \
+ Protobuf_test_messages/Proto3/ForeignEnum.php \
+ Protobuf_test_messages/Proto3/ForeignMessage.php \
+ Protobuf_test_messages/Proto3/TestAllTypes_NestedEnum.php \
+ Protobuf_test_messages/Proto3/TestAllTypes_NestedMessage.php \
+ Protobuf_test_messages/Proto3/TestAllTypes.php
# lite/com/google/protobuf/Any.java \
# lite/com/google/protobuf/AnyOrBuilder.java \
# lite/com/google/protobuf/AnyProto.java \
@@ -138,21 +191,25 @@ EXTRA_DIST = \
conformance.proto \
conformance_python.py \
conformance_ruby.rb \
+ conformance_php.php \
failure_list_cpp.txt \
failure_list_csharp.txt \
failure_list_java.txt \
+ failure_list_js.txt \
failure_list_objc.txt \
failure_list_python.txt \
failure_list_python_cpp.txt \
failure_list_python-post26.txt \
- failure_list_ruby.txt
+ failure_list_ruby.txt \
+ failure_list_php.txt \
+ failure_list_php_c.txt
conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la
conformance_test_runner_SOURCES = conformance_test.h conformance_test.cc \
conformance_test_runner.cc \
third_party/jsoncpp/json.h \
third_party/jsoncpp/jsoncpp.cpp
-nodist_conformance_test_runner_SOURCES = conformance.pb.cc
+nodist_conformance_test_runner_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)
conformance_test_runner_CXXFLAGS = -std=c++11
# Explicit deps beacuse BUILT_SOURCES are only done before a "make all/check"
@@ -162,7 +219,7 @@ conformance_test_runner-conformance_test_runner.$(OBJEXT): conformance.pb.h
conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la
conformance_cpp_SOURCES = conformance_cpp.cc
-nodist_conformance_cpp_SOURCES = conformance.pb.cc
+nodist_conformance_cpp_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
# so a direct "make test_cpp" could fail if parallel enough.
@@ -173,7 +230,7 @@ if OBJC_CONFORMANCE_TEST
bin_PROGRAMS += conformance-objc
conformance_objc_SOURCES = conformance_objc.m ../objectivec/GPBProtocolBuffers.m
-nodist_conformance_objc_SOURCES = Conformance.pbobjc.m
+nodist_conformance_objc_SOURCES = Conformance.pbobjc.m google/protobuf/TestMessagesProto2.pbobjc.m google/protobuf/TestMessagesProto3.pbobjc.m
# On travis, the build fails without the isysroot because whatever system
# headers are being found don't include generics support for
# NSArray/NSDictionary, the only guess is their image at one time had an odd
@@ -182,16 +239,24 @@ conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec -isysroot `xcrun --sdk ma
conformance_objc_LDFLAGS = -framework Foundation
# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
# so a direct "make test_objc" could fail if parallel enough.
-conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h
+conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h google/protobuf/TestMessagesProto2.pbobjc.h google/protobuf/TestMessagesProto3.pbobjc.h
endif
+# JavaScript well-known types are expected to be in a directory called
+# google-protobuf, because they are usually in the google-protobuf npm
+# package. But we want to use the sources from our tree, so we recreate
+# that directory structure here.
+google-protobuf:
+ mkdir google-protobuf
+
if USE_EXTERNAL_PROTOC
# Some implementations include pre-generated versions of well-known types.
-protoc_middleman: $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
- $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. $(conformance_protoc_inputs)
- $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. $(well_known_type_protoc_inputs)
+protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
+ $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs)
+ $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
+ $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs)
## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
touch protoc_middleman
@@ -200,9 +265,10 @@ else
# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
# relative to srcdir, which may not be the same as the current directory when
# building out-of-tree.
-protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
- oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd $(conformance_protoc_inputs) )
- oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd $(well_known_type_protoc_inputs) )
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
+ oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) )
+ oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
+ oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) )
## @mkdir -p lite
## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
touch protoc_middleman
@@ -215,13 +281,13 @@ $(other_language_protoc_outputs): protoc_middleman
BUILT_SOURCES = $(protoc_outputs) $(other_language_protoc_outputs)
-CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp $(other_language_protoc_outputs)
+CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp conformance-php conformance-php-c $(other_language_protoc_outputs)
MAINTAINERCLEANFILES = \
Makefile.in
javac_middleman: ConformanceJava.java protoc_middleman $(other_language_protoc_outputs)
- jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+ jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java com/google/protobuf_test_messages/proto3/TestMessagesProto3.java com/google/protobuf_test_messages/proto2/TestMessagesProto2.java
@touch javac_middleman
conformance-java: javac_middleman
@@ -249,33 +315,57 @@ conformance-csharp: $(other_language_protoc_outputs)
@echo 'dotnet ../csharp/src/Google.Protobuf.Conformance/bin/Release/netcoreapp1.0/Google.Protobuf.Conformance.dll "$$@"' >> conformance-csharp
@chmod +x conformance-csharp
+conformance-php:
+ @echo "Writing shortcut script conformance-php..."
+ @echo '#! /bin/sh' > conformance-php
+ @echo 'php -d auto_prepend_file=autoload.php ./conformance_php.php' >> conformance-php
+ @chmod +x conformance-php
+
+conformance-php-c:
+ @echo "Writing shortcut script conformance-php-c..."
+ @echo '#! /bin/sh' > conformance-php-c
+ @echo 'php -dextension=../php/ext/google/protobuf/modules/protobuf.so ./conformance_php.php' >> conformance-php-c
+ @chmod +x conformance-php-c
+
# Targets for actually running tests.
test_cpp: protoc_middleman conformance-test-runner conformance-cpp
- ./conformance-test-runner --failure_list failure_list_cpp.txt ./conformance-cpp
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt ./conformance-cpp
test_java: protoc_middleman conformance-test-runner conformance-java
- ./conformance-test-runner --failure_list failure_list_java.txt ./conformance-java
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt ./conformance-java
test_java_lite: protoc_middleman conformance-test-runner conformance-java-lite
- ./conformance-test-runner ./conformance-java-lite
+ ./conformance-test-runner --enforce_recommended ./conformance-java-lite
test_csharp: protoc_middleman conformance-test-runner conformance-csharp
- ./conformance-test-runner --failure_list failure_list_csharp.txt ./conformance-csharp
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_csharp.txt ./conformance-csharp
test_ruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
- RUBYLIB=../ruby/lib:. ./conformance-test-runner --failure_list failure_list_ruby.txt ./conformance_ruby.rb
+ RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_ruby.txt ./conformance_ruby.rb
+
+test_php: protoc_middleman conformance-test-runner conformance-php $(other_language_protoc_outputs)
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_php.txt ./conformance-php
+
+test_php_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c.txt ./conformance-php-c
+
+test_php_zts_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_php_zts_c.txt ./conformance-php-c
# These depend on library paths being properly set up. The easiest way to
# run them is to just use "tox" from the python dir.
test_python: protoc_middleman conformance-test-runner
- ./conformance-test-runner --failure_list failure_list_python.txt ./conformance_python.py
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt ./conformance_python.py
test_python_cpp: protoc_middleman conformance-test-runner
- ./conformance-test-runner --failure_list failure_list_python_cpp.txt ./conformance_python.py
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt ./conformance_python.py
+
+test_nodejs: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
+ NODE_PATH=../js:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_js.txt ./conformance_nodejs.js
if OBJC_CONFORMANCE_TEST
test_objc: protoc_middleman conformance-test-runner conformance-objc
- ./conformance-test-runner --failure_list failure_list_objc.txt ./conformance-objc
+ ./conformance-test-runner --enforce_recommended --failure_list failure_list_objc.txt ./conformance-objc
endif
diff --git a/conformance/README.md b/conformance/README.md
index 9388055f..971fe8f6 100644
--- a/conformance/README.md
+++ b/conformance/README.md
@@ -19,11 +19,39 @@ directory to build `protoc`, since all the tests depend on it.
$ make
-Then to run the tests against the C++ implementation, run:
+Running the tests for C++
+-------------------------
+
+To run the tests against the C++ implementation, run:
$ cd conformance && make test_cpp
-More tests and languages will be added soon!
+Running the tests for JavaScript (Node.js)
+------------------------------------------
+
+To run the JavaScript tests against Node.js, make sure you have "node"
+on your path and then run:
+
+ $ cd conformance && make test_nodejs
+
+Running the tests for Ruby (MRI)
+--------------------------------
+
+To run the Ruby tests against MRI, first build the C extension:
+
+ $ cd ruby && rake
+
+Then run the tests like so:
+
+ $ cd conformance && make test_ruby
+
+Running the tests for other languages
+-------------------------------------
+
+Most of the languages in the Protobuf source tree are set up to run
+conformance tests. However some of them are more tricky to set up
+properly. See `tests.sh` in the base of the repository to see how
+Travis runs the tests.
Testing other Protocol Buffer implementations
---------------------------------------------
diff --git a/conformance/autoload.php b/conformance/autoload.php
new file mode 100644
index 00000000..0f49aecb
--- /dev/null
+++ b/conformance/autoload.php
@@ -0,0 +1,21 @@
+<?php
+
+define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\");
+define("GOOGLE_NAMESPACE", "Google\\Protobuf\\");
+define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\");
+
+function protobuf_autoloader_impl($class, $prefix) {
+ $length = strlen($prefix);
+ if ((substr($class, 0, $length) === $prefix)) {
+ $path = '../php/src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php';
+ include_once $path;
+ }
+}
+
+function protobuf_autoloader($class) {
+ protobuf_autoloader_impl($class, GOOGLE_INTERNAL_NAMESPACE);
+ protobuf_autoloader_impl($class, GOOGLE_NAMESPACE);
+ protobuf_autoloader_impl($class, GOOGLE_GPBMETADATA_NAMESPACE);
+}
+
+spl_autoload_register('protobuf_autoloader');
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 95a8fd13..525140e9 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -32,13 +32,6 @@ syntax = "proto3";
package conformance;
option java_package = "com.google.protobuf.conformance";
-import "google/protobuf/any.proto";
-import "google/protobuf/duration.proto";
-import "google/protobuf/field_mask.proto";
-import "google/protobuf/struct.proto";
-import "google/protobuf/timestamp.proto";
-import "google/protobuf/wrappers.proto";
-
// This defines the conformance testing protocol. This protocol exists between
// the conformance test suite itself and the code being tested. For each test,
// the suite will send a ConformanceRequest message and expect a
@@ -70,8 +63,13 @@ enum WireFormat {
// 2. parse the protobuf or JSON payload in "payload" (which may fail)
// 3. if the parse succeeded, serialize the message in the requested format.
message ConformanceRequest {
- // The payload (whether protobuf of JSON) is always for a TestAllTypes proto
- // (see below).
+ // The payload (whether protobuf of JSON) is always for a
+ // protobuf_test_messages.proto3.TestAllTypes proto (as defined in
+ // src/google/protobuf/proto3_test_messages.proto).
+ //
+ // TODO(haberman): if/when we expand the conformance tests to support proto2,
+ // we will want to include a field that lets the payload/response be a
+ // protobuf_test_messages.proto2.TestAllTypes message instead.
oneof payload {
bytes protobuf_payload = 1;
string json_payload = 2;
@@ -79,6 +77,11 @@ message ConformanceRequest {
// Which format should the testee serialize its message to?
WireFormat requested_output_format = 3;
+
+ // The full name for the test message to use; for the moment, either:
+ // protobuf_test_messages.proto3.TestAllTypesProto3 or
+ // protobuf_test_messages.proto2.TestAllTypesProto2.
+ string message_type = 4;
}
// Represents a single test case's output.
@@ -114,172 +117,3 @@ message ConformanceResponse {
string skipped = 5;
}
}
-
-// This proto includes every type of field in both singular and repeated
-// forms.
-message TestAllTypes {
- message NestedMessage {
- int32 a = 1;
- TestAllTypes corecursive = 2;
- }
-
- enum NestedEnum {
- FOO = 0;
- BAR = 1;
- BAZ = 2;
- NEG = -1; // Intentionally negative.
- }
-
- // Singular
- int32 optional_int32 = 1;
- int64 optional_int64 = 2;
- uint32 optional_uint32 = 3;
- uint64 optional_uint64 = 4;
- sint32 optional_sint32 = 5;
- sint64 optional_sint64 = 6;
- fixed32 optional_fixed32 = 7;
- fixed64 optional_fixed64 = 8;
- sfixed32 optional_sfixed32 = 9;
- sfixed64 optional_sfixed64 = 10;
- float optional_float = 11;
- double optional_double = 12;
- bool optional_bool = 13;
- string optional_string = 14;
- bytes optional_bytes = 15;
-
- NestedMessage optional_nested_message = 18;
- ForeignMessage optional_foreign_message = 19;
-
- NestedEnum optional_nested_enum = 21;
- ForeignEnum optional_foreign_enum = 22;
-
- string optional_string_piece = 24 [ctype=STRING_PIECE];
- string optional_cord = 25 [ctype=CORD];
-
- TestAllTypes recursive_message = 27;
-
- // Repeated
- repeated int32 repeated_int32 = 31;
- repeated int64 repeated_int64 = 32;
- repeated uint32 repeated_uint32 = 33;
- repeated uint64 repeated_uint64 = 34;
- repeated sint32 repeated_sint32 = 35;
- repeated sint64 repeated_sint64 = 36;
- repeated fixed32 repeated_fixed32 = 37;
- repeated fixed64 repeated_fixed64 = 38;
- repeated sfixed32 repeated_sfixed32 = 39;
- repeated sfixed64 repeated_sfixed64 = 40;
- repeated float repeated_float = 41;
- repeated double repeated_double = 42;
- repeated bool repeated_bool = 43;
- repeated string repeated_string = 44;
- repeated bytes repeated_bytes = 45;
-
- repeated NestedMessage repeated_nested_message = 48;
- repeated ForeignMessage repeated_foreign_message = 49;
-
- repeated NestedEnum repeated_nested_enum = 51;
- repeated ForeignEnum repeated_foreign_enum = 52;
-
- repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
- repeated string repeated_cord = 55 [ctype=CORD];
-
- // Map
- map < int32, int32> map_int32_int32 = 56;
- map < int64, int64> map_int64_int64 = 57;
- map < uint32, uint32> map_uint32_uint32 = 58;
- map < uint64, uint64> map_uint64_uint64 = 59;
- map < sint32, sint32> map_sint32_sint32 = 60;
- map < sint64, sint64> map_sint64_sint64 = 61;
- map < fixed32, fixed32> map_fixed32_fixed32 = 62;
- map < fixed64, fixed64> map_fixed64_fixed64 = 63;
- map <sfixed32, sfixed32> map_sfixed32_sfixed32 = 64;
- map <sfixed64, sfixed64> map_sfixed64_sfixed64 = 65;
- map < int32, float> map_int32_float = 66;
- map < int32, double> map_int32_double = 67;
- map < bool, bool> map_bool_bool = 68;
- map < string, string> map_string_string = 69;
- map < string, bytes> map_string_bytes = 70;
- map < string, NestedMessage> map_string_nested_message = 71;
- map < string, ForeignMessage> map_string_foreign_message = 72;
- map < string, NestedEnum> map_string_nested_enum = 73;
- map < string, ForeignEnum> map_string_foreign_enum = 74;
-
- oneof oneof_field {
- uint32 oneof_uint32 = 111;
- NestedMessage oneof_nested_message = 112;
- string oneof_string = 113;
- bytes oneof_bytes = 114;
- bool oneof_bool = 115;
- uint64 oneof_uint64 = 116;
- float oneof_float = 117;
- double oneof_double = 118;
- NestedEnum oneof_enum = 119;
- }
-
- // Well-known types
- google.protobuf.BoolValue optional_bool_wrapper = 201;
- google.protobuf.Int32Value optional_int32_wrapper = 202;
- google.protobuf.Int64Value optional_int64_wrapper = 203;
- google.protobuf.UInt32Value optional_uint32_wrapper = 204;
- google.protobuf.UInt64Value optional_uint64_wrapper = 205;
- google.protobuf.FloatValue optional_float_wrapper = 206;
- google.protobuf.DoubleValue optional_double_wrapper = 207;
- google.protobuf.StringValue optional_string_wrapper = 208;
- google.protobuf.BytesValue optional_bytes_wrapper = 209;
-
- repeated google.protobuf.BoolValue repeated_bool_wrapper = 211;
- repeated google.protobuf.Int32Value repeated_int32_wrapper = 212;
- repeated google.protobuf.Int64Value repeated_int64_wrapper = 213;
- repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214;
- repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215;
- repeated google.protobuf.FloatValue repeated_float_wrapper = 216;
- repeated google.protobuf.DoubleValue repeated_double_wrapper = 217;
- repeated google.protobuf.StringValue repeated_string_wrapper = 218;
- repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219;
-
- google.protobuf.Duration optional_duration = 301;
- google.protobuf.Timestamp optional_timestamp = 302;
- google.protobuf.FieldMask optional_field_mask = 303;
- google.protobuf.Struct optional_struct = 304;
- google.protobuf.Any optional_any = 305;
- google.protobuf.Value optional_value = 306;
-
- repeated google.protobuf.Duration repeated_duration = 311;
- repeated google.protobuf.Timestamp repeated_timestamp = 312;
- repeated google.protobuf.FieldMask repeated_fieldmask = 313;
- repeated google.protobuf.Struct repeated_struct = 324;
- repeated google.protobuf.Any repeated_any = 315;
- repeated google.protobuf.Value repeated_value = 316;
-
- // Test field-name-to-JSON-name convention.
- // (protobuf says names can be any valid C/C++ identifier.)
- int32 fieldname1 = 401;
- int32 field_name2 = 402;
- int32 _field_name3 = 403;
- int32 field__name4_ = 404;
- int32 field0name5 = 405;
- int32 field_0_name6 = 406;
- int32 fieldName7 = 407;
- int32 FieldName8 = 408;
- int32 field_Name9 = 409;
- int32 Field_Name10 = 410;
- int32 FIELD_NAME11 = 411;
- int32 FIELD_name12 = 412;
- int32 __field_name13 = 413;
- int32 __Field_name14 = 414;
- int32 field__name15 = 415;
- int32 field__Name16 = 416;
- int32 field_name17__ = 417;
- int32 Field_name18__ = 418;
-}
-
-message ForeignMessage {
- int32 c = 1;
-}
-
-enum ForeignEnum {
- FOREIGN_FOO = 0;
- FOREIGN_BAR = 1;
- FOREIGN_BAZ = 2;
-}
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index 1a265493..97ae1a7a 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -33,20 +33,25 @@
#include <unistd.h>
#include "conformance.pb.h"
+#include <google/protobuf/test_messages_proto3.pb.h>
+#include <google/protobuf/test_messages_proto2.pb.h>
+#include <google/protobuf/message.h>
#include <google/protobuf/util/json_util.h>
#include <google/protobuf/util/type_resolver_util.h>
using conformance::ConformanceRequest;
using conformance::ConformanceResponse;
-using conformance::TestAllTypes;
using google::protobuf::Descriptor;
using google::protobuf::DescriptorPool;
-using google::protobuf::internal::scoped_ptr;
+using google::protobuf::Message;
+using google::protobuf::MessageFactory;
using google::protobuf::util::BinaryToJsonString;
using google::protobuf::util::JsonToBinaryString;
using google::protobuf::util::NewTypeResolverForDescriptorPool;
using google::protobuf::util::Status;
using google::protobuf::util::TypeResolver;
+using protobuf_test_messages::proto3::TestAllTypesProto3;
+using protobuf_test_messages::proto2::TestAllTypesProto2;
using std::string;
static const char kTypeUrlPrefix[] = "type.googleapis.com";
@@ -86,17 +91,24 @@ void CheckedWrite(int fd, const void *buf, size_t len) {
}
void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
- TestAllTypes test_message;
+ Message *test_message;
+ const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(
+ request.message_type());
+ if (!descriptor) {
+ GOOGLE_LOG(FATAL) << "No such message type: " << request.message_type();
+ }
+ test_message = MessageFactory::generated_factory()->GetPrototype(descriptor)->New();
switch (request.payload_case()) {
- case ConformanceRequest::kProtobufPayload:
- if (!test_message.ParseFromString(request.protobuf_payload())) {
+ case ConformanceRequest::kProtobufPayload: {
+ if (!test_message->ParseFromString(request.protobuf_payload())) {
// Getting parse details would involve something like:
// http://stackoverflow.com/questions/22121922/how-can-i-get-more-details-about-errors-generated-during-protobuf-parsing-c
response->set_parse_error("Parse error (no more details available).");
return;
}
break;
+ }
case ConformanceRequest::kJsonPayload: {
string proto_binary;
@@ -108,7 +120,7 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
return;
}
- if (!test_message.ParseFromString(proto_binary)) {
+ if (!test_message->ParseFromString(proto_binary)) {
response->set_runtime_error(
"Parsing JSON generates invalid proto output.");
return;
@@ -126,14 +138,14 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
GOOGLE_LOG(FATAL) << "Unspecified output format";
break;
- case conformance::PROTOBUF:
- GOOGLE_CHECK(
- test_message.SerializeToString(response->mutable_protobuf_payload()));
+ case conformance::PROTOBUF: {
+ GOOGLE_CHECK(test_message->SerializeToString(response->mutable_protobuf_payload()));
break;
+ }
case conformance::JSON: {
string proto_binary;
- GOOGLE_CHECK(test_message.SerializeToString(&proto_binary));
+ GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
response->mutable_json_payload());
if (!status.ok()) {
@@ -196,7 +208,7 @@ bool DoTestIo() {
int main() {
type_resolver = NewTypeResolverForDescriptorPool(
kTypeUrlPrefix, DescriptorPool::generated_pool());
- type_url = new string(GetTypeUrl(TestAllTypes::descriptor()));
+ type_url = new string(GetTypeUrl(TestAllTypesProto3::descriptor()));
while (1) {
if (!DoTestIo()) {
fprintf(stderr, "conformance-cpp: received EOF from test runner "
diff --git a/conformance/conformance_nodejs.js b/conformance/conformance_nodejs.js
new file mode 100755
index 00000000..5d3955f7
--- /dev/null
+++ b/conformance/conformance_nodejs.js
@@ -0,0 +1,182 @@
+#!/usr/bin/env node
+
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2008 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var conformance = require('conformance_pb');
+var test_messages_proto3 = require('google/protobuf/test_messages_proto3_pb');
+var test_messages_proto2 = require('google/protobuf/test_messages_proto2_pb');
+var fs = require('fs');
+
+var testCount = 0;
+
+function doTest(request) {
+ var testMessage;
+ var response = new conformance.ConformanceResponse();
+
+ try {
+ if (request.getRequestedOutputFormat() === conformance.WireFormat.JSON) {
+ response.setSkipped("JSON not supported.");
+ return response;
+ }
+
+ switch (request.getPayloadCase()) {
+ case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD: {
+ if (request.getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
+ try {
+ testMessage = test_messages_proto3.TestAllTypesProto3.deserializeBinary(
+ request.getProtobufPayload());
+ } catch (err) {
+ response.setParseError(err.toString());
+ return response;
+ }
+ } else if (request.getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2"){
+ try {
+ testMessage = test_messages_proto2.TestAllTypesProto2.deserializeBinary(
+ request.getProtobufPayload());
+ } catch (err) {
+ response.setParseError(err.toString());
+ return response;
+ }
+ } else {
+ throw "Protobuf request doesn\'t have specific payload type";
+ }
+ }
+
+ case conformance.ConformanceRequest.PayloadCase.JSON_PAYLOAD:
+ response.setSkipped("JSON not supported.");
+ return response;
+
+ case conformance.ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET:
+ response.setRuntimeError("Request didn't have payload");
+ return response;
+ }
+
+ switch (request.getRequestedOutputFormat()) {
+ case conformance.WireFormat.UNSPECIFIED:
+ response.setRuntimeError("Unspecified output format");
+ return response;
+
+ case conformance.WireFormat.PROTOBUF:
+ response.setProtobufPayload(testMessage.serializeBinary());
+
+ case conformance.WireFormat.JSON:
+ response.setSkipped("JSON not supported.");
+ return response;
+
+ default:
+ throw "Request didn't have requested output format";
+ }
+ } catch (err) {
+ response.setRuntimeError(err.toString());
+ }
+
+ return response;
+}
+
+function onEof(totalRead) {
+ if (totalRead == 0) {
+ return undefined;
+ } else {
+ throw "conformance_nodejs: premature EOF on stdin.";
+ }
+}
+
+// Utility function to read a buffer of N bytes.
+function readBuffer(bytes) {
+ var buf = new Buffer(bytes);
+ var totalRead = 0;
+ while (totalRead < bytes) {
+ var read = 0;
+ try {
+ read = fs.readSync(process.stdin.fd, buf, totalRead, bytes - totalRead);
+ } catch (e) {
+ if (e.code == 'EOF') {
+ return onEof(totalRead)
+ } else if (e.code == 'EAGAIN') {
+ } else {
+ throw "conformance_nodejs: Error reading from stdin." + e;
+ }
+ }
+
+ totalRead += read;
+ }
+
+ return buf;
+}
+
+function writeBuffer(buffer) {
+ var totalWritten = 0;
+ while (totalWritten < buffer.length) {
+ totalWritten += fs.writeSync(
+ process.stdout.fd, buffer, totalWritten, buffer.length - totalWritten);
+ }
+}
+
+// Returns true if the test ran successfully, false on legitimate EOF.
+// If EOF is encountered in an unexpected place, raises IOError.
+function doTestIo() {
+ var lengthBuf = readBuffer(4);
+ if (!lengthBuf) {
+ return false;
+ }
+
+ var length = lengthBuf.readInt32LE(0);
+ var serializedRequest = readBuffer(length);
+ if (!serializedRequest) {
+ throw "conformance_nodejs: Failed to read request.";
+ }
+
+ serializedRequest = new Uint8Array(serializedRequest);
+ var request =
+ conformance.ConformanceRequest.deserializeBinary(serializedRequest);
+ var response = doTest(request);
+
+ var serializedResponse = response.serializeBinary();
+
+ lengthBuf = new Buffer(4);
+ lengthBuf.writeInt32LE(serializedResponse.length, 0);
+ writeBuffer(lengthBuf);
+ writeBuffer(new Buffer(serializedResponse));
+
+ testCount += 1
+
+ return true;
+}
+
+while (true) {
+ if (!doTestIo()) {
+ console.error('conformance_nodejs: received EOF from test runner ' +
+ "after " + testCount + " tests, exiting")
+ break;
+ }
+}
diff --git a/conformance/conformance_objc.m b/conformance/conformance_objc.m
index 1124bfeb..84a43811 100644
--- a/conformance/conformance_objc.m
+++ b/conformance/conformance_objc.m
@@ -31,6 +31,8 @@
#import <Foundation/Foundation.h>
#import "Conformance.pbobjc.h"
+#import "google/protobuf/TestMessagesProto2.pbobjc.h"
+#import "google/protobuf/TestMessagesProto3.pbobjc.h"
static void Die(NSString *format, ...) __dead2;
@@ -62,7 +64,7 @@ static NSData *CheckedReadDataOfLength(NSFileHandle *handle, NSUInteger numBytes
static ConformanceResponse *DoTest(ConformanceRequest *request) {
ConformanceResponse *response = [ConformanceResponse message];
- TestAllTypes *testMessage = nil;
+ GPBMessage *testMessage = nil;
switch (request.payloadOneOfCase) {
case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase:
@@ -70,9 +72,16 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
break;
case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
+ Class msgClass = nil;
+ if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) {
+ msgClass = [Proto3TestAllTypesProto3 class];
+ } else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
+ msgClass = [TestAllTypesProto2 class];
+ } else {
+ Die(@"Protobuf request had an unknown message_type: %@", request.messageType);
+ }
NSError *error = nil;
- testMessage = [TestAllTypes parseFromData:request.protobufPayload
- error:&error];
+ testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
if (!testMessage) {
response.parseError =
[NSString stringWithFormat:@"Parse error: %@", error];
diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php
new file mode 100755
index 00000000..19f9a092
--- /dev/null
+++ b/conformance/conformance_php.php
@@ -0,0 +1,105 @@
+<?php
+
+require_once("Conformance/WireFormat.php");
+require_once("Conformance/ConformanceResponse.php");
+require_once("Conformance/ConformanceRequest.php");
+require_once("Protobuf_test_messages/Proto3/ForeignMessage.php");
+require_once("Protobuf_test_messages/Proto3/ForeignEnum.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php");
+
+require_once("GPBMetadata/Conformance.php");
+require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php");
+
+use \Conformance\WireFormat;
+
+if (!ini_get("date.timezone")) {
+ ini_set("date.timezone", "UTC");
+}
+
+$test_count = 0;
+
+function doTest($request)
+{
+ $test_message = new \Protobuf_test_messages\Proto3\TestAllTypesProto3();
+ $response = new \Conformance\ConformanceResponse();
+ if ($request->getPayload() == "protobuf_payload") {
+ if ($request->getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
+ try {
+ $test_message->mergeFromString($request->getProtobufPayload());
+ } catch (Exception $e) {
+ $response->setParseError($e->getMessage());
+ return $response;
+ }
+ } elseif ($request->getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2") {
+ $response->setSkipped("PHP doesn't support proto2");
+ return $response;
+ } else {
+ trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR);
+ }
+ } elseif ($request->getPayload() == "json_payload") {
+ try {
+ $test_message->mergeFromJsonString($request->getJsonPayload());
+ } catch (Exception $e) {
+ $response->setParseError($e->getMessage());
+ return $response;
+ }
+ } else {
+ trigger_error("Request didn't have payload.", E_USER_ERROR);
+ }
+
+ if ($request->getRequestedOutputFormat() == WireFormat::UNSPECIFIED) {
+ trigger_error("Unspecified output format.", E_USER_ERROR);
+ } elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) {
+ $response->setProtobufPayload($test_message->serializeToString());
+ } elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) {
+ try {
+ $response->setJsonPayload($test_message->serializeToJsonString());
+ } catch (Exception $e) {
+ $response->setSerializeError($e->getMessage());
+ return $response;
+ }
+ }
+
+ return $response;
+}
+
+function doTestIO()
+{
+ $length_bytes = fread(STDIN, 4);
+ if (strlen($length_bytes) == 0) {
+ return false; # EOF
+ } elseif (strlen($length_bytes) != 4) {
+ fwrite(STDERR, "I/O error\n");
+ return false;
+ }
+
+ $length = unpack("V", $length_bytes)[1];
+ $serialized_request = fread(STDIN, $length);
+ if (strlen($serialized_request) != $length) {
+ trigger_error("I/O error", E_USER_ERROR);
+ }
+
+ $request = new \Conformance\ConformanceRequest();
+ $request->mergeFromString($serialized_request);
+
+ $response = doTest($request);
+
+ $serialized_response = $response->serializeToString();
+ fwrite(STDOUT, pack("V", strlen($serialized_response)));
+ fwrite(STDOUT, $serialized_response);
+
+ $GLOBALS['test_count'] += 1;
+
+ return true;
+}
+
+while(true){
+ if (!doTestIO()) {
+ fprintf(STDERR,
+ "conformance_php: received EOF from test runner " +
+ "after %d tests, exiting\n", $test_count);
+ exit;
+ }
+}
diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py
index a490c8e8..c5ba2467 100755
--- a/conformance/conformance_python.py
+++ b/conformance/conformance_python.py
@@ -38,8 +38,12 @@ See conformance.proto for more information.
import struct
import sys
import os
-from google.protobuf import message
+from google.protobuf import descriptor
+from google.protobuf import descriptor_pool
from google.protobuf import json_format
+from google.protobuf import message
+from google.protobuf import test_messages_proto3_pb2
+from google.protobuf import test_messages_proto2_pb2
import conformance_pb2
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
@@ -52,9 +56,17 @@ class ProtocolError(Exception):
pass
def do_test(request):
- test_message = conformance_pb2.TestAllTypes()
+ isProto3 = (request.message_type == "protobuf_test_messages.proto3.TestAllTypesProto3")
+ isJson = (request.WhichOneof('payload') == 'json_payload')
+ isProto2 = (request.message_type == "protobuf_test_messages.proto2.TestAllTypesProto2")
+
+ if (not isProto3) and (not isJson) and (not isProto2):
+ raise ProtocolError("Protobuf request doesn't have specific payload type")
+
+ test_message = test_messages_proto2_pb2.TestAllTypesProto2() if isProto2 else \
+ test_messages_proto3_pb2.TestAllTypesProto3()
+
response = conformance_pb2.ConformanceResponse()
- test_message = conformance_pb2.TestAllTypes()
try:
if request.WhichOneof('payload') == 'protobuf_payload':
@@ -62,12 +74,12 @@ def do_test(request):
test_message.ParseFromString(request.protobuf_payload)
except message.DecodeError as e:
response.parse_error = str(e)
- return response
-
+ return response
+
elif request.WhichOneof('payload') == 'json_payload':
try:
json_format.Parse(request.json_payload, test_message)
- except json_format.ParseError as e:
+ except Exception as e:
response.parse_error = str(e)
return response
@@ -81,7 +93,11 @@ def do_test(request):
response.protobuf_payload = test_message.SerializeToString()
elif request.requested_output_format == conformance_pb2.JSON:
- response.json_payload = json_format.MessageToJson(test_message)
+ try:
+ response.json_payload = json_format.MessageToJson(test_message)
+ except Exception as e:
+ response.serialize_error = str(e)
+ return response
except Exception as e:
response.runtime_error = str(e)
diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb
index aa572144..df63bf7c 100755
--- a/conformance/conformance_ruby.rb
+++ b/conformance/conformance_ruby.rb
@@ -31,28 +31,37 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'conformance_pb'
+require 'google/protobuf/test_messages_proto3_pb'
$test_count = 0
$verbose = false
def do_test(request)
- test_message = Conformance::TestAllTypes.new
+ test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new
response = Conformance::ConformanceResponse.new
begin
case request.payload
when :protobuf_payload
- begin
- test_message =
- Conformance::TestAllTypes.decode(request.protobuf_payload)
- rescue Google::Protobuf::ParseError => err
- response.parse_error = err.message.encode('utf-8')
+ if request.message_type.eql?('protobuf_test_messages.proto3.TestAllTypesProto3')
+ begin
+ test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode(
+ request.protobuf_payload)
+ rescue Google::Protobuf::ParseError => err
+ response.parse_error = err.message.encode('utf-8')
+ return response
+ end
+ elsif request.message_type.eql?('protobuf_test_messages.proto2.TestAllTypesProto2')
+ response.skipped = "Ruby doesn't support proto2"
return response
+ else
+ fail "Protobuf request doesn't have specific payload type"
end
when :json_payload
begin
- test_message = Conformance::TestAllTypes.decode_json(request.json_payload)
+ test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode_json(
+ request.json_payload)
rescue Google::Protobuf::ParseError => err
response.parse_error = err.message.encode('utf-8')
return response
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index fb963f68..22bbbfb3 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -34,11 +34,14 @@
#include "conformance.pb.h"
#include "conformance_test.h"
+#include <google/protobuf/test_messages_proto3.pb.h>
+#include <google/protobuf/test_messages_proto2.pb.h>
+
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/text_format.h>
-#include <google/protobuf/util/json_util.h>
#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/util/json_util.h>
#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/util/type_resolver_util.h>
#include <google/protobuf/wire_format_lite.h>
@@ -47,7 +50,6 @@
using conformance::ConformanceRequest;
using conformance::ConformanceResponse;
-using conformance::TestAllTypes;
using conformance::WireFormat;
using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor;
@@ -58,6 +60,8 @@ using google::protobuf::util::JsonToBinaryString;
using google::protobuf::util::MessageDifferencer;
using google::protobuf::util::NewTypeResolverForDescriptorPool;
using google::protobuf::util::Status;
+using protobuf_test_messages::proto3::TestAllTypesProto3;
+using protobuf_test_messages::proto2::TestAllTypesProto2;
using std::string;
namespace {
@@ -107,13 +111,18 @@ string cat(const string& a, const string& b,
// The maximum number of bytes that it takes to encode a 64-bit varint.
#define VARINT_MAX_LEN 10
-size_t vencode64(uint64_t val, char *buf) {
+size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) {
if (val == 0) { buf[0] = 0; return 1; }
size_t i = 0;
while (val) {
uint8_t byte = val & 0x7fU;
val >>= 7;
- if (val) byte |= 0x80U;
+ if (val || over_encoded_bytes) byte |= 0x80U;
+ buf[i++] = byte;
+ }
+ while (over_encoded_bytes--) {
+ assert(i < 10);
+ uint8_t byte = over_encoded_bytes ? 0x80 : 0;
buf[i++] = byte;
}
return i;
@@ -121,7 +130,15 @@ size_t vencode64(uint64_t val, char *buf) {
string varint(uint64_t x) {
char buf[VARINT_MAX_LEN];
- size_t len = vencode64(x, buf);
+ size_t len = vencode64(x, 0, buf);
+ return string(buf, len);
+}
+
+// Encodes a varint that is |extra| bytes longer than it needs to be, but still
+// valid.
+string longvarint(uint64_t x, int extra) {
+ char buf[VARINT_MAX_LEN];
+ size_t len = vencode64(x, extra, buf);
return string(buf, len);
}
@@ -130,8 +147,8 @@ string fixed32(void *data) { return string(static_cast<char*>(data), 4); }
string fixed64(void *data) { return string(static_cast<char*>(data), 8); }
string delim(const string& buf) { return cat(varint(buf.size()), buf); }
-string uint32(uint32_t u32) { return fixed32(&u32); }
-string uint64(uint64_t u64) { return fixed64(&u64); }
+string u32(uint32_t u32) { return fixed32(&u32); }
+string u64(uint64_t u64) { return fixed64(&u64); }
string flt(float f) { return fixed32(&f); }
string dbl(double d) { return fixed64(&d); }
string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); }
@@ -147,16 +164,19 @@ string submsg(uint32_t fn, const string& buf) {
#define UNKNOWN_FIELD 666
-uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) {
- const Descriptor* d = TestAllTypes().GetDescriptor();
+const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
+ bool repeated, bool isProto3) {
+
+ const Descriptor* d = isProto3 ?
+ TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor();
for (int i = 0; i < d->field_count(); i++) {
const FieldDescriptor* f = d->field(i);
if (f->type() == type && f->is_repeated() == repeated) {
- return f->number();
+ return f;
}
}
GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type;
- return 0;
+ return nullptr;
}
string UpperCase(string str) {
@@ -183,6 +203,7 @@ void ConformanceTestSuite::ReportSuccess(const string& test_name) {
}
void ConformanceTestSuite::ReportFailure(const string& test_name,
+ ConformanceLevel level,
const ConformanceRequest& request,
const ConformanceResponse& response,
const char* fmt, ...) {
@@ -190,6 +211,8 @@ void ConformanceTestSuite::ReportFailure(const string& test_name,
expected_failures_++;
if (!verbose_)
return;
+ } else if (level == RECOMMENDED && !enforce_recommended_) {
+ StringAppendF(&output_, "WARNING, test=%s: ", test_name.c_str());
} else {
StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
unexpected_failing_tests_.insert(test_name);
@@ -214,6 +237,15 @@ void ConformanceTestSuite::ReportSkip(const string& test_name,
skipped_.insert(test_name);
}
+string ConformanceTestSuite::ConformanceLevelToString(ConformanceLevel level) {
+ switch (level) {
+ case REQUIRED: return "Required";
+ case RECOMMENDED: return "Recommended";
+ }
+ GOOGLE_LOG(FATAL) << "Unknown value: " << level;
+ return "";
+}
+
void ConformanceTestSuite::RunTest(const string& test_name,
const ConformanceRequest& request,
ConformanceResponse* response) {
@@ -241,25 +273,65 @@ void ConformanceTestSuite::RunTest(const string& test_name,
}
void ConformanceTestSuite::RunValidInputTest(
- const string& test_name, const string& input, WireFormat input_format,
- const string& equivalent_text_format, WireFormat requested_output) {
- TestAllTypes reference_message;
+ const string& test_name, ConformanceLevel level, const string& input,
+ WireFormat input_format, const string& equivalent_text_format,
+ WireFormat requested_output, bool isProto3) {
+ auto newTestMessage = [&isProto3]() {
+ Message* newMessage;
+ if (isProto3) {
+ newMessage = new TestAllTypesProto3;
+ } else {
+ newMessage = new TestAllTypesProto2;
+ }
+ return newMessage;
+ };
+ Message* reference_message = newTestMessage();
GOOGLE_CHECK(
- TextFormat::ParseFromString(equivalent_text_format, &reference_message))
+ TextFormat::ParseFromString(equivalent_text_format, reference_message))
<< "Failed to parse data for test case: " << test_name
<< ", data: " << equivalent_text_format;
+ const string equivalent_wire_format = reference_message->SerializeAsString();
+ RunValidBinaryInputTest(test_name, level, input, input_format,
+ equivalent_wire_format, requested_output, isProto3);
+}
+
+void ConformanceTestSuite::RunValidBinaryInputTest(
+ const string& test_name, ConformanceLevel level, const string& input,
+ WireFormat input_format, const string& equivalent_wire_format,
+ WireFormat requested_output, bool isProto3) {
+ auto newTestMessage = [&isProto3]() {
+ Message* newMessage;
+ if (isProto3) {
+ newMessage = new TestAllTypesProto3;
+ } else {
+ newMessage = new TestAllTypesProto2;
+ }
+ return newMessage;
+ };
+ Message* reference_message = newTestMessage();
+ GOOGLE_CHECK(
+ reference_message->ParseFromString(equivalent_wire_format))
+ << "Failed to parse wire data for test case: " << test_name;
ConformanceRequest request;
ConformanceResponse response;
switch (input_format) {
- case conformance::PROTOBUF:
+ case conformance::PROTOBUF: {
request.set_protobuf_payload(input);
+ if (isProto3) {
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+ } else {
+ request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2");
+ }
break;
+ }
- case conformance::JSON:
+ case conformance::JSON: {
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
request.set_json_payload(input);
break;
+ }
default:
GOOGLE_LOG(FATAL) << "Unspecified input format";
@@ -269,18 +341,18 @@ void ConformanceTestSuite::RunValidInputTest(
RunTest(test_name, request, &response);
- TestAllTypes test_message;
+ Message *test_message = newTestMessage();
switch (response.result_case()) {
case ConformanceResponse::RESULT_NOT_SET:
- ReportFailure(test_name, request, response,
+ ReportFailure(test_name, level, request, response,
"Response didn't have any field in the Response.");
return;
case ConformanceResponse::kParseError:
case ConformanceResponse::kRuntimeError:
case ConformanceResponse::kSerializeError:
- ReportFailure(test_name, request, response,
+ ReportFailure(test_name, level, request, response,
"Failed to parse input or produce output.");
return;
@@ -291,7 +363,7 @@ void ConformanceTestSuite::RunValidInputTest(
case ConformanceResponse::kJsonPayload: {
if (requested_output != conformance::JSON) {
ReportFailure(
- test_name, request, response,
+ test_name, level, request, response,
"Test was asked for protobuf output but provided JSON instead.");
return;
}
@@ -300,15 +372,15 @@ void ConformanceTestSuite::RunValidInputTest(
JsonToBinaryString(type_resolver_.get(), type_url_,
response.json_payload(), &binary_protobuf);
if (!status.ok()) {
- ReportFailure(test_name, request, response,
+ ReportFailure(test_name, level, request, response,
"JSON output we received from test was unparseable.");
return;
}
- if (!test_message.ParseFromString(binary_protobuf)) {
- ReportFailure(test_name, request, response,
- "INTERNAL ERROR: internal JSON->protobuf transcode "
- "yielded unparseable proto.");
+ if (!test_message->ParseFromString(binary_protobuf)) {
+ ReportFailure(test_name, level, request, response,
+ "INTERNAL ERROR: internal JSON->protobuf transcode "
+ "yielded unparseable proto.");
return;
}
@@ -318,14 +390,14 @@ void ConformanceTestSuite::RunValidInputTest(
case ConformanceResponse::kProtobufPayload: {
if (requested_output != conformance::PROTOBUF) {
ReportFailure(
- test_name, request, response,
+ test_name, level, request, response,
"Test was asked for JSON output but provided protobuf instead.");
return;
}
- if (!test_message.ParseFromString(response.protobuf_payload())) {
- ReportFailure(test_name, request, response,
- "Protobuf output we received from test was unparseable.");
+ if (!test_message->ParseFromString(response.protobuf_payload())) {
+ ReportFailure(test_name, level, request, response,
+ "Protobuf output we received from test was unparseable.");
return;
}
@@ -344,22 +416,30 @@ void ConformanceTestSuite::RunValidInputTest(
string differences;
differencer.ReportDifferencesToString(&differences);
- if (differencer.Compare(reference_message, test_message)) {
+ bool check;
+ check = differencer.Compare(*reference_message, *test_message);
+ if (check) {
ReportSuccess(test_name);
} else {
- ReportFailure(test_name, request, response,
+ ReportFailure(test_name, level, request, response,
"Output was not equivalent to reference message: %s.",
differences.c_str());
}
}
-
-// Expect that this precise protobuf will cause a parse error.
-void ConformanceTestSuite::ExpectParseFailureForProto(
- const string& proto, const string& test_name) {
+void ConformanceTestSuite::ExpectParseFailureForProtoWithProtoVersion (
+ const string& proto, const string& test_name, ConformanceLevel level,
+ bool isProto3) {
ConformanceRequest request;
ConformanceResponse response;
request.set_protobuf_payload(proto);
- string effective_test_name = "ProtobufInput." + test_name;
+ if (isProto3) {
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+ } else {
+ request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2");
+ }
+ string effective_test_name = ConformanceLevelToString(level) +
+ (isProto3 ? ".Proto3" : ".Proto2") +
+ ".ProtobufInput." + test_name;
// We don't expect output, but if the program erroneously accepts the protobuf
// we let it send its response as this. We must not leave it unspecified.
@@ -371,49 +451,87 @@ void ConformanceTestSuite::ExpectParseFailureForProto(
} else if (response.result_case() == ConformanceResponse::kSkipped) {
ReportSkip(effective_test_name, request, response);
} else {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"Should have failed to parse, but didn't.");
}
}
+// Expect that this precise protobuf will cause a parse error.
+void ConformanceTestSuite::ExpectParseFailureForProto(
+ const string& proto, const string& test_name, ConformanceLevel level) {
+ ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true);
+ ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false);
+}
+
// Expect that this protobuf will cause a parse error, even if it is followed
// by valid protobuf data. We can try running this twice: once with this
// data verbatim and once with this data followed by some valid data.
//
// TODO(haberman): implement the second of these.
void ConformanceTestSuite::ExpectHardParseFailureForProto(
- const string& proto, const string& test_name) {
- return ExpectParseFailureForProto(proto, test_name);
+ const string& proto, const string& test_name, ConformanceLevel level) {
+ return ExpectParseFailureForProto(proto, test_name, level);
}
void ConformanceTestSuite::RunValidJsonTest(
- const string& test_name, const string& input_json,
+ const string& test_name, ConformanceLevel level, const string& input_json,
const string& equivalent_text_format) {
- RunValidInputTest("JsonInput." + test_name + ".ProtobufOutput", input_json,
- conformance::JSON, equivalent_text_format,
- conformance::PROTOBUF);
- RunValidInputTest("JsonInput." + test_name + ".JsonOutput", input_json,
- conformance::JSON, equivalent_text_format,
- conformance::JSON);
+ RunValidInputTest(
+ ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name +
+ ".ProtobufOutput", level, input_json, conformance::JSON,
+ equivalent_text_format, conformance::PROTOBUF, true);
+ RunValidInputTest(
+ ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name +
+ ".JsonOutput", level, input_json, conformance::JSON,
+ equivalent_text_format, conformance::JSON, true);
}
void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
- const string& test_name, const TestAllTypes& input,
+ const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input,
const string& equivalent_text_format) {
- RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput",
- input.SerializeAsString(), conformance::PROTOBUF,
- equivalent_text_format, conformance::JSON);
+ RunValidInputTest(
+ ConformanceLevelToString(level) + ".Proto3" + ".ProtobufInput." + test_name +
+ ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF,
+ equivalent_text_format, conformance::JSON, true);
}
void ConformanceTestSuite::RunValidProtobufTest(
- const string& test_name, const TestAllTypes& input,
- const string& equivalent_text_format) {
- RunValidInputTest("ProtobufInput." + test_name + ".ProtobufOutput",
- input.SerializeAsString(), conformance::PROTOBUF,
- equivalent_text_format, conformance::PROTOBUF);
- RunValidInputTest("ProtobufInput." + test_name + ".JsonOutput",
- input.SerializeAsString(), conformance::PROTOBUF,
- equivalent_text_format, conformance::JSON);
+ const string& test_name, ConformanceLevel level,
+ const string& input_protobuf, const string& equivalent_text_format,
+ bool isProto3) {
+ string rname = ".Proto3";
+ if (!isProto3) {
+ rname = ".Proto2";
+ }
+ RunValidInputTest(
+ ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name +
+ ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF,
+ equivalent_text_format, conformance::PROTOBUF, isProto3);
+ if (isProto3) {
+ RunValidInputTest(
+ ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name +
+ ".JsonOutput", level, input_protobuf, conformance::PROTOBUF,
+ equivalent_text_format, conformance::JSON, isProto3);
+ }
+}
+
+void ConformanceTestSuite::RunValidBinaryProtobufTest(
+ const string& test_name, ConformanceLevel level,
+ const string& input_protobuf, bool isProto3) {
+ string rname = ".Proto3";
+ if (!isProto3) {
+ rname = ".Proto2";
+ }
+ RunValidBinaryInputTest(
+ ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name +
+ ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF,
+ input_protobuf, conformance::PROTOBUF, isProto3);
+}
+
+void ConformanceTestSuite::RunValidProtobufTestWithMessage(
+ const string& test_name, ConformanceLevel level, const Message *input,
+ const string& equivalent_text_format, bool isProto3) {
+ RunValidProtobufTest(test_name, level, input->SerializeAsString(), equivalent_text_format, isProto3);
}
// According to proto3 JSON specification, JSON serializers follow more strict
@@ -422,14 +540,16 @@ void ConformanceTestSuite::RunValidProtobufTest(
// method allows strict checking on a proto3 JSON serializer by inspecting
// the JSON output directly.
void ConformanceTestSuite::RunValidJsonTestWithValidator(
- const string& test_name, const string& input_json,
+ const string& test_name, ConformanceLevel level, const string& input_json,
const Validator& validator) {
ConformanceRequest request;
ConformanceResponse response;
request.set_json_payload(input_json);
request.set_requested_output_format(conformance::JSON);
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
- string effective_test_name = "JsonInput." + test_name + ".Validator";
+ string effective_test_name = ConformanceLevelToString(level) +
+ ".Proto3.JsonInput." + test_name + ".Validator";
RunTest(effective_test_name, request, &response);
@@ -439,7 +559,7 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
}
if (response.result_case() != ConformanceResponse::kJsonPayload) {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"Expected JSON payload but got type %d.",
response.result_case());
return;
@@ -447,13 +567,13 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
Json::Reader reader;
Json::Value value;
if (!reader.parse(response.json_payload(), value)) {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"JSON payload cannot be parsed as valid JSON: %s",
reader.getFormattedErrorMessages().c_str());
return;
}
if (!validator(value)) {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"JSON payload validation failed.");
return;
}
@@ -461,11 +581,13 @@ void ConformanceTestSuite::RunValidJsonTestWithValidator(
}
void ConformanceTestSuite::ExpectParseFailureForJson(
- const string& test_name, const string& input_json) {
+ const string& test_name, ConformanceLevel level, const string& input_json) {
ConformanceRequest request;
ConformanceResponse response;
request.set_json_payload(input_json);
- string effective_test_name = "JsonInput." + test_name;
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+ string effective_test_name =
+ ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name;
// We don't expect output, but if the program erroneously accepts the protobuf
// we let it send its response as this. We must not leave it unspecified.
@@ -477,14 +599,14 @@ void ConformanceTestSuite::ExpectParseFailureForJson(
} else if (response.result_case() == ConformanceResponse::kSkipped) {
ReportSkip(effective_test_name, request, response);
} else {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"Should have failed to parse, but didn't.");
}
}
void ConformanceTestSuite::ExpectSerializeFailureForJson(
- const string& test_name, const string& text_format) {
- TestAllTypes payload_message;
+ const string& test_name, ConformanceLevel level, const string& text_format) {
+ TestAllTypesProto3 payload_message;
GOOGLE_CHECK(
TextFormat::ParseFromString(text_format, &payload_message))
<< "Failed to parse: " << text_format;
@@ -492,7 +614,9 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson(
ConformanceRequest request;
ConformanceResponse response;
request.set_protobuf_payload(payload_message.SerializeAsString());
- string effective_test_name = test_name + ".JsonOutput";
+ request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+ string effective_test_name =
+ ConformanceLevelToString(level) + "." + test_name + ".JsonOutput";
request.set_requested_output_format(conformance::JSON);
RunTest(effective_test_name, request, &response);
@@ -501,11 +625,12 @@ void ConformanceTestSuite::ExpectSerializeFailureForJson(
} else if (response.result_case() == ConformanceResponse::kSkipped) {
ReportSkip(effective_test_name, request, response);
} else {
- ReportFailure(effective_test_name, request, response,
+ ReportFailure(effective_test_name, level, request, response,
"Should have failed to serialize, but didn't.");
}
}
+//TODO: proto2?
void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
// Incomplete values for each wire type.
static const string incompletes[6] = {
@@ -517,8 +642,8 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
string("abc") // 32BIT
};
- uint32_t fieldnum = GetFieldNumberForType(type, false);
- uint32_t rep_fieldnum = GetFieldNumberForType(type, true);
+ const FieldDescriptor* field = GetFieldForType(type, false, true);
+ const FieldDescriptor* rep_field = GetFieldForType(type, true, true);
WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
static_cast<WireFormatLite::FieldType>(type));
const string& incomplete = incompletes[wire_type];
@@ -526,42 +651,44 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
UpperCase(string(".") + FieldDescriptor::TypeName(type));
ExpectParseFailureForProto(
- tag(fieldnum, wire_type),
- "PrematureEofBeforeKnownNonRepeatedValue" + type_name);
+ tag(field->number(), wire_type),
+ "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED);
ExpectParseFailureForProto(
- tag(rep_fieldnum, wire_type),
- "PrematureEofBeforeKnownRepeatedValue" + type_name);
+ tag(rep_field->number(), wire_type),
+ "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED);
ExpectParseFailureForProto(
tag(UNKNOWN_FIELD, wire_type),
- "PrematureEofBeforeUnknownValue" + type_name);
+ "PrematureEofBeforeUnknownValue" + type_name, REQUIRED);
ExpectParseFailureForProto(
- cat( tag(fieldnum, wire_type), incomplete ),
- "PrematureEofInsideKnownNonRepeatedValue" + type_name);
+ cat( tag(field->number(), wire_type), incomplete ),
+ "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED);
ExpectParseFailureForProto(
- cat( tag(rep_fieldnum, wire_type), incomplete ),
- "PrematureEofInsideKnownRepeatedValue" + type_name);
+ cat( tag(rep_field->number(), wire_type), incomplete ),
+ "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED);
ExpectParseFailureForProto(
cat( tag(UNKNOWN_FIELD, wire_type), incomplete ),
- "PrematureEofInsideUnknownValue" + type_name);
+ "PrematureEofInsideUnknownValue" + type_name, REQUIRED);
if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
ExpectParseFailureForProto(
- cat( tag(fieldnum, wire_type), varint(1) ),
- "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name);
+ cat( tag(field->number(), wire_type), varint(1) ),
+ "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name,
+ REQUIRED);
ExpectParseFailureForProto(
- cat( tag(rep_fieldnum, wire_type), varint(1) ),
- "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name);
+ cat( tag(rep_field->number(), wire_type), varint(1) ),
+ "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name,
+ REQUIRED);
// EOF in the middle of delimited data for unknown value.
ExpectParseFailureForProto(
cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ),
- "PrematureEofInDelimitedDataForUnknownValue" + type_name);
+ "PrematureEofInDelimitedDataForUnknownValue" + type_name, REQUIRED);
if (type == FieldDescriptor::TYPE_MESSAGE) {
// Submessage ends in the middle of a value.
@@ -569,38 +696,72 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT),
incompletes[WireFormatLite::WIRETYPE_VARINT] );
ExpectHardParseFailureForProto(
- cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+ cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
varint(incomplete_submsg.size()),
incomplete_submsg ),
- "PrematureEofInSubmessageValue" + type_name);
+ "PrematureEofInSubmessageValue" + type_name, REQUIRED);
}
} else if (type != FieldDescriptor::TYPE_GROUP) {
// Non-delimited, non-group: eligible for packing.
// Packed region ends in the middle of a value.
ExpectHardParseFailureForProto(
- cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
- varint(incomplete.size()),
- incomplete ),
- "PrematureEofInPackedFieldValue" + type_name);
+ cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+ varint(incomplete.size()), incomplete),
+ "PrematureEofInPackedFieldValue" + type_name, REQUIRED);
// EOF in the middle of packed region.
ExpectParseFailureForProto(
- cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
- varint(1) ),
- "PrematureEofInPackedField" + type_name);
+ cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+ varint(1)),
+ "PrematureEofInPackedField" + type_name, REQUIRED);
+ }
+}
+
+void ConformanceTestSuite::TestValidDataForType(
+ FieldDescriptor::Type type,
+ std::vector<std::pair<std::string, std::string>> values) {
+ for (int isProto3 = 0; isProto3 < 2; isProto3++) {
+ const string type_name =
+ UpperCase(string(".") + FieldDescriptor::TypeName(type));
+ WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+ static_cast<WireFormatLite::FieldType>(type));
+ const FieldDescriptor* field = GetFieldForType(type, false, isProto3);
+ const FieldDescriptor* rep_field = GetFieldForType(type, true, isProto3);
+
+ RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED,
+ cat(tag(field->number(), wire_type), values[0].first),
+ field->name() + ": " + values[0].second, isProto3);
+
+ string proto;
+ string text = field->name() + ": " + values.back().second;
+ for (size_t i = 0; i < values.size(); i++) {
+ proto += cat(tag(field->number(), wire_type), values[i].first);
+ }
+ RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
+ proto, text, isProto3);
+
+ proto.clear();
+ text.clear();
+
+ for (size_t i = 0; i < values.size(); i++) {
+ proto += cat(tag(rep_field->number(), wire_type), values[i].first);
+ text += rep_field->name() + ": " + values[i].second + " ";
+ }
+ RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED,
+ proto, text, isProto3);
}
}
void ConformanceTestSuite::SetFailureList(const string& filename,
- const vector<string>& failure_list) {
+ const std::vector<string>& failure_list) {
failure_list_filename_ = filename;
expected_to_fail_.clear();
std::copy(failure_list.begin(), failure_list.end(),
std::inserter(expected_to_fail_, expected_to_fail_.end()));
}
-bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
+bool ConformanceTestSuite::CheckSetEmpty(const std::set<string>& set_to_check,
const std::string& write_to_file,
const std::string& msg) {
if (set_to_check.empty()) {
@@ -608,7 +769,7 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
} else {
StringAppendF(&output_, "\n");
StringAppendF(&output_, "%s\n\n", msg.c_str());
- for (set<string>::const_iterator iter = set_to_check.begin();
+ for (std::set<string>::const_iterator iter = set_to_check.begin();
iter != set_to_check.end(); ++iter) {
StringAppendF(&output_, " %s\n", iter->c_str());
}
@@ -617,7 +778,7 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
if (!write_to_file.empty()) {
std::ofstream os(write_to_file);
if (os) {
- for (set<string>::const_iterator iter = set_to_check.begin();
+ for (std::set<string>::const_iterator iter = set_to_check.begin();
iter != set_to_check.end(); ++iter) {
os << *iter << "\n";
}
@@ -631,6 +792,68 @@ bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
}
}
+// TODO: proto2?
+void ConformanceTestSuite::TestIllegalTags() {
+ // field num 0 is illegal
+ string nullfield[] = {
+ "\1DEADBEEF",
+ "\2\1\1",
+ "\3\4",
+ "\5DEAD"
+ };
+ for (int i = 0; i < 4; i++) {
+ string name = "IllegalZeroFieldNum_Case_0";
+ name.back() += i;
+ ExpectParseFailureForProto(nullfield[i], name, REQUIRED);
+ }
+}
+template <class MessageType>
+void ConformanceTestSuite::TestOneofMessage (MessageType &message,
+ bool isProto3) {
+ message.set_oneof_uint32(0);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", isProto3);
+ message.mutable_oneof_nested_message()->set_a(0);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroMessage", RECOMMENDED, &message,
+ isProto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}",
+ isProto3);
+ message.mutable_oneof_nested_message()->set_a(1);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroMessageSetTwice", RECOMMENDED, &message,
+ "oneof_nested_message: {a: 1}",
+ isProto3);
+ message.set_oneof_string("");
+ RunValidProtobufTestWithMessage(
+ "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", isProto3);
+ message.set_oneof_bytes("");
+ RunValidProtobufTestWithMessage(
+ "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", isProto3);
+ message.set_oneof_bool(false);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", isProto3);
+ message.set_oneof_uint64(0);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", isProto3);
+ message.set_oneof_float(0.0f);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", isProto3);
+ message.set_oneof_double(0.0);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", isProto3);
+ message.set_oneof_enum(MessageType::FOO);
+ RunValidProtobufTestWithMessage(
+ "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", isProto3);
+}
+
+template <class MessageType>
+void ConformanceTestSuite::TestUnknownMessage(MessageType& message,
+ bool isProto3) {
+ message.ParseFromString("\xA8\x1F\x01");
+ RunValidBinaryProtobufTest("UnknownVarint", REQUIRED,
+ message.SerializeAsString(), isProto3);
+}
+
bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
std::string* output) {
runner_ = runner;
@@ -642,7 +865,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
unexpected_succeeding_tests_.clear();
type_resolver_.reset(NewTypeResolverForDescriptorPool(
kTypeUrlPrefix, DescriptorPool::generated_pool()));
- type_url_ = GetTypeUrl(TestAllTypes::descriptor());
+ type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor());
output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
@@ -651,18 +874,112 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
}
- RunValidJsonTest("HelloWorld", "{\"optionalString\":\"Hello, World!\"}",
+ TestIllegalTags();
+
+ int64 kInt64Min = -9223372036854775808ULL;
+ int64 kInt64Max = 9223372036854775807ULL;
+ uint64 kUint64Max = 18446744073709551615ULL;
+ int32 kInt32Max = 2147483647;
+ int32 kInt32Min = -2147483648;
+ uint32 kUint32Max = 4294967295UL;
+
+ TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, {
+ {dbl(0.1), "0.1"},
+ {dbl(1.7976931348623157e+308), "1.7976931348623157e+308"},
+ {dbl(2.22507385850720138309e-308), "2.22507385850720138309e-308"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_FLOAT, {
+ {flt(0.1), "0.1"},
+ {flt(1.00000075e-36), "1.00000075e-36"},
+ {flt(3.402823e+38), "3.402823e+38"}, // 3.40282347e+38
+ {flt(1.17549435e-38f), "1.17549435e-38"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_INT64, {
+ {varint(12345), "12345"},
+ {varint(kInt64Max), std::to_string(kInt64Max)},
+ {varint(kInt64Min), std::to_string(kInt64Min)}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_UINT64, {
+ {varint(12345), "12345"},
+ {varint(kUint64Max), std::to_string(kUint64Max)},
+ {varint(0), "0"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_INT32, {
+ {varint(12345), "12345"},
+ {longvarint(12345, 2), "12345"},
+ {longvarint(12345, 7), "12345"},
+ {varint(kInt32Max), std::to_string(kInt32Max)},
+ {varint(kInt32Min), std::to_string(kInt32Min)},
+ {varint(1LL << 33), std::to_string(static_cast<int32>(1LL << 33))},
+ {varint((1LL << 33) - 1),
+ std::to_string(static_cast<int32>((1LL << 33) - 1))},
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
+ {varint(12345), "12345"},
+ {longvarint(12345, 2), "12345"},
+ {longvarint(12345, 7), "12345"},
+ {varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
+ {varint(0), "0"},
+ {varint(1LL << 33), std::to_string(static_cast<uint32>(1LL << 33))},
+ {varint((1LL << 33) - 1),
+ std::to_string(static_cast<uint32>((1LL << 33) - 1))},
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
+ {u64(12345), "12345"},
+ {u64(kUint64Max), std::to_string(kUint64Max)},
+ {u64(0), "0"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_FIXED32, {
+ {u32(12345), "12345"},
+ {u32(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
+ {u32(0), "0"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, {
+ {u64(12345), "12345"},
+ {u64(kInt64Max), std::to_string(kInt64Max)},
+ {u64(kInt64Min), std::to_string(kInt64Min)}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, {
+ {u32(12345), "12345"},
+ {u32(kInt32Max), std::to_string(kInt32Max)},
+ {u32(kInt32Min), std::to_string(kInt32Min)}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_BOOL, {
+ {varint(1), "true"},
+ {varint(0), "false"},
+ {varint(12345678), "true"}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_SINT32, {
+ {zz32(12345), "12345"},
+ {zz32(kInt32Max), std::to_string(kInt32Max)},
+ {zz32(kInt32Min), std::to_string(kInt32Min)}
+ });
+ TestValidDataForType(FieldDescriptor::TYPE_SINT64, {
+ {zz64(12345), "12345"},
+ {zz64(kInt64Max), std::to_string(kInt64Max)},
+ {zz64(kInt64Min), std::to_string(kInt64Min)}
+ });
+
+ // TODO(haberman):
+ // TestValidDataForType(FieldDescriptor::TYPE_STRING
+ // TestValidDataForType(FieldDescriptor::TYPE_GROUP
+ // TestValidDataForType(FieldDescriptor::TYPE_MESSAGE
+ // TestValidDataForType(FieldDescriptor::TYPE_BYTES
+ // TestValidDataForType(FieldDescriptor::TYPE_ENUM
+
+ RunValidJsonTest("HelloWorld", REQUIRED,
+ "{\"optionalString\":\"Hello, World!\"}",
"optional_string: 'Hello, World!'");
// NOTE: The spec for JSON support is still being sorted out, these may not
// all be correct.
// Test field name conventions.
RunValidJsonTest(
- "FieldNameInSnakeCase",
+ "FieldNameInSnakeCase", REQUIRED,
R"({
"fieldname1": 1,
"fieldName2": 2,
- "fieldName3": 3,
+ "FieldName3": 3,
"fieldName4": 4
})",
R"(
@@ -672,7 +989,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
field__name4_: 4
)");
RunValidJsonTest(
- "FieldNameWithNumbers",
+ "FieldNameWithNumbers", REQUIRED,
R"({
"field0name5": 5,
"field0Name6": 6
@@ -682,14 +999,14 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
field_0_name6: 6
)");
RunValidJsonTest(
- "FieldNameWithMixedCases",
+ "FieldNameWithMixedCases", REQUIRED,
R"({
"fieldName7": 7,
- "fieldName8": 8,
+ "FieldName8": 8,
"fieldName9": 9,
- "fieldName10": 10,
- "fIELDNAME11": 11,
- "fIELDName12": 12
+ "FieldName10": 10,
+ "FIELDNAME11": 11,
+ "FIELDName12": 12
})",
R"(
fieldName7: 7
@@ -700,14 +1017,14 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
FIELD_name12: 12
)");
RunValidJsonTest(
- "FieldNameWithDoubleUnderscores",
+ "FieldNameWithDoubleUnderscores", RECOMMENDED,
R"({
- "fieldName13": 13,
- "fieldName14": 14,
+ "FieldName13": 13,
+ "FieldName14": 14,
"fieldName15": 15,
"fieldName16": 16,
"fieldName17": 17,
- "fieldName18": 18
+ "FieldName18": 18
})",
R"(
__field_name13: 13
@@ -719,7 +1036,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// Using the original proto field name in JSON is also allowed.
RunValidJsonTest(
- "OriginalProtoFieldName",
+ "OriginalProtoFieldName", REQUIRED,
R"({
"fieldname1": 1,
"field_name2": 2,
@@ -762,63 +1079,63 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// Field names can be escaped.
RunValidJsonTest(
- "FieldNameEscaped",
+ "FieldNameEscaped", REQUIRED,
R"({"fieldn\u0061me1": 1})",
"fieldname1: 1");
// String ends with escape character.
ExpectParseFailureForJson(
- "StringEndsWithEscapeChar",
+ "StringEndsWithEscapeChar", RECOMMENDED,
"{\"optionalString\": \"abc\\");
// Field names must be quoted (or it's not valid JSON).
ExpectParseFailureForJson(
- "FieldNameNotQuoted",
+ "FieldNameNotQuoted", RECOMMENDED,
"{fieldname1: 1}");
// Trailing comma is not allowed (not valid JSON).
ExpectParseFailureForJson(
- "TrailingCommaInAnObject",
+ "TrailingCommaInAnObject", RECOMMENDED,
R"({"fieldname1":1,})");
ExpectParseFailureForJson(
- "TrailingCommaInAnObjectWithSpace",
+ "TrailingCommaInAnObjectWithSpace", RECOMMENDED,
R"({"fieldname1":1 ,})");
ExpectParseFailureForJson(
- "TrailingCommaInAnObjectWithSpaceCommaSpace",
+ "TrailingCommaInAnObjectWithSpaceCommaSpace", RECOMMENDED,
R"({"fieldname1":1 , })");
ExpectParseFailureForJson(
- "TrailingCommaInAnObjectWithNewlines",
+ "TrailingCommaInAnObjectWithNewlines", RECOMMENDED,
R"({
"fieldname1":1,
})");
// JSON doesn't support comments.
ExpectParseFailureForJson(
- "JsonWithComments",
+ "JsonWithComments", RECOMMENDED,
R"({
// This is a comment.
"fieldname1": 1
})");
// JSON spec says whitespace doesn't matter, so try a few spacings to be sure.
RunValidJsonTest(
- "OneLineNoSpaces",
+ "OneLineNoSpaces", RECOMMENDED,
"{\"optionalInt32\":1,\"optionalInt64\":2}",
R"(
optional_int32: 1
optional_int64: 2
)");
RunValidJsonTest(
- "OneLineWithSpaces",
+ "OneLineWithSpaces", RECOMMENDED,
"{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }",
R"(
optional_int32: 1
optional_int64: 2
)");
RunValidJsonTest(
- "MultilineNoSpaces",
+ "MultilineNoSpaces", RECOMMENDED,
"{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}",
R"(
optional_int32: 1
optional_int64: 2
)");
RunValidJsonTest(
- "MultilineWithSpaces",
+ "MultilineWithSpaces", RECOMMENDED,
"{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n",
R"(
optional_int32: 1
@@ -826,49 +1143,47 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// Missing comma between key/value pairs.
ExpectParseFailureForJson(
- "MissingCommaOneLine",
+ "MissingCommaOneLine", RECOMMENDED,
"{ \"optionalInt32\": 1 \"optionalInt64\": 2 }");
ExpectParseFailureForJson(
- "MissingCommaMultiline",
+ "MissingCommaMultiline", RECOMMENDED,
"{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}");
// Duplicated field names are not allowed.
ExpectParseFailureForJson(
- "FieldNameDuplicate",
+ "FieldNameDuplicate", RECOMMENDED,
R"({
"optionalNestedMessage": {a: 1},
"optionalNestedMessage": {}
})");
ExpectParseFailureForJson(
- "FieldNameDuplicateDifferentCasing1",
+ "FieldNameDuplicateDifferentCasing1", RECOMMENDED,
R"({
"optional_nested_message": {a: 1},
"optionalNestedMessage": {}
})");
ExpectParseFailureForJson(
- "FieldNameDuplicateDifferentCasing2",
+ "FieldNameDuplicateDifferentCasing2", RECOMMENDED,
R"({
"optionalNestedMessage": {a: 1},
"optional_nested_message": {}
})");
- // NOTE: The spec for JSON support is still being sorted out, these may not
- // all be correct.
// Serializers should use lowerCamelCase by default.
RunValidJsonTestWithValidator(
- "FieldNameInLowerCamelCase",
+ "FieldNameInLowerCamelCase", REQUIRED,
R"({
"fieldname1": 1,
"fieldName2": 2,
- "fieldName3": 3,
+ "FieldName3": 3,
"fieldName4": 4
})",
[](const Json::Value& value) {
return value.isMember("fieldname1") &&
value.isMember("fieldName2") &&
- value.isMember("fieldName3") &&
+ value.isMember("FieldName3") &&
value.isMember("fieldName4");
});
RunValidJsonTestWithValidator(
- "FieldNameWithNumbers",
+ "FieldNameWithNumbers", REQUIRED,
R"({
"field0name5": 5,
"field0Name6": 6
@@ -878,65 +1193,65 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
value.isMember("field0Name6");
});
RunValidJsonTestWithValidator(
- "FieldNameWithMixedCases",
+ "FieldNameWithMixedCases", REQUIRED,
R"({
"fieldName7": 7,
- "fieldName8": 8,
+ "FieldName8": 8,
"fieldName9": 9,
- "fieldName10": 10,
- "fIELDNAME11": 11,
- "fIELDName12": 12
+ "FieldName10": 10,
+ "FIELDNAME11": 11,
+ "FIELDName12": 12
})",
[](const Json::Value& value) {
return value.isMember("fieldName7") &&
- value.isMember("fieldName8") &&
+ value.isMember("FieldName8") &&
value.isMember("fieldName9") &&
- value.isMember("fieldName10") &&
- value.isMember("fIELDNAME11") &&
- value.isMember("fIELDName12");
+ value.isMember("FieldName10") &&
+ value.isMember("FIELDNAME11") &&
+ value.isMember("FIELDName12");
});
RunValidJsonTestWithValidator(
- "FieldNameWithDoubleUnderscores",
+ "FieldNameWithDoubleUnderscores", RECOMMENDED,
R"({
- "fieldName13": 13,
- "fieldName14": 14,
+ "FieldName13": 13,
+ "FieldName14": 14,
"fieldName15": 15,
"fieldName16": 16,
"fieldName17": 17,
- "fieldName18": 18
+ "FieldName18": 18
})",
[](const Json::Value& value) {
- return value.isMember("fieldName13") &&
- value.isMember("fieldName14") &&
+ return value.isMember("FieldName13") &&
+ value.isMember("FieldName14") &&
value.isMember("fieldName15") &&
value.isMember("fieldName16") &&
value.isMember("fieldName17") &&
- value.isMember("fieldName18");
+ value.isMember("FieldName18");
});
// Integer fields.
RunValidJsonTest(
- "Int32FieldMaxValue",
+ "Int32FieldMaxValue", REQUIRED,
R"({"optionalInt32": 2147483647})",
"optional_int32: 2147483647");
RunValidJsonTest(
- "Int32FieldMinValue",
+ "Int32FieldMinValue", REQUIRED,
R"({"optionalInt32": -2147483648})",
"optional_int32: -2147483648");
RunValidJsonTest(
- "Uint32FieldMaxValue",
+ "Uint32FieldMaxValue", REQUIRED,
R"({"optionalUint32": 4294967295})",
"optional_uint32: 4294967295");
RunValidJsonTest(
- "Int64FieldMaxValue",
+ "Int64FieldMaxValue", REQUIRED,
R"({"optionalInt64": "9223372036854775807"})",
"optional_int64: 9223372036854775807");
RunValidJsonTest(
- "Int64FieldMinValue",
+ "Int64FieldMinValue", REQUIRED,
R"({"optionalInt64": "-9223372036854775808"})",
"optional_int64: -9223372036854775808");
RunValidJsonTest(
- "Uint64FieldMaxValue",
+ "Uint64FieldMaxValue", REQUIRED,
R"({"optionalUint64": "18446744073709551615"})",
"optional_uint64: 18446744073709551615");
// While not the largest Int64, this is the largest
@@ -946,127 +1261,127 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// work in some implementations, but should not be
// relied upon.
RunValidJsonTest(
- "Int64FieldMaxValueNotQuoted",
+ "Int64FieldMaxValueNotQuoted", REQUIRED,
R"({"optionalInt64": 9223372036854774784})",
"optional_int64: 9223372036854774784");
RunValidJsonTest(
- "Int64FieldMinValueNotQuoted",
+ "Int64FieldMinValueNotQuoted", REQUIRED,
R"({"optionalInt64": -9223372036854775808})",
"optional_int64: -9223372036854775808");
// Largest interoperable Uint64; see comment above
// for Int64FieldMaxValueNotQuoted.
RunValidJsonTest(
- "Uint64FieldMaxValueNotQuoted",
+ "Uint64FieldMaxValueNotQuoted", REQUIRED,
R"({"optionalUint64": 18446744073709549568})",
"optional_uint64: 18446744073709549568");
// Values can be represented as JSON strings.
RunValidJsonTest(
- "Int32FieldStringValue",
+ "Int32FieldStringValue", REQUIRED,
R"({"optionalInt32": "2147483647"})",
"optional_int32: 2147483647");
RunValidJsonTest(
- "Int32FieldStringValueEscaped",
+ "Int32FieldStringValueEscaped", REQUIRED,
R"({"optionalInt32": "2\u003147483647"})",
"optional_int32: 2147483647");
// Parsers reject out-of-bound integer values.
ExpectParseFailureForJson(
- "Int32FieldTooLarge",
+ "Int32FieldTooLarge", REQUIRED,
R"({"optionalInt32": 2147483648})");
ExpectParseFailureForJson(
- "Int32FieldTooSmall",
+ "Int32FieldTooSmall", REQUIRED,
R"({"optionalInt32": -2147483649})");
ExpectParseFailureForJson(
- "Uint32FieldTooLarge",
+ "Uint32FieldTooLarge", REQUIRED,
R"({"optionalUint32": 4294967296})");
ExpectParseFailureForJson(
- "Int64FieldTooLarge",
+ "Int64FieldTooLarge", REQUIRED,
R"({"optionalInt64": "9223372036854775808"})");
ExpectParseFailureForJson(
- "Int64FieldTooSmall",
+ "Int64FieldTooSmall", REQUIRED,
R"({"optionalInt64": "-9223372036854775809"})");
ExpectParseFailureForJson(
- "Uint64FieldTooLarge",
+ "Uint64FieldTooLarge", REQUIRED,
R"({"optionalUint64": "18446744073709551616"})");
// Parser reject non-integer numeric values as well.
ExpectParseFailureForJson(
- "Int32FieldNotInteger",
+ "Int32FieldNotInteger", REQUIRED,
R"({"optionalInt32": 0.5})");
ExpectParseFailureForJson(
- "Uint32FieldNotInteger",
+ "Uint32FieldNotInteger", REQUIRED,
R"({"optionalUint32": 0.5})");
ExpectParseFailureForJson(
- "Int64FieldNotInteger",
+ "Int64FieldNotInteger", REQUIRED,
R"({"optionalInt64": "0.5"})");
ExpectParseFailureForJson(
- "Uint64FieldNotInteger",
+ "Uint64FieldNotInteger", REQUIRED,
R"({"optionalUint64": "0.5"})");
// Integers but represented as float values are accepted.
RunValidJsonTest(
- "Int32FieldFloatTrailingZero",
+ "Int32FieldFloatTrailingZero", REQUIRED,
R"({"optionalInt32": 100000.000})",
"optional_int32: 100000");
RunValidJsonTest(
- "Int32FieldExponentialFormat",
+ "Int32FieldExponentialFormat", REQUIRED,
R"({"optionalInt32": 1e5})",
"optional_int32: 100000");
RunValidJsonTest(
- "Int32FieldMaxFloatValue",
+ "Int32FieldMaxFloatValue", REQUIRED,
R"({"optionalInt32": 2.147483647e9})",
"optional_int32: 2147483647");
RunValidJsonTest(
- "Int32FieldMinFloatValue",
+ "Int32FieldMinFloatValue", REQUIRED,
R"({"optionalInt32": -2.147483648e9})",
"optional_int32: -2147483648");
RunValidJsonTest(
- "Uint32FieldMaxFloatValue",
+ "Uint32FieldMaxFloatValue", REQUIRED,
R"({"optionalUint32": 4.294967295e9})",
"optional_uint32: 4294967295");
// Parser reject non-numeric values.
ExpectParseFailureForJson(
- "Int32FieldNotNumber",
+ "Int32FieldNotNumber", REQUIRED,
R"({"optionalInt32": "3x3"})");
ExpectParseFailureForJson(
- "Uint32FieldNotNumber",
+ "Uint32FieldNotNumber", REQUIRED,
R"({"optionalUint32": "3x3"})");
ExpectParseFailureForJson(
- "Int64FieldNotNumber",
+ "Int64FieldNotNumber", REQUIRED,
R"({"optionalInt64": "3x3"})");
ExpectParseFailureForJson(
- "Uint64FieldNotNumber",
+ "Uint64FieldNotNumber", REQUIRED,
R"({"optionalUint64": "3x3"})");
// JSON does not allow "+" on numric values.
ExpectParseFailureForJson(
- "Int32FieldPlusSign",
+ "Int32FieldPlusSign", REQUIRED,
R"({"optionalInt32": +1})");
// JSON doesn't allow leading 0s.
ExpectParseFailureForJson(
- "Int32FieldLeadingZero",
+ "Int32FieldLeadingZero", REQUIRED,
R"({"optionalInt32": 01})");
ExpectParseFailureForJson(
- "Int32FieldNegativeWithLeadingZero",
+ "Int32FieldNegativeWithLeadingZero", REQUIRED,
R"({"optionalInt32": -01})");
// String values must follow the same syntax rule. Specifically leading
- // or traling spaces are not allowed.
+ // or trailing spaces are not allowed.
ExpectParseFailureForJson(
- "Int32FieldLeadingSpace",
+ "Int32FieldLeadingSpace", REQUIRED,
R"({"optionalInt32": " 1"})");
ExpectParseFailureForJson(
- "Int32FieldTrailingSpace",
+ "Int32FieldTrailingSpace", REQUIRED,
R"({"optionalInt32": "1 "})");
// 64-bit values are serialized as strings.
RunValidJsonTestWithValidator(
- "Int64FieldBeString",
+ "Int64FieldBeString", RECOMMENDED,
R"({"optionalInt64": 1})",
[](const Json::Value& value) {
return value["optionalInt64"].type() == Json::stringValue &&
value["optionalInt64"].asString() == "1";
});
RunValidJsonTestWithValidator(
- "Uint64FieldBeString",
+ "Uint64FieldBeString", RECOMMENDED,
R"({"optionalUint64": 1})",
[](const Json::Value& value) {
return value["optionalUint64"].type() == Json::stringValue &&
@@ -1075,202 +1390,202 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// Bool fields.
RunValidJsonTest(
- "BoolFieldTrue",
+ "BoolFieldTrue", REQUIRED,
R"({"optionalBool":true})",
"optional_bool: true");
RunValidJsonTest(
- "BoolFieldFalse",
+ "BoolFieldFalse", REQUIRED,
R"({"optionalBool":false})",
"optional_bool: false");
// Other forms are not allowed.
ExpectParseFailureForJson(
- "BoolFieldIntegerZero",
+ "BoolFieldIntegerZero", RECOMMENDED,
R"({"optionalBool":0})");
ExpectParseFailureForJson(
- "BoolFieldIntegerOne",
+ "BoolFieldIntegerOne", RECOMMENDED,
R"({"optionalBool":1})");
ExpectParseFailureForJson(
- "BoolFieldCamelCaseTrue",
+ "BoolFieldCamelCaseTrue", RECOMMENDED,
R"({"optionalBool":True})");
ExpectParseFailureForJson(
- "BoolFieldCamelCaseFalse",
+ "BoolFieldCamelCaseFalse", RECOMMENDED,
R"({"optionalBool":False})");
ExpectParseFailureForJson(
- "BoolFieldAllCapitalTrue",
+ "BoolFieldAllCapitalTrue", RECOMMENDED,
R"({"optionalBool":TRUE})");
ExpectParseFailureForJson(
- "BoolFieldAllCapitalFalse",
+ "BoolFieldAllCapitalFalse", RECOMMENDED,
R"({"optionalBool":FALSE})");
ExpectParseFailureForJson(
- "BoolFieldDoubleQuotedTrue",
+ "BoolFieldDoubleQuotedTrue", RECOMMENDED,
R"({"optionalBool":"true"})");
ExpectParseFailureForJson(
- "BoolFieldDoubleQuotedFalse",
+ "BoolFieldDoubleQuotedFalse", RECOMMENDED,
R"({"optionalBool":"false"})");
// Float fields.
RunValidJsonTest(
- "FloatFieldMinPositiveValue",
+ "FloatFieldMinPositiveValue", REQUIRED,
R"({"optionalFloat": 1.175494e-38})",
"optional_float: 1.175494e-38");
RunValidJsonTest(
- "FloatFieldMaxNegativeValue",
+ "FloatFieldMaxNegativeValue", REQUIRED,
R"({"optionalFloat": -1.175494e-38})",
"optional_float: -1.175494e-38");
RunValidJsonTest(
- "FloatFieldMaxPositiveValue",
+ "FloatFieldMaxPositiveValue", REQUIRED,
R"({"optionalFloat": 3.402823e+38})",
"optional_float: 3.402823e+38");
RunValidJsonTest(
- "FloatFieldMinNegativeValue",
+ "FloatFieldMinNegativeValue", REQUIRED,
R"({"optionalFloat": 3.402823e+38})",
"optional_float: 3.402823e+38");
// Values can be quoted.
RunValidJsonTest(
- "FloatFieldQuotedValue",
+ "FloatFieldQuotedValue", REQUIRED,
R"({"optionalFloat": "1"})",
"optional_float: 1");
// Special values.
RunValidJsonTest(
- "FloatFieldNan",
+ "FloatFieldNan", REQUIRED,
R"({"optionalFloat": "NaN"})",
"optional_float: nan");
RunValidJsonTest(
- "FloatFieldInfinity",
+ "FloatFieldInfinity", REQUIRED,
R"({"optionalFloat": "Infinity"})",
"optional_float: inf");
RunValidJsonTest(
- "FloatFieldNegativeInfinity",
+ "FloatFieldNegativeInfinity", REQUIRED,
R"({"optionalFloat": "-Infinity"})",
"optional_float: -inf");
// Non-cannonical Nan will be correctly normalized.
{
- TestAllTypes message;
+ TestAllTypesProto3 message;
// IEEE floating-point standard 32-bit quiet NaN:
// 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
message.set_optional_float(
WireFormatLite::DecodeFloat(0x7FA12345));
RunValidJsonTestWithProtobufInput(
- "FloatFieldNormalizeQuietNan", message,
+ "FloatFieldNormalizeQuietNan", REQUIRED, message,
"optional_float: nan");
// IEEE floating-point standard 64-bit signaling NaN:
// 1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
message.set_optional_float(
WireFormatLite::DecodeFloat(0xFFB54321));
RunValidJsonTestWithProtobufInput(
- "FloatFieldNormalizeSignalingNan", message,
+ "FloatFieldNormalizeSignalingNan", REQUIRED, message,
"optional_float: nan");
}
// Special values must be quoted.
ExpectParseFailureForJson(
- "FloatFieldNanNotQuoted",
+ "FloatFieldNanNotQuoted", RECOMMENDED,
R"({"optionalFloat": NaN})");
ExpectParseFailureForJson(
- "FloatFieldInfinityNotQuoted",
+ "FloatFieldInfinityNotQuoted", RECOMMENDED,
R"({"optionalFloat": Infinity})");
ExpectParseFailureForJson(
- "FloatFieldNegativeInfinityNotQuoted",
+ "FloatFieldNegativeInfinityNotQuoted", RECOMMENDED,
R"({"optionalFloat": -Infinity})");
// Parsers should reject out-of-bound values.
ExpectParseFailureForJson(
- "FloatFieldTooSmall",
+ "FloatFieldTooSmall", REQUIRED,
R"({"optionalFloat": -3.502823e+38})");
ExpectParseFailureForJson(
- "FloatFieldTooLarge",
+ "FloatFieldTooLarge", REQUIRED,
R"({"optionalFloat": 3.502823e+38})");
// Double fields.
RunValidJsonTest(
- "DoubleFieldMinPositiveValue",
+ "DoubleFieldMinPositiveValue", REQUIRED,
R"({"optionalDouble": 2.22507e-308})",
"optional_double: 2.22507e-308");
RunValidJsonTest(
- "DoubleFieldMaxNegativeValue",
+ "DoubleFieldMaxNegativeValue", REQUIRED,
R"({"optionalDouble": -2.22507e-308})",
"optional_double: -2.22507e-308");
RunValidJsonTest(
- "DoubleFieldMaxPositiveValue",
+ "DoubleFieldMaxPositiveValue", REQUIRED,
R"({"optionalDouble": 1.79769e+308})",
"optional_double: 1.79769e+308");
RunValidJsonTest(
- "DoubleFieldMinNegativeValue",
+ "DoubleFieldMinNegativeValue", REQUIRED,
R"({"optionalDouble": -1.79769e+308})",
"optional_double: -1.79769e+308");
// Values can be quoted.
RunValidJsonTest(
- "DoubleFieldQuotedValue",
+ "DoubleFieldQuotedValue", REQUIRED,
R"({"optionalDouble": "1"})",
"optional_double: 1");
// Speical values.
RunValidJsonTest(
- "DoubleFieldNan",
+ "DoubleFieldNan", REQUIRED,
R"({"optionalDouble": "NaN"})",
"optional_double: nan");
RunValidJsonTest(
- "DoubleFieldInfinity",
+ "DoubleFieldInfinity", REQUIRED,
R"({"optionalDouble": "Infinity"})",
"optional_double: inf");
RunValidJsonTest(
- "DoubleFieldNegativeInfinity",
+ "DoubleFieldNegativeInfinity", REQUIRED,
R"({"optionalDouble": "-Infinity"})",
"optional_double: -inf");
// Non-cannonical Nan will be correctly normalized.
{
- TestAllTypes message;
+ TestAllTypesProto3 message;
message.set_optional_double(
WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL));
RunValidJsonTestWithProtobufInput(
- "DoubleFieldNormalizeQuietNan", message,
+ "DoubleFieldNormalizeQuietNan", REQUIRED, message,
"optional_double: nan");
message.set_optional_double(
WireFormatLite::DecodeDouble(0xFFFBCBA987654321LL));
RunValidJsonTestWithProtobufInput(
- "DoubleFieldNormalizeSignalingNan", message,
+ "DoubleFieldNormalizeSignalingNan", REQUIRED, message,
"optional_double: nan");
}
// Special values must be quoted.
ExpectParseFailureForJson(
- "DoubleFieldNanNotQuoted",
+ "DoubleFieldNanNotQuoted", RECOMMENDED,
R"({"optionalDouble": NaN})");
ExpectParseFailureForJson(
- "DoubleFieldInfinityNotQuoted",
+ "DoubleFieldInfinityNotQuoted", RECOMMENDED,
R"({"optionalDouble": Infinity})");
ExpectParseFailureForJson(
- "DoubleFieldNegativeInfinityNotQuoted",
+ "DoubleFieldNegativeInfinityNotQuoted", RECOMMENDED,
R"({"optionalDouble": -Infinity})");
// Parsers should reject out-of-bound values.
ExpectParseFailureForJson(
- "DoubleFieldTooSmall",
+ "DoubleFieldTooSmall", REQUIRED,
R"({"optionalDouble": -1.89769e+308})");
ExpectParseFailureForJson(
- "DoubleFieldTooLarge",
+ "DoubleFieldTooLarge", REQUIRED,
R"({"optionalDouble": +1.89769e+308})");
// Enum fields.
RunValidJsonTest(
- "EnumField",
+ "EnumField", REQUIRED,
R"({"optionalNestedEnum": "FOO"})",
"optional_nested_enum: FOO");
// Enum values must be represented as strings.
ExpectParseFailureForJson(
- "EnumFieldNotQuoted",
+ "EnumFieldNotQuoted", REQUIRED,
R"({"optionalNestedEnum": FOO})");
// Numeric values are allowed.
RunValidJsonTest(
- "EnumFieldNumericValueZero",
+ "EnumFieldNumericValueZero", REQUIRED,
R"({"optionalNestedEnum": 0})",
"optional_nested_enum: FOO");
RunValidJsonTest(
- "EnumFieldNumericValueNonZero",
+ "EnumFieldNumericValueNonZero", REQUIRED,
R"({"optionalNestedEnum": 1})",
"optional_nested_enum: BAR");
// Unknown enum values are represented as numeric values.
RunValidJsonTestWithValidator(
- "EnumFieldUnknownValue",
+ "EnumFieldUnknownValue", REQUIRED,
R"({"optionalNestedEnum": 123})",
[](const Json::Value& value) {
return value["optionalNestedEnum"].type() == Json::intValue &&
@@ -1279,244 +1594,216 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// String fields.
RunValidJsonTest(
- "StringField",
+ "StringField", REQUIRED,
R"({"optionalString": "Hello world!"})",
"optional_string: \"Hello world!\"");
RunValidJsonTest(
- "StringFieldUnicode",
+ "StringFieldUnicode", REQUIRED,
// Google in Chinese.
R"({"optionalString": "谷歌"})",
R"(optional_string: "谷歌")");
RunValidJsonTest(
- "StringFieldEscape",
+ "StringFieldEscape", REQUIRED,
R"({"optionalString": "\"\\\/\b\f\n\r\t"})",
R"(optional_string: "\"\\/\b\f\n\r\t")");
RunValidJsonTest(
- "StringFieldUnicodeEscape",
+ "StringFieldUnicodeEscape", REQUIRED,
R"({"optionalString": "\u8C37\u6B4C"})",
R"(optional_string: "谷歌")");
RunValidJsonTest(
- "StringFieldUnicodeEscapeWithLowercaseHexLetters",
+ "StringFieldUnicodeEscapeWithLowercaseHexLetters", REQUIRED,
R"({"optionalString": "\u8c37\u6b4c"})",
R"(optional_string: "谷歌")");
RunValidJsonTest(
- "StringFieldSurrogatePair",
+ "StringFieldSurrogatePair", REQUIRED,
// The character is an emoji: grinning face with smiling eyes. 😁
R"({"optionalString": "\uD83D\uDE01"})",
R"(optional_string: "\xF0\x9F\x98\x81")");
// Unicode escapes must start with "\u" (lowercase u).
ExpectParseFailureForJson(
- "StringFieldUppercaseEscapeLetter",
+ "StringFieldUppercaseEscapeLetter", RECOMMENDED,
R"({"optionalString": "\U8C37\U6b4C"})");
ExpectParseFailureForJson(
- "StringFieldInvalidEscape",
+ "StringFieldInvalidEscape", RECOMMENDED,
R"({"optionalString": "\uXXXX\u6B4C"})");
ExpectParseFailureForJson(
- "StringFieldUnterminatedEscape",
+ "StringFieldUnterminatedEscape", RECOMMENDED,
R"({"optionalString": "\u8C3"})");
ExpectParseFailureForJson(
- "StringFieldUnpairedHighSurrogate",
+ "StringFieldUnpairedHighSurrogate", RECOMMENDED,
R"({"optionalString": "\uD800"})");
ExpectParseFailureForJson(
- "StringFieldUnpairedLowSurrogate",
+ "StringFieldUnpairedLowSurrogate", RECOMMENDED,
R"({"optionalString": "\uDC00"})");
ExpectParseFailureForJson(
- "StringFieldSurrogateInWrongOrder",
+ "StringFieldSurrogateInWrongOrder", RECOMMENDED,
R"({"optionalString": "\uDE01\uD83D"})");
ExpectParseFailureForJson(
- "StringFieldNotAString",
+ "StringFieldNotAString", REQUIRED,
R"({"optionalString": 12345})");
// Bytes fields.
RunValidJsonTest(
- "BytesField",
+ "BytesField", REQUIRED,
R"({"optionalBytes": "AQI="})",
R"(optional_bytes: "\x01\x02")");
- ExpectParseFailureForJson(
- "BytesFieldNoPadding",
- R"({"optionalBytes": "AQI"})");
- ExpectParseFailureForJson(
- "BytesFieldInvalidBase64Characters",
- R"({"optionalBytes": "-_=="})");
+ RunValidJsonTest(
+ "BytesFieldBase64Url", RECOMMENDED,
+ R"({"optionalBytes": "-_"})",
+ R"(optional_bytes: "\xfb")");
// Message fields.
RunValidJsonTest(
- "MessageField",
+ "MessageField", REQUIRED,
R"({"optionalNestedMessage": {"a": 1234}})",
"optional_nested_message: {a: 1234}");
// Oneof fields.
ExpectParseFailureForJson(
- "OneofFieldDuplicate",
+ "OneofFieldDuplicate", REQUIRED,
R"({"oneofUint32": 1, "oneofString": "test"})");
// Ensure zero values for oneof make it out/backs.
- {
- TestAllTypes message;
- message.set_oneof_uint32(0);
- RunValidProtobufTest(
- "OneofZeroUint32", message, "oneof_uint32: 0");
- message.mutable_oneof_nested_message()->set_a(0);
- RunValidProtobufTest(
- "OneofZeroMessage", message, "oneof_nested_message: {}");
- message.set_oneof_string("");
- RunValidProtobufTest(
- "OneofZeroString", message, "oneof_string: \"\"");
- message.set_oneof_bytes("");
- RunValidProtobufTest(
- "OneofZeroBytes", message, "oneof_bytes: \"\"");
- message.set_oneof_bool(false);
- RunValidProtobufTest(
- "OneofZeroBool", message, "oneof_bool: false");
- message.set_oneof_uint64(0);
- RunValidProtobufTest(
- "OneofZeroUint64", message, "oneof_uint64: 0");
- message.set_oneof_float(0.0f);
- RunValidProtobufTest(
- "OneofZeroFloat", message, "oneof_float: 0");
- message.set_oneof_double(0.0);
- RunValidProtobufTest(
- "OneofZeroDouble", message, "oneof_double: 0");
- message.set_oneof_enum(TestAllTypes::FOO);
- RunValidProtobufTest(
- "OneofZeroEnum", message, "oneof_enum: FOO");
- }
+ TestAllTypesProto3 messageProto3;
+ TestAllTypesProto2 messageProto2;
+ TestOneofMessage(messageProto3, true);
+ TestOneofMessage(messageProto2, false);
RunValidJsonTest(
- "OneofZeroUint32",
+ "OneofZeroUint32", RECOMMENDED,
R"({"oneofUint32": 0})", "oneof_uint32: 0");
RunValidJsonTest(
- "OneofZeroMessage",
+ "OneofZeroMessage", RECOMMENDED,
R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}");
RunValidJsonTest(
- "OneofZeroString",
+ "OneofZeroString", RECOMMENDED,
R"({"oneofString": ""})", "oneof_string: \"\"");
RunValidJsonTest(
- "OneofZeroBytes",
+ "OneofZeroBytes", RECOMMENDED,
R"({"oneofBytes": ""})", "oneof_bytes: \"\"");
RunValidJsonTest(
- "OneofZeroBool",
+ "OneofZeroBool", RECOMMENDED,
R"({"oneofBool": false})", "oneof_bool: false");
RunValidJsonTest(
- "OneofZeroUint64",
+ "OneofZeroUint64", RECOMMENDED,
R"({"oneofUint64": 0})", "oneof_uint64: 0");
RunValidJsonTest(
- "OneofZeroFloat",
+ "OneofZeroFloat", RECOMMENDED,
R"({"oneofFloat": 0.0})", "oneof_float: 0");
RunValidJsonTest(
- "OneofZeroDouble",
+ "OneofZeroDouble", RECOMMENDED,
R"({"oneofDouble": 0.0})", "oneof_double: 0");
RunValidJsonTest(
- "OneofZeroEnum",
+ "OneofZeroEnum", RECOMMENDED,
R"({"oneofEnum":"FOO"})", "oneof_enum: FOO");
// Repeated fields.
RunValidJsonTest(
- "PrimitiveRepeatedField",
+ "PrimitiveRepeatedField", REQUIRED,
R"({"repeatedInt32": [1, 2, 3, 4]})",
"repeated_int32: [1, 2, 3, 4]");
RunValidJsonTest(
- "EnumRepeatedField",
+ "EnumRepeatedField", REQUIRED,
R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})",
"repeated_nested_enum: [FOO, BAR, BAZ]");
RunValidJsonTest(
- "StringRepeatedField",
+ "StringRepeatedField", REQUIRED,
R"({"repeatedString": ["Hello", "world"]})",
R"(repeated_string: ["Hello", "world"])");
RunValidJsonTest(
- "BytesRepeatedField",
+ "BytesRepeatedField", REQUIRED,
R"({"repeatedBytes": ["AAEC", "AQI="]})",
R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])");
RunValidJsonTest(
- "MessageRepeatedField",
+ "MessageRepeatedField", REQUIRED,
R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})",
"repeated_nested_message: {a: 1234}"
"repeated_nested_message: {a: 5678}");
// Repeated field elements are of incorrect type.
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingIntegersGotBool",
+ "RepeatedFieldWrongElementTypeExpectingIntegersGotBool", REQUIRED,
R"({"repeatedInt32": [1, false, 3, 4]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingIntegersGotString",
+ "RepeatedFieldWrongElementTypeExpectingIntegersGotString", REQUIRED,
R"({"repeatedInt32": [1, 2, "name", 4]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage",
+ "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage", REQUIRED,
R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingStringsGotInt",
+ "RepeatedFieldWrongElementTypeExpectingStringsGotInt", REQUIRED,
R"({"repeatedString": ["1", 2, "3", "4"]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingStringsGotBool",
+ "RepeatedFieldWrongElementTypeExpectingStringsGotBool", REQUIRED,
R"({"repeatedString": ["1", "2", false, "4"]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingStringsGotMessage",
+ "RepeatedFieldWrongElementTypeExpectingStringsGotMessage", REQUIRED,
R"({"repeatedString": ["1", 2, "3", {"a": 4}]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingMessagesGotInt",
+ "RepeatedFieldWrongElementTypeExpectingMessagesGotInt", REQUIRED,
R"({"repeatedNestedMessage": [{"a": 1}, 2]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingMessagesGotBool",
+ "RepeatedFieldWrongElementTypeExpectingMessagesGotBool", REQUIRED,
R"({"repeatedNestedMessage": [{"a": 1}, false]})");
ExpectParseFailureForJson(
- "RepeatedFieldWrongElementTypeExpectingMessagesGotString",
+ "RepeatedFieldWrongElementTypeExpectingMessagesGotString", REQUIRED,
R"({"repeatedNestedMessage": [{"a": 1}, "2"]})");
// Trailing comma in the repeated field is not allowed.
ExpectParseFailureForJson(
- "RepeatedFieldTrailingComma",
+ "RepeatedFieldTrailingComma", RECOMMENDED,
R"({"repeatedInt32": [1, 2, 3, 4,]})");
ExpectParseFailureForJson(
- "RepeatedFieldTrailingCommaWithSpace",
+ "RepeatedFieldTrailingCommaWithSpace", RECOMMENDED,
"{\"repeatedInt32\": [1, 2, 3, 4 ,]}");
ExpectParseFailureForJson(
- "RepeatedFieldTrailingCommaWithSpaceCommaSpace",
+ "RepeatedFieldTrailingCommaWithSpaceCommaSpace", RECOMMENDED,
"{\"repeatedInt32\": [1, 2, 3, 4 , ]}");
ExpectParseFailureForJson(
- "RepeatedFieldTrailingCommaWithNewlines",
+ "RepeatedFieldTrailingCommaWithNewlines", RECOMMENDED,
"{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}");
// Map fields.
RunValidJsonTest(
- "Int32MapField",
+ "Int32MapField", REQUIRED,
R"({"mapInt32Int32": {"1": 2, "3": 4}})",
"map_int32_int32: {key: 1 value: 2}"
"map_int32_int32: {key: 3 value: 4}");
ExpectParseFailureForJson(
- "Int32MapFieldKeyNotQuoted",
+ "Int32MapFieldKeyNotQuoted", RECOMMENDED,
R"({"mapInt32Int32": {1: 2, 3: 4}})");
RunValidJsonTest(
- "Uint32MapField",
+ "Uint32MapField", REQUIRED,
R"({"mapUint32Uint32": {"1": 2, "3": 4}})",
"map_uint32_uint32: {key: 1 value: 2}"
"map_uint32_uint32: {key: 3 value: 4}");
ExpectParseFailureForJson(
- "Uint32MapFieldKeyNotQuoted",
+ "Uint32MapFieldKeyNotQuoted", RECOMMENDED,
R"({"mapUint32Uint32": {1: 2, 3: 4}})");
RunValidJsonTest(
- "Int64MapField",
+ "Int64MapField", REQUIRED,
R"({"mapInt64Int64": {"1": 2, "3": 4}})",
"map_int64_int64: {key: 1 value: 2}"
"map_int64_int64: {key: 3 value: 4}");
ExpectParseFailureForJson(
- "Int64MapFieldKeyNotQuoted",
+ "Int64MapFieldKeyNotQuoted", RECOMMENDED,
R"({"mapInt64Int64": {1: 2, 3: 4}})");
RunValidJsonTest(
- "Uint64MapField",
+ "Uint64MapField", REQUIRED,
R"({"mapUint64Uint64": {"1": 2, "3": 4}})",
"map_uint64_uint64: {key: 1 value: 2}"
"map_uint64_uint64: {key: 3 value: 4}");
ExpectParseFailureForJson(
- "Uint64MapFieldKeyNotQuoted",
+ "Uint64MapFieldKeyNotQuoted", RECOMMENDED,
R"({"mapUint64Uint64": {1: 2, 3: 4}})");
RunValidJsonTest(
- "BoolMapField",
+ "BoolMapField", REQUIRED,
R"({"mapBoolBool": {"true": true, "false": false}})",
"map_bool_bool: {key: true value: true}"
"map_bool_bool: {key: false value: false}");
ExpectParseFailureForJson(
- "BoolMapFieldKeyNotQuoted",
+ "BoolMapFieldKeyNotQuoted", RECOMMENDED,
R"({"mapBoolBool": {true: true, false: false}})");
RunValidJsonTest(
- "MessageMapField",
+ "MessageMapField", REQUIRED,
R"({
"mapStringNestedMessage": {
"hello": {"a": 1234},
@@ -1535,26 +1822,34 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// Since Map keys are represented as JSON strings, escaping should be allowed.
RunValidJsonTest(
- "Int32MapEscapedKey",
+ "Int32MapEscapedKey", REQUIRED,
R"({"mapInt32Int32": {"\u0031": 2}})",
"map_int32_int32: {key: 1 value: 2}");
RunValidJsonTest(
- "Int64MapEscapedKey",
+ "Int64MapEscapedKey", REQUIRED,
R"({"mapInt64Int64": {"\u0031": 2}})",
"map_int64_int64: {key: 1 value: 2}");
RunValidJsonTest(
- "BoolMapEscapedKey",
+ "BoolMapEscapedKey", REQUIRED,
R"({"mapBoolBool": {"tr\u0075e": true}})",
"map_bool_bool: {key: true value: true}");
// "null" is accepted for all fields types.
RunValidJsonTest(
- "AllFieldAcceptNull",
+ "AllFieldAcceptNull", REQUIRED,
R"({
"optionalInt32": null,
"optionalInt64": null,
"optionalUint32": null,
"optionalUint64": null,
+ "optionalSint32": null,
+ "optionalSint64": null,
+ "optionalFixed32": null,
+ "optionalFixed64": null,
+ "optionalSfixed32": null,
+ "optionalSfixed64": null,
+ "optionalFloat": null,
+ "optionalDouble": null,
"optionalBool": null,
"optionalString": null,
"optionalBytes": null,
@@ -1564,6 +1859,14 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"repeatedInt64": null,
"repeatedUint32": null,
"repeatedUint64": null,
+ "repeatedSint32": null,
+ "repeatedSint64": null,
+ "repeatedFixed32": null,
+ "repeatedFixed64": null,
+ "repeatedSfixed32": null,
+ "repeatedSfixed64": null,
+ "repeatedFloat": null,
+ "repeatedDouble": null,
"repeatedBool": null,
"repeatedString": null,
"repeatedBytes": null,
@@ -1577,71 +1880,83 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// Repeated field elements cannot be null.
ExpectParseFailureForJson(
- "RepeatedFieldPrimitiveElementIsNull",
+ "RepeatedFieldPrimitiveElementIsNull", RECOMMENDED,
R"({"repeatedInt32": [1, null, 2]})");
ExpectParseFailureForJson(
- "RepeatedFieldMessageElementIsNull",
+ "RepeatedFieldMessageElementIsNull", RECOMMENDED,
R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})");
// Map field keys cannot be null.
ExpectParseFailureForJson(
- "MapFieldKeyIsNull",
+ "MapFieldKeyIsNull", RECOMMENDED,
R"({"mapInt32Int32": {null: 1}})");
// Map field values cannot be null.
ExpectParseFailureForJson(
- "MapFieldValueIsNull",
+ "MapFieldValueIsNull", RECOMMENDED,
R"({"mapInt32Int32": {"0": null}})");
// http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double
// quotes.
ExpectParseFailureForJson(
- "StringFieldSingleQuoteKey",
+ "StringFieldSingleQuoteKey", RECOMMENDED,
R"({'optionalString': "Hello world!"})");
ExpectParseFailureForJson(
- "StringFieldSingleQuoteValue",
+ "StringFieldSingleQuoteValue", RECOMMENDED,
R"({"optionalString": 'Hello world!'})");
ExpectParseFailureForJson(
- "StringFieldSingleQuoteBoth",
+ "StringFieldSingleQuoteBoth", RECOMMENDED,
R"({'optionalString': 'Hello world!'})");
+ // Unknown fields.
+ {
+ TestAllTypesProto3 messageProto3;
+ TestAllTypesProto2 messageProto2;
+ //TODO(yilunchong): update this behavior when unknown field's behavior
+ // changed in open source. Also delete
+ // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
+ // from failure list of python_cpp python java
+ TestUnknownMessage(messageProto3, true);
+ TestUnknownMessage(messageProto2, false);
+ }
+
// Wrapper types.
RunValidJsonTest(
- "OptionalBoolWrapper",
+ "OptionalBoolWrapper", REQUIRED,
R"({"optionalBoolWrapper": false})",
"optional_bool_wrapper: {value: false}");
RunValidJsonTest(
- "OptionalInt32Wrapper",
+ "OptionalInt32Wrapper", REQUIRED,
R"({"optionalInt32Wrapper": 0})",
"optional_int32_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalUint32Wrapper",
+ "OptionalUint32Wrapper", REQUIRED,
R"({"optionalUint32Wrapper": 0})",
"optional_uint32_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalInt64Wrapper",
+ "OptionalInt64Wrapper", REQUIRED,
R"({"optionalInt64Wrapper": 0})",
"optional_int64_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalUint64Wrapper",
+ "OptionalUint64Wrapper", REQUIRED,
R"({"optionalUint64Wrapper": 0})",
"optional_uint64_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalFloatWrapper",
+ "OptionalFloatWrapper", REQUIRED,
R"({"optionalFloatWrapper": 0})",
"optional_float_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalDoubleWrapper",
+ "OptionalDoubleWrapper", REQUIRED,
R"({"optionalDoubleWrapper": 0})",
"optional_double_wrapper: {value: 0}");
RunValidJsonTest(
- "OptionalStringWrapper",
+ "OptionalStringWrapper", REQUIRED,
R"({"optionalStringWrapper": ""})",
R"(optional_string_wrapper: {value: ""})");
RunValidJsonTest(
- "OptionalBytesWrapper",
+ "OptionalBytesWrapper", REQUIRED,
R"({"optionalBytesWrapper": ""})",
R"(optional_bytes_wrapper: {value: ""})");
RunValidJsonTest(
- "OptionalWrapperTypesWithNonDefaultValue",
+ "OptionalWrapperTypesWithNonDefaultValue", REQUIRED,
R"({
"optionalBoolWrapper": true,
"optionalInt32Wrapper": 1,
@@ -1665,56 +1980,56 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
optional_bytes_wrapper: {value: "\x01\x02"}
)");
RunValidJsonTest(
- "RepeatedBoolWrapper",
+ "RepeatedBoolWrapper", REQUIRED,
R"({"repeatedBoolWrapper": [true, false]})",
"repeated_bool_wrapper: {value: true}"
"repeated_bool_wrapper: {value: false}");
RunValidJsonTest(
- "RepeatedInt32Wrapper",
+ "RepeatedInt32Wrapper", REQUIRED,
R"({"repeatedInt32Wrapper": [0, 1]})",
"repeated_int32_wrapper: {value: 0}"
"repeated_int32_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedUint32Wrapper",
+ "RepeatedUint32Wrapper", REQUIRED,
R"({"repeatedUint32Wrapper": [0, 1]})",
"repeated_uint32_wrapper: {value: 0}"
"repeated_uint32_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedInt64Wrapper",
+ "RepeatedInt64Wrapper", REQUIRED,
R"({"repeatedInt64Wrapper": [0, 1]})",
"repeated_int64_wrapper: {value: 0}"
"repeated_int64_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedUint64Wrapper",
+ "RepeatedUint64Wrapper", REQUIRED,
R"({"repeatedUint64Wrapper": [0, 1]})",
"repeated_uint64_wrapper: {value: 0}"
"repeated_uint64_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedFloatWrapper",
+ "RepeatedFloatWrapper", REQUIRED,
R"({"repeatedFloatWrapper": [0, 1]})",
"repeated_float_wrapper: {value: 0}"
"repeated_float_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedDoubleWrapper",
+ "RepeatedDoubleWrapper", REQUIRED,
R"({"repeatedDoubleWrapper": [0, 1]})",
"repeated_double_wrapper: {value: 0}"
"repeated_double_wrapper: {value: 1}");
RunValidJsonTest(
- "RepeatedStringWrapper",
+ "RepeatedStringWrapper", REQUIRED,
R"({"repeatedStringWrapper": ["", "AQI="]})",
R"(
repeated_string_wrapper: {value: ""}
repeated_string_wrapper: {value: "AQI="}
)");
RunValidJsonTest(
- "RepeatedBytesWrapper",
+ "RepeatedBytesWrapper", REQUIRED,
R"({"repeatedBytesWrapper": ["", "AQI="]})",
R"(
repeated_bytes_wrapper: {value: ""}
repeated_bytes_wrapper: {value: "\x01\x02"}
)");
RunValidJsonTest(
- "WrapperTypesWithNullValue",
+ "WrapperTypesWithNullValue", REQUIRED,
R"({
"optionalBoolWrapper": null,
"optionalInt32Wrapper": null,
@@ -1739,55 +2054,59 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// Duration
RunValidJsonTest(
- "DurationMinValue",
+ "DurationMinValue", REQUIRED,
R"({"optionalDuration": "-315576000000.999999999s"})",
"optional_duration: {seconds: -315576000000 nanos: -999999999}");
RunValidJsonTest(
- "DurationMaxValue",
+ "DurationMaxValue", REQUIRED,
R"({"optionalDuration": "315576000000.999999999s"})",
"optional_duration: {seconds: 315576000000 nanos: 999999999}");
RunValidJsonTest(
- "DurationRepeatedValue",
+ "DurationRepeatedValue", REQUIRED,
R"({"repeatedDuration": ["1.5s", "-1.5s"]})",
"repeated_duration: {seconds: 1 nanos: 500000000}"
"repeated_duration: {seconds: -1 nanos: -500000000}");
+ RunValidJsonTest(
+ "DurationNull", REQUIRED,
+ R"({"optionalDuration": null})",
+ "");
ExpectParseFailureForJson(
- "DurationMissingS",
+ "DurationMissingS", REQUIRED,
R"({"optionalDuration": "1"})");
ExpectParseFailureForJson(
- "DurationJsonInputTooSmall",
+ "DurationJsonInputTooSmall", REQUIRED,
R"({"optionalDuration": "-315576000001.000000000s"})");
ExpectParseFailureForJson(
- "DurationJsonInputTooLarge",
+ "DurationJsonInputTooLarge", REQUIRED,
R"({"optionalDuration": "315576000001.000000000s"})");
ExpectSerializeFailureForJson(
- "DurationProtoInputTooSmall",
+ "DurationProtoInputTooSmall", REQUIRED,
"optional_duration: {seconds: -315576000001 nanos: 0}");
ExpectSerializeFailureForJson(
- "DurationProtoInputTooLarge",
+ "DurationProtoInputTooLarge", REQUIRED,
"optional_duration: {seconds: 315576000001 nanos: 0}");
RunValidJsonTestWithValidator(
- "DurationHasZeroFractionalDigit",
+ "DurationHasZeroFractionalDigit", RECOMMENDED,
R"({"optionalDuration": "1.000000000s"})",
[](const Json::Value& value) {
return value["optionalDuration"].asString() == "1s";
});
RunValidJsonTestWithValidator(
- "DurationHas3FractionalDigits",
+ "DurationHas3FractionalDigits", RECOMMENDED,
R"({"optionalDuration": "1.010000000s"})",
[](const Json::Value& value) {
return value["optionalDuration"].asString() == "1.010s";
});
RunValidJsonTestWithValidator(
- "DurationHas6FractionalDigits",
+ "DurationHas6FractionalDigits", RECOMMENDED,
R"({"optionalDuration": "1.000010000s"})",
[](const Json::Value& value) {
return value["optionalDuration"].asString() == "1.000010s";
});
RunValidJsonTestWithValidator(
- "DurationHas9FractionalDigits",
+ "DurationHas9FractionalDigits", RECOMMENDED,
R"({"optionalDuration": "1.000000010s"})",
[](const Json::Value& value) {
return value["optionalDuration"].asString() == "1.000000010s";
@@ -1795,15 +2114,15 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// Timestamp
RunValidJsonTest(
- "TimestampMinValue",
+ "TimestampMinValue", REQUIRED,
R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})",
"optional_timestamp: {seconds: -62135596800}");
RunValidJsonTest(
- "TimestampMaxValue",
+ "TimestampMaxValue", REQUIRED,
R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})",
"optional_timestamp: {seconds: 253402300799 nanos: 999999999}");
RunValidJsonTest(
- "TimestampRepeatedValue",
+ "TimestampRepeatedValue", REQUIRED,
R"({
"repeatedTimestamp": [
"0001-01-01T00:00:00Z",
@@ -1813,68 +2132,72 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"repeated_timestamp: {seconds: -62135596800}"
"repeated_timestamp: {seconds: 253402300799 nanos: 999999999}");
RunValidJsonTest(
- "TimestampWithPositiveOffset",
+ "TimestampWithPositiveOffset", REQUIRED,
R"({"optionalTimestamp": "1970-01-01T08:00:00+08:00"})",
"optional_timestamp: {seconds: 0}");
RunValidJsonTest(
- "TimestampWithNegativeOffset",
+ "TimestampWithNegativeOffset", REQUIRED,
R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
"optional_timestamp: {seconds: 0}");
+ RunValidJsonTest(
+ "TimestampNull", REQUIRED,
+ R"({"optionalTimestamp": null})",
+ "");
ExpectParseFailureForJson(
- "TimestampJsonInputTooSmall",
+ "TimestampJsonInputTooSmall", REQUIRED,
R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})");
ExpectParseFailureForJson(
- "TimestampJsonInputTooLarge",
+ "TimestampJsonInputTooLarge", REQUIRED,
R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})");
ExpectParseFailureForJson(
- "TimestampJsonInputMissingZ",
+ "TimestampJsonInputMissingZ", REQUIRED,
R"({"optionalTimestamp": "0001-01-01T00:00:00"})");
ExpectParseFailureForJson(
- "TimestampJsonInputMissingT",
+ "TimestampJsonInputMissingT", REQUIRED,
R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})");
ExpectParseFailureForJson(
- "TimestampJsonInputLowercaseZ",
+ "TimestampJsonInputLowercaseZ", REQUIRED,
R"({"optionalTimestamp": "0001-01-01T00:00:00z"})");
ExpectParseFailureForJson(
- "TimestampJsonInputLowercaseT",
+ "TimestampJsonInputLowercaseT", REQUIRED,
R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})");
ExpectSerializeFailureForJson(
- "TimestampProtoInputTooSmall",
+ "TimestampProtoInputTooSmall", REQUIRED,
"optional_timestamp: {seconds: -62135596801}");
ExpectSerializeFailureForJson(
- "TimestampProtoInputTooLarge",
+ "TimestampProtoInputTooLarge", REQUIRED,
"optional_timestamp: {seconds: 253402300800}");
RunValidJsonTestWithValidator(
- "TimestampZeroNormalized",
+ "TimestampZeroNormalized", RECOMMENDED,
R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})",
[](const Json::Value& value) {
return value["optionalTimestamp"].asString() ==
"1970-01-01T00:00:00Z";
});
RunValidJsonTestWithValidator(
- "TimestampHasZeroFractionalDigit",
+ "TimestampHasZeroFractionalDigit", RECOMMENDED,
R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})",
[](const Json::Value& value) {
return value["optionalTimestamp"].asString() ==
"1970-01-01T00:00:00Z";
});
RunValidJsonTestWithValidator(
- "TimestampHas3FractionalDigits",
+ "TimestampHas3FractionalDigits", RECOMMENDED,
R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})",
[](const Json::Value& value) {
return value["optionalTimestamp"].asString() ==
"1970-01-01T00:00:00.010Z";
});
RunValidJsonTestWithValidator(
- "TimestampHas6FractionalDigits",
+ "TimestampHas6FractionalDigits", RECOMMENDED,
R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})",
[](const Json::Value& value) {
return value["optionalTimestamp"].asString() ==
"1970-01-01T00:00:00.000010Z";
});
RunValidJsonTestWithValidator(
- "TimestampHas9FractionalDigits",
+ "TimestampHas9FractionalDigits", RECOMMENDED,
R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})",
[](const Json::Value& value) {
return value["optionalTimestamp"].asString() ==
@@ -1883,25 +2206,25 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// FieldMask
RunValidJsonTest(
- "FieldMask",
+ "FieldMask", REQUIRED,
R"({"optionalFieldMask": "foo,barBaz"})",
R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})");
ExpectParseFailureForJson(
- "FieldMaskInvalidCharacter",
+ "FieldMaskInvalidCharacter", RECOMMENDED,
R"({"optionalFieldMask": "foo,bar_bar"})");
ExpectSerializeFailureForJson(
- "FieldMaskPathsDontRoundTrip",
+ "FieldMaskPathsDontRoundTrip", RECOMMENDED,
R"(optional_field_mask: {paths: "fooBar"})");
ExpectSerializeFailureForJson(
- "FieldMaskNumbersDontRoundTrip",
+ "FieldMaskNumbersDontRoundTrip", RECOMMENDED,
R"(optional_field_mask: {paths: "foo_3_bar"})");
ExpectSerializeFailureForJson(
- "FieldMaskTooManyUnderscore",
+ "FieldMaskTooManyUnderscore", RECOMMENDED,
R"(optional_field_mask: {paths: "foo__bar"})");
// Struct
RunValidJsonTest(
- "Struct",
+ "Struct", REQUIRED,
R"({
"optionalStruct": {
"nullValue": null,
@@ -1967,27 +2290,27 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// Value
RunValidJsonTest(
- "ValueAcceptInteger",
+ "ValueAcceptInteger", REQUIRED,
R"({"optionalValue": 1})",
"optional_value: { number_value: 1}");
RunValidJsonTest(
- "ValueAcceptFloat",
+ "ValueAcceptFloat", REQUIRED,
R"({"optionalValue": 1.5})",
"optional_value: { number_value: 1.5}");
RunValidJsonTest(
- "ValueAcceptBool",
+ "ValueAcceptBool", REQUIRED,
R"({"optionalValue": false})",
"optional_value: { bool_value: false}");
RunValidJsonTest(
- "ValueAcceptNull",
+ "ValueAcceptNull", REQUIRED,
R"({"optionalValue": null})",
"optional_value: { null_value: NULL_VALUE}");
RunValidJsonTest(
- "ValueAcceptString",
+ "ValueAcceptString", REQUIRED,
R"({"optionalValue": "hello"})",
R"(optional_value: { string_value: "hello"})");
RunValidJsonTest(
- "ValueAcceptList",
+ "ValueAcceptList", REQUIRED,
R"({"optionalValue": [0, "hello"]})",
R"(
optional_value: {
@@ -2002,7 +2325,25 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "ValueAcceptObject",
+ "ValueAcceptListWithNull", REQUIRED,
+ R"({"optionalValue": ["x", null, "y"]})",
+ R"(
+ optional_value: {
+ list_value: {
+ values: {
+ string_value: "x"
+ }
+ values: {
+ null_value: NULL_VALUE
+ }
+ values: {
+ string_value: "y"
+ }
+ }
+ }
+ )");
+ RunValidJsonTest(
+ "ValueAcceptObject", REQUIRED,
R"({"optionalValue": {"value": 1}})",
R"(
optional_value: {
@@ -2019,27 +2360,27 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
// Any
RunValidJsonTest(
- "Any",
+ "Any", REQUIRED,
R"({
"optionalAny": {
- "@type": "type.googleapis.com/conformance.TestAllTypes",
+ "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
"optionalInt32": 12345
}
})",
R"(
optional_any: {
- [type.googleapis.com/conformance.TestAllTypes] {
+ [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
optional_int32: 12345
}
}
)");
RunValidJsonTest(
- "AnyNested",
+ "AnyNested", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Any",
"value": {
- "@type": "type.googleapis.com/conformance.TestAllTypes",
+ "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
"optionalInt32": 12345
}
}
@@ -2047,7 +2388,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
R"(
optional_any: {
[type.googleapis.com/google.protobuf.Any] {
- [type.googleapis.com/conformance.TestAllTypes] {
+ [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
optional_int32: 12345
}
}
@@ -2055,23 +2396,23 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)");
// The special "@type" tag is not required to appear first.
RunValidJsonTest(
- "AnyUnorderedTypeTag",
+ "AnyUnorderedTypeTag", REQUIRED,
R"({
"optionalAny": {
"optionalInt32": 12345,
- "@type": "type.googleapis.com/conformance.TestAllTypes"
+ "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
}
})",
R"(
optional_any: {
- [type.googleapis.com/conformance.TestAllTypes] {
+ [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
optional_int32: 12345
}
}
)");
// Well-known types in Any.
RunValidJsonTest(
- "AnyWithInt32ValueWrapper",
+ "AnyWithInt32ValueWrapper", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Int32Value",
@@ -2086,7 +2427,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithDuration",
+ "AnyWithDuration", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Duration",
@@ -2102,7 +2443,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithTimestamp",
+ "AnyWithTimestamp", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Timestamp",
@@ -2118,7 +2459,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithFieldMask",
+ "AnyWithFieldMask", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.FieldMask",
@@ -2133,7 +2474,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithStruct",
+ "AnyWithStruct", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Struct",
@@ -2155,7 +2496,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithValueForJsonObject",
+ "AnyWithValueForJsonObject", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Value",
@@ -2179,7 +2520,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
}
)");
RunValidJsonTest(
- "AnyWithValueForInteger",
+ "AnyWithValueForInteger", REQUIRED,
R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Value",
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 56689318..2649f8b2 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -49,9 +49,14 @@
namespace conformance {
class ConformanceRequest;
class ConformanceResponse;
-class TestAllTypes;
} // namespace conformance
+namespace protobuf_test_messages {
+namespace proto3 {
+class TestAllTypesProto3;
+} // namespace proto3
+} // namespace protobuf_test_messages
+
namespace google {
namespace protobuf {
@@ -91,7 +96,7 @@ class ConformanceTestRunner {
//
class ConformanceTestSuite {
public:
- ConformanceTestSuite() : verbose_(false) {}
+ ConformanceTestSuite() : verbose_(false), enforce_recommended_(false) {}
void SetVerbose(bool verbose) { verbose_ = verbose; }
@@ -104,6 +109,18 @@ class ConformanceTestSuite {
void SetFailureList(const std::string& filename,
const std::vector<std::string>& failure_list);
+ // Whether to require the testee to pass RECOMMENDED tests. By default failing
+ // a RECOMMENDED test case will not fail the entire suite but will only
+ // generated a warning. If this flag is set to true, RECOMMENDED tests will
+ // be treated the same way as REQUIRED tests and failing a RECOMMENDED test
+ // case will cause the entire test suite to fail as well. An implementation
+ // can enable this if it wants to be strictly conforming to protobuf spec.
+ // See the comments about ConformanceLevel below to learn more about the
+ // difference between REQUIRED and RECOMMENDED test cases.
+ void SetEnforceRecommended(bool value) {
+ enforce_recommended_ = value;
+ }
+
// Run all the conformance tests against the given test runner.
// Test output will be stored in "output".
//
@@ -113,8 +130,27 @@ class ConformanceTestSuite {
bool RunSuite(ConformanceTestRunner* runner, std::string* output);
private:
+ // Test cases are classified into a few categories:
+ // REQUIRED: the test case must be passed for an implementation to be
+ // interoperable with other implementations. For example, a
+ // parser implementaiton must accept both packed and unpacked
+ // form of repeated primitive fields.
+ // RECOMMENDED: the test case is not required for the implementation to
+ // be interoperable with other implementations, but is
+ // recommended for best performance and compatibility. For
+ // example, a proto3 serializer should serialize repeated
+ // primitive fields in packed form, but an implementation
+ // failing to do so will still be able to communicate with
+ // other implementations.
+ enum ConformanceLevel {
+ REQUIRED = 0,
+ RECOMMENDED = 1,
+ };
+ string ConformanceLevelToString(ConformanceLevel level);
+
void ReportSuccess(const std::string& test_name);
void ReportFailure(const string& test_name,
+ ConformanceLevel level,
const conformance::ConformanceRequest& request,
const conformance::ConformanceResponse& response,
const char* fmt, ...);
@@ -124,38 +160,82 @@ class ConformanceTestSuite {
void RunTest(const std::string& test_name,
const conformance::ConformanceRequest& request,
conformance::ConformanceResponse* response);
- void RunValidInputTest(const string& test_name, const string& input,
+ void RunValidInputTest(const string& test_name,
+ ConformanceLevel level,
+ const string& input,
conformance::WireFormat input_format,
const string& equivalent_text_format,
- conformance::WireFormat requested_output);
- void RunValidJsonTest(const string& test_name, const string& input_json,
+ conformance::WireFormat requested_output,
+ bool isProto3);
+ void RunValidBinaryInputTest(const string& test_name,
+ ConformanceLevel level,
+ const string& input,
+ conformance::WireFormat input_format,
+ const string& equivalent_wire_format,
+ conformance::WireFormat requested_output,
+ bool isProto3);
+ void RunValidJsonTest(const string& test_name,
+ ConformanceLevel level,
+ const string& input_json,
const string& equivalent_text_format);
- void RunValidJsonTestWithProtobufInput(const string& test_name,
- const conformance::TestAllTypes& input,
- const string& equivalent_text_format);
- void RunValidProtobufTest(const string& test_name,
- const conformance::TestAllTypes& input,
- const string& equivalent_text_format);
+ void RunValidJsonTestWithProtobufInput(
+ const string& test_name,
+ ConformanceLevel level,
+ const protobuf_test_messages::proto3::TestAllTypesProto3& input,
+ const string& equivalent_text_format);
+ void RunValidProtobufTest(const string& test_name, ConformanceLevel level,
+ const string& input_protobuf,
+ const string& equivalent_text_format,
+ bool isProto3);
+ void RunValidBinaryProtobufTest(const string& test_name,
+ ConformanceLevel level,
+ const string& input_protobuf,
+ bool isProto3);
+ void RunValidProtobufTestWithMessage(
+ const string& test_name, ConformanceLevel level,
+ const Message *input,
+ const string& equivalent_text_format,
+ bool isProto3);
typedef std::function<bool(const Json::Value&)> Validator;
void RunValidJsonTestWithValidator(const string& test_name,
+ ConformanceLevel level,
const string& input_json,
const Validator& validator);
void ExpectParseFailureForJson(const string& test_name,
+ ConformanceLevel level,
const string& input_json);
void ExpectSerializeFailureForJson(const string& test_name,
+ ConformanceLevel level,
const string& text_format);
+ void ExpectParseFailureForProtoWithProtoVersion (const string& proto,
+ const string& test_name,
+ ConformanceLevel level,
+ bool isProto3);
void ExpectParseFailureForProto(const std::string& proto,
- const std::string& test_name);
+ const std::string& test_name,
+ ConformanceLevel level);
void ExpectHardParseFailureForProto(const std::string& proto,
- const std::string& test_name);
+ const std::string& test_name,
+ ConformanceLevel level);
void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type);
- bool CheckSetEmpty(const set<string>& set_to_check,
+ void TestIllegalTags();
+ template <class MessageType>
+ void TestOneofMessage (MessageType &message,
+ bool isProto3);
+ template <class MessageType>
+ void TestUnknownMessage (MessageType &message,
+ bool isProto3);
+ void TestValidDataForType(
+ google::protobuf::FieldDescriptor::Type,
+ std::vector<std::pair<std::string, std::string>> values);
+ bool CheckSetEmpty(const std::set<string>& set_to_check,
const std::string& write_to_file, const std::string& msg);
ConformanceTestRunner* runner_;
int successes_;
int expected_failures_;
bool verbose_;
+ bool enforce_recommended_;
std::string output_;
std::string failure_list_filename_;
@@ -176,8 +256,7 @@ class ConformanceTestSuite {
// The set of tests that the testee opted out of;
std::set<std::string> skipped_;
- google::protobuf::internal::scoped_ptr<google::protobuf::util::TypeResolver>
- type_resolver_;
+ std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver_;
std::string type_url_;
};
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index d6b1175c..b0357b87 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -68,7 +68,6 @@
using conformance::ConformanceRequest;
using conformance::ConformanceResponse;
-using google::protobuf::internal::scoped_array;
using google::protobuf::StringAppendF;
using std::string;
using std::vector;
@@ -183,7 +182,7 @@ class ForkPipeRunner : public google::protobuf::ConformanceTestRunner {
CHECK_SYSCALL(close(toproc_pipe_fd[1]));
CHECK_SYSCALL(close(fromproc_pipe_fd[0]));
- scoped_array<char> executable(new char[executable_.size() + 1]);
+ std::unique_ptr<char[]> executable(new char[executable_.size() + 1]);
memcpy(executable.get(), executable_.c_str(), executable_.size());
executable[executable_.size()] = '\0';
@@ -251,10 +250,20 @@ void UsageError() {
" should contain one test name per\n");
fprintf(stderr,
" line. Use '#' for comments.\n");
+ fprintf(stderr,
+ " --enforce_recommended Enforce that recommended test\n");
+ fprintf(stderr,
+ " cases are also passing. Specify\n");
+ fprintf(stderr,
+ " this flag if you want to be\n");
+ fprintf(stderr,
+ " strictly conforming to protobuf\n");
+ fprintf(stderr,
+ " spec.\n");
exit(1);
}
-void ParseFailureList(const char *filename, vector<string>* failure_list) {
+void ParseFailureList(const char *filename, std::vector<string>* failure_list) {
std::ifstream infile(filename);
if (!infile.is_open()) {
@@ -281,7 +290,7 @@ int main(int argc, char *argv[]) {
google::protobuf::ConformanceTestSuite suite;
string failure_list_filename;
- vector<string> failure_list;
+ std::vector<string> failure_list;
for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], "--failure_list") == 0) {
@@ -290,6 +299,8 @@ int main(int argc, char *argv[]) {
ParseFailureList(argv[arg], &failure_list);
} else if (strcmp(argv[arg], "--verbose") == 0) {
suite.SetVerbose(true);
+ } else if (strcmp(argv[arg], "--enforce_recommended") == 0) {
+ suite.SetEnforceRecommended(true);
} else if (argv[arg][0] == '-') {
fprintf(stderr, "Unknown option: %s\n", argv[arg]);
UsageError();
diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt
index 5e17176e..752fbb5d 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -7,48 +7,50 @@
# TODO(haberman): insert links to corresponding bugs tracking the issue.
# Should we use GitHub issues or the Google-internal bug tracker?
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.AnyUnorderedTypeTag.JsonOutput
-JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-JsonInput.BoolFieldDoubleQuotedFalse
-JsonInput.BoolFieldDoubleQuotedTrue
-JsonInput.BytesFieldNoPadding
-JsonInput.DoubleFieldTooSmall
-JsonInput.DurationHasZeroFractionalDigit.Validator
-JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldNameDuplicate
-JsonInput.FieldNameDuplicateDifferentCasing1
-JsonInput.FieldNameDuplicateDifferentCasing2
-JsonInput.FieldNameNotQuoted
-JsonInput.MapFieldValueIsNull
-JsonInput.RepeatedFieldMessageElementIsNull
-JsonInput.RepeatedFieldPrimitiveElementIsNull
-JsonInput.RepeatedFieldTrailingComma
-JsonInput.RepeatedFieldTrailingCommaWithNewlines
-JsonInput.RepeatedFieldTrailingCommaWithSpace
-JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
-JsonInput.StringFieldSingleQuoteBoth
-JsonInput.StringFieldSingleQuoteKey
-JsonInput.StringFieldSingleQuoteValue
-JsonInput.StringFieldUppercaseEscapeLetter
-JsonInput.TrailingCommaInAnObject
-JsonInput.TrailingCommaInAnObjectWithNewlines
-JsonInput.TrailingCommaInAnObjectWithSpace
-JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
-JsonInput.WrapperTypesWithNullValue.JsonOutput
-JsonInput.WrapperTypesWithNullValue.ProtobufOutput
-ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
-ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-ProtobufInput.PrematureEofInPackedField.BOOL
-ProtobufInput.PrematureEofInPackedField.ENUM
-ProtobufInput.PrematureEofInPackedField.INT32
-ProtobufInput.PrematureEofInPackedField.INT64
-ProtobufInput.PrematureEofInPackedField.SINT32
-ProtobufInput.PrematureEofInPackedField.SINT64
-ProtobufInput.PrematureEofInPackedField.UINT32
-ProtobufInput.PrematureEofInPackedField.UINT64
-ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.FieldNameDuplicate
+Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1
+Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2
+Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
+Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter
+Recommended.Proto3.JsonInput.TrailingCommaInAnObject
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt
index d8bfe1bb..2a20aa78 100644
--- a/conformance/failure_list_csharp.txt
+++ b/conformance/failure_list_csharp.txt
@@ -1,4 +1,2 @@
-JsonInput.FieldNameWithMixedCases.JsonOutput
-JsonInput.FieldNameWithMixedCases.ProtobufOutput
-JsonInput.FieldNameWithMixedCases.Validator
-JsonInput.OriginalProtoFieldName.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt
index b2122c8b..dc1f9ba5 100644
--- a/conformance/failure_list_java.txt
+++ b/conformance/failure_list_java.txt
@@ -4,48 +4,44 @@
# By listing them here we can keep tabs on which ones are failing and be sure
# that we don't introduce regressions in other tests.
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.BoolFieldAllCapitalFalse
-JsonInput.BoolFieldAllCapitalTrue
-JsonInput.BoolFieldCamelCaseFalse
-JsonInput.BoolFieldCamelCaseTrue
-JsonInput.BoolFieldDoubleQuotedFalse
-JsonInput.BoolFieldDoubleQuotedTrue
-JsonInput.BoolMapFieldKeyNotQuoted
-JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.EnumFieldNotQuoted
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FieldNameDuplicate
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
-JsonInput.FieldNameNotQuoted
-JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
-JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
-JsonInput.FieldNameWithDoubleUnderscores.Validator
-JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.Int32FieldLeadingZero
-JsonInput.Int32FieldNegativeWithLeadingZero
-JsonInput.Int32FieldPlusSign
-JsonInput.Int32MapFieldKeyNotQuoted
-JsonInput.Int64MapFieldKeyNotQuoted
-JsonInput.JsonWithComments
-JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
-JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-JsonInput.StringFieldNotAString
-JsonInput.StringFieldSingleQuoteBoth
-JsonInput.StringFieldSingleQuoteKey
-JsonInput.StringFieldSingleQuoteValue
-JsonInput.StringFieldSurrogateInWrongOrder
-JsonInput.StringFieldUnpairedHighSurrogate
-JsonInput.StringFieldUnpairedLowSurrogate
-JsonInput.StringFieldUppercaseEscapeLetter
-JsonInput.Uint32MapFieldKeyNotQuoted
-JsonInput.Uint64MapFieldKeyNotQuoted
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
+Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.FieldNameDuplicate
+Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.JsonWithComments
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
+Required.Proto3.JsonInput.EnumFieldNotQuoted
+Required.Proto3.JsonInput.Int32FieldLeadingZero
+Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
+Required.Proto3.JsonInput.Int32FieldPlusSign
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.Proto3.JsonInput.StringFieldNotAString
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt
new file mode 100644
index 00000000..f8f6a578
--- /dev/null
+++ b/conformance/failure_list_js.txt
@@ -0,0 +1,13 @@
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
diff --git a/conformance/failure_list_objc.txt b/conformance/failure_list_objc.txt
index dd538c10..e34501ea 100644
--- a/conformance/failure_list_objc.txt
+++ b/conformance/failure_list_objc.txt
@@ -1,4 +1,2 @@
-# All tests currently passing.
-#
# JSON input or output tests are skipped (in conformance_objc.m) as mobile
# platforms don't support JSON wire format to avoid code bloat.
diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt
new file mode 100644
index 00000000..0d234112
--- /dev/null
+++ b/conformance/failure_list_php.txt
@@ -0,0 +1,20 @@
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.Int32FieldNotInteger
+Required.Proto3.JsonInput.Int64FieldNotInteger
+Required.Proto3.JsonInput.Uint32FieldNotInteger
+Required.Proto3.JsonInput.Uint64FieldNotInteger
+Required.Proto3.JsonInput.Int32FieldLeadingSpace
+Required.Proto3.JsonInput.OneofFieldDuplicate
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
new file mode 100644
index 00000000..088708e9
--- /dev/null
+++ b/conformance/failure_list_php_c.txt
@@ -0,0 +1,182 @@
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto3.JsonInput.BoolFieldIntegerOne
+Recommended.Proto3.JsonInput.BoolFieldIntegerZero
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.Int64FieldBeString.Validator
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
+Recommended.Proto3.JsonInput.OneofZeroBytes.ProtobufOutput
+Recommended.Proto3.JsonInput.OneofZeroString.JsonOutput
+Recommended.Proto3.JsonInput.OneofZeroString.ProtobufOutput
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput
+Required.DurationProtoInputTooLarge.JsonOutput
+Required.DurationProtoInputTooSmall.JsonOutput
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.BoolMapField.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldInfinity.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldNan.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldQuotedValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMinValue.JsonOutput
+Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueZero.JsonOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator
+Required.Proto3.JsonInput.FieldMask.JsonOutput
+Required.Proto3.JsonInput.FieldMask.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNan.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldQuotedValue.JsonOutput
+Required.Proto3.JsonInput.FloatFieldQuotedValue.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.Int32FieldExponentialFormat.JsonOutput
+Required.Proto3.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldMaxFloatValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldMinFloatValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldStringValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldStringValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldStringValueEscaped.JsonOutput
+Required.Proto3.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
+Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput
+Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput
+Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
+Required.Proto3.JsonInput.MessageField.JsonOutput
+Required.Proto3.JsonInput.MessageField.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldEscape.JsonOutput
+Required.Proto3.JsonInput.StringFieldEscape.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldNotAString
+Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscape.JsonOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
+Required.Proto3.JsonInput.Struct.JsonOutput
+Required.Proto3.JsonInput.Struct.ProtobufOutput
+Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput
+Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
+Required.TimestampProtoInputTooLarge.JsonOutput
+Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_php_zts_c.txt b/conformance/failure_list_php_zts_c.txt
new file mode 100644
index 00000000..d9a8fe36
--- /dev/null
+++ b/conformance/failure_list_php_zts_c.txt
@@ -0,0 +1,225 @@
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.JsonInput.BoolFieldIntegerOne
+Recommended.JsonInput.BoolFieldIntegerZero
+Recommended.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.JsonInput.Int64FieldBeString.Validator
+Recommended.JsonInput.OneofZeroBytes.JsonOutput
+Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
+Recommended.JsonInput.OneofZeroDouble.JsonOutput
+Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
+Recommended.JsonInput.OneofZeroFloat.JsonOutput
+Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
+Recommended.JsonInput.OneofZeroString.JsonOutput
+Recommended.JsonInput.OneofZeroString.ProtobufOutput
+Recommended.JsonInput.OneofZeroUint32.JsonOutput
+Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
+Recommended.JsonInput.OneofZeroUint64.JsonOutput
+Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
+Recommended.JsonInput.StringEndsWithEscapeChar
+Recommended.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
+Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
+Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
+Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
+Recommended.JsonInput.TimestampZeroNormalized.Validator
+Recommended.JsonInput.Uint64FieldBeString.Validator
+Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
+Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
+Recommended.ProtobufInput.OneofZeroString.JsonOutput
+Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
+Required.DurationProtoInputTooLarge.JsonOutput
+Required.DurationProtoInputTooSmall.JsonOutput
+Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
+Required.JsonInput.Any.JsonOutput
+Required.JsonInput.Any.ProtobufOutput
+Required.JsonInput.AnyNested.JsonOutput
+Required.JsonInput.AnyNested.ProtobufOutput
+Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.JsonInput.AnyWithDuration.JsonOutput
+Required.JsonInput.AnyWithDuration.ProtobufOutput
+Required.JsonInput.AnyWithFieldMask.JsonOutput
+Required.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.JsonInput.AnyWithStruct.JsonOutput
+Required.JsonInput.AnyWithStruct.ProtobufOutput
+Required.JsonInput.AnyWithTimestamp.JsonOutput
+Required.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.JsonInput.BoolFieldFalse.ProtobufOutput
+Required.JsonInput.BoolMapField.JsonOutput
+Required.JsonInput.DoubleFieldInfinity.JsonOutput
+Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
+Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
+Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
+Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.JsonInput.DoubleFieldNan.JsonOutput
+Required.JsonInput.DoubleFieldNan.ProtobufOutput
+Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
+Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
+Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
+Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
+Required.JsonInput.DurationMaxValue.JsonOutput
+Required.JsonInput.DurationMaxValue.ProtobufOutput
+Required.JsonInput.DurationMinValue.JsonOutput
+Required.JsonInput.DurationMinValue.ProtobufOutput
+Required.JsonInput.DurationRepeatedValue.JsonOutput
+Required.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.JsonInput.EnumField.ProtobufOutput
+Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
+Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+Required.JsonInput.EnumFieldUnknownValue.Validator
+Required.JsonInput.FieldMask.JsonOutput
+Required.JsonInput.FieldMask.ProtobufOutput
+Required.JsonInput.FloatFieldInfinity.JsonOutput
+Required.JsonInput.FloatFieldInfinity.ProtobufOutput
+Required.JsonInput.FloatFieldNan.JsonOutput
+Required.JsonInput.FloatFieldNan.ProtobufOutput
+Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
+Required.JsonInput.FloatFieldQuotedValue.JsonOutput
+Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
+Required.JsonInput.FloatFieldTooLarge
+Required.JsonInput.FloatFieldTooSmall
+Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
+Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
+Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
+Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+Required.JsonInput.Int32FieldStringValue.JsonOutput
+Required.JsonInput.Int32FieldStringValue.ProtobufOutput
+Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
+Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
+Required.JsonInput.Int32MapEscapedKey.JsonOutput
+Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
+Required.JsonInput.Int32MapField.JsonOutput
+Required.JsonInput.Int32MapField.ProtobufOutput
+Required.JsonInput.Int64FieldMaxValue.JsonOutput
+Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
+Required.JsonInput.Int64FieldMinValue.JsonOutput
+Required.JsonInput.Int64FieldMinValue.ProtobufOutput
+Required.JsonInput.Int64MapEscapedKey.JsonOutput
+Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
+Required.JsonInput.Int64MapField.JsonOutput
+Required.JsonInput.Int64MapField.ProtobufOutput
+Required.JsonInput.MessageField.JsonOutput
+Required.JsonInput.MessageField.ProtobufOutput
+Required.JsonInput.MessageMapField.JsonOutput
+Required.JsonInput.MessageMapField.ProtobufOutput
+Required.JsonInput.MessageRepeatedField.JsonOutput
+Required.JsonInput.MessageRepeatedField.ProtobufOutput
+Required.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.JsonInput.OptionalStringWrapper.JsonOutput
+Required.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.JsonInput.PrimitiveRepeatedField.JsonOutput
+Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
+Required.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.JsonInput.StringFieldEscape.JsonOutput
+Required.JsonInput.StringFieldEscape.ProtobufOutput
+Required.JsonInput.StringFieldNotAString
+Required.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
+Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
+Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
+Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
+Required.JsonInput.Struct.JsonOutput
+Required.JsonInput.Struct.ProtobufOutput
+Required.JsonInput.TimestampMaxValue.JsonOutput
+Required.JsonInput.TimestampMaxValue.ProtobufOutput
+Required.JsonInput.TimestampMinValue.JsonOutput
+Required.JsonInput.TimestampMinValue.ProtobufOutput
+Required.JsonInput.TimestampRepeatedValue.JsonOutput
+Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
+Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
+Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
+Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
+Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
+Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+Required.JsonInput.Uint32MapField.JsonOutput
+Required.JsonInput.Uint32MapField.ProtobufOutput
+Required.JsonInput.Uint64FieldMaxValue.JsonOutput
+Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
+Required.JsonInput.Uint64MapField.JsonOutput
+Required.JsonInput.Uint64MapField.ProtobufOutput
+Required.JsonInput.ValueAcceptBool.JsonOutput
+Required.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.JsonInput.ValueAcceptFloat.JsonOutput
+Required.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.JsonInput.ValueAcceptInteger.JsonOutput
+Required.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.JsonInput.ValueAcceptList.JsonOutput
+Required.JsonInput.ValueAcceptList.ProtobufOutput
+Required.JsonInput.ValueAcceptNull.JsonOutput
+Required.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.JsonInput.ValueAcceptObject.JsonOutput
+Required.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.JsonInput.ValueAcceptString.JsonOutput
+Required.JsonInput.ValueAcceptString.ProtobufOutput
+Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
+Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
+Required.TimestampProtoInputTooLarge.JsonOutput
+Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index d38b7828..e3ce7af7 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -1,46 +1,21 @@
-DurationProtoInputTooLarge.JsonOutput
-DurationProtoInputTooSmall.JsonOutput
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.AnyWithFieldMask.ProtobufOutput
-JsonInput.BytesFieldInvalidBase64Characters
-JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.DoubleFieldTooSmall
-JsonInput.DurationJsonInputTooLarge
-JsonInput.DurationJsonInputTooSmall
-JsonInput.DurationMissingS
-JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-JsonInput.EnumFieldNumericValueZero.JsonOutput
-JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.FieldMask.ProtobufOutput
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.FloatFieldTooLarge
-JsonInput.FloatFieldTooSmall
-JsonInput.Int32FieldExponentialFormat.JsonOutput
-JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-JsonInput.Int32FieldMaxFloatValue.JsonOutput
-JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Int32FieldMinFloatValue.JsonOutput
-JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-JsonInput.OneofZeroMessage.JsonOutput
-JsonInput.OneofZeroMessage.ProtobufOutput
-JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.OriginalProtoFieldName.ProtobufOutput
-JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-JsonInput.TimestampJsonInputLowercaseT
-JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-JsonInput.ValueAcceptNull.JsonOutput
-JsonInput.ValueAcceptNull.ProtobufOutput
-TimestampProtoInputTooLarge.JsonOutput
-TimestampProtoInputTooSmall.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_0
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_1
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_2
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_3
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 84d9fccd..a498ad1a 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -7,65 +7,48 @@
# TODO(haberman): insert links to corresponding bugs tracking the issue.
# Should we use GitHub issues or the Google-internal bug tracker?
-DurationProtoInputTooLarge.JsonOutput
-DurationProtoInputTooSmall.JsonOutput
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.AnyWithFieldMask.ProtobufOutput
-JsonInput.BytesFieldInvalidBase64Characters
-JsonInput.DoubleFieldInfinityNotQuoted
-JsonInput.DoubleFieldNanNotQuoted
-JsonInput.DoubleFieldNegativeInfinityNotQuoted
-JsonInput.DoubleFieldTooSmall
-JsonInput.DurationJsonInputTooLarge
-JsonInput.DurationJsonInputTooSmall
-JsonInput.DurationMissingS
-JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-JsonInput.EnumFieldNumericValueZero.JsonOutput
-JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.FieldMask.ProtobufOutput
-JsonInput.FieldMaskInvalidCharacter
-JsonInput.FloatFieldInfinityNotQuoted
-JsonInput.FloatFieldNanNotQuoted
-JsonInput.FloatFieldNegativeInfinityNotQuoted
-JsonInput.FloatFieldTooLarge
-JsonInput.FloatFieldTooSmall
-JsonInput.Int32FieldExponentialFormat.JsonOutput
-JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-JsonInput.Int32FieldMaxFloatValue.JsonOutput
-JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Int32FieldMinFloatValue.JsonOutput
-JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-JsonInput.OneofZeroMessage.JsonOutput
-JsonInput.OneofZeroMessage.ProtobufOutput
-JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.OriginalProtoFieldName.ProtobufOutput
-JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-JsonInput.TimestampJsonInputLowercaseT
-JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-JsonInput.ValueAcceptNull.JsonOutput
-JsonInput.ValueAcceptNull.ProtobufOutput
-ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-ProtobufInput.PrematureEofInPackedField.BOOL
-ProtobufInput.PrematureEofInPackedField.DOUBLE
-ProtobufInput.PrematureEofInPackedField.ENUM
-ProtobufInput.PrematureEofInPackedField.FIXED32
-ProtobufInput.PrematureEofInPackedField.FIXED64
-ProtobufInput.PrematureEofInPackedField.FLOAT
-ProtobufInput.PrematureEofInPackedField.INT32
-ProtobufInput.PrematureEofInPackedField.INT64
-ProtobufInput.PrematureEofInPackedField.SFIXED32
-ProtobufInput.PrematureEofInPackedField.SFIXED64
-ProtobufInput.PrematureEofInPackedField.SINT32
-ProtobufInput.PrematureEofInPackedField.SINT64
-ProtobufInput.PrematureEofInPackedField.UINT32
-ProtobufInput.PrematureEofInPackedField.UINT64
-TimestampProtoInputTooLarge.JsonOutput
-TimestampProtoInputTooSmall.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.DOUBLE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FLOAT
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.DOUBLE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FLOAT
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 2a533aa5..b2683372 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -1,213 +1,137 @@
-DurationProtoInputTooLarge.JsonOutput
-DurationProtoInputTooSmall.JsonOutput
-FieldMaskNumbersDontRoundTrip.JsonOutput
-FieldMaskPathsDontRoundTrip.JsonOutput
-FieldMaskTooManyUnderscore.JsonOutput
-JsonInput.Any.JsonOutput
-JsonInput.Any.ProtobufOutput
-JsonInput.AnyNested.JsonOutput
-JsonInput.AnyNested.ProtobufOutput
-JsonInput.AnyUnorderedTypeTag.JsonOutput
-JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-JsonInput.AnyWithDuration.JsonOutput
-JsonInput.AnyWithDuration.ProtobufOutput
-JsonInput.AnyWithFieldMask.JsonOutput
-JsonInput.AnyWithFieldMask.ProtobufOutput
-JsonInput.AnyWithInt32ValueWrapper.JsonOutput
-JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
-JsonInput.AnyWithStruct.JsonOutput
-JsonInput.AnyWithStruct.ProtobufOutput
-JsonInput.AnyWithTimestamp.JsonOutput
-JsonInput.AnyWithTimestamp.ProtobufOutput
-JsonInput.AnyWithValueForInteger.JsonOutput
-JsonInput.AnyWithValueForInteger.ProtobufOutput
-JsonInput.AnyWithValueForJsonObject.JsonOutput
-JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-JsonInput.BoolFieldIntegerOne
-JsonInput.BoolFieldIntegerZero
-JsonInput.DoubleFieldInfinity.JsonOutput
-JsonInput.DoubleFieldInfinity.ProtobufOutput
-JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
-JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
-JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-JsonInput.DoubleFieldNan.JsonOutput
-JsonInput.DoubleFieldNan.ProtobufOutput
-JsonInput.DoubleFieldNegativeInfinity.JsonOutput
-JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
-JsonInput.DoubleFieldQuotedValue.JsonOutput
-JsonInput.DoubleFieldQuotedValue.ProtobufOutput
-JsonInput.DurationHas3FractionalDigits.Validator
-JsonInput.DurationHas6FractionalDigits.Validator
-JsonInput.DurationHas9FractionalDigits.Validator
-JsonInput.DurationHasZeroFractionalDigit.Validator
-JsonInput.DurationMaxValue.JsonOutput
-JsonInput.DurationMaxValue.ProtobufOutput
-JsonInput.DurationMinValue.JsonOutput
-JsonInput.DurationMinValue.ProtobufOutput
-JsonInput.DurationRepeatedValue.JsonOutput
-JsonInput.DurationRepeatedValue.ProtobufOutput
-JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-JsonInput.EnumFieldNumericValueZero.JsonOutput
-JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-JsonInput.EnumFieldUnknownValue.Validator
-JsonInput.FieldMask.JsonOutput
-JsonInput.FieldMask.ProtobufOutput
-JsonInput.FieldNameInLowerCamelCase.Validator
-JsonInput.FieldNameInSnakeCase.JsonOutput
-JsonInput.FieldNameInSnakeCase.ProtobufOutput
-JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
-JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
-JsonInput.FieldNameWithDoubleUnderscores.Validator
-JsonInput.FieldNameWithMixedCases.JsonOutput
-JsonInput.FieldNameWithMixedCases.ProtobufOutput
-JsonInput.FieldNameWithMixedCases.Validator
-JsonInput.FloatFieldInfinity.JsonOutput
-JsonInput.FloatFieldInfinity.ProtobufOutput
-JsonInput.FloatFieldNan.JsonOutput
-JsonInput.FloatFieldNan.ProtobufOutput
-JsonInput.FloatFieldNegativeInfinity.JsonOutput
-JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
-JsonInput.FloatFieldQuotedValue.JsonOutput
-JsonInput.FloatFieldQuotedValue.ProtobufOutput
-JsonInput.FloatFieldTooLarge
-JsonInput.FloatFieldTooSmall
-JsonInput.Int32FieldExponentialFormat.JsonOutput
-JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-JsonInput.Int32FieldMaxFloatValue.JsonOutput
-JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Int32FieldMinFloatValue.JsonOutput
-JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-JsonInput.Int32FieldStringValue.JsonOutput
-JsonInput.Int32FieldStringValue.ProtobufOutput
-JsonInput.Int32FieldStringValueEscaped.JsonOutput
-JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
-JsonInput.Int32MapEscapedKey.JsonOutput
-JsonInput.Int32MapEscapedKey.ProtobufOutput
-JsonInput.Int32MapField.JsonOutput
-JsonInput.Int32MapField.ProtobufOutput
-JsonInput.Int64FieldBeString.Validator
-JsonInput.Int64FieldMaxValue.JsonOutput
-JsonInput.Int64FieldMaxValue.ProtobufOutput
-JsonInput.Int64FieldMinValue.JsonOutput
-JsonInput.Int64FieldMinValue.ProtobufOutput
-JsonInput.Int64MapEscapedKey.JsonOutput
-JsonInput.Int64MapEscapedKey.ProtobufOutput
-JsonInput.Int64MapField.JsonOutput
-JsonInput.Int64MapField.ProtobufOutput
-JsonInput.MessageField.JsonOutput
-JsonInput.MessageField.ProtobufOutput
-JsonInput.MessageMapField.JsonOutput
-JsonInput.MessageMapField.ProtobufOutput
-JsonInput.MessageRepeatedField.JsonOutput
-JsonInput.MessageRepeatedField.ProtobufOutput
-JsonInput.OneofZeroDouble.JsonOutput
-JsonInput.OneofZeroDouble.ProtobufOutput
-JsonInput.OneofZeroFloat.JsonOutput
-JsonInput.OneofZeroFloat.ProtobufOutput
-JsonInput.OneofZeroUint32.JsonOutput
-JsonInput.OneofZeroUint32.ProtobufOutput
-JsonInput.OneofZeroUint64.JsonOutput
-JsonInput.OneofZeroUint64.ProtobufOutput
-JsonInput.OptionalBoolWrapper.JsonOutput
-JsonInput.OptionalBoolWrapper.ProtobufOutput
-JsonInput.OptionalBytesWrapper.JsonOutput
-JsonInput.OptionalBytesWrapper.ProtobufOutput
-JsonInput.OptionalDoubleWrapper.JsonOutput
-JsonInput.OptionalDoubleWrapper.ProtobufOutput
-JsonInput.OptionalFloatWrapper.JsonOutput
-JsonInput.OptionalFloatWrapper.ProtobufOutput
-JsonInput.OptionalInt32Wrapper.JsonOutput
-JsonInput.OptionalInt32Wrapper.ProtobufOutput
-JsonInput.OptionalInt64Wrapper.JsonOutput
-JsonInput.OptionalInt64Wrapper.ProtobufOutput
-JsonInput.OptionalStringWrapper.JsonOutput
-JsonInput.OptionalStringWrapper.ProtobufOutput
-JsonInput.OptionalUint32Wrapper.JsonOutput
-JsonInput.OptionalUint32Wrapper.ProtobufOutput
-JsonInput.OptionalUint64Wrapper.JsonOutput
-JsonInput.OptionalUint64Wrapper.ProtobufOutput
-JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
-JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
-JsonInput.OriginalProtoFieldName.JsonOutput
-JsonInput.PrimitiveRepeatedField.JsonOutput
-JsonInput.PrimitiveRepeatedField.ProtobufOutput
-JsonInput.RepeatedBoolWrapper.JsonOutput
-JsonInput.RepeatedBoolWrapper.ProtobufOutput
-JsonInput.RepeatedBytesWrapper.JsonOutput
-JsonInput.RepeatedBytesWrapper.ProtobufOutput
-JsonInput.RepeatedDoubleWrapper.JsonOutput
-JsonInput.RepeatedDoubleWrapper.ProtobufOutput
-JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-JsonInput.RepeatedFloatWrapper.JsonOutput
-JsonInput.RepeatedFloatWrapper.ProtobufOutput
-JsonInput.RepeatedInt32Wrapper.JsonOutput
-JsonInput.RepeatedInt32Wrapper.ProtobufOutput
-JsonInput.RepeatedInt64Wrapper.JsonOutput
-JsonInput.RepeatedInt64Wrapper.ProtobufOutput
-JsonInput.RepeatedStringWrapper.JsonOutput
-JsonInput.RepeatedStringWrapper.ProtobufOutput
-JsonInput.RepeatedUint32Wrapper.JsonOutput
-JsonInput.RepeatedUint32Wrapper.ProtobufOutput
-JsonInput.RepeatedUint64Wrapper.JsonOutput
-JsonInput.RepeatedUint64Wrapper.ProtobufOutput
-JsonInput.StringEndsWithEscapeChar
-JsonInput.StringFieldNotAString
-JsonInput.StringFieldSurrogateInWrongOrder
-JsonInput.StringFieldSurrogatePair.JsonOutput
-JsonInput.StringFieldSurrogatePair.ProtobufOutput
-JsonInput.StringFieldUnpairedHighSurrogate
-JsonInput.StringFieldUnpairedLowSurrogate
-JsonInput.Struct.JsonOutput
-JsonInput.Struct.ProtobufOutput
-JsonInput.TimestampHas3FractionalDigits.Validator
-JsonInput.TimestampHas6FractionalDigits.Validator
-JsonInput.TimestampHas9FractionalDigits.Validator
-JsonInput.TimestampHasZeroFractionalDigit.Validator
-JsonInput.TimestampMaxValue.JsonOutput
-JsonInput.TimestampMaxValue.ProtobufOutput
-JsonInput.TimestampMinValue.JsonOutput
-JsonInput.TimestampMinValue.ProtobufOutput
-JsonInput.TimestampRepeatedValue.JsonOutput
-JsonInput.TimestampRepeatedValue.ProtobufOutput
-JsonInput.TimestampWithNegativeOffset.JsonOutput
-JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-JsonInput.TimestampWithPositiveOffset.JsonOutput
-JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-JsonInput.TimestampZeroNormalized.Validator
-JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-JsonInput.Uint32MapField.JsonOutput
-JsonInput.Uint32MapField.ProtobufOutput
-JsonInput.Uint64FieldBeString.Validator
-JsonInput.Uint64FieldMaxValue.JsonOutput
-JsonInput.Uint64FieldMaxValue.ProtobufOutput
-JsonInput.Uint64MapField.JsonOutput
-JsonInput.Uint64MapField.ProtobufOutput
-JsonInput.ValueAcceptBool.JsonOutput
-JsonInput.ValueAcceptBool.ProtobufOutput
-JsonInput.ValueAcceptFloat.JsonOutput
-JsonInput.ValueAcceptFloat.ProtobufOutput
-JsonInput.ValueAcceptInteger.JsonOutput
-JsonInput.ValueAcceptInteger.ProtobufOutput
-JsonInput.ValueAcceptList.JsonOutput
-JsonInput.ValueAcceptList.ProtobufOutput
-JsonInput.ValueAcceptNull.JsonOutput
-JsonInput.ValueAcceptNull.ProtobufOutput
-JsonInput.ValueAcceptObject.JsonOutput
-JsonInput.ValueAcceptObject.ProtobufOutput
-JsonInput.ValueAcceptString.JsonOutput
-JsonInput.ValueAcceptString.ProtobufOutput
-ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-TimestampProtoInputTooLarge.JsonOutput
-TimestampProtoInputTooSmall.JsonOutput
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.Int64FieldBeString.Validator
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator
+Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator
+Required.DurationProtoInputTooLarge.JsonOutput
+Required.DurationProtoInputTooSmall.JsonOutput
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMinValue.JsonOutput
+Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.FieldMask.JsonOutput
+Required.Proto3.JsonInput.FieldMask.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.OneofFieldDuplicate
+Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.Proto3.JsonInput.Struct.JsonOutput
+Required.Proto3.JsonInput.Struct.ProtobufOutput
+Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput
+Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
+Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput
+Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
+Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput
+Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptListWithNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptListWithNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
+Required.TimestampProtoInputTooLarge.JsonOutput
+Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/update_failure_list.py b/conformance/update_failure_list.py
index 69f210e3..ad42ed3c 100755
--- a/conformance/update_failure_list.py
+++ b/conformance/update_failure_list.py
@@ -35,7 +35,6 @@ This is sort of like comm(1), except it recognizes comments and ignores them.
"""
import argparse
-import fileinput
parser = argparse.ArgumentParser(
description='Adds/removes failures from the failure list.')
@@ -57,12 +56,13 @@ for remove_file in (args.remove_list or []):
with open(remove_file) as f:
for line in f:
if line in add_set:
- raise "Asked to both add and remove test: " + line
+ raise Exception("Asked to both add and remove test: " + line)
remove_set.add(line.strip())
add_list = sorted(add_set, reverse=True)
-existing_list = file(args.filename).read()
+with open(args.filename) as in_file:
+ existing_list = in_file.read()
with open(args.filename, "w") as f:
for line in existing_list.splitlines(True):