cpp.sh 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #!/bin/bash
  2. # SwiftProtobuf/Performance/generators/cpp.sh - C++ test harness generator
  3. #
  4. # This source file is part of the Swift.org open source project
  5. #
  6. # Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
  7. # Licensed under Apache License v2.0 with Runtime Library Exception
  8. #
  9. # See http://swift.org/LICENSE.txt for license information
  10. # See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  11. #
  12. # -----------------------------------------------------------------------------
  13. #
  14. # Functions for generating the C++ harness.
  15. #
  16. # -----------------------------------------------------------------------------
  17. function print_cpp_set_field() {
  18. num=$1
  19. type=$2
  20. case "$type" in
  21. repeated\ message)
  22. echo " for (auto i = 0; i < repeated_count; i++) {"
  23. echo " message.add_field$num()->set_optional_int32($((200+num)));"
  24. echo " }"
  25. ;;
  26. repeated\ string)
  27. echo " for (auto i = 0; i < repeated_count; i++) {"
  28. echo " message.add_field$num(\"$((200+num))\");"
  29. echo " }"
  30. ;;
  31. repeated\ bytes)
  32. echo " for (auto i = 0; i < repeated_count; i++) {"
  33. echo " message.add_field$num(std::string(20, (char)$((num))));"
  34. echo " }"
  35. ;;
  36. repeated\ enum)
  37. echo " for (auto i = 0; i < repeated_count; i++) {"
  38. echo " message.add_field$num(PerfMessage::FOO);"
  39. echo " }"
  40. ;;
  41. repeated\ float)
  42. echo " for (auto i = 0; i < repeated_count; i++) {"
  43. echo " message.add_field$num($((200+num)).$((200+num)));"
  44. echo " }"
  45. ;;
  46. repeated\ double)
  47. echo " for (auto i = 0; i < repeated_count; i++) {"
  48. echo " message.add_field$num($((200+num)).$((200+num)));"
  49. echo " }"
  50. ;;
  51. repeated\ *)
  52. echo " for (auto i = 0; i < repeated_count; i++) {"
  53. echo " message.add_field$num($((200+num)));"
  54. echo " }"
  55. ;;
  56. message)
  57. echo " message.mutable_field$num()->set_optional_int32($((200+num)));"
  58. ;;
  59. string)
  60. echo " message.set_field$num(\"$((200+num))\");"
  61. ;;
  62. bytes)
  63. echo " message.set_field$num(std::string(20, (char)$((num))));"
  64. ;;
  65. enum)
  66. echo " message.set_field$num(PerfMessage::FOO);"
  67. ;;
  68. float)
  69. echo " message.set_field$num($((200+num)).$((200+num)));"
  70. ;;
  71. double)
  72. echo " message.set_field$num($((200+num)).$((200+num)));"
  73. ;;
  74. *)
  75. echo " message.set_field$num($((200+num)));"
  76. ;;
  77. esac
  78. }
  79. function generate_cpp_harness() {
  80. cat >"$gen_harness_path" <<EOF
  81. #include "Harness.h"
  82. #include "message.pb.h"
  83. #include <iostream>
  84. #include <google/protobuf/text_format.h>
  85. #include <google/protobuf/util/json_util.h>
  86. #include <google/protobuf/util/message_differencer.h>
  87. #include <google/protobuf/util/type_resolver_util.h>
  88. using google::protobuf::Descriptor;
  89. using google::protobuf::DescriptorPool;
  90. using google::protobuf::TextFormat;
  91. using google::protobuf::util::BinaryToJsonString;
  92. using google::protobuf::util::JsonToBinaryString;
  93. using google::protobuf::util::MessageDifferencer;
  94. using google::protobuf::util::NewTypeResolverForDescriptorPool;
  95. using google::protobuf::util::Status;
  96. using google::protobuf::util::TypeResolver;
  97. using std::cerr;
  98. using std::endl;
  99. using std::string;
  100. static const char kTypeUrlPrefix[] = "type.googleapis.com";
  101. static string GetTypeUrl(const Descriptor* message) {
  102. return string(kTypeUrlPrefix) + "/" + message->full_name();
  103. }
  104. TypeResolver* type_resolver;
  105. string* type_url;
  106. static void populate_fields(PerfMessage& message, int repeated_count);
  107. void Harness::run() {
  108. GOOGLE_PROTOBUF_VERIFY_VERSION;
  109. type_resolver = NewTypeResolverForDescriptorPool(
  110. kTypeUrlPrefix, DescriptorPool::generated_pool());
  111. type_url = new string(GetTypeUrl(PerfMessage::descriptor()));
  112. measure([&]() {
  113. measure_subtask("New message", [&]() {
  114. return PerfMessage();
  115. });
  116. auto message = PerfMessage();
  117. measure_subtask("Populate fields", [&]() {
  118. populate_fields(message, repeated_count);
  119. // Dummy return value since void won't propagate.
  120. return false;
  121. });
  122. // Exercise binary serialization.
  123. auto data = measure_subtask("Encode binary", [&]() {
  124. return message.SerializeAsString();
  125. });
  126. auto decoded_message = measure_subtask("Decode binary", [&]() {
  127. auto result = PerfMessage();
  128. result.ParseFromString(data);
  129. return result;
  130. });
  131. // Exercise JSON serialization.
  132. auto json = measure_subtask("Encode JSON", [&]() {
  133. string out_json;
  134. BinaryToJsonString(type_resolver, *type_url, data, &out_json);
  135. return out_json;
  136. });
  137. auto decoded_binary = measure_subtask("Decode JSON", [&]() {
  138. string out_binary;
  139. JsonToBinaryString(type_resolver, *type_url, json, &out_binary);
  140. return out_binary;
  141. });
  142. // Exercise text serialization.
  143. auto text = measure_subtask("Encode text", [&]() {
  144. string out_text;
  145. TextFormat::PrintToString(message, &out_text);
  146. return out_text;
  147. });
  148. measure_subtask("Decode text", [&]() {
  149. auto result = PerfMessage();
  150. TextFormat::ParseFromString(text, &result);
  151. return result;
  152. });
  153. // Exercise equality.
  154. measure_subtask("Equality", [&]() {
  155. return MessageDifferencer::Equals(message, decoded_message);
  156. });
  157. });
  158. google::protobuf::ShutdownProtobufLibrary();
  159. }
  160. void populate_fields(PerfMessage& message, int repeated_count) {
  161. (void)repeated_count; /* Possibly unused: Quiet the compiler */
  162. EOF
  163. if [[ "$proto_type" == "homogeneous" ]]; then
  164. generate_cpp_homogenerous_populate_fields_body
  165. else
  166. generate_cpp_heterogenerous_populate_fields_body
  167. fi
  168. cat >> "$gen_harness_path" <<EOF
  169. }
  170. int Harness::run_count() const {
  171. return ${run_count};
  172. }
  173. EOF
  174. }
  175. function generate_cpp_homogenerous_populate_fields_body() {
  176. for field_number in $(seq 1 "$field_count"); do
  177. print_cpp_set_field "$field_number" "$field_type" >>"$gen_harness_path"
  178. done
  179. }
  180. function generate_cpp_heterogenerous_populate_fields_body() {
  181. cat >> "$gen_harness_path" <<EOF
  182. message.set_optional_int32(1);
  183. message.set_optional_int64(2);
  184. message.set_optional_uint32(3);
  185. message.set_optional_uint64(4);
  186. message.set_optional_sint32(5);
  187. message.set_optional_sint64(6);
  188. message.set_optional_fixed32(7);
  189. message.set_optional_fixed64(8);
  190. message.set_optional_sfixed32(9);
  191. message.set_optional_sfixed64(10);
  192. message.set_optional_float(11);
  193. message.set_optional_double(12);
  194. message.set_optional_bool(true);
  195. message.set_optional_string("14");
  196. message.set_optional_bytes(std::string(20, (char)15));
  197. message.set_optional_enum(PerfMessage::FOO);
  198. EOF
  199. if [[ "$proto_syntax" == "2" ]]; then
  200. cat >>"$gen_harness_path" <<EOF
  201. message.mutable_optionalgroup()->set_optional_group_int32(101);
  202. message.mutable_optionalgroup()->set_optional_group_int64(102);
  203. message.mutable_optionalgroup()->set_optional_group_uint32(103);
  204. message.mutable_optionalgroup()->set_optional_group_uint64(104);
  205. message.mutable_optionalgroup()->set_optional_group_sint32(105);
  206. message.mutable_optionalgroup()->set_optional_group_sint64(106);
  207. message.mutable_optionalgroup()->set_optional_group_fixed32(107);
  208. message.mutable_optionalgroup()->set_optional_group_fixed64(108);
  209. message.mutable_optionalgroup()->set_optional_group_sfixed32(109);
  210. message.mutable_optionalgroup()->set_optional_group_sfixed64(110);
  211. message.mutable_optionalgroup()->set_optional_group_float(111);
  212. message.mutable_optionalgroup()->set_optional_group_double(112);
  213. message.mutable_optionalgroup()->set_optional_group_bool(true);
  214. message.mutable_optionalgroup()->set_optional_group_string("114");
  215. message.mutable_optionalgroup()->set_optional_group_bytes(std::string(20, (char)115));
  216. message.mutable_optionalgroup()->set_optional_group_enum(PerfMessage::FOO);
  217. EOF
  218. fi
  219. cat >>"$gen_harness_path" <<EOF
  220. for (auto i = 0; i < repeated_count; i++) {
  221. message.add_repeated_int32(201);
  222. message.add_repeated_int64(202);
  223. message.add_repeated_uint32(203);
  224. message.add_repeated_uint64(204);
  225. message.add_repeated_sint32(205);
  226. message.add_repeated_sint64(206);
  227. message.add_repeated_fixed32(207);
  228. message.add_repeated_fixed64(208);
  229. message.add_repeated_sfixed32(209);
  230. message.add_repeated_sfixed64(210);
  231. message.add_repeated_float(211);
  232. message.add_repeated_double(212);
  233. message.add_repeated_bool(true);
  234. message.add_repeated_string("214");
  235. message.add_repeated_bytes(std::string(20, (char)215));
  236. message.add_repeated_enum(PerfMessage::FOO);
  237. }
  238. // Instead of writing a ton of code that populates the nested messages,
  239. // just do some bulk assignments from a snapshot of the message we just
  240. // populated.
  241. auto snapshot = message;
  242. *(message.mutable_optional_message()) = snapshot;
  243. EOF
  244. if [[ "$proto_syntax" == "2" ]]; then
  245. cat >>"$gen_harness_path" <<EOF
  246. *(message.mutable_optionalgroup()->mutable_optional_group_message()) = snapshot;
  247. EOF
  248. fi
  249. cat >>"$gen_harness_path" <<EOF
  250. for (auto i = 0; i < repeated_count; i++) {
  251. auto element = message.add_repeated_message();
  252. *element = snapshot;
  253. }
  254. EOF
  255. }