1d4afb5ceSopenharmony_ci /* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci * 24d4afb5ceSopenharmony_ci * An abstract transport that is useful for unit testing an abstract protocol. 25d4afb5ceSopenharmony_ci * It doesn't actually connect to anything, but checks the protocol's response 26d4afb5ceSopenharmony_ci * to provided canned packets from an array of test vectors. 27d4afb5ceSopenharmony_ci */ 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ci#include "private-lib-core.h" 30d4afb5ceSopenharmony_ci#include "private-lib-abstract.h" 31d4afb5ceSopenharmony_ci 32d4afb5ceSopenharmony_ci/* this is the transport priv instantiated at abs->ati */ 33d4afb5ceSopenharmony_ci 34d4afb5ceSopenharmony_citypedef struct lws_abstxp_unit_test_priv { 35d4afb5ceSopenharmony_ci char note[128]; 36d4afb5ceSopenharmony_ci struct lws_abs *abs; 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci struct lws_sequencer *seq; 39d4afb5ceSopenharmony_ci lws_unit_test_t *current_test; 40d4afb5ceSopenharmony_ci lws_unit_test_packet_t *expect; 41d4afb5ceSopenharmony_ci lws_unit_test_packet_test_cb result_cb; 42d4afb5ceSopenharmony_ci const void *result_cb_arg; 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ci lws_unit_test_packet_disposition disposition; 45d4afb5ceSopenharmony_ci /* synthesized protocol timeout */ 46d4afb5ceSopenharmony_ci time_t timeout; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci uint8_t established:1; 49d4afb5ceSopenharmony_ci uint8_t connecting:1; 50d4afb5ceSopenharmony_ci} abs_unit_test_priv_t; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_citypedef struct seq_priv { 53d4afb5ceSopenharmony_ci lws_abs_t *ai; 54d4afb5ceSopenharmony_ci} seq_priv_t; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_cienum { 57d4afb5ceSopenharmony_ci UTSEQ_MSG_WRITEABLE = LWSSEQ_USER_BASE, 58d4afb5ceSopenharmony_ci UTSEQ_MSG_CLOSING, 59d4afb5ceSopenharmony_ci UTSEQ_MSG_TIMEOUT, 60d4afb5ceSopenharmony_ci UTSEQ_MSG_CONNECTING, 61d4afb5ceSopenharmony_ci UTSEQ_MSG_POST_TX_KICK, 62d4afb5ceSopenharmony_ci UTSEQ_MSG_DISPOSITION_KNOWN 63d4afb5ceSopenharmony_ci}; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci/* 66d4afb5ceSopenharmony_ci * A definitive result has appeared for the current test 67d4afb5ceSopenharmony_ci */ 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_cistatic lws_unit_test_packet_disposition 70d4afb5ceSopenharmony_cilws_unit_test_packet_dispose(abs_unit_test_priv_t *priv, 71d4afb5ceSopenharmony_ci lws_unit_test_packet_disposition disp, 72d4afb5ceSopenharmony_ci const char *note) 73d4afb5ceSopenharmony_ci{ 74d4afb5ceSopenharmony_ci assert(priv->disposition == LPE_CONTINUE); 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci lwsl_info("%s: %d\n", __func__, disp); 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci if (note) 79d4afb5ceSopenharmony_ci lws_strncpy(priv->note, note, sizeof(priv->note)); 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci priv->disposition = disp; 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci lws_seq_queue_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN, 84d4afb5ceSopenharmony_ci NULL, NULL); 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci return disp; 87d4afb5ceSopenharmony_ci} 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci/* 90d4afb5ceSopenharmony_ci * start on the next step of the test 91d4afb5ceSopenharmony_ci */ 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_cilws_unit_test_packet_disposition 94d4afb5ceSopenharmony_ciprocess_expect(abs_unit_test_priv_t *priv) 95d4afb5ceSopenharmony_ci{ 96d4afb5ceSopenharmony_ci assert(priv->disposition == LPE_CONTINUE); 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci while (priv->expect->flags & LWS_AUT_EXPECT_RX && 99d4afb5ceSopenharmony_ci priv->disposition == LPE_CONTINUE) { 100d4afb5ceSopenharmony_ci int f = priv->expect->flags & LWS_AUT_EXPECT_LOCAL_CLOSE, s; 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci if (priv->expect->pre) 103d4afb5ceSopenharmony_ci priv->expect->pre(priv->abs); 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci lwsl_info("%s: rx()\n", __func__); 106d4afb5ceSopenharmony_ci lwsl_hexdump_debug(priv->expect->buffer, priv->expect->len); 107d4afb5ceSopenharmony_ci s = priv->abs->ap->rx(priv->abs->api, priv->expect->buffer, 108d4afb5ceSopenharmony_ci priv->expect->len); 109d4afb5ceSopenharmony_ci 110d4afb5ceSopenharmony_ci if (!!f != !!s) { 111d4afb5ceSopenharmony_ci lwsl_notice("%s: expected rx return %d, got %d\n", 112d4afb5ceSopenharmony_ci __func__, !!f, s); 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci return lws_unit_test_packet_dispose(priv, LPE_FAILED, 115d4afb5ceSopenharmony_ci "rx unexpected return"); 116d4afb5ceSopenharmony_ci } 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci if (priv->expect->flags & LWS_AUT_EXPECT_TEST_END) { 119d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, LPE_SUCCEEDED, NULL); 120d4afb5ceSopenharmony_ci break; 121d4afb5ceSopenharmony_ci } 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci priv->expect++; 124d4afb5ceSopenharmony_ci } 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci return LPE_CONTINUE; 127d4afb5ceSopenharmony_ci} 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_cistatic lws_seq_cb_return_t 130d4afb5ceSopenharmony_ciunit_test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, 131d4afb5ceSopenharmony_ci void *data, void *aux) 132d4afb5ceSopenharmony_ci{ 133d4afb5ceSopenharmony_ci seq_priv_t *s = (seq_priv_t *)user; 134d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)s->ai->ati; 135d4afb5ceSopenharmony_ci time_t now; 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci switch ((int)event) { 138d4afb5ceSopenharmony_ci case LWSSEQ_CREATED: /* our sequencer just got started */ 139d4afb5ceSopenharmony_ci lwsl_notice("%s: %s: created\n", __func__, 140d4afb5ceSopenharmony_ci lws_seq_name(seq)); 141d4afb5ceSopenharmony_ci if (s->ai->at->client_conn(s->ai)) { 142d4afb5ceSopenharmony_ci lwsl_notice("%s: %s: abstract client conn failed\n", 143d4afb5ceSopenharmony_ci __func__, lws_seq_name(seq)); 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 146d4afb5ceSopenharmony_ci } 147d4afb5ceSopenharmony_ci break; 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci case LWSSEQ_DESTROYED: 150d4afb5ceSopenharmony_ci /* 151d4afb5ceSopenharmony_ci * This sequencer is about to be destroyed. If we have any 152d4afb5ceSopenharmony_ci * other assets in play, detach them from us. 153d4afb5ceSopenharmony_ci */ 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci if (priv->abs) 156d4afb5ceSopenharmony_ci lws_abs_destroy_instance(&priv->abs); 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci break; 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci case LWSSEQ_HEARTBEAT: 161d4afb5ceSopenharmony_ci 162d4afb5ceSopenharmony_ci /* synthesize a wsi-style timeout */ 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci if (!priv->timeout) 165d4afb5ceSopenharmony_ci goto ph; 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci time(&now); 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_ci if (now <= priv->timeout) 170d4afb5ceSopenharmony_ci goto ph; 171d4afb5ceSopenharmony_ci 172d4afb5ceSopenharmony_ci if (priv->expect->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT) { 173d4afb5ceSopenharmony_ci lwsl_user("%s: test got expected timeout\n", 174d4afb5ceSopenharmony_ci __func__); 175d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, 176d4afb5ceSopenharmony_ci LPE_FAILED_UNEXPECTED_TIMEOUT, NULL); 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 179d4afb5ceSopenharmony_ci } 180d4afb5ceSopenharmony_ci lwsl_user("%s: seq timed out\n", __func__); 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ciph: 183d4afb5ceSopenharmony_ci if (priv->abs->ap->heartbeat) 184d4afb5ceSopenharmony_ci priv->abs->ap->heartbeat(priv->abs->api); 185d4afb5ceSopenharmony_ci break; 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci case UTSEQ_MSG_DISPOSITION_KNOWN: 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci lwsl_info("%s: %s: DISPOSITION_KNOWN %s: %s\n", __func__, 190d4afb5ceSopenharmony_ci priv->abs->ap->name, 191d4afb5ceSopenharmony_ci priv->current_test->name, 192d4afb5ceSopenharmony_ci priv->disposition == LPE_SUCCEEDED ? "OK" : "FAIL"); 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci /* 195d4afb5ceSopenharmony_ci * if the test has a callback, call it back to let it 196d4afb5ceSopenharmony_ci * know the result 197d4afb5ceSopenharmony_ci */ 198d4afb5ceSopenharmony_ci if (priv->result_cb) 199d4afb5ceSopenharmony_ci priv->result_cb(priv->result_cb_arg, priv->disposition); 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci case UTSEQ_MSG_CONNECTING: 204d4afb5ceSopenharmony_ci lwsl_debug("UTSEQ_MSG_CONNECTING\n"); 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci if (priv->abs->ap->accept) 207d4afb5ceSopenharmony_ci priv->abs->ap->accept(priv->abs->api); 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci priv->established = 1; 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci /* fallthru */ 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_ci case UTSEQ_MSG_POST_TX_KICK: 214d4afb5ceSopenharmony_ci if (priv->disposition) 215d4afb5ceSopenharmony_ci break; 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci if (process_expect(priv) != LPE_CONTINUE) { 218d4afb5ceSopenharmony_ci lwsl_notice("%s: UTSEQ_MSG_POST_TX_KICK failed\n", 219d4afb5ceSopenharmony_ci __func__); 220d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 221d4afb5ceSopenharmony_ci } 222d4afb5ceSopenharmony_ci break; 223d4afb5ceSopenharmony_ci 224d4afb5ceSopenharmony_ci case UTSEQ_MSG_WRITEABLE: 225d4afb5ceSopenharmony_ci /* 226d4afb5ceSopenharmony_ci * inform the protocol our transport is writeable now 227d4afb5ceSopenharmony_ci */ 228d4afb5ceSopenharmony_ci priv->abs->ap->writeable(priv->abs->api, 1024); 229d4afb5ceSopenharmony_ci break; 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci case UTSEQ_MSG_CLOSING: 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci if (!(priv->expect->flags & LWS_AUT_EXPECT_LOCAL_CLOSE)) { 234d4afb5ceSopenharmony_ci lwsl_user("%s: got unexpected close\n", __func__); 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, 237d4afb5ceSopenharmony_ci LPE_FAILED_UNEXPECTED_CLOSE, NULL); 238d4afb5ceSopenharmony_ci goto done; 239d4afb5ceSopenharmony_ci } 240d4afb5ceSopenharmony_ci 241d4afb5ceSopenharmony_ci /* tell the abstract protocol we are closing on them */ 242d4afb5ceSopenharmony_ci 243d4afb5ceSopenharmony_ci if (priv->abs && priv->abs->ap->closed) 244d4afb5ceSopenharmony_ci priv->abs->ap->closed(priv->abs->api); 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci goto done; 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci case UTSEQ_MSG_TIMEOUT: /* current step timed out */ 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci s->ai->at->close(s->ai->ati); 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_ci if (!(priv->expect->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT)) { 253d4afb5ceSopenharmony_ci lwsl_user("%s: got unexpected timeout\n", __func__); 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, 256d4afb5ceSopenharmony_ci LPE_FAILED_UNEXPECTED_TIMEOUT, NULL); 257d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 258d4afb5ceSopenharmony_ci } 259d4afb5ceSopenharmony_ci goto done; 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_cidone: 262d4afb5ceSopenharmony_ci lws_seq_timeout_us(lws_seq_from_user(s), 263d4afb5ceSopenharmony_ci LWSSEQTO_NONE); 264d4afb5ceSopenharmony_ci priv->expect++; 265d4afb5ceSopenharmony_ci if (!priv->expect->buffer) { 266d4afb5ceSopenharmony_ci /* the sequence has completed */ 267d4afb5ceSopenharmony_ci lwsl_user("%s: sequence completed OK\n", __func__); 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci return LWSSEQ_RET_DESTROY; 270d4afb5ceSopenharmony_ci } 271d4afb5ceSopenharmony_ci break; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci default: 274d4afb5ceSopenharmony_ci break; 275d4afb5ceSopenharmony_ci } 276d4afb5ceSopenharmony_ci 277d4afb5ceSopenharmony_ci return LWSSEQ_RET_CONTINUE; 278d4afb5ceSopenharmony_ci} 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_cistatic int 281d4afb5ceSopenharmony_cilws_atcut_close(lws_abs_transport_inst_t *ati) 282d4afb5ceSopenharmony_ci{ 283d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci lwsl_notice("%s\n", __func__); 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci lws_seq_queue_event(priv->seq, UTSEQ_MSG_CLOSING, NULL, NULL); 288d4afb5ceSopenharmony_ci 289d4afb5ceSopenharmony_ci return 0; 290d4afb5ceSopenharmony_ci} 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_cistatic int 293d4afb5ceSopenharmony_cilws_atcut_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len) 294d4afb5ceSopenharmony_ci{ 295d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_ci assert(priv->disposition == LPE_CONTINUE); 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci lwsl_info("%s: received tx\n", __func__); 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci if (priv->expect->pre) 302d4afb5ceSopenharmony_ci priv->expect->pre(priv->abs); 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci if (!(priv->expect->flags & LWS_AUT_EXPECT_TX)) { 305d4afb5ceSopenharmony_ci lwsl_notice("%s: unexpected tx\n", __func__); 306d4afb5ceSopenharmony_ci lwsl_hexdump_notice(buf, len); 307d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, LPE_FAILED, "unexpected tx"); 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci return 1; 310d4afb5ceSopenharmony_ci } 311d4afb5ceSopenharmony_ci 312d4afb5ceSopenharmony_ci if (len != priv->expect->len) { 313d4afb5ceSopenharmony_ci lwsl_notice("%s: unexpected tx len %zu, expected %zu\n", 314d4afb5ceSopenharmony_ci __func__, len, priv->expect->len); 315d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, LPE_FAILED, 316d4afb5ceSopenharmony_ci "tx len mismatch"); 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci return 1; 319d4afb5ceSopenharmony_ci } 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci if (memcmp(buf, priv->expect->buffer, len)) { 322d4afb5ceSopenharmony_ci lwsl_notice("%s: tx mismatch (exp / actual)\n", __func__); 323d4afb5ceSopenharmony_ci lwsl_hexdump_debug(priv->expect->buffer, len); 324d4afb5ceSopenharmony_ci lwsl_hexdump_debug(buf, len); 325d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, LPE_FAILED, 326d4afb5ceSopenharmony_ci "tx data mismatch"); 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci return 1; 329d4afb5ceSopenharmony_ci } 330d4afb5ceSopenharmony_ci 331d4afb5ceSopenharmony_ci if (priv->expect->flags & LWS_AUT_EXPECT_TEST_END) { 332d4afb5ceSopenharmony_ci lws_unit_test_packet_dispose(priv, LPE_SUCCEEDED, NULL); 333d4afb5ceSopenharmony_ci 334d4afb5ceSopenharmony_ci return 1; 335d4afb5ceSopenharmony_ci } 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci priv->expect++; 338d4afb5ceSopenharmony_ci 339d4afb5ceSopenharmony_ci lws_seq_queue_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL); 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci return 0; 342d4afb5ceSopenharmony_ci} 343d4afb5ceSopenharmony_ci 344d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT) 345d4afb5ceSopenharmony_cistatic int 346d4afb5ceSopenharmony_cilws_atcut_client_conn(const lws_abs_t *abs) 347d4afb5ceSopenharmony_ci{ 348d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)abs->ati; 349d4afb5ceSopenharmony_ci const lws_token_map_t *tm; 350d4afb5ceSopenharmony_ci 351d4afb5ceSopenharmony_ci if (priv->established) { 352d4afb5ceSopenharmony_ci lwsl_err("%s: already established\n", __func__); 353d4afb5ceSopenharmony_ci return 1; 354d4afb5ceSopenharmony_ci } 355d4afb5ceSopenharmony_ci 356d4afb5ceSopenharmony_ci /* set up the test start pieces... the array of test expects... */ 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_ci tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_EXPECT_TEST); 359d4afb5ceSopenharmony_ci if (!tm) { 360d4afb5ceSopenharmony_ci lwsl_notice("%s: unit_test needs LTMI_PEER_V_EXPECT_TEST\n", 361d4afb5ceSopenharmony_ci __func__); 362d4afb5ceSopenharmony_ci 363d4afb5ceSopenharmony_ci return 1; 364d4afb5ceSopenharmony_ci } 365d4afb5ceSopenharmony_ci priv->current_test = (lws_unit_test_t *)tm->u.value; 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci /* ... and the callback to deliver the result to */ 368d4afb5ceSopenharmony_ci tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_EXPECT_RESULT_CB); 369d4afb5ceSopenharmony_ci if (tm) 370d4afb5ceSopenharmony_ci priv->result_cb = (lws_unit_test_packet_test_cb)tm->u.value; 371d4afb5ceSopenharmony_ci else 372d4afb5ceSopenharmony_ci priv->result_cb = NULL; 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci /* ... and the arg to deliver it with */ 375d4afb5ceSopenharmony_ci tm = lws_abs_get_token(abs->at_tokens, 376d4afb5ceSopenharmony_ci LTMI_PEER_V_EXPECT_RESULT_CB_ARG); 377d4afb5ceSopenharmony_ci if (tm) 378d4afb5ceSopenharmony_ci priv->result_cb_arg = tm->u.value; 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci priv->expect = priv->current_test->expect_array; 381d4afb5ceSopenharmony_ci priv->disposition = LPE_CONTINUE; 382d4afb5ceSopenharmony_ci priv->note[0] = '\0'; 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci lws_seq_timeout_us(priv->seq, priv->current_test->max_secs * 385d4afb5ceSopenharmony_ci LWS_US_PER_SEC); 386d4afb5ceSopenharmony_ci 387d4afb5ceSopenharmony_ci lwsl_notice("%s: %s: test '%s': start\n", __func__, abs->ap->name, 388d4afb5ceSopenharmony_ci priv->current_test->name); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci lws_seq_queue_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL, NULL); 391d4afb5ceSopenharmony_ci 392d4afb5ceSopenharmony_ci return 0; 393d4afb5ceSopenharmony_ci} 394d4afb5ceSopenharmony_ci#endif 395d4afb5ceSopenharmony_ci 396d4afb5ceSopenharmony_cistatic int 397d4afb5ceSopenharmony_cilws_atcut_ask_for_writeable(lws_abs_transport_inst_t *ati) 398d4afb5ceSopenharmony_ci{ 399d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; 400d4afb5ceSopenharmony_ci 401d4afb5ceSopenharmony_ci if (!priv->established) 402d4afb5ceSopenharmony_ci return 1; 403d4afb5ceSopenharmony_ci 404d4afb5ceSopenharmony_ci /* 405d4afb5ceSopenharmony_ci * Queue a writeable event... this won't be handled by teh sequencer 406d4afb5ceSopenharmony_ci * until we have returned to the event loop, just like a real 407d4afb5ceSopenharmony_ci * callback_on_writable() 408d4afb5ceSopenharmony_ci */ 409d4afb5ceSopenharmony_ci lws_seq_queue_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL, NULL); 410d4afb5ceSopenharmony_ci 411d4afb5ceSopenharmony_ci return 0; 412d4afb5ceSopenharmony_ci} 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci/* 415d4afb5ceSopenharmony_ci * An abstract protocol + transport has been instantiated 416d4afb5ceSopenharmony_ci */ 417d4afb5ceSopenharmony_ci 418d4afb5ceSopenharmony_cistatic int 419d4afb5ceSopenharmony_cilws_atcut_create(lws_abs_t *ai) 420d4afb5ceSopenharmony_ci{ 421d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv; 422d4afb5ceSopenharmony_ci struct lws_sequencer *seq; 423d4afb5ceSopenharmony_ci lws_seq_info_t i; 424d4afb5ceSopenharmony_ci seq_priv_t *s; 425d4afb5ceSopenharmony_ci 426d4afb5ceSopenharmony_ci memset(&i, 0, sizeof(i)); 427d4afb5ceSopenharmony_ci i.context = ai->vh->context; 428d4afb5ceSopenharmony_ci i.user_size = sizeof(*s); 429d4afb5ceSopenharmony_ci i.puser = (void **)&s; 430d4afb5ceSopenharmony_ci i.cb = unit_test_sequencer_cb; 431d4afb5ceSopenharmony_ci i.name = "unit-test-seq"; 432d4afb5ceSopenharmony_ci 433d4afb5ceSopenharmony_ci /* 434d4afb5ceSopenharmony_ci * Create the sequencer for the steps in a single unit test 435d4afb5ceSopenharmony_ci */ 436d4afb5ceSopenharmony_ci 437d4afb5ceSopenharmony_ci seq = lws_seq_create(&i); 438d4afb5ceSopenharmony_ci if (!seq) { 439d4afb5ceSopenharmony_ci lwsl_err("%s: unable to create sequencer\n", __func__); 440d4afb5ceSopenharmony_ci 441d4afb5ceSopenharmony_ci return 1; 442d4afb5ceSopenharmony_ci } 443d4afb5ceSopenharmony_ci 444d4afb5ceSopenharmony_ci priv = ai->ati; 445d4afb5ceSopenharmony_ci memset(s, 0, sizeof(*s)); 446d4afb5ceSopenharmony_ci memset(priv, 0, sizeof(*priv)); 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_ci /* the sequencer priv just points to the lws_abs_t */ 449d4afb5ceSopenharmony_ci s->ai = ai; 450d4afb5ceSopenharmony_ci priv->abs = ai; 451d4afb5ceSopenharmony_ci priv->seq = seq; 452d4afb5ceSopenharmony_ci 453d4afb5ceSopenharmony_ci return 0; 454d4afb5ceSopenharmony_ci} 455d4afb5ceSopenharmony_ci 456d4afb5ceSopenharmony_cistatic void 457d4afb5ceSopenharmony_cilws_atcut_destroy(lws_abs_transport_inst_t **pati) 458d4afb5ceSopenharmony_ci{ 459d4afb5ceSopenharmony_ci /* 460d4afb5ceSopenharmony_ci * We don't free anything because the abstract layer combined our 461d4afb5ceSopenharmony_ci * allocation with that of the instance, and it will free the whole 462d4afb5ceSopenharmony_ci * thing after this. 463d4afb5ceSopenharmony_ci */ 464d4afb5ceSopenharmony_ci *pati = NULL; 465d4afb5ceSopenharmony_ci} 466d4afb5ceSopenharmony_ci 467d4afb5ceSopenharmony_cistatic int 468d4afb5ceSopenharmony_cilws_atcut_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs) 469d4afb5ceSopenharmony_ci{ 470d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; 471d4afb5ceSopenharmony_ci time_t now; 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci time(&now); 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci if (secs) 476d4afb5ceSopenharmony_ci priv->timeout = now + secs; 477d4afb5ceSopenharmony_ci else 478d4afb5ceSopenharmony_ci priv->timeout = 0; 479d4afb5ceSopenharmony_ci 480d4afb5ceSopenharmony_ci return 0; 481d4afb5ceSopenharmony_ci} 482d4afb5ceSopenharmony_ci 483d4afb5ceSopenharmony_cistatic int 484d4afb5ceSopenharmony_cilws_atcut_state(lws_abs_transport_inst_t *ati) 485d4afb5ceSopenharmony_ci{ 486d4afb5ceSopenharmony_ci abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; 487d4afb5ceSopenharmony_ci 488d4afb5ceSopenharmony_ci if (!priv || (!priv->established && !priv->connecting)) 489d4afb5ceSopenharmony_ci return 0; 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci return 1; 492d4afb5ceSopenharmony_ci} 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_cistatic const char *dnames[] = { 495d4afb5ceSopenharmony_ci "INCOMPLETE", 496d4afb5ceSopenharmony_ci "PASS", 497d4afb5ceSopenharmony_ci "FAIL", 498d4afb5ceSopenharmony_ci "FAIL(TIMEOUT)", 499d4afb5ceSopenharmony_ci "FAIL(UNEXPECTED PASS)", 500d4afb5ceSopenharmony_ci "FAIL(UNEXPECTED CLOSE)", 501d4afb5ceSopenharmony_ci "SKIPPED" 502d4afb5ceSopenharmony_ci "?", 503d4afb5ceSopenharmony_ci "?" 504d4afb5ceSopenharmony_ci}; 505d4afb5ceSopenharmony_ci 506d4afb5ceSopenharmony_ci 507d4afb5ceSopenharmony_ciconst char * 508d4afb5ceSopenharmony_cilws_unit_test_result_name(int in) 509d4afb5ceSopenharmony_ci{ 510d4afb5ceSopenharmony_ci if (in < 0 || in > (int)LWS_ARRAY_SIZE(dnames)) 511d4afb5ceSopenharmony_ci return "unknown"; 512d4afb5ceSopenharmony_ci 513d4afb5ceSopenharmony_ci return dnames[in]; 514d4afb5ceSopenharmony_ci} 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_cistatic int 517d4afb5ceSopenharmony_cilws_atcut_compare(lws_abs_t *abs1, lws_abs_t *abs2) 518d4afb5ceSopenharmony_ci{ 519d4afb5ceSopenharmony_ci return 0; 520d4afb5ceSopenharmony_ci} 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ciconst lws_abs_transport_t lws_abs_transport_cli_unit_test = { 523d4afb5ceSopenharmony_ci .name = "unit_test", 524d4afb5ceSopenharmony_ci .alloc = sizeof(abs_unit_test_priv_t), 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ci .create = lws_atcut_create, 527d4afb5ceSopenharmony_ci .destroy = lws_atcut_destroy, 528d4afb5ceSopenharmony_ci .compare = lws_atcut_compare, 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ci .tx = lws_atcut_tx, 531d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_CLIENT) 532d4afb5ceSopenharmony_ci .client_conn = NULL, 533d4afb5ceSopenharmony_ci#else 534d4afb5ceSopenharmony_ci .client_conn = lws_atcut_client_conn, 535d4afb5ceSopenharmony_ci#endif 536d4afb5ceSopenharmony_ci .close = lws_atcut_close, 537d4afb5ceSopenharmony_ci .ask_for_writeable = lws_atcut_ask_for_writeable, 538d4afb5ceSopenharmony_ci .set_timeout = lws_atcut_set_timeout, 539d4afb5ceSopenharmony_ci .state = lws_atcut_state, 540d4afb5ceSopenharmony_ci}; 541