• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include "text_format_conformance_suite.h"
32 
33 #include "conformance_test.h"
34 
35 #include <google/protobuf/any.pb.h>
36 #include <google/protobuf/test_messages_proto2.pb.h>
37 #include <google/protobuf/test_messages_proto3.pb.h>
38 #include <google/protobuf/text_format.h>
39 
40 using conformance::ConformanceRequest;
41 using conformance::ConformanceResponse;
42 using conformance::WireFormat;
43 using google::protobuf::Message;
44 using google::protobuf::TextFormat;
45 using protobuf_test_messages::proto2::TestAllTypesProto2;
46 using protobuf_test_messages::proto2::UnknownToTestAllTypes;
47 using protobuf_test_messages::proto3::TestAllTypesProto3;
48 using std::string;
49 
50 namespace google {
51 namespace protobuf {
52 
TextFormatConformanceTestSuite()53 TextFormatConformanceTestSuite::TextFormatConformanceTestSuite() {
54   SetFailureListFlagName("--text_format_failure_list");
55 }
56 
ParseTextFormatResponse(const ConformanceResponse & response,const ConformanceRequestSetting & setting,Message * test_message)57 bool TextFormatConformanceTestSuite::ParseTextFormatResponse(
58     const ConformanceResponse& response,
59     const ConformanceRequestSetting& setting, Message* test_message) {
60   TextFormat::Parser parser;
61   const ConformanceRequest& request = setting.GetRequest();
62   if (request.print_unknown_fields()) {
63     parser.AllowFieldNumber(true);
64   }
65   if (!parser.ParseFromString(response.text_payload(), test_message)) {
66     GOOGLE_LOG(ERROR) << "INTERNAL ERROR: internal text->protobuf transcode "
67                       << "yielded unparseable proto. Text payload: "
68                       << response.text_payload();
69     return false;
70   }
71 
72   return true;
73 }
74 
ParseResponse(const ConformanceResponse & response,const ConformanceRequestSetting & setting,Message * test_message)75 bool TextFormatConformanceTestSuite::ParseResponse(
76     const ConformanceResponse& response,
77     const ConformanceRequestSetting& setting, Message* test_message) {
78   const ConformanceRequest& request = setting.GetRequest();
79   WireFormat requested_output = request.requested_output_format();
80   const string& test_name = setting.GetTestName();
81   ConformanceLevel level = setting.GetLevel();
82 
83   switch (response.result_case()) {
84     case ConformanceResponse::kProtobufPayload: {
85       if (requested_output != conformance::PROTOBUF) {
86         ReportFailure(
87             test_name, level, request, response,
88             StrCat("Test was asked for ", WireFormatToString(requested_output),
89                    " output but provided PROTOBUF instead.")
90                 .c_str());
91         return false;
92       }
93 
94       if (!test_message->ParseFromString(response.protobuf_payload())) {
95         ReportFailure(test_name, level, request, response,
96                       "Protobuf output we received from test was unparseable.");
97         return false;
98       }
99 
100       break;
101     }
102 
103     case ConformanceResponse::kTextPayload: {
104       if (requested_output != conformance::TEXT_FORMAT) {
105         ReportFailure(
106             test_name, level, request, response,
107             StrCat("Test was asked for ", WireFormatToString(requested_output),
108                    " output but provided TEXT_FORMAT instead.")
109                 .c_str());
110         return false;
111       }
112 
113       if (!ParseTextFormatResponse(response, setting, test_message)) {
114         ReportFailure(
115             test_name, level, request, response,
116             "TEXT_FORMAT output we received from test was unparseable.");
117         return false;
118       }
119 
120       break;
121     }
122 
123     default:
124       GOOGLE_LOG(FATAL) << test_name
125                         << ": unknown payload type: " << response.result_case();
126   }
127 
128   return true;
129 }
130 
ExpectParseFailure(const string & test_name,ConformanceLevel level,const string & input)131 void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name,
132                                                         ConformanceLevel level,
133                                                         const string& input) {
134   TestAllTypesProto3 prototype;
135   // We don't expect output, but if the program erroneously accepts the protobuf
136   // we let it send its response as this.  We must not leave it unspecified.
137   ConformanceRequestSetting setting(
138       level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
139       conformance::TEXT_FORMAT_TEST, prototype, test_name, input);
140   const ConformanceRequest& request = setting.GetRequest();
141   ConformanceResponse response;
142   string effective_test_name = StrCat(setting.ConformanceLevelToString(level),
143                                       ".Proto3.TextFormatInput.", test_name);
144 
145   RunTest(effective_test_name, request, &response);
146   if (response.result_case() == ConformanceResponse::kParseError) {
147     ReportSuccess(effective_test_name);
148   } else if (response.result_case() == ConformanceResponse::kSkipped) {
149     ReportSkip(effective_test_name, request, response);
150   } else {
151     ReportFailure(effective_test_name, level, request, response,
152                   "Should have failed to parse, but didn't.");
153   }
154 }
155 
RunValidTextFormatTest(const string & test_name,ConformanceLevel level,const string & input_text)156 void TextFormatConformanceTestSuite::RunValidTextFormatTest(
157     const string& test_name, ConformanceLevel level, const string& input_text) {
158   TestAllTypesProto3 prototype;
159   RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
160 }
161 
RunValidTextFormatTestProto2(const string & test_name,ConformanceLevel level,const string & input_text)162 void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2(
163     const string& test_name, ConformanceLevel level, const string& input_text) {
164   TestAllTypesProto2 prototype;
165   RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
166 }
167 
RunValidTextFormatTestWithMessage(const string & test_name,ConformanceLevel level,const string & input_text,const Message & prototype)168 void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage(
169     const string& test_name, ConformanceLevel level, const string& input_text,
170     const Message& prototype) {
171   ConformanceRequestSetting setting1(
172       level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
173       conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
174   RunValidInputTest(setting1, input_text);
175   ConformanceRequestSetting setting2(
176       level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
177       conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
178   RunValidInputTest(setting2, input_text);
179 }
180 
RunValidUnknownTextFormatTest(const string & test_name,const Message & message)181 void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest(
182     const string& test_name, const Message& message) {
183   string serialized_input;
184   message.SerializeToString(&serialized_input);
185   TestAllTypesProto3 prototype;
186   ConformanceRequestSetting setting1(
187       RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
188       conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Drop",
189       serialized_input);
190   setting1.SetPrototypeMessageForCompare(message);
191   RunValidBinaryInputTest(setting1, "");
192 
193   ConformanceRequestSetting setting2(
194       RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
195       conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Print",
196       serialized_input);
197   setting2.SetPrototypeMessageForCompare(message);
198   setting2.SetPrintUnknownFields(true);
199   RunValidBinaryInputTest(setting2, serialized_input);
200 }
201 
RunSuiteImpl()202 void TextFormatConformanceTestSuite::RunSuiteImpl() {
203   RunValidTextFormatTest("HelloWorld", REQUIRED,
204                          "optional_string: 'Hello, World!'");
205   // Integer fields.
206   RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED,
207                          "optional_int32: 2147483647");
208   RunValidTextFormatTest("Int32FieldMinValue", REQUIRED,
209                          "optional_int32: -2147483648");
210   RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED,
211                          "optional_uint32: 4294967295");
212   RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED,
213                          "optional_int64: 9223372036854775807");
214   RunValidTextFormatTest("Int64FieldMinValue", REQUIRED,
215                          "optional_int64: -9223372036854775808");
216   RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED,
217                          "optional_uint64: 18446744073709551615");
218 
219   // Parsers reject out-of-bound integer values.
220   ExpectParseFailure("Int32FieldTooLarge", REQUIRED,
221                      "optional_int32: 2147483648");
222   ExpectParseFailure("Int32FieldTooSmall", REQUIRED,
223                      "optional_int32: -2147483649");
224   ExpectParseFailure("Uint32FieldTooLarge", REQUIRED,
225                      "optional_uint32: 4294967296");
226   ExpectParseFailure("Int64FieldTooLarge", REQUIRED,
227                      "optional_int64: 9223372036854775808");
228   ExpectParseFailure("Int64FieldTooSmall", REQUIRED,
229                      "optional_int64: -9223372036854775809");
230   ExpectParseFailure("Uint64FieldTooLarge", REQUIRED,
231                      "optional_uint64: 18446744073709551616");
232 
233   // Floating point fields
234   RunValidTextFormatTest("FloatField", REQUIRED,
235                          "optional_float: 3.192837");
236   RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED,
237                          "optional_float: 3.123456789123456789");
238   RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED,
239                          "optional_float: 3.4028235e+38");
240   RunValidTextFormatTest("FloatFieldMinValue", REQUIRED,
241                          "optional_float: 1.17549e-38");
242   RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED,
243                          "optional_float: NaN");
244   RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED,
245                          "optional_float: inf");
246   RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED,
247                          "optional_float: -inf");
248   RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED,
249                          "optional_float: 4294967296");
250   RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED,
251                          "optional_float: 9223372036854775808");
252   RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED,
253                          "optional_float: 3.4028235e+39");
254   RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED,
255                          "optional_float: 1.17549e-39");
256   RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED,
257                          "optional_float: 18446744073709551616");
258 
259   // Group fields
260   RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
261                                "Data { group_int32: 1 }");
262   RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED,
263                                "Data: { group_int32: 1 }");
264   RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED,
265                                "Data {}");
266 
267 
268   // Unknown Fields
269   UnknownToTestAllTypes message;
270   // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
271   // Fixed32/Fixed64 fields are not added in the tests.
272   message.set_optional_int32(123);
273   message.set_optional_string("hello");
274   message.set_optional_bool(true);
275   RunValidUnknownTextFormatTest("ScalarUnknownFields", message);
276 
277   message.Clear();
278   message.mutable_nested_message()->set_c(111);
279   RunValidUnknownTextFormatTest("MessageUnknownFields", message);
280 
281   message.Clear();
282   message.mutable_optionalgroup()->set_a(321);
283   RunValidUnknownTextFormatTest("GroupUnknownFields", message);
284 
285   message.add_repeated_int32(1);
286   message.add_repeated_int32(2);
287   message.add_repeated_int32(3);
288   RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
289 
290   // Any fields
291   RunValidTextFormatTest("AnyField", REQUIRED,
292                          R"(
293       optional_any: {
294         [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
295           optional_int32: 12345
296         }
297       }
298       )");
299   RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
300                          R"(
301       optional_any: {
302         type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
303         value: "\b\271`"
304       }
305       )");
306   ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
307                      R"(
308       optional_any: {
309         [type.googleapis.com/unknown] {
310           optional_int32: 12345
311         }
312       }
313       )");
314 }
315 
316 }  // namespace protobuf
317 }  // namespace google
318