cpp.sh 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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::TypeResolver;
  96. using std::cerr;
  97. using std::endl;
  98. using std::string;
  99. static const char kTypeUrlPrefix[] = "type.googleapis.com";
  100. static string GetTypeUrl(const Descriptor* message) {
  101. return string(kTypeUrlPrefix) + "/" + message->full_name();
  102. }
  103. TypeResolver* type_resolver;
  104. string* type_url;
  105. static void populate_fields(PerfMessage& message, int repeated_count);
  106. void Harness::run() {
  107. GOOGLE_PROTOBUF_VERIFY_VERSION;
  108. type_resolver = NewTypeResolverForDescriptorPool(
  109. kTypeUrlPrefix, DescriptorPool::generated_pool());
  110. type_url = new string(GetTypeUrl(PerfMessage::descriptor()));
  111. measure([&]() {
  112. measure_subtask("New message", [&]() {
  113. return PerfMessage();
  114. });
  115. auto message = PerfMessage();
  116. measure_subtask("Populate fields", [&]() {
  117. populate_fields(message, repeated_count);
  118. // Dummy return value since void won't propagate.
  119. return false;
  120. });
  121. // Exercise binary serialization.
  122. auto data = measure_subtask("Encode binary", [&]() {
  123. return message.SerializeAsString();
  124. });
  125. auto decoded_message = measure_subtask("Decode binary", [&]() {
  126. auto result = PerfMessage();
  127. result.ParseFromString(data);
  128. return result;
  129. });
  130. // Exercise JSON serialization.
  131. auto json = measure_subtask("Encode JSON", [&]() {
  132. string out_json;
  133. auto r = BinaryToJsonString(type_resolver, *type_url, data, &out_json);
  134. (void)r; // UNUSED
  135. return out_json;
  136. });
  137. auto decoded_binary = measure_subtask("Decode JSON", [&]() {
  138. string out_binary;
  139. auto r = JsonToBinaryString(type_resolver, *type_url, json, &out_binary);
  140. (void)r; // UNUSED
  141. return out_binary;
  142. });
  143. // Exercise text serialization.
  144. auto text = measure_subtask("Encode text", [&]() {
  145. string out_text;
  146. TextFormat::PrintToString(message, &out_text);
  147. return out_text;
  148. });
  149. measure_subtask("Decode text", [&]() {
  150. auto result = PerfMessage();
  151. TextFormat::ParseFromString(text, &result);
  152. return result;
  153. });
  154. // Exercise equality.
  155. measure_subtask("Equality", [&]() {
  156. return MessageDifferencer::Equals(message, decoded_message);
  157. });
  158. });
  159. google::protobuf::ShutdownProtobufLibrary();
  160. }
  161. void populate_fields(PerfMessage& message, int repeated_count) {
  162. (void)repeated_count; /* Possibly unused: Quiet the compiler */
  163. EOF
  164. if [[ "$proto_type" == "homogeneous" ]]; then
  165. generate_cpp_homogenerous_populate_fields_body
  166. else
  167. generate_cpp_heterogenerous_populate_fields_body
  168. fi
  169. cat >> "$gen_harness_path" <<EOF
  170. }
  171. int Harness::run_count() const {
  172. return ${run_count};
  173. }
  174. EOF
  175. }
  176. function generate_cpp_homogenerous_populate_fields_body() {
  177. for field_number in $(seq 1 "$field_count"); do
  178. print_cpp_set_field "$field_number" "$field_type" >>"$gen_harness_path"
  179. done
  180. }
  181. function generate_cpp_heterogenerous_populate_fields_body() {
  182. cat >> "$gen_harness_path" <<EOF
  183. message.set_optional_int32(1);
  184. message.set_optional_int64(2);
  185. message.set_optional_uint32(3);
  186. message.set_optional_uint64(4);
  187. message.set_optional_sint32(5);
  188. message.set_optional_sint64(6);
  189. message.set_optional_fixed32(7);
  190. message.set_optional_fixed64(8);
  191. message.set_optional_sfixed32(9);
  192. message.set_optional_sfixed64(10);
  193. message.set_optional_float(11);
  194. message.set_optional_double(12);
  195. message.set_optional_bool(true);
  196. message.set_optional_string("14");
  197. message.set_optional_bytes(std::string(20, (char)15));
  198. message.set_optional_enum(PerfMessage::FOO);
  199. EOF
  200. if [[ "$proto_syntax" == "2" ]]; then
  201. cat >>"$gen_harness_path" <<EOF
  202. message.mutable_optionalgroup()->set_optional_group_int32(101);
  203. message.mutable_optionalgroup()->set_optional_group_int64(102);
  204. message.mutable_optionalgroup()->set_optional_group_uint32(103);
  205. message.mutable_optionalgroup()->set_optional_group_uint64(104);
  206. message.mutable_optionalgroup()->set_optional_group_sint32(105);
  207. message.mutable_optionalgroup()->set_optional_group_sint64(106);
  208. message.mutable_optionalgroup()->set_optional_group_fixed32(107);
  209. message.mutable_optionalgroup()->set_optional_group_fixed64(108);
  210. message.mutable_optionalgroup()->set_optional_group_sfixed32(109);
  211. message.mutable_optionalgroup()->set_optional_group_sfixed64(110);
  212. message.mutable_optionalgroup()->set_optional_group_float(111);
  213. message.mutable_optionalgroup()->set_optional_group_double(112);
  214. message.mutable_optionalgroup()->set_optional_group_bool(true);
  215. message.mutable_optionalgroup()->set_optional_group_string("114");
  216. message.mutable_optionalgroup()->set_optional_group_bytes(std::string(20, (char)115));
  217. message.mutable_optionalgroup()->set_optional_group_enum(PerfMessage::FOO);
  218. EOF
  219. fi
  220. cat >>"$gen_harness_path" <<EOF
  221. for (auto i = 0; i < repeated_count; i++) {
  222. message.add_repeated_int32(201);
  223. message.add_repeated_int64(202);
  224. message.add_repeated_uint32(203);
  225. message.add_repeated_uint64(204);
  226. message.add_repeated_sint32(205);
  227. message.add_repeated_sint64(206);
  228. message.add_repeated_fixed32(207);
  229. message.add_repeated_fixed64(208);
  230. message.add_repeated_sfixed32(209);
  231. message.add_repeated_sfixed64(210);
  232. message.add_repeated_float(211);
  233. message.add_repeated_double(212);
  234. message.add_repeated_bool(true);
  235. message.add_repeated_string("214");
  236. message.add_repeated_bytes(std::string(20, (char)215));
  237. message.add_repeated_enum(PerfMessage::FOO);
  238. }
  239. // Instead of writing a ton of code that populates the nested messages,
  240. // just do some bulk assignments from a snapshot of the message we just
  241. // populated.
  242. auto snapshot = message;
  243. *(message.mutable_optional_message()) = snapshot;
  244. EOF
  245. if [[ "$proto_syntax" == "2" ]]; then
  246. cat >>"$gen_harness_path" <<EOF
  247. *(message.mutable_optionalgroup()->mutable_optional_group_message()) = snapshot;
  248. EOF
  249. fi
  250. cat >>"$gen_harness_path" <<EOF
  251. for (auto i = 0; i < repeated_count; i++) {
  252. auto element = message.add_repeated_message();
  253. *element = snapshot;
  254. }
  255. EOF
  256. }