xref: /aosp_15_r20/external/protobuf/conformance/conformance_python.py (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker#!/usr/bin/env python
2*1b3f573fSAndroid Build Coastguard Worker# Protocol Buffers - Google's data interchange format
3*1b3f573fSAndroid Build Coastguard Worker# Copyright 2008 Google Inc.  All rights reserved.
4*1b3f573fSAndroid Build Coastguard Worker# https://developers.google.com/protocol-buffers/
5*1b3f573fSAndroid Build Coastguard Worker#
6*1b3f573fSAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without
7*1b3f573fSAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are
8*1b3f573fSAndroid Build Coastguard Worker# met:
9*1b3f573fSAndroid Build Coastguard Worker#
10*1b3f573fSAndroid Build Coastguard Worker#     * Redistributions of source code must retain the above copyright
11*1b3f573fSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer.
12*1b3f573fSAndroid Build Coastguard Worker#     * Redistributions in binary form must reproduce the above
13*1b3f573fSAndroid Build Coastguard Worker# copyright notice, this list of conditions and the following disclaimer
14*1b3f573fSAndroid Build Coastguard Worker# in the documentation and/or other materials provided with the
15*1b3f573fSAndroid Build Coastguard Worker# distribution.
16*1b3f573fSAndroid Build Coastguard Worker#     * Neither the name of Google Inc. nor the names of its
17*1b3f573fSAndroid Build Coastguard Worker# contributors may be used to endorse or promote products derived from
18*1b3f573fSAndroid Build Coastguard Worker# this software without specific prior written permission.
19*1b3f573fSAndroid Build Coastguard Worker#
20*1b3f573fSAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*1b3f573fSAndroid Build Coastguard Worker# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*1b3f573fSAndroid Build Coastguard Worker# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*1b3f573fSAndroid Build Coastguard Worker# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*1b3f573fSAndroid Build Coastguard Worker# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*1b3f573fSAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*1b3f573fSAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*1b3f573fSAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*1b3f573fSAndroid Build Coastguard Worker# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*1b3f573fSAndroid Build Coastguard Worker
32*1b3f573fSAndroid Build Coastguard Worker"""A conformance test implementation for the Python protobuf library.
33*1b3f573fSAndroid Build Coastguard Worker
34*1b3f573fSAndroid Build Coastguard WorkerSee conformance.proto for more information.
35*1b3f573fSAndroid Build Coastguard Worker"""
36*1b3f573fSAndroid Build Coastguard Worker
37*1b3f573fSAndroid Build Coastguard Workerimport struct
38*1b3f573fSAndroid Build Coastguard Workerimport sys
39*1b3f573fSAndroid Build Coastguard Workerimport os
40*1b3f573fSAndroid Build Coastguard Workerfrom google.protobuf import json_format
41*1b3f573fSAndroid Build Coastguard Workerfrom google.protobuf import message
42*1b3f573fSAndroid Build Coastguard Workerfrom google.protobuf import test_messages_proto3_pb2
43*1b3f573fSAndroid Build Coastguard Workerfrom google.protobuf import test_messages_proto2_pb2
44*1b3f573fSAndroid Build Coastguard Workerfrom google.protobuf import text_format
45*1b3f573fSAndroid Build Coastguard Workerimport conformance_pb2
46*1b3f573fSAndroid Build Coastguard Worker
47*1b3f573fSAndroid Build Coastguard Workersys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
48*1b3f573fSAndroid Build Coastguard Workersys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
49*1b3f573fSAndroid Build Coastguard Worker
50*1b3f573fSAndroid Build Coastguard Workertest_count = 0
51*1b3f573fSAndroid Build Coastguard Workerverbose = False
52*1b3f573fSAndroid Build Coastguard Worker
53*1b3f573fSAndroid Build Coastguard Workerclass ProtocolError(Exception):
54*1b3f573fSAndroid Build Coastguard Worker  pass
55*1b3f573fSAndroid Build Coastguard Worker
56*1b3f573fSAndroid Build Coastguard Workerdef do_test(request):
57*1b3f573fSAndroid Build Coastguard Worker  response = conformance_pb2.ConformanceResponse()
58*1b3f573fSAndroid Build Coastguard Worker
59*1b3f573fSAndroid Build Coastguard Worker  if request.message_type == "conformance.FailureSet":
60*1b3f573fSAndroid Build Coastguard Worker    failure_set = conformance_pb2.FailureSet()
61*1b3f573fSAndroid Build Coastguard Worker    failures = []
62*1b3f573fSAndroid Build Coastguard Worker    # TODO(gerbens): Remove, this is a hack to detect if the old vs new
63*1b3f573fSAndroid Build Coastguard Worker    # parser is used by the cpp code. Relying on a bug in the old parser.
64*1b3f573fSAndroid Build Coastguard Worker    hack_proto = test_messages_proto2_pb2.TestAllTypesProto2()
65*1b3f573fSAndroid Build Coastguard Worker    old_parser = True
66*1b3f573fSAndroid Build Coastguard Worker    try:
67*1b3f573fSAndroid Build Coastguard Worker      hack_proto.ParseFromString(b"\322\002\001")
68*1b3f573fSAndroid Build Coastguard Worker    except message.DecodeError as e:
69*1b3f573fSAndroid Build Coastguard Worker      old_parser = False
70*1b3f573fSAndroid Build Coastguard Worker    if old_parser:
71*1b3f573fSAndroid Build Coastguard Worker      # the string above is one of the failing conformance test strings of the
72*1b3f573fSAndroid Build Coastguard Worker      # old parser. If we succeed the c++ implementation is using the old
73*1b3f573fSAndroid Build Coastguard Worker      # parser so we add the list of failing conformance tests.
74*1b3f573fSAndroid Build Coastguard Worker      failures = [
75*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE",
76*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE",
77*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL",
78*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.DOUBLE",
79*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM",
80*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED32",
81*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED64",
82*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FLOAT",
83*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32",
84*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64",
85*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED32",
86*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED64",
87*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32",
88*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64",
89*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32",
90*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64",
91*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE",
92*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE",
93*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL",
94*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.DOUBLE",
95*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM",
96*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED32",
97*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED64",
98*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FLOAT",
99*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32",
100*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64",
101*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED32",
102*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED64",
103*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32",
104*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64",
105*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32",
106*1b3f573fSAndroid Build Coastguard Worker          "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64",
107*1b3f573fSAndroid Build Coastguard Worker      ]
108*1b3f573fSAndroid Build Coastguard Worker    for x in failures:
109*1b3f573fSAndroid Build Coastguard Worker      failure_set.failure.append(x)
110*1b3f573fSAndroid Build Coastguard Worker    response.protobuf_payload = failure_set.SerializeToString()
111*1b3f573fSAndroid Build Coastguard Worker    return response
112*1b3f573fSAndroid Build Coastguard Worker
113*1b3f573fSAndroid Build Coastguard Worker  isProto3 = (request.message_type == "protobuf_test_messages.proto3.TestAllTypesProto3")
114*1b3f573fSAndroid Build Coastguard Worker  isJson = (request.WhichOneof('payload') == 'json_payload')
115*1b3f573fSAndroid Build Coastguard Worker  isProto2 = (request.message_type == "protobuf_test_messages.proto2.TestAllTypesProto2")
116*1b3f573fSAndroid Build Coastguard Worker
117*1b3f573fSAndroid Build Coastguard Worker  if (not isProto3) and (not isJson) and (not isProto2):
118*1b3f573fSAndroid Build Coastguard Worker    raise ProtocolError("Protobuf request doesn't have specific payload type")
119*1b3f573fSAndroid Build Coastguard Worker
120*1b3f573fSAndroid Build Coastguard Worker  test_message = test_messages_proto2_pb2.TestAllTypesProto2() if isProto2 else \
121*1b3f573fSAndroid Build Coastguard Worker    test_messages_proto3_pb2.TestAllTypesProto3()
122*1b3f573fSAndroid Build Coastguard Worker
123*1b3f573fSAndroid Build Coastguard Worker  try:
124*1b3f573fSAndroid Build Coastguard Worker    if request.WhichOneof('payload') == 'protobuf_payload':
125*1b3f573fSAndroid Build Coastguard Worker      try:
126*1b3f573fSAndroid Build Coastguard Worker        test_message.ParseFromString(request.protobuf_payload)
127*1b3f573fSAndroid Build Coastguard Worker      except message.DecodeError as e:
128*1b3f573fSAndroid Build Coastguard Worker        response.parse_error = str(e)
129*1b3f573fSAndroid Build Coastguard Worker        return response
130*1b3f573fSAndroid Build Coastguard Worker
131*1b3f573fSAndroid Build Coastguard Worker    elif request.WhichOneof('payload') == 'json_payload':
132*1b3f573fSAndroid Build Coastguard Worker      try:
133*1b3f573fSAndroid Build Coastguard Worker        ignore_unknown_fields = \
134*1b3f573fSAndroid Build Coastguard Worker            request.test_category == \
135*1b3f573fSAndroid Build Coastguard Worker                conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST
136*1b3f573fSAndroid Build Coastguard Worker        json_format.Parse(request.json_payload, test_message,
137*1b3f573fSAndroid Build Coastguard Worker                          ignore_unknown_fields)
138*1b3f573fSAndroid Build Coastguard Worker      except Exception as e:
139*1b3f573fSAndroid Build Coastguard Worker        response.parse_error = str(e)
140*1b3f573fSAndroid Build Coastguard Worker        return response
141*1b3f573fSAndroid Build Coastguard Worker
142*1b3f573fSAndroid Build Coastguard Worker    elif request.WhichOneof('payload') == 'text_payload':
143*1b3f573fSAndroid Build Coastguard Worker      try:
144*1b3f573fSAndroid Build Coastguard Worker        text_format.Parse(request.text_payload, test_message)
145*1b3f573fSAndroid Build Coastguard Worker      except Exception as e:
146*1b3f573fSAndroid Build Coastguard Worker        response.parse_error = str(e)
147*1b3f573fSAndroid Build Coastguard Worker        return response
148*1b3f573fSAndroid Build Coastguard Worker
149*1b3f573fSAndroid Build Coastguard Worker    else:
150*1b3f573fSAndroid Build Coastguard Worker      raise ProtocolError("Request didn't have payload.")
151*1b3f573fSAndroid Build Coastguard Worker
152*1b3f573fSAndroid Build Coastguard Worker    if request.requested_output_format == conformance_pb2.UNSPECIFIED:
153*1b3f573fSAndroid Build Coastguard Worker      raise ProtocolError("Unspecified output format")
154*1b3f573fSAndroid Build Coastguard Worker
155*1b3f573fSAndroid Build Coastguard Worker    elif request.requested_output_format == conformance_pb2.PROTOBUF:
156*1b3f573fSAndroid Build Coastguard Worker      response.protobuf_payload = test_message.SerializeToString()
157*1b3f573fSAndroid Build Coastguard Worker
158*1b3f573fSAndroid Build Coastguard Worker    elif request.requested_output_format == conformance_pb2.JSON:
159*1b3f573fSAndroid Build Coastguard Worker      try:
160*1b3f573fSAndroid Build Coastguard Worker        response.json_payload = json_format.MessageToJson(test_message)
161*1b3f573fSAndroid Build Coastguard Worker      except Exception as e:
162*1b3f573fSAndroid Build Coastguard Worker        response.serialize_error = str(e)
163*1b3f573fSAndroid Build Coastguard Worker        return response
164*1b3f573fSAndroid Build Coastguard Worker
165*1b3f573fSAndroid Build Coastguard Worker    elif request.requested_output_format == conformance_pb2.TEXT_FORMAT:
166*1b3f573fSAndroid Build Coastguard Worker      response.text_payload = text_format.MessageToString(
167*1b3f573fSAndroid Build Coastguard Worker          test_message, print_unknown_fields=request.print_unknown_fields)
168*1b3f573fSAndroid Build Coastguard Worker
169*1b3f573fSAndroid Build Coastguard Worker  except Exception as e:
170*1b3f573fSAndroid Build Coastguard Worker    response.runtime_error = str(e)
171*1b3f573fSAndroid Build Coastguard Worker
172*1b3f573fSAndroid Build Coastguard Worker  return response
173*1b3f573fSAndroid Build Coastguard Worker
174*1b3f573fSAndroid Build Coastguard Workerdef do_test_io():
175*1b3f573fSAndroid Build Coastguard Worker  length_bytes = sys.stdin.read(4)
176*1b3f573fSAndroid Build Coastguard Worker  if len(length_bytes) == 0:
177*1b3f573fSAndroid Build Coastguard Worker    return False   # EOF
178*1b3f573fSAndroid Build Coastguard Worker  elif len(length_bytes) != 4:
179*1b3f573fSAndroid Build Coastguard Worker    raise IOError("I/O error")
180*1b3f573fSAndroid Build Coastguard Worker
181*1b3f573fSAndroid Build Coastguard Worker  # "I" is "unsigned int", so this depends on running on a platform with
182*1b3f573fSAndroid Build Coastguard Worker  # 32-bit "unsigned int" type.  The Python struct module unfortunately
183*1b3f573fSAndroid Build Coastguard Worker  # has no format specifier for uint32_t.
184*1b3f573fSAndroid Build Coastguard Worker  length = struct.unpack("<I", length_bytes)[0]
185*1b3f573fSAndroid Build Coastguard Worker  serialized_request = sys.stdin.read(length)
186*1b3f573fSAndroid Build Coastguard Worker  if len(serialized_request) != length:
187*1b3f573fSAndroid Build Coastguard Worker    raise IOError("I/O error")
188*1b3f573fSAndroid Build Coastguard Worker
189*1b3f573fSAndroid Build Coastguard Worker  request = conformance_pb2.ConformanceRequest()
190*1b3f573fSAndroid Build Coastguard Worker  request.ParseFromString(serialized_request)
191*1b3f573fSAndroid Build Coastguard Worker
192*1b3f573fSAndroid Build Coastguard Worker  response = do_test(request)
193*1b3f573fSAndroid Build Coastguard Worker
194*1b3f573fSAndroid Build Coastguard Worker  serialized_response = response.SerializeToString()
195*1b3f573fSAndroid Build Coastguard Worker  sys.stdout.write(struct.pack("<I", len(serialized_response)))
196*1b3f573fSAndroid Build Coastguard Worker  sys.stdout.write(serialized_response)
197*1b3f573fSAndroid Build Coastguard Worker  sys.stdout.flush()
198*1b3f573fSAndroid Build Coastguard Worker
199*1b3f573fSAndroid Build Coastguard Worker  if verbose:
200*1b3f573fSAndroid Build Coastguard Worker    sys.stderr.write("conformance_python: request=%s, response=%s\n" % (
201*1b3f573fSAndroid Build Coastguard Worker                       request.ShortDebugString().c_str(),
202*1b3f573fSAndroid Build Coastguard Worker                       response.ShortDebugString().c_str()))
203*1b3f573fSAndroid Build Coastguard Worker
204*1b3f573fSAndroid Build Coastguard Worker  global test_count
205*1b3f573fSAndroid Build Coastguard Worker  test_count += 1
206*1b3f573fSAndroid Build Coastguard Worker
207*1b3f573fSAndroid Build Coastguard Worker  return True
208*1b3f573fSAndroid Build Coastguard Worker
209*1b3f573fSAndroid Build Coastguard Workerwhile True:
210*1b3f573fSAndroid Build Coastguard Worker  if not do_test_io():
211*1b3f573fSAndroid Build Coastguard Worker    sys.stderr.write("conformance_python: received EOF from test runner " +
212*1b3f573fSAndroid Build Coastguard Worker                     "after %s tests, exiting\n" % (test_count))
213*1b3f573fSAndroid Build Coastguard Worker    sys.exit(0)
214