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