xref: /aosp_15_r20/external/protobuf/conformance/conformance_ruby.rb (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1#!/usr/bin/env ruby
2#
3# Protocol Buffers - Google's data interchange format
4# Copyright 2008 Google Inc.  All rights reserved.
5# https://developers.google.com/protocol-buffers/
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are
9# met:
10#
11#     * Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer.
13#     * Redistributions in binary form must reproduce the above
14# copyright notice, this list of conditions and the following disclaimer
15# in the documentation and/or other materials provided with the
16# distribution.
17#     * Neither the name of Google Inc. nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33require 'conformance_pb'
34require 'google/protobuf/test_messages_proto3_pb'
35require 'google/protobuf/test_messages_proto2_pb'
36
37$test_count = 0
38$verbose = false
39
40def do_test(request)
41  test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new
42  response = Conformance::ConformanceResponse.new
43  descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(request.message_type)
44
45  unless descriptor
46    response.skipped = "Unknown message type: " + request.message_type
47  end
48
49  begin
50    case request.payload
51    when :protobuf_payload
52      begin
53        test_message = descriptor.msgclass.decode(request.protobuf_payload)
54      rescue Google::Protobuf::ParseError => err
55        response.parse_error = err.message.encode('utf-8')
56        return response
57      end
58
59    when :json_payload
60      begin
61        options = {}
62        if request.test_category == :JSON_IGNORE_UNKNOWN_PARSING_TEST
63          options[:ignore_unknown_fields] = true
64        end
65        test_message = descriptor.msgclass.decode_json(request.json_payload, options)
66      rescue Google::Protobuf::ParseError => err
67        response.parse_error = err.message.encode('utf-8')
68        return response
69      end
70
71    when :text_payload
72      begin
73        response.skipped = "Ruby doesn't support text format"
74        return response
75      end
76
77    when nil
78      fail "Request didn't have payload"
79    end
80
81    case request.requested_output_format
82    when :UNSPECIFIED
83      fail 'Unspecified output format'
84
85    when :PROTOBUF
86      begin
87        response.protobuf_payload = test_message.to_proto
88      rescue Google::Protobuf::ParseError => err
89        response.serialize_error = err.message.encode('utf-8')
90      end
91
92    when :JSON
93      begin
94        response.json_payload = test_message.to_json
95      rescue Google::Protobuf::ParseError => err
96        response.serialize_error = err.message.encode('utf-8')
97      end
98
99    when nil
100      fail "Request didn't have requested output format"
101    end
102  rescue StandardError => err
103    response.runtime_error = err.message.encode('utf-8')
104  end
105
106  response
107end
108
109# Returns true if the test ran successfully, false on legitimate EOF.
110# If EOF is encountered in an unexpected place, raises IOError.
111def do_test_io
112  length_bytes = STDIN.read(4)
113  return false if length_bytes.nil?
114
115  length = length_bytes.unpack('V').first
116  serialized_request = STDIN.read(length)
117  if serialized_request.nil? || serialized_request.length != length
118    fail IOError
119  end
120
121  request = Conformance::ConformanceRequest.decode(serialized_request)
122
123  response = do_test(request)
124
125  serialized_response = Conformance::ConformanceResponse.encode(response)
126  STDOUT.write([serialized_response.length].pack('V'))
127  STDOUT.write(serialized_response)
128  STDOUT.flush
129
130  if $verbose
131    STDERR.puts("conformance_ruby: request=#{request.to_json}, " \
132                                 "response=#{response.to_json}\n")
133  end
134
135  $test_count += 1
136
137  true
138end
139
140loop do
141  unless do_test_io
142    STDERR.puts('conformance_ruby: received EOF from test runner ' \
143                "after #{$test_count} tests, exiting")
144    break
145  end
146end
147