text_format_conformance_suite.cc 13 KB

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