mem_release.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* Make sure that all fields are freed in various scenarios. */
  2. #include <pb_decode.h>
  3. #include <pb_encode.h>
  4. #include <malloc_wrappers.h>
  5. #include <stdio.h>
  6. #include <test_helpers.h>
  7. #include "mem_release.pb.h"
  8. #define TEST(x) if (!(x)) { \
  9. fprintf(stderr, "Test %s on line %d failed.\n", #x, __LINE__); \
  10. return false; \
  11. }
  12. static char *test_str_arr[] = {"1", "2", ""};
  13. static SubMessage test_msg_arr[] = {SubMessage_init_zero, SubMessage_init_zero};
  14. static pb_extension_t ext1, ext2;
  15. static void fill_TestMessage(TestMessage *msg)
  16. {
  17. msg->static_req_submsg.dynamic_str = "12345";
  18. msg->static_req_submsg.dynamic_str_arr_count = 3;
  19. msg->static_req_submsg.dynamic_str_arr = test_str_arr;
  20. msg->static_req_submsg.dynamic_submsg_count = 2;
  21. msg->static_req_submsg.dynamic_submsg = test_msg_arr;
  22. msg->static_req_submsg.dynamic_submsg[1].dynamic_str = "abc";
  23. msg->static_opt_submsg.dynamic_str = "abc";
  24. msg->static_rep_submsg_count = 2;
  25. msg->static_rep_submsg[1].dynamic_str = "abc";
  26. msg->has_static_opt_submsg = true;
  27. msg->dynamic_submsg = &msg->static_req_submsg;
  28. msg->extensions = &ext1;
  29. ext1.type = &dynamic_ext;
  30. ext1.dest = &msg->static_req_submsg;
  31. ext1.next = &ext2;
  32. ext2.type = &static_ext;
  33. ext2.dest = &msg->static_req_submsg;
  34. ext2.next = NULL;
  35. }
  36. /* Basic fields, nested submessages, extensions */
  37. static bool test_TestMessage()
  38. {
  39. uint8_t buffer[256];
  40. size_t msgsize;
  41. /* Construct a message with various fields filled in */
  42. {
  43. TestMessage msg = TestMessage_init_zero;
  44. pb_ostream_t stream;
  45. fill_TestMessage(&msg);
  46. stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
  47. if (!pb_encode(&stream, TestMessage_fields, &msg))
  48. {
  49. fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
  50. return false;
  51. }
  52. msgsize = stream.bytes_written;
  53. }
  54. /* Output encoded message for debug */
  55. SET_BINARY_MODE(stdout);
  56. fwrite(buffer, 1, msgsize, stdout);
  57. /* Decode memory using dynamic allocation */
  58. {
  59. TestMessage msg = TestMessage_init_zero;
  60. pb_istream_t stream;
  61. SubMessage ext2_dest;
  62. msg.extensions = &ext1;
  63. ext1.type = &dynamic_ext;
  64. ext1.dest = NULL;
  65. ext1.next = &ext2;
  66. ext2.type = &static_ext;
  67. ext2.dest = &ext2_dest;
  68. ext2.next = NULL;
  69. stream = pb_istream_from_buffer(buffer, msgsize);
  70. if (!pb_decode(&stream, TestMessage_fields, &msg))
  71. {
  72. fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream));
  73. return false;
  74. }
  75. /* Make sure it encodes back to same data */
  76. {
  77. uint8_t buffer2[256];
  78. pb_ostream_t ostream = pb_ostream_from_buffer(buffer2, sizeof(buffer2));
  79. TEST(pb_encode(&ostream, TestMessage_fields, &msg));
  80. TEST(ostream.bytes_written == msgsize);
  81. TEST(memcmp(buffer, buffer2, msgsize) == 0);
  82. }
  83. /* Make sure that malloc counters work */
  84. TEST(get_alloc_count() > 0);
  85. /* Make sure that pb_release releases everything */
  86. pb_release(TestMessage_fields, &msg);
  87. TEST(get_alloc_count() == 0);
  88. /* Check that double-free is a no-op */
  89. pb_release(TestMessage_fields, &msg);
  90. TEST(get_alloc_count() == 0);
  91. }
  92. return true;
  93. }
  94. /* Oneofs */
  95. static bool test_OneofMessage()
  96. {
  97. uint8_t buffer[256];
  98. size_t msgsize;
  99. {
  100. pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
  101. /* Encode first with TestMessage */
  102. {
  103. OneofMessage msg = OneofMessage_init_zero;
  104. msg.which_msgs = OneofMessage_msg1_tag;
  105. fill_TestMessage(&msg.msgs.msg1);
  106. if (!pb_encode(&stream, OneofMessage_fields, &msg))
  107. {
  108. fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
  109. return false;
  110. }
  111. }
  112. /* Encode second with SubMessage, replacing the oneof item */
  113. {
  114. OneofMessage msg = OneofMessage_init_zero;
  115. char *teststr = "1";
  116. msg.which_msgs = OneofMessage_msg2_tag;
  117. msg.first = 999;
  118. msg.msgs.msg2.dynamic_str = "ABCD";
  119. msg.msgs.msg2.dynamic_str_arr_count = 1;
  120. msg.msgs.msg2.dynamic_str_arr = &teststr;
  121. msg.last = 888;
  122. if (!pb_encode(&stream, OneofMessage_fields, &msg))
  123. {
  124. fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
  125. return false;
  126. }
  127. }
  128. /* Encode second SubMessage, invoking submessage merge behavior */
  129. {
  130. OneofMessage msg = OneofMessage_init_zero;
  131. char *teststr = "2";
  132. msg.which_msgs = OneofMessage_msg2_tag;
  133. msg.first = 99;
  134. msg.msgs.msg2.dynamic_str = "EFGH";
  135. msg.msgs.msg2.dynamic_str_arr_count = 1;
  136. msg.msgs.msg2.dynamic_str_arr = &teststr;
  137. msg.last = 88;
  138. if (!pb_encode(&stream, OneofMessage_fields, &msg))
  139. {
  140. fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
  141. return false;
  142. }
  143. }
  144. msgsize = stream.bytes_written;
  145. }
  146. {
  147. OneofMessage msg = OneofMessage_init_zero;
  148. pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
  149. if (!pb_decode(&stream, OneofMessage_fields, &msg))
  150. {
  151. fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream));
  152. return false;
  153. }
  154. TEST(msg.first == 99);
  155. TEST(msg.which_msgs == OneofMessage_msg2_tag);
  156. TEST(msg.msgs.msg2.dynamic_str);
  157. TEST(strcmp(msg.msgs.msg2.dynamic_str, "EFGH") == 0);
  158. TEST(msg.msgs.msg2.dynamic_str_arr != NULL);
  159. TEST(msg.msgs.msg2.dynamic_str_arr_count == 2);
  160. TEST(strcmp(msg.msgs.msg2.dynamic_str_arr[0], "1") == 0);
  161. TEST(strcmp(msg.msgs.msg2.dynamic_str_arr[1], "2") == 0);
  162. TEST(msg.msgs.msg2.dynamic_submsg == NULL);
  163. TEST(msg.last == 88);
  164. pb_release(OneofMessage_fields, &msg);
  165. TEST(get_alloc_count() == 0);
  166. pb_release(OneofMessage_fields, &msg);
  167. TEST(get_alloc_count() == 0);
  168. }
  169. return true;
  170. }
  171. static bool dummy_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg)
  172. {
  173. return false;
  174. }
  175. /* Garbage input */
  176. static bool test_Garbage()
  177. {
  178. const uint8_t buffer[] = "I'm only happy when it rains";
  179. const size_t msgsize = sizeof(buffer);
  180. {
  181. OneofMessage msg = OneofMessage_init_zero;
  182. pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
  183. TEST(!pb_decode(&stream, OneofMessage_fields, &msg));
  184. }
  185. {
  186. TestMessage msg = TestMessage_init_zero;
  187. pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
  188. TEST(!pb_decode(&stream, TestMessage_fields, &msg));
  189. }
  190. {
  191. RepeatedMessage msg = RepeatedMessage_init_zero;
  192. pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
  193. msg.subs.arg = NULL;
  194. msg.subs.funcs.decode = dummy_decode_cb;
  195. TEST(!pb_decode(&stream, RepeatedMessage_fields, &msg));
  196. }
  197. return true;
  198. }
  199. int main()
  200. {
  201. if (test_TestMessage() && test_OneofMessage() && test_Garbage())
  202. return 0;
  203. else
  204. return 1;
  205. }