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