test-sequencer.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. *
  24. * A helper for running multiple unit tests against abstract protocols.
  25. *
  26. * An lws_seq_t is used to base its actions in the event loop and manage
  27. * the sequencing of multiple tests. A new abstract connection is instantiated
  28. * for each test using te
  29. */
  30. #include <private-lib-core.h>
  31. struct lws_seq_test_sequencer {
  32. lws_abs_t original_abs;
  33. lws_test_sequencer_args_t args;
  34. struct lws_context *context;
  35. struct lws_vhost *vhost;
  36. struct lws_sequencer *unit_test_seq;
  37. /* holds the per-test token for the unit-test transport to consume */
  38. lws_token_map_t uttt[4];
  39. lws_abs_t *instance;
  40. int state;
  41. };
  42. /* sequencer messages specific to this sequencer */
  43. enum {
  44. SEQ_MSG_PASS = LWSSEQ_USER_BASE,
  45. SEQ_MSG_FAIL,
  46. SEQ_MSG_FAIL_TIMEOUT,
  47. };
  48. /*
  49. * We get called back when the unit test transport has decided if the test
  50. * passed or failed. We get the priv, and report to the sequencer message queue
  51. * what the result was.
  52. */
  53. static int
  54. unit_test_result_cb(const void *cb_user, int disposition)
  55. {
  56. const struct lws_seq_test_sequencer *s =
  57. (const struct lws_seq_test_sequencer *)cb_user;
  58. int r;
  59. lwsl_debug("%s: disp %d\n", __func__, disposition);
  60. switch (disposition) {
  61. case LPE_FAILED_UNEXPECTED_PASS:
  62. case LPE_FAILED_UNEXPECTED_CLOSE:
  63. case LPE_FAILED:
  64. r = SEQ_MSG_FAIL;
  65. break;
  66. case LPE_FAILED_UNEXPECTED_TIMEOUT:
  67. r = SEQ_MSG_FAIL_TIMEOUT;
  68. break;
  69. case LPE_SUCCEEDED:
  70. r = SEQ_MSG_PASS;
  71. break;
  72. default:
  73. assert(0);
  74. return -1;
  75. }
  76. lws_seq_queue_event(s->unit_test_seq, r, NULL, NULL);
  77. ((struct lws_seq_test_sequencer *)s)->instance = NULL;
  78. return 0;
  79. }
  80. /*
  81. * We receive the unit test result callback's messages via the message queue.
  82. *
  83. * We log the results and always move on to the next test until there are no
  84. * more tests.
  85. */
  86. static lws_seq_cb_return_t
  87. test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data,
  88. void *aux)
  89. {
  90. struct lws_seq_test_sequencer *s =
  91. (struct lws_seq_test_sequencer *)user;
  92. lws_unit_test_packet_t *exp = (lws_unit_test_packet_t *)
  93. s->args.tests[s->state].expect_array;
  94. lws_abs_t test_abs;
  95. switch ((int)event) {
  96. case LWSSEQ_CREATED: /* our sequencer just got started */
  97. lwsl_notice("%s: %s: created\n", __func__,
  98. lws_seq_name(seq));
  99. s->state = 0; /* first thing we'll do is the first url */
  100. goto step;
  101. case LWSSEQ_DESTROYED:
  102. /*
  103. * We are going down... if we have a child unit test sequencer
  104. * still around inform and destroy it
  105. */
  106. if (s->instance) {
  107. s->instance->at->close(s->instance);
  108. s->instance = NULL;
  109. }
  110. break;
  111. case SEQ_MSG_FAIL_TIMEOUT: /* current step timed out */
  112. if (exp->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT) {
  113. lwsl_user("%s: test %d got expected timeout\n",
  114. __func__, s->state);
  115. goto pass;
  116. }
  117. lwsl_user("%s: seq timed out at step %d\n", __func__, s->state);
  118. s->args.results[s->state] = LPE_FAILED_UNEXPECTED_TIMEOUT;
  119. goto done; /* always move on to the next test */
  120. case SEQ_MSG_FAIL:
  121. if (exp->flags & LWS_AUT_EXPECT_SHOULD_FAIL) {
  122. /*
  123. * in this case, we expected to fail like this, it's OK
  124. */
  125. lwsl_user("%s: test %d failed as expected\n",
  126. __func__, s->state);
  127. goto pass; /* always move on to the next test */
  128. }
  129. lwsl_user("%s: seq failed at step %d\n", __func__, s->state);
  130. s->args.results[s->state] = LPE_FAILED;
  131. goto done; /* always move on to the next test */
  132. case SEQ_MSG_PASS:
  133. if (exp->flags & (LWS_AUT_EXPECT_SHOULD_FAIL |
  134. LWS_AUT_EXPECT_SHOULD_TIMEOUT)) {
  135. /*
  136. * In these specific cases, done would be a failure,
  137. * we expected to timeout or fail
  138. */
  139. lwsl_user("%s: seq failed at step %d\n", __func__,
  140. s->state);
  141. s->args.results[s->state] = LPE_FAILED_UNEXPECTED_PASS;
  142. goto done; /* always move on to the next test */
  143. }
  144. lwsl_info("%s: seq done test %d\n", __func__, s->state);
  145. pass:
  146. (*s->args.count_passes)++;
  147. s->args.results[s->state] = LPE_SUCCEEDED;
  148. done:
  149. lws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE);
  150. s->state++;
  151. step:
  152. if (!s->args.tests[s->state].name) {
  153. /* the sequence has completed */
  154. lwsl_user("%s: sequence completed OK\n", __func__);
  155. if (s->args.cb)
  156. s->args.cb(s->args.cb_user);
  157. return LWSSEQ_RET_DESTROY;
  158. }
  159. lwsl_info("%s: starting test %d\n", __func__, s->state);
  160. if (s->state >= s->args.results_max) {
  161. lwsl_err("%s: results array is too small\n", __func__);
  162. return LWSSEQ_RET_DESTROY;
  163. }
  164. test_abs = s->original_abs;
  165. s->uttt[0].name_index = LTMI_PEER_V_EXPECT_TEST;
  166. s->uttt[0].u.value = (void *)&s->args.tests[s->state];
  167. s->uttt[1].name_index = LTMI_PEER_V_EXPECT_RESULT_CB;
  168. s->uttt[1].u.value = (void *)unit_test_result_cb;
  169. s->uttt[2].name_index = LTMI_PEER_V_EXPECT_RESULT_CB_ARG;
  170. s->uttt[2].u.value = (void *)s;
  171. /* give the unit test transport the test tokens */
  172. test_abs.at_tokens = s->uttt;
  173. s->instance = lws_abs_bind_and_create_instance(&test_abs);
  174. if (!s->instance) {
  175. lwsl_notice("%s: failed to create step %d unit test\n",
  176. __func__, s->state);
  177. return LWSSEQ_RET_DESTROY;
  178. }
  179. (*s->args.count_tests)++;
  180. break;
  181. default:
  182. break;
  183. }
  184. return LWSSEQ_RET_CONTINUE;
  185. }
  186. /*
  187. * Creates an lws_sequencer to manage the test sequence
  188. */
  189. int
  190. lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args)
  191. {
  192. struct lws_seq_test_sequencer *s;
  193. struct lws_sequencer *seq;
  194. lws_seq_info_t i;
  195. memset(&i, 0, sizeof(i));
  196. i.context = args->abs->vh->context;
  197. i.user_size = sizeof(struct lws_seq_test_sequencer);
  198. i.puser = (void **)&s;
  199. i.cb = test_sequencer_cb;
  200. i.name = "test-seq";
  201. /*
  202. * Create a sequencer in the event loop to manage the tests
  203. */
  204. seq = lws_seq_create(&i);
  205. if (!seq) {
  206. lwsl_err("%s: unable to create sequencer\n", __func__);
  207. return 1;
  208. }
  209. /*
  210. * Take a copy of the original lws_abs_t we were passed so we can use
  211. * it as the basis of the lws_abs_t we create the individual tests with
  212. */
  213. s->original_abs = *args->abs;
  214. s->args = *args;
  215. s->context = args->abs->vh->context;
  216. s->vhost = args->abs->vh;
  217. s->unit_test_seq = seq;
  218. *s->args.count_tests = 0;
  219. *s->args.count_passes = 0;
  220. return 0;
  221. }