main.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * lws-unit-tests-smtp-client
  3. *
  4. * Written in 2010-2019 by Andy Green <[email protected]>
  5. *
  6. * This file is made available under the Creative Commons CC0 1.0
  7. * Universal Public Domain Dedication.
  8. *
  9. * This performs unit tests for the SMTP client abstract protocol
  10. */
  11. #include <libwebsockets.h>
  12. #include <signal.h>
  13. static int interrupted, results[10], count_tests, count_passes;
  14. static int
  15. email_sent_or_failed(struct lws_smtp_email *email, void *buf, size_t len)
  16. {
  17. free(email);
  18. return 0;
  19. }
  20. /*
  21. * The test helper calls this on the instance it created to prepare it for
  22. * the test. In our case, we need to queue up a test email to send on the
  23. * smtp client abstract protocol.
  24. */
  25. static int
  26. smtp_test_instance_init(lws_abs_t *instance)
  27. {
  28. lws_smtp_email_t *email = (lws_smtp_email_t *)
  29. malloc(sizeof(*email) + 2048);
  30. if (!email)
  31. return 1;
  32. /* attach an email to it */
  33. memset(email, 0, sizeof(*email));
  34. email->data = NULL /* email specific user data */;
  35. email->email_from = "[email protected]";
  36. email->email_to = "[email protected]";
  37. email->payload = (void *)&email[1];
  38. lws_snprintf((char *)email->payload, 2048,
  39. "From: [email protected]\n"
  40. "To: %s\n"
  41. "Subject: Test email for lws smtp-client\n"
  42. "\n"
  43. "Hello this was an api test for lws smtp-client\n"
  44. "\r\n.\r\n", "[email protected]");
  45. email->done = email_sent_or_failed;
  46. if (lws_smtpc_add_email(instance, email)) {
  47. lwsl_err("%s: failed to add email\n", __func__);
  48. return 1;
  49. }
  50. return 0;
  51. }
  52. /*
  53. * from https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
  54. *
  55. * test vector sent to protocol
  56. * test vector received from protocol
  57. */
  58. static lws_unit_test_packet_t test_send1[] = {
  59. {
  60. "220 smtp.example.com ESMTP Postfix",
  61. smtp_test_instance_init, 34, LWS_AUT_EXPECT_RX
  62. }, {
  63. "HELO lws-test-client\x0a",
  64. NULL, 21, LWS_AUT_EXPECT_TX
  65. }, {
  66. "250 smtp.example.com, I am glad to meet you",
  67. NULL, 43, LWS_AUT_EXPECT_RX
  68. }, {
  69. "MAIL FROM: <[email protected]>\x0a",
  70. NULL, 33, LWS_AUT_EXPECT_TX
  71. }, {
  72. "250 Ok",
  73. NULL, 6, LWS_AUT_EXPECT_RX
  74. }, {
  75. "RCPT TO: <[email protected]>\x0a",
  76. NULL, 28, LWS_AUT_EXPECT_TX
  77. }, {
  78. "250 Ok",
  79. NULL, 6, LWS_AUT_EXPECT_RX
  80. }, {
  81. "DATA\x0a",
  82. NULL, 5, LWS_AUT_EXPECT_TX
  83. }, {
  84. "354 End data with <CR><LF>.<CR><LF>\x0a",
  85. NULL, 35, LWS_AUT_EXPECT_RX
  86. }, {
  87. "From: [email protected]\n"
  88. "To: [email protected]\n"
  89. "Subject: Test email for lws smtp-client\n"
  90. "\n"
  91. "Hello this was an api test for lws smtp-client\n"
  92. "\r\n.\r\n",
  93. NULL, 27 + 21 + 39 + 1 + 47 + 5, LWS_AUT_EXPECT_TX
  94. }, {
  95. "250 Ok: queued as 12345\x0a",
  96. NULL, 23, LWS_AUT_EXPECT_RX
  97. }, {
  98. "quit\x0a",
  99. NULL, 5, LWS_AUT_EXPECT_TX
  100. }, {
  101. "221 Bye\x0a",
  102. NULL, 7, LWS_AUT_EXPECT_RX |
  103. LWS_AUT_EXPECT_LOCAL_CLOSE |
  104. LWS_AUT_EXPECT_DO_REMOTE_CLOSE |
  105. LWS_AUT_EXPECT_TEST_END
  106. }, { /* sentinel */
  107. }
  108. };
  109. static lws_unit_test_packet_t test_send2[] = {
  110. {
  111. "220 smtp.example.com ESMTP Postfix",
  112. smtp_test_instance_init, 34, LWS_AUT_EXPECT_RX
  113. }, {
  114. "HELO lws-test-client\x0a",
  115. NULL, 21, LWS_AUT_EXPECT_TX
  116. }, {
  117. "250 smtp.example.com, I am glad to meet you",
  118. NULL, 43, LWS_AUT_EXPECT_RX
  119. }, {
  120. "MAIL FROM: <[email protected]>\x0a",
  121. NULL, 33, LWS_AUT_EXPECT_TX
  122. }, {
  123. "500 Service Unavailable",
  124. NULL, 23, LWS_AUT_EXPECT_RX |
  125. LWS_AUT_EXPECT_DO_REMOTE_CLOSE |
  126. LWS_AUT_EXPECT_TEST_END
  127. }, { /* sentinel */
  128. }
  129. };
  130. static lws_unit_test_t tests[] = {
  131. { "sending", test_send1, 3 },
  132. { "rejected", test_send2, 3 },
  133. { } /* sentinel */
  134. };
  135. static void
  136. sigint_handler(int sig)
  137. {
  138. interrupted = 1;
  139. }
  140. /*
  141. * set the HELO our SMTP client will use
  142. */
  143. static const lws_token_map_t smtp_ap_tokens[] = {
  144. {
  145. .u = { .value = "lws-test-client" },
  146. .name_index = LTMI_PSMTP_V_HELO,
  147. }, { /* sentinel */
  148. }
  149. };
  150. void
  151. tests_completion_cb(const void *cb_user)
  152. {
  153. interrupted = 1;
  154. }
  155. int main(int argc, const char **argv)
  156. {
  157. int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
  158. struct lws_context_creation_info info;
  159. lws_test_sequencer_args_t args;
  160. struct lws_context *context;
  161. lws_abs_t *abs = NULL;
  162. struct lws_vhost *vh;
  163. const char *p;
  164. /* the normal lws init */
  165. signal(SIGINT, sigint_handler);
  166. if ((p = lws_cmdline_option(argc, argv, "-d")))
  167. logs = atoi(p);
  168. lws_set_log_level(logs, NULL);
  169. lwsl_user("LWS API selftest: SMTP client unit tests\n");
  170. memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
  171. info.port = CONTEXT_PORT_NO_LISTEN;
  172. info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
  173. context = lws_create_context(&info);
  174. if (!context) {
  175. lwsl_err("lws init failed\n");
  176. return 1;
  177. }
  178. vh = lws_create_vhost(context, &info);
  179. if (!vh) {
  180. lwsl_err("Failed to create first vhost\n");
  181. goto bail1;
  182. }
  183. /* create the abs used to create connections */
  184. abs = lws_abstract_alloc(vh, NULL, "smtp.unit_test",
  185. &smtp_ap_tokens[0], NULL);
  186. if (!abs)
  187. goto bail1;
  188. /* configure the test sequencer */
  189. args.abs = abs;
  190. args.tests = tests;
  191. args.results = results;
  192. args.results_max = LWS_ARRAY_SIZE(results);
  193. args.count_tests = &count_tests;
  194. args.count_passes = &count_passes;
  195. args.cb = tests_completion_cb;
  196. args.cb_user = NULL;
  197. if (lws_abs_unit_test_sequencer(&args)) {
  198. lwsl_err("%s: failed to create test sequencer\n", __func__);
  199. goto bail1;
  200. }
  201. /* the usual lws event loop */
  202. while (n >= 0 && !interrupted)
  203. n = lws_service(context, 0);
  204. /* describe the overall test results */
  205. lwsl_user("%s: %d tests %d fail\n", __func__, count_tests,
  206. count_tests - count_passes);
  207. for (n = 0; n < count_tests; n++)
  208. lwsl_user(" test %d: %s\n", n,
  209. lws_unit_test_result_name(results[n]));
  210. bail1:
  211. lwsl_user("Completed: %s\n",
  212. !count_tests || count_passes != count_tests ? "FAIL" : "PASS");
  213. lws_context_destroy(context);
  214. lws_abstract_free(&abs);
  215. return !count_tests || count_passes != count_tests;
  216. }