text_format_conformance_suite.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. #include "text_format_conformance_suite.h"
  31. #include <google/protobuf/any.pb.h>
  32. #include <google/protobuf/text_format.h>
  33. #include "conformance_test.h"
  34. #include <google/protobuf/test_messages_proto2.pb.h>
  35. #include <google/protobuf/test_messages_proto3.pb.h>
  36. namespace proto2_messages = protobuf_test_messages::proto2;
  37. using conformance::ConformanceRequest;
  38. using conformance::ConformanceResponse;
  39. using conformance::WireFormat;
  40. using google::protobuf::Message;
  41. using google::protobuf::TextFormat;
  42. using proto2_messages::TestAllTypesProto2;
  43. using proto2_messages::UnknownToTestAllTypes;
  44. using protobuf_test_messages::proto3::TestAllTypesProto3;
  45. using std::string;
  46. namespace google {
  47. namespace protobuf {
  48. TextFormatConformanceTestSuite::TextFormatConformanceTestSuite() {
  49. SetFailureListFlagName("--text_format_failure_list");
  50. }
  51. bool TextFormatConformanceTestSuite::ParseTextFormatResponse(
  52. const ConformanceResponse& response,
  53. const ConformanceRequestSetting& setting, Message* test_message) {
  54. TextFormat::Parser parser;
  55. const ConformanceRequest& request = setting.GetRequest();
  56. if (request.print_unknown_fields()) {
  57. parser.AllowFieldNumber(true);
  58. }
  59. if (!parser.ParseFromString(response.text_payload(), test_message)) {
  60. GOOGLE_LOG(ERROR) << "INTERNAL ERROR: internal text->protobuf transcode "
  61. << "yielded unparseable proto. Text payload: "
  62. << response.text_payload();
  63. return false;
  64. }
  65. return true;
  66. }
  67. bool TextFormatConformanceTestSuite::ParseResponse(
  68. const ConformanceResponse& response,
  69. const ConformanceRequestSetting& setting, Message* test_message) {
  70. const ConformanceRequest& request = setting.GetRequest();
  71. WireFormat requested_output = request.requested_output_format();
  72. const string& test_name = setting.GetTestName();
  73. ConformanceLevel level = setting.GetLevel();
  74. switch (response.result_case()) {
  75. case ConformanceResponse::kProtobufPayload: {
  76. if (requested_output != conformance::PROTOBUF) {
  77. ReportFailure(test_name, level, request, response,
  78. StrCat("Test was asked for ",
  79. WireFormatToString(requested_output),
  80. " output but provided PROTOBUF instead.")
  81. .c_str());
  82. return false;
  83. }
  84. if (!test_message->ParseFromString(response.protobuf_payload())) {
  85. ReportFailure(test_name, level, request, response,
  86. "Protobuf output we received from test was unparseable.");
  87. return false;
  88. }
  89. break;
  90. }
  91. case ConformanceResponse::kTextPayload: {
  92. if (requested_output != conformance::TEXT_FORMAT) {
  93. ReportFailure(test_name, level, request, response,
  94. StrCat("Test was asked for ",
  95. WireFormatToString(requested_output),
  96. " output but provided TEXT_FORMAT instead.")
  97. .c_str());
  98. return false;
  99. }
  100. if (!ParseTextFormatResponse(response, setting, test_message)) {
  101. ReportFailure(
  102. test_name, level, request, response,
  103. "TEXT_FORMAT output we received from test was unparseable.");
  104. return false;
  105. }
  106. break;
  107. }
  108. default:
  109. GOOGLE_LOG(FATAL) << test_name
  110. << ": unknown payload type: " << response.result_case();
  111. }
  112. return true;
  113. }
  114. void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name,
  115. ConformanceLevel level,
  116. const string& input) {
  117. TestAllTypesProto3 prototype;
  118. // We don't expect output, but if the program erroneously accepts the protobuf
  119. // we let it send its response as this. We must not leave it unspecified.
  120. ConformanceRequestSetting setting(
  121. level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
  122. conformance::TEXT_FORMAT_TEST, prototype, test_name, input);
  123. const ConformanceRequest& request = setting.GetRequest();
  124. ConformanceResponse response;
  125. string effective_test_name =
  126. StrCat(setting.ConformanceLevelToString(level),
  127. ".Proto3.TextFormatInput.", test_name);
  128. RunTest(effective_test_name, request, &response);
  129. if (response.result_case() == ConformanceResponse::kParseError) {
  130. ReportSuccess(effective_test_name);
  131. } else if (response.result_case() == ConformanceResponse::kSkipped) {
  132. ReportSkip(effective_test_name, request, response);
  133. } else {
  134. ReportFailure(effective_test_name, level, request, response,
  135. "Should have failed to parse, but didn't.");
  136. }
  137. }
  138. void TextFormatConformanceTestSuite::RunValidTextFormatTest(
  139. const string& test_name, ConformanceLevel level, const string& input_text) {
  140. TestAllTypesProto3 prototype;
  141. RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
  142. }
  143. void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2(
  144. const string& test_name, ConformanceLevel level, const string& input_text) {
  145. TestAllTypesProto2 prototype;
  146. RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
  147. }
  148. void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage(
  149. const string& test_name, ConformanceLevel level, const string& input_text,
  150. const Message& prototype) {
  151. ConformanceRequestSetting setting1(
  152. level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
  153. conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
  154. RunValidInputTest(setting1, input_text);
  155. ConformanceRequestSetting setting2(
  156. level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
  157. conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
  158. RunValidInputTest(setting2, input_text);
  159. }
  160. void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest(
  161. const string& test_name, const Message& message) {
  162. string serialized_input;
  163. message.SerializeToString(&serialized_input);
  164. TestAllTypesProto3 prototype;
  165. ConformanceRequestSetting setting1(
  166. RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
  167. conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Drop",
  168. serialized_input);
  169. setting1.SetPrototypeMessageForCompare(message);
  170. RunValidBinaryInputTest(setting1, "");
  171. ConformanceRequestSetting setting2(
  172. RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
  173. conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Print",
  174. serialized_input);
  175. setting2.SetPrototypeMessageForCompare(message);
  176. setting2.SetPrintUnknownFields(true);
  177. RunValidBinaryInputTest(setting2, serialized_input);
  178. }
  179. void TextFormatConformanceTestSuite::RunSuiteImpl() {
  180. RunValidTextFormatTest("HelloWorld", REQUIRED,
  181. "optional_string: 'Hello, World!'");
  182. // Integer fields.
  183. RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED,
  184. "optional_int32: 2147483647");
  185. RunValidTextFormatTest("Int32FieldMinValue", REQUIRED,
  186. "optional_int32: -2147483648");
  187. RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED,
  188. "optional_uint32: 4294967295");
  189. RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED,
  190. "optional_int64: 9223372036854775807");
  191. RunValidTextFormatTest("Int64FieldMinValue", REQUIRED,
  192. "optional_int64: -9223372036854775808");
  193. RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED,
  194. "optional_uint64: 18446744073709551615");
  195. // Parsers reject out-of-bound integer values.
  196. ExpectParseFailure("Int32FieldTooLarge", REQUIRED,
  197. "optional_int32: 2147483648");
  198. ExpectParseFailure("Int32FieldTooSmall", REQUIRED,
  199. "optional_int32: -2147483649");
  200. ExpectParseFailure("Uint32FieldTooLarge", REQUIRED,
  201. "optional_uint32: 4294967296");
  202. ExpectParseFailure("Int64FieldTooLarge", REQUIRED,
  203. "optional_int64: 9223372036854775808");
  204. ExpectParseFailure("Int64FieldTooSmall", REQUIRED,
  205. "optional_int64: -9223372036854775809");
  206. ExpectParseFailure("Uint64FieldTooLarge", REQUIRED,
  207. "optional_uint64: 18446744073709551616");
  208. // Floating point fields
  209. RunValidTextFormatTest("FloatField", REQUIRED,
  210. "optional_float: 3.192837");
  211. RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED,
  212. "optional_float: 3.123456789123456789");
  213. RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED,
  214. "optional_float: 3.4028235e+38");
  215. RunValidTextFormatTest("FloatFieldMinValue", REQUIRED,
  216. "optional_float: 1.17549e-38");
  217. RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED,
  218. "optional_float: NaN");
  219. RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED,
  220. "optional_float: inf");
  221. RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED,
  222. "optional_float: -inf");
  223. RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED,
  224. "optional_float: 4294967296");
  225. RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED,
  226. "optional_float: 9223372036854775808");
  227. RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED,
  228. "optional_float: 3.4028235e+39");
  229. RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED,
  230. "optional_float: 1.17549e-39");
  231. RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED,
  232. "optional_float: 18446744073709551616");
  233. // Group fields
  234. RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
  235. "Data { group_int32: 1 }");
  236. RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED,
  237. "Data: { group_int32: 1 }");
  238. RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED,
  239. "Data {}");
  240. // Unknown Fields
  241. UnknownToTestAllTypes message;
  242. // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
  243. // Fixed32/Fixed64 fields are not added in the tests.
  244. message.set_optional_int32(123);
  245. message.set_optional_string("hello");
  246. message.set_optional_bool(true);
  247. RunValidUnknownTextFormatTest("ScalarUnknownFields", message);
  248. message.Clear();
  249. message.mutable_nested_message()->set_c(111);
  250. RunValidUnknownTextFormatTest("MessageUnknownFields", message);
  251. message.Clear();
  252. message.mutable_optionalgroup()->set_a(321);
  253. RunValidUnknownTextFormatTest("GroupUnknownFields", message);
  254. message.add_repeated_int32(1);
  255. message.add_repeated_int32(2);
  256. message.add_repeated_int32(3);
  257. RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
  258. // Any fields
  259. RunValidTextFormatTest("AnyField", REQUIRED,
  260. R"(
  261. optional_any: {
  262. [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
  263. optional_int32: 12345
  264. }
  265. }
  266. )");
  267. RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
  268. R"(
  269. optional_any: {
  270. type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
  271. value: "\b\271`"
  272. }
  273. )");
  274. ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
  275. R"(
  276. optional_any: {
  277. [type.googleapis.com/unknown] {
  278. optional_int32: 12345
  279. }
  280. }
  281. )");
  282. // Map fields
  283. TestAllTypesProto3 prototype;
  284. (*prototype.mutable_map_string_string())["c"] = "value";
  285. (*prototype.mutable_map_string_string())["b"] = "value";
  286. (*prototype.mutable_map_string_string())["a"] = "value";
  287. RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys",
  288. REQUIRED,
  289. R"(
  290. map_string_string {
  291. key: "a"
  292. value: "value"
  293. }
  294. map_string_string {
  295. key: "b"
  296. value: "value"
  297. }
  298. map_string_string {
  299. key: "c"
  300. value: "value"
  301. }
  302. )",
  303. prototype);
  304. prototype.Clear();
  305. (*prototype.mutable_map_int32_int32())[3] = 0;
  306. (*prototype.mutable_map_int32_int32())[2] = 0;
  307. (*prototype.mutable_map_int32_int32())[1] = 0;
  308. RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED,
  309. R"(
  310. map_int32_int32 {
  311. key: 1
  312. value: 0
  313. }
  314. map_int32_int32 {
  315. key: 2
  316. value: 0
  317. }
  318. map_int32_int32 {
  319. key: 3
  320. value: 0
  321. }
  322. )",
  323. prototype);
  324. prototype.Clear();
  325. (*prototype.mutable_map_bool_bool())[true] = false;
  326. (*prototype.mutable_map_bool_bool())[false] = false;
  327. RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED,
  328. R"(
  329. map_bool_bool {
  330. key: false
  331. value: false
  332. }
  333. map_bool_bool {
  334. key: true
  335. value: false
  336. }
  337. )",
  338. prototype);
  339. }
  340. } // namespace protobuf
  341. } // namespace google