xref: /aosp_15_r20/external/protobuf/conformance/conformance_test.cc (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format
2*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc.  All rights reserved.
3*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/
4*1b3f573fSAndroid Build Coastguard Worker //
5*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
6*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
7*1b3f573fSAndroid Build Coastguard Worker // met:
8*1b3f573fSAndroid Build Coastguard Worker //
9*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions of source code must retain the above copyright
10*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
11*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions in binary form must reproduce the above
12*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
13*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
14*1b3f573fSAndroid Build Coastguard Worker // distribution.
15*1b3f573fSAndroid Build Coastguard Worker //     * Neither the name of Google Inc. nor the names of its
16*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
17*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission.
18*1b3f573fSAndroid Build Coastguard Worker //
19*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*1b3f573fSAndroid Build Coastguard Worker 
31*1b3f573fSAndroid Build Coastguard Worker #include "conformance_test.h"
32*1b3f573fSAndroid Build Coastguard Worker 
33*1b3f573fSAndroid Build Coastguard Worker #include <stdarg.h>
34*1b3f573fSAndroid Build Coastguard Worker 
35*1b3f573fSAndroid Build Coastguard Worker #include <fstream>
36*1b3f573fSAndroid Build Coastguard Worker #include <set>
37*1b3f573fSAndroid Build Coastguard Worker #include <string>
38*1b3f573fSAndroid Build Coastguard Worker 
39*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/stubs/stringprintf.h>
40*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/message.h>
41*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/text_format.h>
42*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/util/field_comparator.h>
43*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/util/json_util.h>
44*1b3f573fSAndroid Build Coastguard Worker #include <google/protobuf/util/message_differencer.h>
45*1b3f573fSAndroid Build Coastguard Worker #include "conformance.pb.h"
46*1b3f573fSAndroid Build Coastguard Worker 
47*1b3f573fSAndroid Build Coastguard Worker using conformance::ConformanceRequest;
48*1b3f573fSAndroid Build Coastguard Worker using conformance::ConformanceResponse;
49*1b3f573fSAndroid Build Coastguard Worker using conformance::WireFormat;
50*1b3f573fSAndroid Build Coastguard Worker using google::protobuf::TextFormat;
51*1b3f573fSAndroid Build Coastguard Worker using google::protobuf::util::DefaultFieldComparator;
52*1b3f573fSAndroid Build Coastguard Worker using google::protobuf::util::MessageDifferencer;
53*1b3f573fSAndroid Build Coastguard Worker using std::string;
54*1b3f573fSAndroid Build Coastguard Worker 
55*1b3f573fSAndroid Build Coastguard Worker namespace {
56*1b3f573fSAndroid Build Coastguard Worker 
ToOctString(const string & binary_string)57*1b3f573fSAndroid Build Coastguard Worker static string ToOctString(const string& binary_string) {
58*1b3f573fSAndroid Build Coastguard Worker   string oct_string;
59*1b3f573fSAndroid Build Coastguard Worker   for (size_t i = 0; i < binary_string.size(); i++) {
60*1b3f573fSAndroid Build Coastguard Worker     uint8_t c = binary_string.at(i);
61*1b3f573fSAndroid Build Coastguard Worker     uint8_t high = c / 64;
62*1b3f573fSAndroid Build Coastguard Worker     uint8_t mid = (c % 64) / 8;
63*1b3f573fSAndroid Build Coastguard Worker     uint8_t low = c % 8;
64*1b3f573fSAndroid Build Coastguard Worker     oct_string.push_back('\\');
65*1b3f573fSAndroid Build Coastguard Worker     oct_string.push_back('0' + high);
66*1b3f573fSAndroid Build Coastguard Worker     oct_string.push_back('0' + mid);
67*1b3f573fSAndroid Build Coastguard Worker     oct_string.push_back('0' + low);
68*1b3f573fSAndroid Build Coastguard Worker   }
69*1b3f573fSAndroid Build Coastguard Worker   return oct_string;
70*1b3f573fSAndroid Build Coastguard Worker }
71*1b3f573fSAndroid Build Coastguard Worker 
72*1b3f573fSAndroid Build Coastguard Worker }  // namespace
73*1b3f573fSAndroid Build Coastguard Worker 
74*1b3f573fSAndroid Build Coastguard Worker namespace google {
75*1b3f573fSAndroid Build Coastguard Worker namespace protobuf {
76*1b3f573fSAndroid Build Coastguard Worker 
ConformanceRequestSetting(ConformanceLevel level,conformance::WireFormat input_format,conformance::WireFormat output_format,conformance::TestCategory test_category,const Message & prototype_message,const string & test_name,const string & input)77*1b3f573fSAndroid Build Coastguard Worker ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting(
78*1b3f573fSAndroid Build Coastguard Worker     ConformanceLevel level,
79*1b3f573fSAndroid Build Coastguard Worker     conformance::WireFormat input_format,
80*1b3f573fSAndroid Build Coastguard Worker     conformance::WireFormat output_format,
81*1b3f573fSAndroid Build Coastguard Worker     conformance::TestCategory test_category,
82*1b3f573fSAndroid Build Coastguard Worker     const Message& prototype_message,
83*1b3f573fSAndroid Build Coastguard Worker     const string& test_name, const string& input)
84*1b3f573fSAndroid Build Coastguard Worker     : level_(level),
85*1b3f573fSAndroid Build Coastguard Worker       input_format_(input_format),
86*1b3f573fSAndroid Build Coastguard Worker       output_format_(output_format),
87*1b3f573fSAndroid Build Coastguard Worker       prototype_message_(prototype_message),
88*1b3f573fSAndroid Build Coastguard Worker       prototype_message_for_compare_(prototype_message.New()),
89*1b3f573fSAndroid Build Coastguard Worker       test_name_(test_name) {
90*1b3f573fSAndroid Build Coastguard Worker   switch (input_format) {
91*1b3f573fSAndroid Build Coastguard Worker     case conformance::PROTOBUF: {
92*1b3f573fSAndroid Build Coastguard Worker       request_.set_protobuf_payload(input);
93*1b3f573fSAndroid Build Coastguard Worker       break;
94*1b3f573fSAndroid Build Coastguard Worker     }
95*1b3f573fSAndroid Build Coastguard Worker 
96*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSON: {
97*1b3f573fSAndroid Build Coastguard Worker       request_.set_json_payload(input);
98*1b3f573fSAndroid Build Coastguard Worker       break;
99*1b3f573fSAndroid Build Coastguard Worker     }
100*1b3f573fSAndroid Build Coastguard Worker 
101*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSPB: {
102*1b3f573fSAndroid Build Coastguard Worker       request_.set_jspb_payload(input);
103*1b3f573fSAndroid Build Coastguard Worker       break;
104*1b3f573fSAndroid Build Coastguard Worker     }
105*1b3f573fSAndroid Build Coastguard Worker 
106*1b3f573fSAndroid Build Coastguard Worker     case conformance::TEXT_FORMAT: {
107*1b3f573fSAndroid Build Coastguard Worker       request_.set_text_payload(input);
108*1b3f573fSAndroid Build Coastguard Worker       break;
109*1b3f573fSAndroid Build Coastguard Worker     }
110*1b3f573fSAndroid Build Coastguard Worker 
111*1b3f573fSAndroid Build Coastguard Worker     default:
112*1b3f573fSAndroid Build Coastguard Worker       GOOGLE_LOG(FATAL) << "Unspecified input format";
113*1b3f573fSAndroid Build Coastguard Worker   }
114*1b3f573fSAndroid Build Coastguard Worker 
115*1b3f573fSAndroid Build Coastguard Worker   request_.set_test_category(test_category);
116*1b3f573fSAndroid Build Coastguard Worker 
117*1b3f573fSAndroid Build Coastguard Worker   request_.set_message_type(prototype_message.GetDescriptor()->full_name());
118*1b3f573fSAndroid Build Coastguard Worker   request_.set_requested_output_format(output_format);
119*1b3f573fSAndroid Build Coastguard Worker }
120*1b3f573fSAndroid Build Coastguard Worker 
121*1b3f573fSAndroid Build Coastguard Worker std::unique_ptr<Message>
NewTestMessage() const122*1b3f573fSAndroid Build Coastguard Worker ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const {
123*1b3f573fSAndroid Build Coastguard Worker   return std::unique_ptr<Message>(prototype_message_for_compare_->New());
124*1b3f573fSAndroid Build Coastguard Worker }
125*1b3f573fSAndroid Build Coastguard Worker 
126*1b3f573fSAndroid Build Coastguard Worker string ConformanceTestSuite::ConformanceRequestSetting::
GetTestName() const127*1b3f573fSAndroid Build Coastguard Worker     GetTestName() const {
128*1b3f573fSAndroid Build Coastguard Worker   string rname =
129*1b3f573fSAndroid Build Coastguard Worker       prototype_message_.GetDescriptor()->file()->syntax() ==
130*1b3f573fSAndroid Build Coastguard Worker         FileDescriptor::SYNTAX_PROTO3 ? "Proto3" : "Proto2";
131*1b3f573fSAndroid Build Coastguard Worker 
132*1b3f573fSAndroid Build Coastguard Worker   return StrCat(ConformanceLevelToString(level_), ".", rname, ".",
133*1b3f573fSAndroid Build Coastguard Worker                       InputFormatString(input_format_), ".", test_name_, ".",
134*1b3f573fSAndroid Build Coastguard Worker                       OutputFormatString(output_format_));
135*1b3f573fSAndroid Build Coastguard Worker }
136*1b3f573fSAndroid Build Coastguard Worker 
137*1b3f573fSAndroid Build Coastguard Worker string ConformanceTestSuite::ConformanceRequestSetting::
ConformanceLevelToString(ConformanceLevel level) const138*1b3f573fSAndroid Build Coastguard Worker     ConformanceLevelToString(
139*1b3f573fSAndroid Build Coastguard Worker         ConformanceLevel level) const {
140*1b3f573fSAndroid Build Coastguard Worker   switch (level) {
141*1b3f573fSAndroid Build Coastguard Worker     case REQUIRED: return "Required";
142*1b3f573fSAndroid Build Coastguard Worker     case RECOMMENDED: return "Recommended";
143*1b3f573fSAndroid Build Coastguard Worker   }
144*1b3f573fSAndroid Build Coastguard Worker   GOOGLE_LOG(FATAL) << "Unknown value: " << level;
145*1b3f573fSAndroid Build Coastguard Worker   return "";
146*1b3f573fSAndroid Build Coastguard Worker }
147*1b3f573fSAndroid Build Coastguard Worker 
148*1b3f573fSAndroid Build Coastguard Worker string ConformanceTestSuite::ConformanceRequestSetting::
InputFormatString(conformance::WireFormat format) const149*1b3f573fSAndroid Build Coastguard Worker     InputFormatString(conformance::WireFormat format) const {
150*1b3f573fSAndroid Build Coastguard Worker   switch (format) {
151*1b3f573fSAndroid Build Coastguard Worker     case conformance::PROTOBUF:
152*1b3f573fSAndroid Build Coastguard Worker       return "ProtobufInput";
153*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSON:
154*1b3f573fSAndroid Build Coastguard Worker       return "JsonInput";
155*1b3f573fSAndroid Build Coastguard Worker     case conformance::TEXT_FORMAT:
156*1b3f573fSAndroid Build Coastguard Worker       return "TextFormatInput";
157*1b3f573fSAndroid Build Coastguard Worker     default:
158*1b3f573fSAndroid Build Coastguard Worker       GOOGLE_LOG(FATAL) << "Unspecified output format";
159*1b3f573fSAndroid Build Coastguard Worker   }
160*1b3f573fSAndroid Build Coastguard Worker   return "";
161*1b3f573fSAndroid Build Coastguard Worker }
162*1b3f573fSAndroid Build Coastguard Worker 
163*1b3f573fSAndroid Build Coastguard Worker string ConformanceTestSuite::ConformanceRequestSetting::
OutputFormatString(conformance::WireFormat format) const164*1b3f573fSAndroid Build Coastguard Worker     OutputFormatString(conformance::WireFormat format) const {
165*1b3f573fSAndroid Build Coastguard Worker   switch (format) {
166*1b3f573fSAndroid Build Coastguard Worker     case conformance::PROTOBUF:
167*1b3f573fSAndroid Build Coastguard Worker       return "ProtobufOutput";
168*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSON:
169*1b3f573fSAndroid Build Coastguard Worker       return "JsonOutput";
170*1b3f573fSAndroid Build Coastguard Worker     case conformance::TEXT_FORMAT:
171*1b3f573fSAndroid Build Coastguard Worker       return "TextFormatOutput";
172*1b3f573fSAndroid Build Coastguard Worker     default:
173*1b3f573fSAndroid Build Coastguard Worker       GOOGLE_LOG(FATAL) << "Unspecified output format";
174*1b3f573fSAndroid Build Coastguard Worker   }
175*1b3f573fSAndroid Build Coastguard Worker   return "";
176*1b3f573fSAndroid Build Coastguard Worker }
177*1b3f573fSAndroid Build Coastguard Worker 
ReportSuccess(const string & test_name)178*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::ReportSuccess(const string& test_name) {
179*1b3f573fSAndroid Build Coastguard Worker   if (expected_to_fail_.erase(test_name) != 0) {
180*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_,
181*1b3f573fSAndroid Build Coastguard Worker                   "ERROR: test %s is in the failure list, but test succeeded.  "
182*1b3f573fSAndroid Build Coastguard Worker                   "Remove it from the failure list.\n",
183*1b3f573fSAndroid Build Coastguard Worker                   test_name.c_str());
184*1b3f573fSAndroid Build Coastguard Worker     unexpected_succeeding_tests_.insert(test_name);
185*1b3f573fSAndroid Build Coastguard Worker   }
186*1b3f573fSAndroid Build Coastguard Worker   successes_++;
187*1b3f573fSAndroid Build Coastguard Worker }
188*1b3f573fSAndroid Build Coastguard Worker 
ReportFailure(const string & test_name,ConformanceLevel level,const ConformanceRequest & request,const ConformanceResponse & response,const char * fmt,...)189*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::ReportFailure(const string& test_name,
190*1b3f573fSAndroid Build Coastguard Worker                                          ConformanceLevel level,
191*1b3f573fSAndroid Build Coastguard Worker                                          const ConformanceRequest& request,
192*1b3f573fSAndroid Build Coastguard Worker                                          const ConformanceResponse& response,
193*1b3f573fSAndroid Build Coastguard Worker                                          const char* fmt, ...) {
194*1b3f573fSAndroid Build Coastguard Worker   if (expected_to_fail_.erase(test_name) == 1) {
195*1b3f573fSAndroid Build Coastguard Worker     expected_failures_++;
196*1b3f573fSAndroid Build Coastguard Worker     if (!verbose_)
197*1b3f573fSAndroid Build Coastguard Worker       return;
198*1b3f573fSAndroid Build Coastguard Worker   } else if (level == RECOMMENDED && !enforce_recommended_) {
199*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "WARNING, test=%s: ", test_name.c_str());
200*1b3f573fSAndroid Build Coastguard Worker   } else {
201*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
202*1b3f573fSAndroid Build Coastguard Worker     unexpected_failing_tests_.insert(test_name);
203*1b3f573fSAndroid Build Coastguard Worker   }
204*1b3f573fSAndroid Build Coastguard Worker   va_list args;
205*1b3f573fSAndroid Build Coastguard Worker   va_start(args, fmt);
206*1b3f573fSAndroid Build Coastguard Worker   StringAppendV(&output_, fmt, args);
207*1b3f573fSAndroid Build Coastguard Worker   va_end(args);
208*1b3f573fSAndroid Build Coastguard Worker   StringAppendF(&output_, " request=%s, response=%s\n",
209*1b3f573fSAndroid Build Coastguard Worker                 request.ShortDebugString().c_str(),
210*1b3f573fSAndroid Build Coastguard Worker                 response.ShortDebugString().c_str());
211*1b3f573fSAndroid Build Coastguard Worker }
212*1b3f573fSAndroid Build Coastguard Worker 
ReportSkip(const string & test_name,const ConformanceRequest & request,const ConformanceResponse & response)213*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::ReportSkip(const string& test_name,
214*1b3f573fSAndroid Build Coastguard Worker                                       const ConformanceRequest& request,
215*1b3f573fSAndroid Build Coastguard Worker                                       const ConformanceResponse& response) {
216*1b3f573fSAndroid Build Coastguard Worker   if (verbose_) {
217*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "SKIPPED, test=%s request=%s, response=%s\n",
218*1b3f573fSAndroid Build Coastguard Worker                   test_name.c_str(), request.ShortDebugString().c_str(),
219*1b3f573fSAndroid Build Coastguard Worker                   response.ShortDebugString().c_str());
220*1b3f573fSAndroid Build Coastguard Worker   }
221*1b3f573fSAndroid Build Coastguard Worker   skipped_.insert(test_name);
222*1b3f573fSAndroid Build Coastguard Worker }
223*1b3f573fSAndroid Build Coastguard Worker 
RunValidInputTest(const ConformanceRequestSetting & setting,const string & equivalent_text_format)224*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::RunValidInputTest(
225*1b3f573fSAndroid Build Coastguard Worker     const ConformanceRequestSetting& setting,
226*1b3f573fSAndroid Build Coastguard Worker     const string& equivalent_text_format) {
227*1b3f573fSAndroid Build Coastguard Worker   std::unique_ptr<Message> reference_message(setting.NewTestMessage());
228*1b3f573fSAndroid Build Coastguard Worker   GOOGLE_CHECK(TextFormat::ParseFromString(equivalent_text_format,
229*1b3f573fSAndroid Build Coastguard Worker                                     reference_message.get()))
230*1b3f573fSAndroid Build Coastguard Worker       << "Failed to parse data for test case: " << setting.GetTestName()
231*1b3f573fSAndroid Build Coastguard Worker       << ", data: " << equivalent_text_format;
232*1b3f573fSAndroid Build Coastguard Worker   const string equivalent_wire_format = reference_message->SerializeAsString();
233*1b3f573fSAndroid Build Coastguard Worker   RunValidBinaryInputTest(setting, equivalent_wire_format);
234*1b3f573fSAndroid Build Coastguard Worker }
235*1b3f573fSAndroid Build Coastguard Worker 
RunValidBinaryInputTest(const ConformanceRequestSetting & setting,const string & equivalent_wire_format,bool require_same_wire_format)236*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::RunValidBinaryInputTest(
237*1b3f573fSAndroid Build Coastguard Worker     const ConformanceRequestSetting& setting,
238*1b3f573fSAndroid Build Coastguard Worker     const string& equivalent_wire_format, bool require_same_wire_format) {
239*1b3f573fSAndroid Build Coastguard Worker   const ConformanceRequest& request = setting.GetRequest();
240*1b3f573fSAndroid Build Coastguard Worker   ConformanceResponse response;
241*1b3f573fSAndroid Build Coastguard Worker   RunTest(setting.GetTestName(), request, &response);
242*1b3f573fSAndroid Build Coastguard Worker   VerifyResponse(setting, equivalent_wire_format, response, true,
243*1b3f573fSAndroid Build Coastguard Worker                  require_same_wire_format);
244*1b3f573fSAndroid Build Coastguard Worker }
245*1b3f573fSAndroid Build Coastguard Worker 
VerifyResponse(const ConformanceRequestSetting & setting,const string & equivalent_wire_format,const ConformanceResponse & response,bool need_report_success,bool require_same_wire_format)246*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::VerifyResponse(
247*1b3f573fSAndroid Build Coastguard Worker     const ConformanceRequestSetting& setting,
248*1b3f573fSAndroid Build Coastguard Worker     const string& equivalent_wire_format, const ConformanceResponse& response,
249*1b3f573fSAndroid Build Coastguard Worker     bool need_report_success, bool require_same_wire_format) {
250*1b3f573fSAndroid Build Coastguard Worker   std::unique_ptr<Message> test_message(setting.NewTestMessage());
251*1b3f573fSAndroid Build Coastguard Worker   const ConformanceRequest& request = setting.GetRequest();
252*1b3f573fSAndroid Build Coastguard Worker   const string& test_name = setting.GetTestName();
253*1b3f573fSAndroid Build Coastguard Worker   ConformanceLevel level = setting.GetLevel();
254*1b3f573fSAndroid Build Coastguard Worker   std::unique_ptr<Message> reference_message = setting.NewTestMessage();
255*1b3f573fSAndroid Build Coastguard Worker 
256*1b3f573fSAndroid Build Coastguard Worker   GOOGLE_CHECK(reference_message->ParseFromString(equivalent_wire_format))
257*1b3f573fSAndroid Build Coastguard Worker       << "Failed to parse wire data for test case: " << test_name;
258*1b3f573fSAndroid Build Coastguard Worker 
259*1b3f573fSAndroid Build Coastguard Worker   switch (response.result_case()) {
260*1b3f573fSAndroid Build Coastguard Worker     case ConformanceResponse::RESULT_NOT_SET:
261*1b3f573fSAndroid Build Coastguard Worker       ReportFailure(test_name, level, request, response,
262*1b3f573fSAndroid Build Coastguard Worker                     "Response didn't have any field in the Response.");
263*1b3f573fSAndroid Build Coastguard Worker       return;
264*1b3f573fSAndroid Build Coastguard Worker 
265*1b3f573fSAndroid Build Coastguard Worker     case ConformanceResponse::kParseError:
266*1b3f573fSAndroid Build Coastguard Worker     case ConformanceResponse::kRuntimeError:
267*1b3f573fSAndroid Build Coastguard Worker     case ConformanceResponse::kSerializeError:
268*1b3f573fSAndroid Build Coastguard Worker       ReportFailure(test_name, level, request, response,
269*1b3f573fSAndroid Build Coastguard Worker                     "Failed to parse input or produce output.");
270*1b3f573fSAndroid Build Coastguard Worker       return;
271*1b3f573fSAndroid Build Coastguard Worker 
272*1b3f573fSAndroid Build Coastguard Worker     case ConformanceResponse::kSkipped:
273*1b3f573fSAndroid Build Coastguard Worker       ReportSkip(test_name, request, response);
274*1b3f573fSAndroid Build Coastguard Worker       return;
275*1b3f573fSAndroid Build Coastguard Worker 
276*1b3f573fSAndroid Build Coastguard Worker     default:
277*1b3f573fSAndroid Build Coastguard Worker       if (!ParseResponse(response, setting, test_message.get())) return;
278*1b3f573fSAndroid Build Coastguard Worker   }
279*1b3f573fSAndroid Build Coastguard Worker 
280*1b3f573fSAndroid Build Coastguard Worker   MessageDifferencer differencer;
281*1b3f573fSAndroid Build Coastguard Worker   DefaultFieldComparator field_comparator;
282*1b3f573fSAndroid Build Coastguard Worker   field_comparator.set_treat_nan_as_equal(true);
283*1b3f573fSAndroid Build Coastguard Worker   differencer.set_field_comparator(&field_comparator);
284*1b3f573fSAndroid Build Coastguard Worker   string differences;
285*1b3f573fSAndroid Build Coastguard Worker   differencer.ReportDifferencesToString(&differences);
286*1b3f573fSAndroid Build Coastguard Worker 
287*1b3f573fSAndroid Build Coastguard Worker   bool check = false;
288*1b3f573fSAndroid Build Coastguard Worker 
289*1b3f573fSAndroid Build Coastguard Worker   if (require_same_wire_format) {
290*1b3f573fSAndroid Build Coastguard Worker     GOOGLE_DCHECK_EQ(response.result_case(), ConformanceResponse::kProtobufPayload);
291*1b3f573fSAndroid Build Coastguard Worker     const string& protobuf_payload = response.protobuf_payload();
292*1b3f573fSAndroid Build Coastguard Worker     check = equivalent_wire_format == protobuf_payload;
293*1b3f573fSAndroid Build Coastguard Worker     differences = StrCat("Expect: ", ToOctString(equivalent_wire_format),
294*1b3f573fSAndroid Build Coastguard Worker                                ", but got: ", ToOctString(protobuf_payload));
295*1b3f573fSAndroid Build Coastguard Worker   } else {
296*1b3f573fSAndroid Build Coastguard Worker     check = differencer.Compare(*reference_message, *test_message);
297*1b3f573fSAndroid Build Coastguard Worker   }
298*1b3f573fSAndroid Build Coastguard Worker 
299*1b3f573fSAndroid Build Coastguard Worker   if (check) {
300*1b3f573fSAndroid Build Coastguard Worker     if (need_report_success) {
301*1b3f573fSAndroid Build Coastguard Worker       ReportSuccess(test_name);
302*1b3f573fSAndroid Build Coastguard Worker     }
303*1b3f573fSAndroid Build Coastguard Worker   } else {
304*1b3f573fSAndroid Build Coastguard Worker     ReportFailure(test_name, level, request, response,
305*1b3f573fSAndroid Build Coastguard Worker                   "Output was not equivalent to reference message: %s.",
306*1b3f573fSAndroid Build Coastguard Worker                   differences.c_str());
307*1b3f573fSAndroid Build Coastguard Worker   }
308*1b3f573fSAndroid Build Coastguard Worker }
309*1b3f573fSAndroid Build Coastguard Worker 
RunTest(const string & test_name,const ConformanceRequest & request,ConformanceResponse * response)310*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::RunTest(const string& test_name,
311*1b3f573fSAndroid Build Coastguard Worker                                    const ConformanceRequest& request,
312*1b3f573fSAndroid Build Coastguard Worker                                    ConformanceResponse* response) {
313*1b3f573fSAndroid Build Coastguard Worker   if (test_names_.insert(test_name).second == false) {
314*1b3f573fSAndroid Build Coastguard Worker     GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name;
315*1b3f573fSAndroid Build Coastguard Worker   }
316*1b3f573fSAndroid Build Coastguard Worker 
317*1b3f573fSAndroid Build Coastguard Worker   string serialized_request;
318*1b3f573fSAndroid Build Coastguard Worker   string serialized_response;
319*1b3f573fSAndroid Build Coastguard Worker   request.SerializeToString(&serialized_request);
320*1b3f573fSAndroid Build Coastguard Worker 
321*1b3f573fSAndroid Build Coastguard Worker   runner_->RunTest(test_name, serialized_request, &serialized_response);
322*1b3f573fSAndroid Build Coastguard Worker 
323*1b3f573fSAndroid Build Coastguard Worker   if (!response->ParseFromString(serialized_response)) {
324*1b3f573fSAndroid Build Coastguard Worker     response->Clear();
325*1b3f573fSAndroid Build Coastguard Worker     response->set_runtime_error("response proto could not be parsed.");
326*1b3f573fSAndroid Build Coastguard Worker   }
327*1b3f573fSAndroid Build Coastguard Worker 
328*1b3f573fSAndroid Build Coastguard Worker   if (verbose_) {
329*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_,
330*1b3f573fSAndroid Build Coastguard Worker                   "conformance test: name=%s, request=%s, response=%s\n",
331*1b3f573fSAndroid Build Coastguard Worker                   test_name.c_str(),
332*1b3f573fSAndroid Build Coastguard Worker                   request.ShortDebugString().c_str(),
333*1b3f573fSAndroid Build Coastguard Worker                   response->ShortDebugString().c_str());
334*1b3f573fSAndroid Build Coastguard Worker   }
335*1b3f573fSAndroid Build Coastguard Worker }
336*1b3f573fSAndroid Build Coastguard Worker 
CheckSetEmpty(const std::set<string> & set_to_check,const std::string & write_to_file,const std::string & msg)337*1b3f573fSAndroid Build Coastguard Worker bool ConformanceTestSuite::CheckSetEmpty(
338*1b3f573fSAndroid Build Coastguard Worker     const std::set<string>& set_to_check,
339*1b3f573fSAndroid Build Coastguard Worker     const std::string& write_to_file,
340*1b3f573fSAndroid Build Coastguard Worker     const std::string& msg) {
341*1b3f573fSAndroid Build Coastguard Worker   if (set_to_check.empty()) {
342*1b3f573fSAndroid Build Coastguard Worker     return true;
343*1b3f573fSAndroid Build Coastguard Worker   } else {
344*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "\n");
345*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "%s\n\n", msg.c_str());
346*1b3f573fSAndroid Build Coastguard Worker     for (std::set<string>::const_iterator iter = set_to_check.begin();
347*1b3f573fSAndroid Build Coastguard Worker          iter != set_to_check.end(); ++iter) {
348*1b3f573fSAndroid Build Coastguard Worker       StringAppendF(&output_, "  %s\n", iter->c_str());
349*1b3f573fSAndroid Build Coastguard Worker     }
350*1b3f573fSAndroid Build Coastguard Worker     StringAppendF(&output_, "\n");
351*1b3f573fSAndroid Build Coastguard Worker 
352*1b3f573fSAndroid Build Coastguard Worker     if (!write_to_file.empty()) {
353*1b3f573fSAndroid Build Coastguard Worker       std::string full_filename;
354*1b3f573fSAndroid Build Coastguard Worker       const std::string* filename = &write_to_file;
355*1b3f573fSAndroid Build Coastguard Worker       if (!output_dir_.empty()) {
356*1b3f573fSAndroid Build Coastguard Worker         full_filename = output_dir_;
357*1b3f573fSAndroid Build Coastguard Worker         if (*output_dir_.rbegin() != '/') {
358*1b3f573fSAndroid Build Coastguard Worker           full_filename.push_back('/');
359*1b3f573fSAndroid Build Coastguard Worker         }
360*1b3f573fSAndroid Build Coastguard Worker         full_filename += write_to_file;
361*1b3f573fSAndroid Build Coastguard Worker         filename = &full_filename;
362*1b3f573fSAndroid Build Coastguard Worker       }
363*1b3f573fSAndroid Build Coastguard Worker       std::ofstream os(*filename);
364*1b3f573fSAndroid Build Coastguard Worker       if (os) {
365*1b3f573fSAndroid Build Coastguard Worker         for (std::set<string>::const_iterator iter = set_to_check.begin();
366*1b3f573fSAndroid Build Coastguard Worker              iter != set_to_check.end(); ++iter) {
367*1b3f573fSAndroid Build Coastguard Worker           os << *iter << "\n";
368*1b3f573fSAndroid Build Coastguard Worker         }
369*1b3f573fSAndroid Build Coastguard Worker       } else {
370*1b3f573fSAndroid Build Coastguard Worker         StringAppendF(&output_, "Failed to open file: %s\n",
371*1b3f573fSAndroid Build Coastguard Worker                       filename->c_str());
372*1b3f573fSAndroid Build Coastguard Worker       }
373*1b3f573fSAndroid Build Coastguard Worker     }
374*1b3f573fSAndroid Build Coastguard Worker 
375*1b3f573fSAndroid Build Coastguard Worker     return false;
376*1b3f573fSAndroid Build Coastguard Worker   }
377*1b3f573fSAndroid Build Coastguard Worker }
378*1b3f573fSAndroid Build Coastguard Worker 
WireFormatToString(WireFormat wire_format)379*1b3f573fSAndroid Build Coastguard Worker string ConformanceTestSuite::WireFormatToString(
380*1b3f573fSAndroid Build Coastguard Worker     WireFormat wire_format) {
381*1b3f573fSAndroid Build Coastguard Worker   switch (wire_format) {
382*1b3f573fSAndroid Build Coastguard Worker     case conformance::PROTOBUF:
383*1b3f573fSAndroid Build Coastguard Worker       return "PROTOBUF";
384*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSON:
385*1b3f573fSAndroid Build Coastguard Worker       return "JSON";
386*1b3f573fSAndroid Build Coastguard Worker     case conformance::JSPB:
387*1b3f573fSAndroid Build Coastguard Worker       return "JSPB";
388*1b3f573fSAndroid Build Coastguard Worker     case conformance::TEXT_FORMAT:
389*1b3f573fSAndroid Build Coastguard Worker       return "TEXT_FORMAT";
390*1b3f573fSAndroid Build Coastguard Worker     case conformance::UNSPECIFIED:
391*1b3f573fSAndroid Build Coastguard Worker       return "UNSPECIFIED";
392*1b3f573fSAndroid Build Coastguard Worker     default:
393*1b3f573fSAndroid Build Coastguard Worker       GOOGLE_LOG(FATAL) << "unknown wire type: " << wire_format;
394*1b3f573fSAndroid Build Coastguard Worker   }
395*1b3f573fSAndroid Build Coastguard Worker   return "";
396*1b3f573fSAndroid Build Coastguard Worker }
397*1b3f573fSAndroid Build Coastguard Worker 
AddExpectedFailedTest(const std::string & test_name)398*1b3f573fSAndroid Build Coastguard Worker void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) {
399*1b3f573fSAndroid Build Coastguard Worker   expected_to_fail_.insert(test_name);
400*1b3f573fSAndroid Build Coastguard Worker }
401*1b3f573fSAndroid Build Coastguard Worker 
RunSuite(ConformanceTestRunner * runner,std::string * output,const string & filename,conformance::FailureSet * failure_list)402*1b3f573fSAndroid Build Coastguard Worker bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
403*1b3f573fSAndroid Build Coastguard Worker                                     std::string* output, const string& filename,
404*1b3f573fSAndroid Build Coastguard Worker                                     conformance::FailureSet* failure_list) {
405*1b3f573fSAndroid Build Coastguard Worker   runner_ = runner;
406*1b3f573fSAndroid Build Coastguard Worker   successes_ = 0;
407*1b3f573fSAndroid Build Coastguard Worker   expected_failures_ = 0;
408*1b3f573fSAndroid Build Coastguard Worker   skipped_.clear();
409*1b3f573fSAndroid Build Coastguard Worker   test_names_.clear();
410*1b3f573fSAndroid Build Coastguard Worker   unexpected_failing_tests_.clear();
411*1b3f573fSAndroid Build Coastguard Worker   unexpected_succeeding_tests_.clear();
412*1b3f573fSAndroid Build Coastguard Worker 
413*1b3f573fSAndroid Build Coastguard Worker   output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
414*1b3f573fSAndroid Build Coastguard Worker 
415*1b3f573fSAndroid Build Coastguard Worker   failure_list_filename_ = filename;
416*1b3f573fSAndroid Build Coastguard Worker   expected_to_fail_.clear();
417*1b3f573fSAndroid Build Coastguard Worker   for (const string& failure : failure_list->failure()) {
418*1b3f573fSAndroid Build Coastguard Worker     AddExpectedFailedTest(failure);
419*1b3f573fSAndroid Build Coastguard Worker   }
420*1b3f573fSAndroid Build Coastguard Worker   RunSuiteImpl();
421*1b3f573fSAndroid Build Coastguard Worker 
422*1b3f573fSAndroid Build Coastguard Worker   bool ok = true;
423*1b3f573fSAndroid Build Coastguard Worker   if (!CheckSetEmpty(expected_to_fail_, "nonexistent_tests.txt",
424*1b3f573fSAndroid Build Coastguard Worker                      "These tests were listed in the failure list, but they "
425*1b3f573fSAndroid Build Coastguard Worker                      "don't exist.  Remove them from the failure list by "
426*1b3f573fSAndroid Build Coastguard Worker                      "running:\n"
427*1b3f573fSAndroid Build Coastguard Worker                      "  ./update_failure_list.py " + failure_list_filename_ +
428*1b3f573fSAndroid Build Coastguard Worker                      " --remove nonexistent_tests.txt")) {
429*1b3f573fSAndroid Build Coastguard Worker     ok = false;
430*1b3f573fSAndroid Build Coastguard Worker   }
431*1b3f573fSAndroid Build Coastguard Worker   if (!CheckSetEmpty(unexpected_failing_tests_, "failing_tests.txt",
432*1b3f573fSAndroid Build Coastguard Worker                      "These tests failed.  If they can't be fixed right now, "
433*1b3f573fSAndroid Build Coastguard Worker                      "you can add them to the failure list so the overall "
434*1b3f573fSAndroid Build Coastguard Worker                      "suite can succeed.  Add them to the failure list by "
435*1b3f573fSAndroid Build Coastguard Worker                      "running:\n"
436*1b3f573fSAndroid Build Coastguard Worker                      "  ./update_failure_list.py " + failure_list_filename_ +
437*1b3f573fSAndroid Build Coastguard Worker                      " --add failing_tests.txt")) {
438*1b3f573fSAndroid Build Coastguard Worker     ok = false;
439*1b3f573fSAndroid Build Coastguard Worker   }
440*1b3f573fSAndroid Build Coastguard Worker   if (!CheckSetEmpty(unexpected_succeeding_tests_, "succeeding_tests.txt",
441*1b3f573fSAndroid Build Coastguard Worker                      "These tests succeeded, even though they were listed in "
442*1b3f573fSAndroid Build Coastguard Worker                      "the failure list.  Remove them from the failure list "
443*1b3f573fSAndroid Build Coastguard Worker                      "by running:\n"
444*1b3f573fSAndroid Build Coastguard Worker                      "  ./update_failure_list.py " + failure_list_filename_ +
445*1b3f573fSAndroid Build Coastguard Worker                      " --remove succeeding_tests.txt")) {
446*1b3f573fSAndroid Build Coastguard Worker     ok = false;
447*1b3f573fSAndroid Build Coastguard Worker   }
448*1b3f573fSAndroid Build Coastguard Worker 
449*1b3f573fSAndroid Build Coastguard Worker   if (verbose_) {
450*1b3f573fSAndroid Build Coastguard Worker     CheckSetEmpty(skipped_, "",
451*1b3f573fSAndroid Build Coastguard Worker                   "These tests were skipped (probably because support for some "
452*1b3f573fSAndroid Build Coastguard Worker                   "features is not implemented)");
453*1b3f573fSAndroid Build Coastguard Worker   }
454*1b3f573fSAndroid Build Coastguard Worker 
455*1b3f573fSAndroid Build Coastguard Worker   StringAppendF(&output_,
456*1b3f573fSAndroid Build Coastguard Worker                 "CONFORMANCE SUITE %s: %d successes, %zu skipped, "
457*1b3f573fSAndroid Build Coastguard Worker                 "%d expected failures, %zu unexpected failures.\n",
458*1b3f573fSAndroid Build Coastguard Worker                 ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
459*1b3f573fSAndroid Build Coastguard Worker                 expected_failures_, unexpected_failing_tests_.size());
460*1b3f573fSAndroid Build Coastguard Worker   StringAppendF(&output_, "\n");
461*1b3f573fSAndroid Build Coastguard Worker 
462*1b3f573fSAndroid Build Coastguard Worker   output->assign(output_);
463*1b3f573fSAndroid Build Coastguard Worker 
464*1b3f573fSAndroid Build Coastguard Worker   return ok;
465*1b3f573fSAndroid Build Coastguard Worker }
466*1b3f573fSAndroid Build Coastguard Worker 
467*1b3f573fSAndroid Build Coastguard Worker }  // namespace protobuf
468*1b3f573fSAndroid Build Coastguard Worker }  // namespace google
469