1 /** @file
2
3 Implements unit test for SDK APIs
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 // Turn off -Wdeprecated so that we can still test our own deprecated APIs.
25 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
26 #pragma GCC diagnostic ignored "-Wdeprecated"
27 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
28 #endif
29
30 #include <sys/types.h>
31 #include <arpa/inet.h> /* For htonl */
32
33 #include <cerrno>
34 #include <pthread.h>
35 #include <unistd.h>
36 #include <cstdio>
37 #include <cstring>
38
39 #include "tscore/ink_config.h"
40 #include "tscore/ink_sprintf.h"
41 #include "tscore/ink_file.h"
42 #include "tscore/Regression.h"
43 #include "tscore/Filenames.h"
44 #include "ts/ts.h"
45 #include "ts/experimental.h"
46 #include "records/I_RecCore.h"
47
48 #include "P_Net.h"
49 #include "records/I_RecHttp.h"
50
51 #include "http/HttpSM.h"
52 #include "tscore/TestBox.h"
53
54 // This used to be in InkAPITestTool.cc, which we'd just #include here... But that seemed silly.
55 #define SDBG_TAG "SockServer"
56 #define CDBG_TAG "SockClient"
57
58 #define IP(a, b, c, d) htonl((a) << 24 | (b) << 16 | (c) << 8 | (d))
59
60 #define SET_TEST_HANDLER(_d, _s) \
61 { \
62 _d = _s; \
63 }
64
65 #define MAGIC_ALIVE 0xfeedbaba
66 #define MAGIC_DEAD 0xdeadbeef
67
68 #define SYNSERVER_LISTEN_PORT 3300
69 #define SYNSERVER_DUMMY_PORT -1
70
71 #define PROXY_CONFIG_NAME_HTTP_PORT "proxy.config.http.server_port"
72 #define PROXY_HTTP_DEFAULT_PORT 8080
73
74 #define REQUEST_MAX_SIZE 4095
75 #define RESPONSE_MAX_SIZE 4095
76
77 #define HTTP_REQUEST_END "\r\n\r\n"
78
79 // each request/response includes an identifier as a Mime field
80 #define X_REQUEST_ID "X-Request-ID"
81 #define X_RESPONSE_ID "X-Response-ID"
82
83 #define ERROR_BODY "TESTING ERROR PAGE"
84 #define TRANSFORM_APPEND_STRING "This is a transformed response"
85
86 //////////////////////////////////////////////////////////////////////////////
87 // STRUCTURES
88 //////////////////////////////////////////////////////////////////////////////
89
90 using TxnHandler = int (*)(TSCont, TSEvent, void *);
91
92 /* Server transaction structure */
93 struct ServerTxn {
94 TSVConn vconn;
95
96 TSVIO read_vio;
97 TSIOBuffer req_buffer;
98 TSIOBufferReader req_reader;
99
100 TSVIO write_vio;
101 TSIOBuffer resp_buffer;
102 TSIOBufferReader resp_reader;
103
104 char request[REQUEST_MAX_SIZE + 1];
105 int request_len;
106
107 TxnHandler current_handler;
108 unsigned int magic;
109 };
110
111 /* Server structure */
112 struct SocketServer {
113 int accept_port;
114 TSAction accept_action;
115 TSCont accept_cont;
116 unsigned int magic;
117 };
118
119 enum RequestStatus {
120 REQUEST_SUCCESS,
121 REQUEST_INPROGRESS,
122 REQUEST_FAILURE,
123 };
124
125 /* Client structure */
126 struct ClientTxn {
127 TSVConn vconn;
128
129 TSVIO read_vio;
130 TSIOBuffer req_buffer;
131 TSIOBufferReader req_reader;
132
133 TSVIO write_vio;
134 TSIOBuffer resp_buffer;
135 TSIOBufferReader resp_reader;
136
137 char *request;
138 char response[RESPONSE_MAX_SIZE + 1];
139 int response_len;
140
141 RequestStatus status;
142
143 int connect_port;
144 int local_port;
145 uint64_t connect_ip;
146 TSAction connect_action;
147
148 TxnHandler current_handler;
149
150 unsigned int magic;
151 };
152
153 //////////////////////////////////////////////////////////////////////////////
154 // DECLARATIONS
155 //////////////////////////////////////////////////////////////////////////////
156
157 /* utility */
158 static char *get_body_ptr(const char *request);
159 static char *generate_request(int test_case);
160 static char *generate_response(const char *request);
161 static int get_request_id(TSHttpTxn txnp);
162
163 /* client side */
164 static ClientTxn *synclient_txn_create();
165 static int synclient_txn_delete(ClientTxn *txn);
166 static void synclient_txn_close(ClientTxn *txn);
167 static int synclient_txn_send_request(ClientTxn *txn, char *request);
168 static int synclient_txn_send_request_to_vc(ClientTxn *txn, char *request, TSVConn vc);
169 static int synclient_txn_read_response(TSCont contp);
170 static int synclient_txn_read_response_handler(TSCont contp, TSEvent event, void *data);
171 static int synclient_txn_write_request(TSCont contp);
172 static int synclient_txn_write_request_handler(TSCont contp, TSEvent event, void *data);
173 static int synclient_txn_connect_handler(TSCont contp, TSEvent event, void *data);
174 static int synclient_txn_main_handler(TSCont contp, TSEvent event, void *data);
175
176 /* Server side */
177 SocketServer *synserver_create(int port);
178 static int synserver_start(SocketServer *s);
179 static int synserver_stop(SocketServer *s);
180 static int synserver_delete(SocketServer *s);
181 static int synserver_vc_accept(TSCont contp, TSEvent event, void *data);
182 static int synserver_vc_refuse(TSCont contp, TSEvent event, void *data);
183 static int synserver_txn_close(TSCont contp);
184 static int synserver_txn_write_response(TSCont contp);
185 static int synserver_txn_write_response_handler(TSCont contp, TSEvent event, void *data);
186 static int synserver_txn_read_request(TSCont contp);
187 static int synserver_txn_read_request_handler(TSCont contp, TSEvent event, void *data);
188 static int synserver_txn_main_handler(TSCont contp, TSEvent event, void *data);
189
190 //////////////////////////////////////////////////////////////////////////////
191 // REQUESTS/RESPONSES GENERATION
192 //////////////////////////////////////////////////////////////////////////////
193
194 static char *
get_body_ptr(const char * request)195 get_body_ptr(const char *request)
196 {
197 char *ptr = const_cast<char *>(strstr(request, (const char *)"\r\n\r\n"));
198 return (ptr != nullptr) ? (ptr + 4) : nullptr;
199 }
200
201 /* Caller must free returned request */
202 static char *
generate_request(int test_case)203 generate_request(int test_case)
204 {
205 // We define request formats.
206 // Each format has an X-Request-ID field that contains the id of the testcase
207 #define HTTP_REQUEST_DEFAULT_FORMAT \
208 "GET http://127.0.0.1:%d/default.html HTTP/1.0\r\n" \
209 "X-Request-ID: %d\r\n" \
210 "\r\n"
211
212 #define HTTP_REQUEST_FORMAT1 \
213 "GET http://127.0.0.1:%d/format1.html HTTP/1.0\r\n" \
214 "X-Request-ID: %d\r\n" \
215 "\r\n"
216
217 #define HTTP_REQUEST_FORMAT2 \
218 "GET http://127.0.0.1:%d/format2.html HTTP/1.0\r\n" \
219 "X-Request-ID: %d\r\n" \
220 "Content-Type: text/html\r\n" \
221 "\r\n"
222 #define HTTP_REQUEST_FORMAT3 \
223 "GET http://127.0.0.1:%d/format3.html HTTP/1.0\r\n" \
224 "X-Request-ID: %d\r\n" \
225 "Response: Error\r\n" \
226 "\r\n"
227 #define HTTP_REQUEST_FORMAT4 \
228 "GET http://127.0.0.1:%d/format4.html HTTP/1.0\r\n" \
229 "X-Request-ID: %d\r\n" \
230 "Request:%d\r\n" \
231 "\r\n"
232 #define HTTP_REQUEST_FORMAT5 \
233 "GET http://127.0.0.1:%d/format5.html HTTP/1.0\r\n" \
234 "X-Request-ID: %d\r\n" \
235 "Request:%d\r\n" \
236 "\r\n"
237 #define HTTP_REQUEST_FORMAT6 \
238 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
239 "X-Request-ID: %d\r\n" \
240 "Accept-Language: English\r\n" \
241 "\r\n"
242 #define HTTP_REQUEST_FORMAT7 \
243 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
244 "X-Request-ID: %d\r\n" \
245 "Accept-Language: French\r\n" \
246 "\r\n"
247 #define HTTP_REQUEST_FORMAT8 \
248 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
249 "X-Request-ID: %d\r\n" \
250 "Accept-Language: English,French\r\n" \
251 "\r\n"
252 #define HTTP_REQUEST_FORMAT9 \
253 "GET http://trafficserver.apache.org/format9.html HTTP/1.0\r\n" \
254 "X-Request-ID: %d\r\n" \
255 "\r\n"
256 #define HTTP_REQUEST_FORMAT10 \
257 "GET http://trafficserver.apache.org/format10.html HTTP/1.0\r\n" \
258 "X-Request-ID: %d\r\n" \
259 "\r\n"
260 #define HTTP_REQUEST_FORMAT11 \
261 "GET http://trafficserver.apache.org/format11.html HTTP/1.0\r\n" \
262 "X-Request-ID: %d\r\n" \
263 "\r\n"
264 char *request = static_cast<char *>(TSmalloc(REQUEST_MAX_SIZE + 1));
265
266 switch (test_case) {
267 case 1:
268 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT1, SYNSERVER_LISTEN_PORT, test_case);
269 break;
270 case 2:
271 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT2, SYNSERVER_LISTEN_PORT, test_case);
272 break;
273 case 3:
274 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT3, SYNSERVER_LISTEN_PORT, test_case);
275 break;
276 case 4:
277 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT4, SYNSERVER_LISTEN_PORT, test_case, 1);
278 break;
279 case 5:
280 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT5, SYNSERVER_LISTEN_PORT, test_case, 2);
281 break;
282 case 6:
283 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT6, SYNSERVER_LISTEN_PORT, test_case);
284 break;
285 case 7:
286 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT7, SYNSERVER_LISTEN_PORT, test_case - 1);
287 break;
288 case 8:
289 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT8, SYNSERVER_LISTEN_PORT, test_case - 2);
290 break;
291 case 9:
292 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT9, test_case);
293 break;
294 case 10:
295 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT10, test_case);
296 break;
297 case 11:
298 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT11, test_case);
299 break;
300 default:
301 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_DEFAULT_FORMAT, SYNSERVER_LISTEN_PORT, test_case);
302 break;
303 }
304
305 return request;
306 }
307
308 /* Caller must free returned response */
309 static char *
generate_response(const char * request)310 generate_response(const char *request)
311 {
312 // define format for response
313 // Each response contains a field X-Response-ID that contains the id of the testcase
314 #define HTTP_REQUEST_TESTCASE_FORMAT \
315 "GET %1024s HTTP/1.%d\r\n" \
316 "X-Request-ID: %d\r\n"
317
318 #define HTTP_RESPONSE_DEFAULT_FORMAT \
319 "HTTP/1.0 200 OK\r\n" \
320 "X-Response-ID: %d\r\n" \
321 "Cache-Control: max-age=86400\r\n" \
322 "Content-Type: text/html\r\n" \
323 "\r\n" \
324 "Default body"
325
326 #define HTTP_RESPONSE_FORMAT1 \
327 "HTTP/1.0 200 OK\r\n" \
328 "X-Response-ID: %d\r\n" \
329 "Content-Type: text/html\r\n" \
330 "Cache-Control: no-cache\r\n" \
331 "\r\n" \
332 "Body for response 1"
333
334 #define HTTP_RESPONSE_FORMAT2 \
335 "HTTP/1.0 200 OK\r\n" \
336 "X-Response-ID: %d\r\n" \
337 "Cache-Control: max-age=86400\r\n" \
338 "Content-Type: text/html\r\n" \
339 "\r\n" \
340 "Body for response 2"
341 #define HTTP_RESPONSE_FORMAT4 \
342 "HTTP/1.0 200 OK\r\n" \
343 "X-Response-ID: %d\r\n" \
344 "Cache-Control: max-age=86400\r\n" \
345 "Content-Type: text/html\r\n" \
346 "\r\n" \
347 "Body for response 4"
348 #define HTTP_RESPONSE_FORMAT5 \
349 "HTTP/1.0 200 OK\r\n" \
350 "X-Response-ID: %d\r\n" \
351 "Content-Type: text/html\r\n" \
352 "\r\n" \
353 "Body for response 5"
354 #define HTTP_RESPONSE_FORMAT6 \
355 "HTTP/1.0 200 OK\r\n" \
356 "X-Response-ID: %d\r\n" \
357 "Cache-Control: max-age=86400\r\n" \
358 "Content-Language: English\r\n" \
359 "\r\n" \
360 "Body for response 6"
361 #define HTTP_RESPONSE_FORMAT7 \
362 "HTTP/1.0 200 OK\r\n" \
363 "X-Response-ID: %d\r\n" \
364 "Cache-Control: max-age=86400\r\n" \
365 "Content-Language: French\r\n" \
366 "\r\n" \
367 "Body for response 7"
368
369 #define HTTP_RESPONSE_FORMAT8 \
370 "HTTP/1.0 200 OK\r\n" \
371 "X-Response-ID: %d\r\n" \
372 "Cache-Control: max-age=86400\r\n" \
373 "Content-Language: French, English\r\n" \
374 "\r\n" \
375 "Body for response 8"
376
377 #define HTTP_RESPONSE_FORMAT9 \
378 "HTTP/1.0 200 OK\r\n" \
379 "Cache-Control: max-age=86400\r\n" \
380 "X-Response-ID: %d\r\n" \
381 "\r\n" \
382 "Body for response 9"
383
384 #define HTTP_RESPONSE_FORMAT10 \
385 "HTTP/1.0 200 OK\r\n" \
386 "Cache-Control: max-age=86400\r\n" \
387 "X-Response-ID: %d\r\n" \
388 "\r\n" \
389 "Body for response 10"
390
391 #define HTTP_RESPONSE_FORMAT11 \
392 "HTTP/1.0 200 OK\r\n" \
393 "Cache-Control: private,no-store\r\n" \
394 "X-Response-ID: %d\r\n" \
395 "\r\n" \
396 "Body for response 11"
397
398 int test_case, match, http_version;
399
400 char *response = static_cast<char *>(TSmalloc(RESPONSE_MAX_SIZE + 1));
401 char url[1025];
402
403 // coverity[secure_coding]
404 match = sscanf(request, HTTP_REQUEST_TESTCASE_FORMAT, url, &http_version, &test_case);
405 if (match == 3) {
406 switch (test_case) {
407 case 1:
408 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT1, test_case);
409 break;
410 case 2:
411 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT2, test_case);
412 break;
413 case 4:
414 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT4, test_case);
415 break;
416 case 5:
417 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT5, test_case);
418 break;
419 case 6:
420 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT6, test_case);
421 break;
422 case 7:
423 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT7, test_case);
424 break;
425 case 8:
426 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT8, test_case);
427 break;
428 case 9:
429 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT9, test_case);
430 break;
431 case 10:
432 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT10, test_case);
433 break;
434 case 11:
435 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT11, test_case);
436 break;
437 default:
438 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_DEFAULT_FORMAT, test_case);
439 break;
440 }
441 } else {
442 /* Didn't recognize a testcase request. send the default response */
443 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_DEFAULT_FORMAT, test_case);
444 }
445
446 return response;
447 }
448
449 static int
get_request_id_value(const char * name,TSMBuffer buf,TSMLoc hdr)450 get_request_id_value(const char *name, TSMBuffer buf, TSMLoc hdr)
451 {
452 int id = -1;
453 TSMLoc field;
454
455 field = TSMimeHdrFieldFind(buf, hdr, name, -1);
456 if (field != TS_NULL_MLOC) {
457 id = TSMimeHdrFieldValueIntGet(buf, hdr, field, 0);
458 }
459
460 TSHandleMLocRelease(buf, hdr, field);
461 return id;
462 }
463
464 // This routine can be called by tests, from the READ_REQUEST_HDR_HOOK
465 // to figure out the id of a test message
466 // Returns id/-1 in case of error
467 static int
get_request_id(TSHttpTxn txnp)468 get_request_id(TSHttpTxn txnp)
469 {
470 TSMBuffer bufp;
471 TSMLoc hdr_loc;
472 int id = -1;
473
474 if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
475 return -1;
476 }
477
478 id = get_request_id_value(X_REQUEST_ID, bufp, hdr_loc);
479 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
480 return id;
481 }
482
483 // This routine can be called by tests, from the READ_RESPONSE_HDR_HOOK
484 // to figure out the id of a test message
485 // Returns id/-1 in case of error
486 static int
get_response_id(TSHttpTxn txnp)487 get_response_id(TSHttpTxn txnp)
488 {
489 TSMBuffer bufp;
490 TSMLoc hdr_loc;
491 int id = -1;
492
493 if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
494 return -1;
495 }
496
497 id = get_request_id_value(X_RESPONSE_ID, bufp, hdr_loc);
498 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
499 return id;
500 }
501
502 //////////////////////////////////////////////////////////////////////////////
503 // SOCKET CLIENT
504 //////////////////////////////////////////////////////////////////////////////
505
506 static ClientTxn *
synclient_txn_create()507 synclient_txn_create()
508 {
509 const HttpProxyPort *proxy_port;
510
511 ClientTxn *txn = static_cast<ClientTxn *>(TSmalloc(sizeof(ClientTxn)));
512
513 ink_zero(*txn);
514
515 if (nullptr == (proxy_port = HttpProxyPort::findHttp(AF_INET))) {
516 txn->connect_port = PROXY_HTTP_DEFAULT_PORT;
517 } else {
518 txn->connect_port = proxy_port->m_port;
519 }
520
521 txn->connect_ip = IP(127, 0, 0, 1);
522 txn->status = REQUEST_INPROGRESS;
523 txn->magic = MAGIC_ALIVE;
524
525 TSDebug(CDBG_TAG, "Connecting to proxy 127.0.0.1 on port %d", txn->connect_port);
526 return txn;
527 }
528
529 static int
synclient_txn_delete(ClientTxn * txn)530 synclient_txn_delete(ClientTxn *txn)
531 {
532 TSAssert(txn->magic == MAGIC_ALIVE);
533 if (txn->connect_action && !TSActionDone(txn->connect_action)) {
534 TSActionCancel(txn->connect_action);
535 txn->connect_action = nullptr;
536 }
537
538 ats_free(txn->request);
539 txn->magic = MAGIC_DEAD;
540 TSfree(txn);
541 return 1;
542 }
543
544 static void
synclient_txn_close(ClientTxn * txn)545 synclient_txn_close(ClientTxn *txn)
546 {
547 if (txn) {
548 if (txn->vconn != nullptr) {
549 TSVConnClose(txn->vconn);
550 txn->vconn = nullptr;
551 }
552
553 if (txn->req_buffer != nullptr) {
554 TSIOBufferDestroy(txn->req_buffer);
555 txn->req_buffer = nullptr;
556 }
557
558 if (txn->resp_buffer != nullptr) {
559 TSIOBufferDestroy(txn->resp_buffer);
560 txn->resp_buffer = nullptr;
561 }
562
563 TSDebug(CDBG_TAG, "Client Txn destroyed");
564 }
565 }
566
567 static int
synclient_txn_send_request(ClientTxn * txn,char * request)568 synclient_txn_send_request(ClientTxn *txn, char *request)
569 {
570 TSCont cont;
571 sockaddr_in addr;
572
573 TSAssert(txn->magic == MAGIC_ALIVE);
574 txn->request = ats_strdup(request);
575 SET_TEST_HANDLER(txn->current_handler, synclient_txn_connect_handler);
576
577 cont = TSContCreate(synclient_txn_main_handler, TSMutexCreate());
578 TSContDataSet(cont, txn);
579
580 ats_ip4_set(&addr, txn->connect_ip, htons(txn->connect_port));
581 TSNetConnect(cont, ats_ip_sa_cast(&addr));
582 return 1;
583 }
584
585 /* This can be used to send a request to a specific VC */
586 static int
synclient_txn_send_request_to_vc(ClientTxn * txn,char * request,TSVConn vc)587 synclient_txn_send_request_to_vc(ClientTxn *txn, char *request, TSVConn vc)
588 {
589 TSCont cont;
590 TSAssert(txn->magic == MAGIC_ALIVE);
591 txn->request = ats_strdup(request);
592 SET_TEST_HANDLER(txn->current_handler, synclient_txn_connect_handler);
593
594 cont = TSContCreate(synclient_txn_main_handler, TSMutexCreate());
595 TSContDataSet(cont, txn);
596
597 TSContCall(cont, TS_EVENT_NET_CONNECT, vc);
598 return 1;
599 }
600
601 static int
synclient_txn_read_response(TSCont contp)602 synclient_txn_read_response(TSCont contp)
603 {
604 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
605 TSAssert(txn->magic == MAGIC_ALIVE);
606
607 TSIOBufferBlock block = TSIOBufferReaderStart(txn->resp_reader);
608 while (block != nullptr) {
609 int64_t blocklen;
610 const char *blockptr = TSIOBufferBlockReadStart(block, txn->resp_reader, &blocklen);
611
612 if (txn->response_len + blocklen <= RESPONSE_MAX_SIZE) {
613 memcpy((txn->response + txn->response_len), blockptr, blocklen);
614 txn->response_len += blocklen;
615 } else {
616 TSError("Error: Response length %" PRId64 " > response buffer size %d", txn->response_len + blocklen, RESPONSE_MAX_SIZE);
617 }
618
619 block = TSIOBufferBlockNext(block);
620 }
621
622 txn->response[txn->response_len] = '\0';
623 TSDebug(CDBG_TAG, "Response = |%s|, req len = %d", txn->response, txn->response_len);
624
625 return 1;
626 }
627
628 static int
synclient_txn_read_response_handler(TSCont contp,TSEvent event,void *)629 synclient_txn_read_response_handler(TSCont contp, TSEvent event, void * /* data ATS_UNUSED */)
630 {
631 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
632 TSAssert(txn->magic == MAGIC_ALIVE);
633
634 int64_t avail;
635
636 switch (event) {
637 case TS_EVENT_VCONN_READ_READY:
638 case TS_EVENT_VCONN_READ_COMPLETE:
639 if (event == TS_EVENT_VCONN_READ_READY) {
640 TSDebug(CDBG_TAG, "READ_READY");
641 } else {
642 TSDebug(CDBG_TAG, "READ_COMPLETE");
643 }
644
645 avail = TSIOBufferReaderAvail(txn->resp_reader);
646 TSDebug(CDBG_TAG, "%" PRId64 " bytes available in buffer", avail);
647
648 if (avail > 0) {
649 synclient_txn_read_response(contp);
650 TSIOBufferReaderConsume(txn->resp_reader, avail);
651 }
652
653 TSVIOReenable(txn->read_vio);
654 break;
655
656 case TS_EVENT_VCONN_EOS:
657 TSDebug(CDBG_TAG, "READ_EOS");
658 // Connection closed. In HTTP/1.0 it means we're done for this request.
659 txn->status = REQUEST_SUCCESS;
660 synclient_txn_close(static_cast<ClientTxn *>(TSContDataGet(contp)));
661 TSContDestroy(contp);
662 return 1;
663
664 case TS_EVENT_ERROR:
665 TSDebug(CDBG_TAG, "READ_ERROR");
666 txn->status = REQUEST_FAILURE;
667 synclient_txn_close(static_cast<ClientTxn *>(TSContDataGet(contp)));
668 TSContDestroy(contp);
669 return 1;
670
671 default:
672 TSAssert(!"Invalid event");
673 break;
674 }
675 return 1;
676 }
677
678 static int
synclient_txn_write_request(TSCont contp)679 synclient_txn_write_request(TSCont contp)
680 {
681 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
682 TSAssert(txn->magic == MAGIC_ALIVE);
683
684 TSIOBufferBlock block;
685 char *ptr_block;
686 int64_t len, ndone, ntodo, towrite, avail;
687
688 len = strlen(txn->request);
689
690 ndone = 0;
691 ntodo = len;
692 while (ntodo > 0) {
693 block = TSIOBufferStart(txn->req_buffer);
694 ptr_block = TSIOBufferBlockWriteStart(block, &avail);
695 towrite = std::min(ntodo, avail);
696 memcpy(ptr_block, txn->request + ndone, towrite);
697 TSIOBufferProduce(txn->req_buffer, towrite);
698 ntodo -= towrite;
699 ndone += towrite;
700 }
701
702 /* Start writing the response */
703 TSDebug(CDBG_TAG, "Writing |%s| (%" PRId64 ") bytes", txn->request, len);
704 txn->write_vio = TSVConnWrite(txn->vconn, contp, txn->req_reader, len);
705
706 return 1;
707 }
708
709 static int
synclient_txn_write_request_handler(TSCont contp,TSEvent event,void *)710 synclient_txn_write_request_handler(TSCont contp, TSEvent event, void * /* data ATS_UNUSED */)
711 {
712 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
713 TSAssert(txn->magic == MAGIC_ALIVE);
714
715 switch (event) {
716 case TS_EVENT_VCONN_WRITE_READY:
717 TSDebug(CDBG_TAG, "WRITE_READY");
718 TSVIOReenable(txn->write_vio);
719 break;
720
721 case TS_EVENT_VCONN_WRITE_COMPLETE:
722 TSDebug(CDBG_TAG, "WRITE_COMPLETE");
723 // Weird: synclient should not close the write part of vconn.
724 // Otherwise some strangeness...
725
726 /* Start reading */
727 SET_TEST_HANDLER(txn->current_handler, synclient_txn_read_response_handler);
728 txn->read_vio = TSVConnRead(txn->vconn, contp, txn->resp_buffer, INT64_MAX);
729 break;
730
731 case TS_EVENT_VCONN_EOS:
732 TSDebug(CDBG_TAG, "WRITE_EOS");
733 txn->status = REQUEST_FAILURE;
734 synclient_txn_close(static_cast<ClientTxn *>(TSContDataGet(contp)));
735 TSContDestroy(contp);
736 break;
737
738 case TS_EVENT_ERROR:
739 TSDebug(CDBG_TAG, "WRITE_ERROR");
740 txn->status = REQUEST_FAILURE;
741 synclient_txn_close(static_cast<ClientTxn *>(TSContDataGet(contp)));
742 TSContDestroy(contp);
743 break;
744
745 default:
746 TSAssert(!"Invalid event");
747 break;
748 }
749 return TS_EVENT_IMMEDIATE;
750 }
751
752 static int
synclient_txn_connect_handler(TSCont contp,TSEvent event,void * data)753 synclient_txn_connect_handler(TSCont contp, TSEvent event, void *data)
754 {
755 TSAssert((event == TS_EVENT_NET_CONNECT) || (event == TS_EVENT_NET_CONNECT_FAILED));
756
757 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
758 TSAssert(txn->magic == MAGIC_ALIVE);
759
760 if (event == TS_EVENT_NET_CONNECT) {
761 TSDebug(CDBG_TAG, "NET_CONNECT");
762
763 txn->req_buffer = TSIOBufferCreate();
764 txn->req_reader = TSIOBufferReaderAlloc(txn->req_buffer);
765 txn->resp_buffer = TSIOBufferCreate();
766 txn->resp_reader = TSIOBufferReaderAlloc(txn->resp_buffer);
767
768 txn->response[0] = '\0';
769 txn->response_len = 0;
770
771 txn->vconn = static_cast<TSVConn>(data);
772 txn->local_port = (int)((NetVConnection *)data)->get_local_port();
773
774 txn->write_vio = nullptr;
775 txn->read_vio = nullptr;
776
777 /* start writing */
778 SET_TEST_HANDLER(txn->current_handler, synclient_txn_write_request_handler);
779 synclient_txn_write_request(contp);
780
781 return TS_EVENT_IMMEDIATE;
782 } else {
783 TSDebug(CDBG_TAG, "NET_CONNECT_FAILED");
784 txn->status = REQUEST_FAILURE;
785 synclient_txn_close(static_cast<ClientTxn *>(TSContDataGet(contp)));
786 TSContDestroy(contp);
787 }
788
789 return TS_EVENT_IMMEDIATE;
790 }
791
792 static int
synclient_txn_main_handler(TSCont contp,TSEvent event,void * data)793 synclient_txn_main_handler(TSCont contp, TSEvent event, void *data)
794 {
795 ClientTxn *txn = static_cast<ClientTxn *>(TSContDataGet(contp));
796 TSAssert(txn->magic == MAGIC_ALIVE);
797
798 TxnHandler handler = txn->current_handler;
799 return (*handler)(contp, event, data);
800 }
801
802 //////////////////////////////////////////////////////////////////////////////
803 // SOCKET SERVER
804 //////////////////////////////////////////////////////////////////////////////
805
806 SocketServer *
synserver_create(int port,TSCont cont)807 synserver_create(int port, TSCont cont)
808 {
809 if (port != SYNSERVER_DUMMY_PORT) {
810 TSAssert(port > 0);
811 TSAssert(port < INT16_MAX);
812 }
813
814 SocketServer *s = static_cast<SocketServer *>(TSmalloc(sizeof(SocketServer)));
815 s->magic = MAGIC_ALIVE;
816 s->accept_port = port;
817 s->accept_action = nullptr;
818 s->accept_cont = cont;
819 TSContDataSet(s->accept_cont, s);
820 return s;
821 }
822
823 SocketServer *
synserver_create(int port)824 synserver_create(int port)
825 {
826 return synserver_create(port, TSContCreate(synserver_vc_accept, TSMutexCreate()));
827 }
828
829 static int
synserver_start(SocketServer * s)830 synserver_start(SocketServer *s)
831 {
832 TSAssert(s->magic == MAGIC_ALIVE);
833 TSAssert(s->accept_action == nullptr);
834
835 if (s->accept_port != SYNSERVER_DUMMY_PORT) {
836 TSAssert(s->accept_port > 0);
837 TSAssert(s->accept_port < INT16_MAX);
838
839 s->accept_action = TSNetAccept(s->accept_cont, s->accept_port, AF_INET, 0);
840 }
841
842 return 1;
843 }
844
845 static int
synserver_stop(SocketServer * s)846 synserver_stop(SocketServer *s)
847 {
848 TSAssert(s->magic == MAGIC_ALIVE);
849 if (s->accept_action && !TSActionDone(s->accept_action)) {
850 TSActionCancel(s->accept_action);
851 s->accept_action = nullptr;
852 TSDebug(SDBG_TAG, "Had to cancel action");
853 }
854 TSDebug(SDBG_TAG, "stopped");
855 return 1;
856 }
857
858 static int
synserver_delete(SocketServer * s)859 synserver_delete(SocketServer *s)
860 {
861 if (s != nullptr) {
862 TSAssert(s->magic == MAGIC_ALIVE);
863 synserver_stop(s);
864
865 if (s->accept_cont) {
866 TSContDestroy(s->accept_cont);
867 s->accept_cont = nullptr;
868 TSDebug(SDBG_TAG, "destroyed accept cont");
869 }
870
871 s->magic = MAGIC_DEAD;
872 TSfree(s);
873 TSDebug(SDBG_TAG, "deleted server");
874 }
875
876 return 1;
877 }
878
879 static int
synserver_vc_refuse(TSCont contp,TSEvent event,void * data)880 synserver_vc_refuse(TSCont contp, TSEvent event, void *data)
881 {
882 TSAssert((event == TS_EVENT_NET_ACCEPT) || (event == TS_EVENT_NET_ACCEPT_FAILED));
883
884 SocketServer *s = static_cast<SocketServer *>(TSContDataGet(contp));
885 TSAssert(s->magic == MAGIC_ALIVE);
886
887 TSDebug(SDBG_TAG, "%s: NET_ACCEPT", __func__);
888
889 if (event == TS_EVENT_NET_ACCEPT_FAILED) {
890 Warning("Synserver failed to bind to port %d.", ntohs(s->accept_port));
891 ink_release_assert(!"Synserver must be able to bind to a port, check system netstat");
892 TSDebug(SDBG_TAG, "%s: NET_ACCEPT_FAILED", __func__);
893 return TS_EVENT_IMMEDIATE;
894 }
895
896 TSVConnClose(static_cast<TSVConn>(data));
897 return TS_EVENT_IMMEDIATE;
898 }
899
900 static int
synserver_vc_accept(TSCont contp,TSEvent event,void * data)901 synserver_vc_accept(TSCont contp, TSEvent event, void *data)
902 {
903 TSAssert((event == TS_EVENT_NET_ACCEPT) || (event == TS_EVENT_NET_ACCEPT_FAILED));
904
905 SocketServer *s = static_cast<SocketServer *>(TSContDataGet(contp));
906 TSAssert(s->magic == MAGIC_ALIVE);
907
908 if (event == TS_EVENT_NET_ACCEPT_FAILED) {
909 Warning("Synserver failed to bind to port %d.", ntohs(s->accept_port));
910 ink_release_assert(!"Synserver must be able to bind to a port, check system netstat");
911 TSDebug(SDBG_TAG, "%s: NET_ACCEPT_FAILED", __func__);
912 return TS_EVENT_IMMEDIATE;
913 }
914
915 TSDebug(SDBG_TAG, "%s: NET_ACCEPT", __func__);
916
917 /* Create a new transaction */
918 ServerTxn *txn = static_cast<ServerTxn *>(TSmalloc(sizeof(ServerTxn)));
919 txn->magic = MAGIC_ALIVE;
920
921 SET_TEST_HANDLER(txn->current_handler, synserver_txn_read_request_handler);
922
923 TSCont txn_cont = TSContCreate(synserver_txn_main_handler, TSMutexCreate());
924 TSContDataSet(txn_cont, txn);
925
926 txn->req_buffer = TSIOBufferCreate();
927 txn->req_reader = TSIOBufferReaderAlloc(txn->req_buffer);
928
929 txn->resp_buffer = TSIOBufferCreate();
930 txn->resp_reader = TSIOBufferReaderAlloc(txn->resp_buffer);
931
932 txn->request[0] = '\0';
933 txn->request_len = 0;
934
935 txn->vconn = static_cast<TSVConn>(data);
936
937 txn->write_vio = nullptr;
938
939 /* start reading */
940 txn->read_vio = TSVConnRead(txn->vconn, txn_cont, txn->req_buffer, INT64_MAX);
941
942 return TS_EVENT_IMMEDIATE;
943 }
944
945 static int
synserver_txn_close(TSCont contp)946 synserver_txn_close(TSCont contp)
947 {
948 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
949 TSAssert(txn->magic == MAGIC_ALIVE);
950
951 if (txn->vconn != nullptr) {
952 TSVConnClose(txn->vconn);
953 }
954 if (txn->req_buffer) {
955 TSIOBufferDestroy(txn->req_buffer);
956 }
957 if (txn->resp_buffer) {
958 TSIOBufferDestroy(txn->resp_buffer);
959 }
960
961 txn->magic = MAGIC_DEAD;
962 TSfree(txn);
963 TSContDestroy(contp);
964
965 TSDebug(SDBG_TAG, "Server Txn destroyed");
966 return TS_EVENT_IMMEDIATE;
967 }
968
969 static int
synserver_txn_write_response(TSCont contp)970 synserver_txn_write_response(TSCont contp)
971 {
972 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
973 TSAssert(txn->magic == MAGIC_ALIVE);
974
975 SET_TEST_HANDLER(txn->current_handler, synserver_txn_write_response_handler);
976
977 TSIOBufferBlock block;
978 char *ptr_block;
979 int64_t len, ndone, ntodo, towrite, avail;
980 char *response;
981
982 response = generate_response(txn->request);
983 len = strlen(response);
984
985 ndone = 0;
986 ntodo = len;
987 while (ntodo > 0) {
988 block = TSIOBufferStart(txn->resp_buffer);
989 ptr_block = TSIOBufferBlockWriteStart(block, &avail);
990 towrite = std::min(ntodo, avail);
991 memcpy(ptr_block, response + ndone, towrite);
992 TSIOBufferProduce(txn->resp_buffer, towrite);
993 ntodo -= towrite;
994 ndone += towrite;
995 }
996
997 /* Start writing the response */
998 TSDebug(SDBG_TAG, "Writing response: |%s| (%" PRId64 ") bytes)", response, len);
999 txn->write_vio = TSVConnWrite(txn->vconn, contp, txn->resp_reader, len);
1000
1001 /* Now that response is in IOBuffer, free up response */
1002 TSfree(response);
1003
1004 return TS_EVENT_IMMEDIATE;
1005 }
1006
1007 static int
synserver_txn_write_response_handler(TSCont contp,TSEvent event,void *)1008 synserver_txn_write_response_handler(TSCont contp, TSEvent event, void * /* data ATS_UNUSED */)
1009 {
1010 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
1011 TSAssert(txn->magic == MAGIC_ALIVE);
1012
1013 switch (event) {
1014 case TS_EVENT_VCONN_WRITE_READY:
1015 TSDebug(SDBG_TAG, "WRITE_READY");
1016 TSVIOReenable(txn->write_vio);
1017 break;
1018
1019 case TS_EVENT_VCONN_WRITE_COMPLETE:
1020 TSDebug(SDBG_TAG, "WRITE_COMPLETE");
1021 TSVConnShutdown(txn->vconn, 0, 1);
1022 return synserver_txn_close(contp);
1023 break;
1024
1025 case TS_EVENT_VCONN_EOS:
1026 TSDebug(SDBG_TAG, "WRITE_EOS");
1027 return synserver_txn_close(contp);
1028 break;
1029
1030 case TS_EVENT_ERROR:
1031 TSDebug(SDBG_TAG, "WRITE_ERROR");
1032 return synserver_txn_close(contp);
1033 break;
1034
1035 default:
1036 TSAssert(!"Invalid event");
1037 break;
1038 }
1039 return TS_EVENT_IMMEDIATE;
1040 }
1041
1042 static int
synserver_txn_read_request(TSCont contp)1043 synserver_txn_read_request(TSCont contp)
1044 {
1045 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
1046 TSAssert(txn->magic == MAGIC_ALIVE);
1047
1048 int end;
1049 TSIOBufferBlock block = TSIOBufferReaderStart(txn->req_reader);
1050
1051 while (block != nullptr) {
1052 int64_t blocklen;
1053 const char *blockptr = TSIOBufferBlockReadStart(block, txn->req_reader, &blocklen);
1054
1055 if (txn->request_len + blocklen <= REQUEST_MAX_SIZE) {
1056 memcpy((txn->request + txn->request_len), blockptr, blocklen);
1057 txn->request_len += blocklen;
1058 } else {
1059 TSError("Error: Request length %" PRId64 " > request buffer size %d", txn->request_len + blocklen, REQUEST_MAX_SIZE);
1060 }
1061
1062 block = TSIOBufferBlockNext(block);
1063 }
1064
1065 txn->request[txn->request_len] = '\0';
1066 TSDebug(SDBG_TAG, "Request = |%s|, req len = %d", txn->request, txn->request_len);
1067
1068 end = (strstr(txn->request, HTTP_REQUEST_END) != nullptr);
1069 TSDebug(SDBG_TAG, "End of request = %d", end);
1070
1071 return end;
1072 }
1073
1074 static int
synserver_txn_read_request_handler(TSCont contp,TSEvent event,void *)1075 synserver_txn_read_request_handler(TSCont contp, TSEvent event, void * /* data ATS_UNUSED */)
1076 {
1077 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
1078 TSAssert(txn->magic == MAGIC_ALIVE);
1079
1080 int64_t avail;
1081 int end_of_request;
1082
1083 switch (event) {
1084 case TS_EVENT_VCONN_READ_READY:
1085 case TS_EVENT_VCONN_READ_COMPLETE:
1086 TSDebug(SDBG_TAG, (event == TS_EVENT_VCONN_READ_READY) ? "READ_READY" : "READ_COMPLETE");
1087 avail = TSIOBufferReaderAvail(txn->req_reader);
1088 TSDebug(SDBG_TAG, "%" PRId64 " bytes available in buffer", avail);
1089
1090 if (avail > 0) {
1091 end_of_request = synserver_txn_read_request(contp);
1092 TSIOBufferReaderConsume(txn->req_reader, avail);
1093
1094 if (end_of_request) {
1095 TSVConnShutdown(txn->vconn, 1, 0);
1096 return synserver_txn_write_response(contp);
1097 }
1098 }
1099
1100 TSVIOReenable(txn->read_vio);
1101 break;
1102
1103 case TS_EVENT_VCONN_EOS:
1104 TSDebug(SDBG_TAG, "READ_EOS");
1105 return synserver_txn_close(contp);
1106 break;
1107
1108 case TS_EVENT_ERROR:
1109 TSDebug(SDBG_TAG, "READ_ERROR");
1110 return synserver_txn_close(contp);
1111 break;
1112
1113 default:
1114 TSAssert(!"Invalid event");
1115 break;
1116 }
1117 return TS_EVENT_IMMEDIATE;
1118 }
1119
1120 static int
synserver_txn_main_handler(TSCont contp,TSEvent event,void * data)1121 synserver_txn_main_handler(TSCont contp, TSEvent event, void *data)
1122 {
1123 ServerTxn *txn = static_cast<ServerTxn *>(TSContDataGet(contp));
1124 TSAssert(txn->magic == MAGIC_ALIVE);
1125
1126 TxnHandler handler = txn->current_handler;
1127 return (*handler)(contp, event, data);
1128 }
1129
1130 // End of the previous #include "InkAPITestTool.cc"
1131
1132 #define TC_PASS 1
1133 #define TC_FAIL 0
1134
1135 #define UTDBG_TAG "sdk_ut"
1136
1137 // Since there's no way to unregister global hooks, tests that register a hook
1138 // have to co-operate once they are complete by re-enabling and transactions
1139 // and getting out of the way.
1140 #define CHECK_SPURIOUS_EVENT(cont, event, edata) \
1141 if (TSContDataGet(cont) == NULL) { \
1142 switch (event) { \
1143 case TS_EVENT_IMMEDIATE: \
1144 case TS_EVENT_TIMEOUT: \
1145 return TS_EVENT_NONE; \
1146 case TS_EVENT_HTTP_SELECT_ALT: \
1147 return TS_EVENT_NONE; \
1148 case TS_EVENT_HTTP_READ_REQUEST_HDR: \
1149 case TS_EVENT_HTTP_OS_DNS: \
1150 case TS_EVENT_HTTP_SEND_REQUEST_HDR: \
1151 case TS_EVENT_HTTP_READ_CACHE_HDR: \
1152 case TS_EVENT_HTTP_READ_RESPONSE_HDR: \
1153 case TS_EVENT_HTTP_SEND_RESPONSE_HDR: \
1154 case TS_EVENT_HTTP_REQUEST_TRANSFORM: \
1155 case TS_EVENT_HTTP_RESPONSE_TRANSFORM: \
1156 case TS_EVENT_HTTP_TXN_START: \
1157 case TS_EVENT_HTTP_TXN_CLOSE: \
1158 case TS_EVENT_HTTP_SSN_START: \
1159 case TS_EVENT_HTTP_SSN_CLOSE: \
1160 case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: \
1161 case TS_EVENT_HTTP_PRE_REMAP: \
1162 case TS_EVENT_HTTP_POST_REMAP: \
1163 TSHttpTxnReenable((TSHttpTxn)(edata), TS_EVENT_HTTP_CONTINUE); \
1164 return TS_EVENT_NONE; \
1165 default: \
1166 break; \
1167 } \
1168 }
1169
1170 /******************************************************************************/
1171
1172 /* Use SDK_RPRINT to report failure or success for each test case */
1173 int
SDK_RPRINT(RegressionTest * t,const char * api_name,const char * testcase_name,int status,const char * err_details_format,...)1174 SDK_RPRINT(RegressionTest *t, const char *api_name, const char *testcase_name, int status, const char *err_details_format, ...)
1175 {
1176 int l;
1177 char buffer[8192];
1178 char format2[8192];
1179 snprintf(format2, sizeof(format2), "[%s] %s : [%s] <<%s>> { %s }\n", t->name, api_name, testcase_name,
1180 status == TC_PASS ? "PASS" : "FAIL", err_details_format);
1181 va_list ap;
1182 va_start(ap, err_details_format);
1183 l = ink_bvsprintf(buffer, format2, ap);
1184 va_end(ap);
1185 fputs(buffer, stderr);
1186 return (l);
1187 }
1188
1189 /*
1190 REGRESSION_TEST(SDK_<test_name>)(RegressionTest *t, int atype, int *pstatus)
1191
1192 RegressionTest *test is a pointer on object that will run the test.
1193 Do not modify.
1194
1195 int atype is one of:
1196 REGRESSION_TEST_NONE
1197 REGRESSION_TEST_QUICK
1198 REGRESSION_TEST_NIGHTLY
1199 REGRESSION_TEST_EXTENDED
1200
1201 int *pstatus should be set to one of:
1202 REGRESSION_TEST_PASSED
1203 REGRESSION_TEST_INPROGRESS
1204 REGRESSION_TEST_FAILED
1205 REGRESSION_TEST_NOT_RUN
1206 Note: pstatus is polled and can be used for asynchronous tests.
1207
1208 */
1209
1210 /* Misc */
1211 ////////////////////////////////////////////////
1212 // SDK_API_TSTrafficServerVersionGet
1213 //
1214 // Unit Test for API: TSTrafficServerVersionGet
1215 ////////////////////////////////////////////////
REGRESSION_TEST(SDK_API_TSTrafficServerVersionGet)1216 REGRESSION_TEST(SDK_API_TSTrafficServerVersionGet)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1217 {
1218 *pstatus = REGRESSION_TEST_INPROGRESS;
1219
1220 /* Assume the UT runs on TS5.0 and higher */
1221 const char *ts_version = TSTrafficServerVersionGet();
1222 if (!ts_version) {
1223 SDK_RPRINT(test, "TSTrafficServerVersionGet", "TestCase1", TC_FAIL, "can't get traffic server version");
1224 *pstatus = REGRESSION_TEST_FAILED;
1225 return;
1226 }
1227
1228 int major_ts_version = 0;
1229 int minor_ts_version = 0;
1230 int patch_ts_version = 0;
1231 // coverity[secure_coding]
1232 if (sscanf(ts_version, "%d.%d.%d", &major_ts_version, &minor_ts_version, &patch_ts_version) != 3) {
1233 SDK_RPRINT(test, "TSTrafficServerVersionGet", "TestCase2", TC_FAIL, "traffic server version format is incorrect");
1234 *pstatus = REGRESSION_TEST_FAILED;
1235 return;
1236 }
1237
1238 if (major_ts_version < 2) {
1239 SDK_RPRINT(test, "TSTrafficServerVersionGet", "TestCase3", TC_FAIL, "traffic server major version is incorrect");
1240 *pstatus = REGRESSION_TEST_FAILED;
1241 return;
1242 }
1243
1244 SDK_RPRINT(test, "TSTrafficServerVersionGet", "TestCase1", TC_PASS, "ok");
1245 *pstatus = REGRESSION_TEST_PASSED;
1246 return;
1247 }
1248
1249 ////////////////////////////////////////////////
1250 // SDK_API_TSPluginDirGet
1251 //
1252 // Unit Test for API: TSPluginDirGet
1253 // TSInstallDirGet
1254 // TSRuntimeDirGet
1255 ////////////////////////////////////////////////
REGRESSION_TEST(SDK_API_TSPluginDirGet)1256 REGRESSION_TEST(SDK_API_TSPluginDirGet)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1257 {
1258 *pstatus = REGRESSION_TEST_INPROGRESS;
1259
1260 const char *plugin_dir = TSPluginDirGet();
1261 const char *install_dir = TSInstallDirGet();
1262 const char *runtime_dir = TSRuntimeDirGet();
1263
1264 if (!plugin_dir) {
1265 SDK_RPRINT(test, "TSPluginDirGet", "TestCase1", TC_FAIL, "can't get plugin dir");
1266 *pstatus = REGRESSION_TEST_FAILED;
1267 return;
1268 }
1269
1270 if (!install_dir) {
1271 SDK_RPRINT(test, "TSInstallDirGet", "TestCase1", TC_FAIL, "can't get installation dir");
1272 *pstatus = REGRESSION_TEST_FAILED;
1273 return;
1274 }
1275
1276 if (!runtime_dir) {
1277 SDK_RPRINT(test, "TSRuntimeDirGet", "TestCase1", TC_FAIL, "can't get runtime dir");
1278 *pstatus = REGRESSION_TEST_FAILED;
1279 return;
1280 }
1281
1282 if (strstr(plugin_dir, TS_BUILD_LIBEXECDIR) == nullptr) {
1283 SDK_RPRINT(test, "TSPluginDirGet", "TestCase2", TC_FAIL, "plugin dir(%s) is incorrect, expected (%s) in path.", plugin_dir,
1284 TS_BUILD_LIBEXECDIR);
1285 *pstatus = REGRESSION_TEST_FAILED;
1286 return;
1287 }
1288
1289 if (strstr(plugin_dir, install_dir) == nullptr) {
1290 SDK_RPRINT(test, "TSInstallDirGet", "TestCase2", TC_FAIL, "install dir is incorrect");
1291 *pstatus = REGRESSION_TEST_FAILED;
1292 return;
1293 }
1294
1295 if (strstr(runtime_dir, TS_BUILD_RUNTIMEDIR) == nullptr) {
1296 SDK_RPRINT(test, "TSRuntimeDirGet", "TestCase2", TC_FAIL, "runtime dir is incorrect");
1297 *pstatus = REGRESSION_TEST_FAILED;
1298 return;
1299 }
1300
1301 SDK_RPRINT(test, "TSPluginDirGet", "TestCase1", TC_PASS, "ok");
1302 SDK_RPRINT(test, "TSInstallDirGet", "TestCase1", TC_PASS, "ok");
1303 SDK_RPRINT(test, "TSRuntimeDirGet", "TestCase1", TC_PASS, "ok");
1304 *pstatus = REGRESSION_TEST_PASSED;
1305 return;
1306 }
1307
1308 /* TSConfig */
1309 ////////////////////////////////////////////////
1310 // SDK_API_TSConfig
1311 //
1312 // Unit Test for API: TSConfigSet
1313 // TSConfigGet
1314 // TSConfigRelease
1315 // TSConfigDataGet
1316 ////////////////////////////////////////////////
1317 static int my_config_id = 0;
1318 struct ConfigData {
1319 const char *a;
1320 const char *b;
1321 };
1322
REGRESSION_TEST(SDK_API_TSConfig)1323 REGRESSION_TEST(SDK_API_TSConfig)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1324 {
1325 *pstatus = REGRESSION_TEST_INPROGRESS;
1326 ConfigData *config = new ConfigData;
1327 config->a = "unit";
1328 config->b = "test";
1329
1330 my_config_id = TSConfigSet(my_config_id, config, [](void *cfg) { delete static_cast<ConfigData *>(cfg); });
1331
1332 TSConfig test_config = nullptr;
1333 test_config = TSConfigGet(my_config_id);
1334
1335 if (!test_config) {
1336 SDK_RPRINT(test, "TSConfigSet", "TestCase1", TC_FAIL, "can't correctly set global config structure");
1337 SDK_RPRINT(test, "TSConfigGet", "TestCase1", TC_FAIL, "can't correctly get global config structure");
1338 TSConfigRelease(my_config_id, reinterpret_cast<TSConfig>(config));
1339 *pstatus = REGRESSION_TEST_FAILED;
1340 return;
1341 }
1342
1343 if (TSConfigDataGet(test_config) != config) {
1344 SDK_RPRINT(test, "TSConfigDataGet", "TestCase1", TC_FAIL, "failed to get config data");
1345 TSConfigRelease(my_config_id, reinterpret_cast<TSConfig>(config));
1346 *pstatus = REGRESSION_TEST_FAILED;
1347 return;
1348 }
1349
1350 SDK_RPRINT(test, "TSConfigGet", "TestCase1", TC_PASS, "ok");
1351 SDK_RPRINT(test, "TSConfigSet", "TestCase1", TC_PASS, "ok");
1352 SDK_RPRINT(test, "TSConfigDataGet", "TestCase1", TC_PASS, "ok");
1353
1354 TSConfigRelease(my_config_id, reinterpret_cast<TSConfig>(config));
1355 *pstatus = REGRESSION_TEST_PASSED;
1356 return;
1357 }
1358
1359 /* TSNetVConn */
1360 //////////////////////////////////////////////
1361 // SDK_API_TSNetVConn
1362 //
1363 // Unit Test for API: TSNetVConnRemoteIPGet
1364 // TSNetVConnRemotePortGet
1365 // TSNetAccept
1366 // TSNetConnect
1367 //////////////////////////////////////////////
1368
1369 struct SDK_NetVConn_Params {
SDK_NetVConn_ParamsSDK_NetVConn_Params1370 SDK_NetVConn_Params(const char *_a, RegressionTest *_t, int *_p)
1371 : buffer(nullptr), api(_a), port(0), test(_t), pstatus(_p), vc(nullptr)
1372 {
1373 this->status.client = this->status.server = REGRESSION_TEST_INPROGRESS;
1374 }
1375
~SDK_NetVConn_ParamsSDK_NetVConn_Params1376 ~SDK_NetVConn_Params()
1377 {
1378 if (this->buffer) {
1379 TSIOBufferDestroy(this->buffer);
1380 }
1381 if (this->vc) {
1382 TSVConnClose(this->vc);
1383 }
1384 }
1385
1386 TSIOBuffer buffer;
1387 const char *api;
1388 unsigned short port;
1389 RegressionTest *test;
1390 int *pstatus;
1391 TSVConn vc;
1392 struct {
1393 int client;
1394 int server;
1395 } status;
1396 };
1397
1398 int
server_handler(TSCont contp,TSEvent event,void * data)1399 server_handler(TSCont contp, TSEvent event, void *data)
1400 {
1401 SDK_NetVConn_Params *params = static_cast<SDK_NetVConn_Params *>(TSContDataGet(contp));
1402
1403 if (event == TS_EVENT_NET_ACCEPT) {
1404 // Kick off a read so that we can receive an EOS event.
1405 SDK_RPRINT(params->test, params->api, "ServerEvent NET_ACCEPT", TC_PASS, "ok");
1406 params->buffer = TSIOBufferCreate();
1407 params->vc = static_cast<TSVConn>(data);
1408 TSVConnRead(static_cast<TSVConn>(data), contp, params->buffer, 100);
1409 } else if (event == TS_EVENT_VCONN_EOS) {
1410 // The server end of the test passes if it receives an EOF event. This means that it must have
1411 // connected to the endpoint. Since this always happens *after* the accept, we know that it is
1412 // safe to delete the params.
1413 TSContDestroy(contp);
1414
1415 SDK_RPRINT(params->test, params->api, "ServerEvent EOS", TC_PASS, "ok");
1416 *params->pstatus = REGRESSION_TEST_PASSED;
1417 delete params;
1418 } else if (event == TS_EVENT_VCONN_READ_READY) {
1419 SDK_RPRINT(params->test, params->api, "ServerEvent READ_READY", TC_PASS, "ok");
1420 } else {
1421 SDK_RPRINT(params->test, params->api, "ServerEvent", TC_FAIL, "received unexpected event %d", event);
1422 *params->pstatus = REGRESSION_TEST_FAILED;
1423 delete params;
1424 }
1425
1426 return 1;
1427 }
1428
1429 int
client_handler(TSCont contp,TSEvent event,void * data)1430 client_handler(TSCont contp, TSEvent event, void *data)
1431 {
1432 SDK_NetVConn_Params *params = static_cast<SDK_NetVConn_Params *>(TSContDataGet(contp));
1433
1434 if (event == TS_EVENT_NET_CONNECT_FAILED) {
1435 SDK_RPRINT(params->test, params->api, "ClientConnect", TC_FAIL, "can't connect to server");
1436
1437 *params->pstatus = REGRESSION_TEST_FAILED;
1438
1439 // no need to continue, return
1440 // Fix me: how to deal with server side cont?
1441 TSContDestroy(contp);
1442 return 1;
1443 } else if (TS_EVENT_NET_CONNECT == event) {
1444 sockaddr const *addr = TSNetVConnRemoteAddrGet(static_cast<TSVConn>(data));
1445 uint16_t input_server_port = ats_ip_port_host_order(addr);
1446
1447 // If DEFER_ACCEPT is enabled in the OS then the user space accept() doesn't
1448 // happen until data arrives on the socket. Because we're just testing the accept()
1449 // we write a small amount of ignored data to make sure this gets triggered.
1450 UnixNetVConnection *vc = static_cast<UnixNetVConnection *>(data);
1451 ink_release_assert(::write(vc->con.fd, "Bob's your uncle", 16) != 0);
1452
1453 sleep(1); // XXX this sleep ensures the server end gets the accept event.
1454
1455 if (ats_is_ip_loopback(addr)) {
1456 SDK_RPRINT(params->test, params->api, "TSNetVConnRemoteIPGet", TC_PASS, "ok");
1457 } else {
1458 ip_text_buffer s, ipb;
1459 IpEndpoint loopback;
1460 ats_ip4_set(&loopback, htonl(INADDR_LOOPBACK));
1461 SDK_RPRINT(params->test, params->api, "TSNetVConnRemoteIPGet", TC_FAIL, "server ip [%s] is incorrect - expected [%s]",
1462 ats_ip_ntop(addr, s, sizeof s), ats_ip_ntop(&loopback.sa, ipb, sizeof ipb));
1463
1464 TSContDestroy(contp);
1465 // Fix me: how to deal with server side cont?
1466 *params->pstatus = REGRESSION_TEST_FAILED;
1467 return 1;
1468 }
1469
1470 if (input_server_port == params->port) {
1471 SDK_RPRINT(params->test, params->api, "TSNetVConnRemotePortGet", TC_PASS, "ok");
1472 } else {
1473 SDK_RPRINT(params->test, params->api, "TSNetVConnRemotePortGet", TC_FAIL, "server port [%d] is incorrect -- expected [%d]",
1474 input_server_port, params->port);
1475
1476 TSContDestroy(contp);
1477 // Fix me: how to deal with server side cont?
1478 *params->pstatus = REGRESSION_TEST_FAILED;
1479 return 1;
1480 }
1481
1482 SDK_RPRINT(params->test, params->api, "TSNetConnect", TC_PASS, "ok");
1483
1484 // XXX We really ought to do a write/read exchange with the server. The sleep above works around this.
1485
1486 // Looks good from the client end. Next we disconnect so that the server end can set the final test status.
1487 TSVConnClose(static_cast<TSVConn>(data));
1488 }
1489
1490 TSContDestroy(contp);
1491
1492 return 1;
1493 }
1494
REGRESSION_TEST(SDK_API_TSNetVConn)1495 REGRESSION_TEST(SDK_API_TSNetVConn)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1496 {
1497 *pstatus = REGRESSION_TEST_INPROGRESS;
1498
1499 SDK_NetVConn_Params *params = new SDK_NetVConn_Params("TSNetAccept", test, pstatus);
1500
1501 params->port = 12345;
1502
1503 TSCont server_cont = TSContCreate(server_handler, TSMutexCreate());
1504 TSCont client_cont = TSContCreate(client_handler, TSMutexCreate());
1505
1506 TSContDataSet(server_cont, params);
1507 TSContDataSet(client_cont, params);
1508
1509 TSNetAccept(server_cont, params->port, -1, 0);
1510
1511 IpEndpoint addr;
1512 ats_ip4_set(&addr, htonl(INADDR_LOOPBACK), htons(params->port));
1513 TSNetConnect(client_cont, &addr.sa);
1514 }
1515
REGRESSION_TEST(SDK_API_TSPortDescriptor)1516 REGRESSION_TEST(SDK_API_TSPortDescriptor)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1517 {
1518 *pstatus = REGRESSION_TEST_INPROGRESS;
1519
1520 TSPortDescriptor port;
1521 char desc[64];
1522 SDK_NetVConn_Params *params = new SDK_NetVConn_Params("TSPortDescriptorAccept", test, pstatus);
1523 TSCont server_cont = TSContCreate(server_handler, TSMutexCreate());
1524 TSCont client_cont = TSContCreate(client_handler, TSMutexCreate());
1525
1526 params->port = 54321;
1527
1528 TSContDataSet(server_cont, params);
1529 TSContDataSet(client_cont, params);
1530
1531 port = TSPortDescriptorParse(nullptr);
1532 if (port) {
1533 SDK_RPRINT(test, "TSPortDescriptorParse", "NULL port descriptor", TC_FAIL, "TSPortDescriptorParse(NULL) returned %s", port);
1534 *pstatus = REGRESSION_TEST_FAILED;
1535 return;
1536 }
1537
1538 snprintf(desc, sizeof(desc), "%u", params->port);
1539 port = TSPortDescriptorParse(desc);
1540
1541 if (TSPortDescriptorAccept(port, server_cont) == TS_ERROR) {
1542 SDK_RPRINT(test, "TSPortDescriptorParse", "Basic port descriptor", TC_FAIL, "TSPortDescriptorParse(%s) returned TS_ERROR",
1543 desc);
1544 *pstatus = REGRESSION_TEST_FAILED;
1545 return;
1546 }
1547
1548 IpEndpoint addr;
1549 ats_ip4_set(&addr, htonl(INADDR_LOOPBACK), htons(params->port));
1550 TSNetConnect(client_cont, &addr.sa);
1551 }
1552
1553 /* TSCache, TSVConn, TSVIO */
1554 //////////////////////////////////////////////
1555 // SDK_API_TSCache
1556 //
1557 // Unit Test for API: TSCacheReady
1558 // TSCacheWrite
1559 // TSCacheRead
1560 // TSCacheKeyCreate
1561 // TSCacheKeyDigestSet
1562 // TSVConnCacheObjectSizeGet
1563 // TSVConnClose
1564 // TSVConnClosedGet
1565 // TSVConnRead
1566 // TSVConnReadVIOGet
1567 // TSVConnWrite
1568 // TSVConnWriteVIOGet
1569 // TSVIOBufferGet
1570 // TSVIOContGet
1571 // TSVIOMutexGet
1572 // TSVIONBytesGet
1573 // TSVIONBytesSet
1574 // TSVIONDoneGet
1575 // TSVIONDoneSet
1576 // TSVIONTodoGet
1577 // TSVIOReaderGet
1578 // TSVIOReenable
1579 // TSVIOVConnGet
1580 //////////////////////////////////////////////
1581
1582 // TSVConnAbort can't be tested
1583 // Fix me: test TSVConnShutdown, TSCacheKeyDataTypeSet,
1584 // TSCacheKeyHostNameSet, TSCacheKeyPinnedSet
1585
1586 // Logic of the test:
1587 // - write OBJECT_SIZE bytes in the cache in 3 shots
1588 // (OBJECT_SIZE/2, then OBJECT_SIZE-100 and finally OBJECT_SIZE)
1589 // - read object from the cache
1590 // - remove it from the cache
1591 // - try to read it (should fail)
1592
1593 #define OBJECT_SIZE 100000 // size of the object we'll write/read/remove in cache
1594
1595 RegressionTest *SDK_Cache_test;
1596 int *SDK_Cache_pstatus;
1597 static char content[OBJECT_SIZE];
1598 static int read_counter = 0;
1599
1600 struct CacheVConnStruct {
1601 TSIOBuffer bufp;
1602 TSIOBuffer out_bufp;
1603 TSIOBufferReader readerp;
1604 TSIOBufferReader out_readerp;
1605
1606 TSVConn write_vconnp;
1607 TSVConn read_vconnp;
1608 TSVIO read_vio;
1609 TSVIO write_vio;
1610
1611 TSCacheKey key;
1612 };
1613
1614 int
cache_handler(TSCont contp,TSEvent event,void * data)1615 cache_handler(TSCont contp, TSEvent event, void *data)
1616 {
1617 Debug("sdk_ut_cache_write", "Event %d data %p", event, data);
1618
1619 CacheVConnStruct *cache_vconn = static_cast<CacheVConnStruct *>(TSContDataGet(contp));
1620
1621 TSIOBufferBlock blockp;
1622 char *ptr_block;
1623 int64_t ntodo, ndone, nbytes, towrite, avail, content_length;
1624
1625 switch (event) {
1626 case TS_EVENT_CACHE_OPEN_WRITE:
1627 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_OPEN_WRITE %d %p", event, data);
1628 SDK_RPRINT(SDK_Cache_test, "TSCacheWrite", "TestCase1", TC_PASS, "ok");
1629
1630 // data is write_vc
1631 cache_vconn->write_vconnp = static_cast<TSVConn>(data);
1632
1633 // Create buffers/readers to write and read data into the cache
1634 cache_vconn->bufp = TSIOBufferCreate();
1635 cache_vconn->readerp = TSIOBufferReaderAlloc(cache_vconn->bufp);
1636 cache_vconn->out_bufp = TSIOBufferCreate();
1637 cache_vconn->out_readerp = TSIOBufferReaderAlloc(cache_vconn->out_bufp);
1638
1639 // Write content into upstream IOBuffer
1640 ntodo = OBJECT_SIZE;
1641 ndone = 0;
1642 while (ntodo > 0) {
1643 blockp = TSIOBufferStart(cache_vconn->bufp);
1644 ptr_block = TSIOBufferBlockWriteStart(blockp, &avail);
1645 towrite = ((ntodo < avail) ? ntodo : avail);
1646 memcpy(ptr_block, content + ndone, towrite);
1647 TSIOBufferProduce(cache_vconn->bufp, towrite);
1648 ntodo -= towrite;
1649 ndone += towrite;
1650 }
1651
1652 // first write half of the data. To test TSVIOReenable
1653 cache_vconn->write_vio = TSVConnWrite(static_cast<TSVConn>(data), contp, cache_vconn->readerp, OBJECT_SIZE / 2);
1654 return 1;
1655
1656 case TS_EVENT_CACHE_OPEN_WRITE_FAILED:
1657 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_OPEN_WRITE_FAILED %d %p", event, data);
1658 SDK_RPRINT(SDK_Cache_test, "TSCacheWrite", "TestCase1", TC_FAIL, "can't open cache vc, edtata = %p", data);
1659 TSReleaseAssert(!"cache");
1660
1661 // no need to continue, return
1662 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1663 return 1;
1664
1665 case TS_EVENT_CACHE_OPEN_READ:
1666 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_OPEN_READ %d %p", event, data);
1667 if (read_counter == 2) {
1668 SDK_RPRINT(SDK_Cache_test, "TSCacheRead", "TestCase2", TC_FAIL, "shouldn't open cache vc");
1669
1670 // no need to continue, return
1671 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1672 return 1;
1673 }
1674
1675 SDK_RPRINT(SDK_Cache_test, "TSCacheRead", "TestCase1", TC_PASS, "ok");
1676
1677 cache_vconn->read_vconnp = static_cast<TSVConn>(data);
1678 content_length = TSVConnCacheObjectSizeGet(cache_vconn->read_vconnp);
1679 Debug(UTDBG_TAG "_cache_read", "In cache open read [Content-Length: %" PRId64 "]", content_length);
1680 if (content_length != OBJECT_SIZE) {
1681 SDK_RPRINT(SDK_Cache_test, "TSVConnCacheObjectSizeGet", "TestCase1", TC_FAIL, "cached data size is incorrect");
1682
1683 // no need to continue, return
1684 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1685 return 1;
1686 } else {
1687 SDK_RPRINT(SDK_Cache_test, "TSVConnCacheObjectSizeGet", "TestCase1", TC_PASS, "ok");
1688 cache_vconn->read_vio = TSVConnRead(static_cast<TSVConn>(data), contp, cache_vconn->out_bufp, content_length);
1689 }
1690 return 1;
1691
1692 case TS_EVENT_CACHE_OPEN_READ_FAILED:
1693 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_OPEN_READ_FAILED %d %p", event, data);
1694 if (read_counter == 1) {
1695 SDK_RPRINT(SDK_Cache_test, "TSCacheRead", "TestCase1", TC_FAIL, "can't open cache vc");
1696
1697 // no need to continue, return
1698 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1699 return 1;
1700 }
1701 SDK_RPRINT(SDK_Cache_test, "TSCacheRead", "TestCase2", TC_PASS, "ok");
1702
1703 // ok, all tests passed!
1704 break;
1705
1706 case TS_EVENT_CACHE_REMOVE:
1707 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_REMOVE %d %p", event, data);
1708 SDK_RPRINT(SDK_Cache_test, "TSCacheRemove", "TestCase1", TC_PASS, "ok");
1709
1710 // read the data which has been removed
1711 read_counter++;
1712 TSCacheRead(contp, cache_vconn->key);
1713 return 1;
1714
1715 case TS_EVENT_CACHE_REMOVE_FAILED:
1716 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_CACHE_REMOVE_FAILED %d %p", event, data);
1717 SDK_RPRINT(SDK_Cache_test, "TSCacheRemove", "TestCase1", TC_FAIL, "can't remove cached item");
1718
1719 // no need to continue, return
1720 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1721 return 1;
1722
1723 case TS_EVENT_VCONN_WRITE_COMPLETE:
1724 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_VCONN_WRITE_COMPLETE %d %p", event, data);
1725
1726 // VConn/VIO APIs
1727 nbytes = TSVIONBytesGet(cache_vconn->write_vio);
1728 ndone = TSVIONDoneGet(cache_vconn->write_vio);
1729 ntodo = TSVIONTodoGet(cache_vconn->write_vio);
1730 Debug(UTDBG_TAG "_cache_write", "Nbytes=%" PRId64 " Ndone=%" PRId64 " Ntodo=%" PRId64 "", nbytes, ndone, ntodo);
1731
1732 if (ndone == (OBJECT_SIZE / 2)) {
1733 TSVIONBytesSet(cache_vconn->write_vio, (OBJECT_SIZE - 100));
1734 TSVIOReenable(cache_vconn->write_vio);
1735 Debug(UTDBG_TAG "_cache_write", "Increment write_counter in write_complete [a]");
1736 return 1;
1737 } else if (ndone == (OBJECT_SIZE - 100)) {
1738 TSVIONBytesSet(cache_vconn->write_vio, OBJECT_SIZE);
1739 TSVIOReenable(cache_vconn->write_vio);
1740 Debug(UTDBG_TAG "_cache_write", "Increment write_counter in write_complete [b]");
1741 return 1;
1742 } else if (ndone == OBJECT_SIZE) {
1743 Debug(UTDBG_TAG "_cache_write", "finishing up [c]");
1744
1745 SDK_RPRINT(SDK_Cache_test, "TSVIOReenable", "TestCase2", TC_PASS, "ok");
1746 SDK_RPRINT(SDK_Cache_test, "TSVIONBytesSet", "TestCase1", TC_PASS, "ok");
1747 SDK_RPRINT(SDK_Cache_test, "TSVConnWrite", "TestCase1", TC_PASS, "ok");
1748 } else {
1749 SDK_RPRINT(SDK_Cache_test, "TSCacheWrite", "TestCase1", TC_FAIL, "Did not write expected # of bytes");
1750 // no need to continue, return
1751 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1752 return 1;
1753 }
1754
1755 if (static_cast<TSVIO>(data) != cache_vconn->write_vio) {
1756 SDK_RPRINT(SDK_Cache_test, "TSVConnWrite", "TestCase1", TC_FAIL, "write_vio corrupted");
1757 // no need to continue, return
1758 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1759 return 1;
1760 }
1761 Debug(UTDBG_TAG "_cache_write", "finishing up [d]");
1762
1763 if (TSVIOBufferGet(cache_vconn->write_vio) != cache_vconn->bufp) {
1764 SDK_RPRINT(SDK_Cache_test, "TSVIOBufferGet", "TestCase1", TC_FAIL, "write_vio corrupted");
1765 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1766 return 1;
1767 } else {
1768 SDK_RPRINT(SDK_Cache_test, "TSVIOBufferGet", "TestCase1", TC_PASS, "ok");
1769 }
1770
1771 if (TSVIOContGet(cache_vconn->write_vio) != contp) {
1772 SDK_RPRINT(SDK_Cache_test, "TSVIOContGet", "TestCase1", TC_FAIL, "write_vio corrupted");
1773 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1774 return 1;
1775 } else {
1776 SDK_RPRINT(SDK_Cache_test, "TSVIOContGet", "TestCase1", TC_PASS, "ok");
1777 }
1778
1779 Debug(UTDBG_TAG "_cache_write", "finishing up [f]");
1780
1781 if (TSVIOMutexGet(cache_vconn->write_vio) != TSContMutexGet(contp)) {
1782 SDK_RPRINT(SDK_Cache_test, "TSVIOMutexGet", "TestCase1", TC_FAIL, "write_vio corrupted");
1783 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1784 return 1;
1785 } else {
1786 SDK_RPRINT(SDK_Cache_test, "TSVIOMutexGet", "TestCase1", TC_PASS, "ok");
1787 }
1788
1789 if (TSVIOVConnGet(cache_vconn->write_vio) != cache_vconn->write_vconnp) {
1790 SDK_RPRINT(SDK_Cache_test, "TSVIOVConnGet", "TestCase1", TC_FAIL, "write_vio corrupted");
1791 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1792 return 1;
1793 } else {
1794 SDK_RPRINT(SDK_Cache_test, "TSVIOVConnGet", "TestCase1", TC_PASS, "ok");
1795 }
1796
1797 Debug(UTDBG_TAG "_cache_write", "finishing up [g]");
1798
1799 if (TSVIOReaderGet(cache_vconn->write_vio) != cache_vconn->readerp) {
1800 SDK_RPRINT(SDK_Cache_test, "TSVIOReaderGet", "TestCase1", TC_FAIL, "write_vio corrupted");
1801 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1802 return 1;
1803 } else {
1804 SDK_RPRINT(SDK_Cache_test, "TSVIOReaderGet", "TestCase1", TC_PASS, "ok");
1805 }
1806
1807 // tests for write is done, close write_vconnp
1808 TSVConnClose(cache_vconn->write_vconnp);
1809 cache_vconn->write_vconnp = nullptr;
1810
1811 Debug(UTDBG_TAG "_cache_write", "finishing up [h]");
1812
1813 // start to read data out of cache
1814 read_counter++;
1815 TSCacheRead(contp, cache_vconn->key);
1816 Debug(UTDBG_TAG "_cache_read", "starting read [i]");
1817 return 1;
1818
1819 case TS_EVENT_VCONN_WRITE_READY:
1820 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_VCONN_WRITE_READY %d %p", event, data);
1821 if (static_cast<TSVIO>(data) != cache_vconn->write_vio) {
1822 SDK_RPRINT(SDK_Cache_test, "TSVConnWrite", "TestCase1", TC_FAIL, "write_vio corrupted");
1823 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1824 return 1;
1825 }
1826
1827 nbytes = TSVIONBytesGet(cache_vconn->write_vio);
1828 ndone = TSVIONDoneGet(cache_vconn->write_vio);
1829 ntodo = TSVIONTodoGet(cache_vconn->write_vio);
1830 Debug(UTDBG_TAG "_cache_write", "Nbytes=%" PRId64 " Ndone=%" PRId64 " Ntodo=%" PRId64 "", nbytes, ndone, ntodo);
1831
1832 TSVIOReenable(cache_vconn->write_vio);
1833 return 1;
1834
1835 case TS_EVENT_VCONN_READ_COMPLETE:
1836 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_VCONN_READ_COMPLETE %d %p", event, data);
1837 if (static_cast<TSVIO>(data) != cache_vconn->read_vio) {
1838 SDK_RPRINT(SDK_Cache_test, "TSVConnRead", "TestCase1", TC_FAIL, "read_vio corrupted");
1839
1840 // no need to continue, return
1841 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1842 return 1;
1843 }
1844
1845 nbytes = TSVIONBytesGet(cache_vconn->read_vio);
1846 ntodo = TSVIONTodoGet(cache_vconn->read_vio);
1847 ndone = TSVIONDoneGet(cache_vconn->read_vio);
1848 Debug(UTDBG_TAG "_cache_read", "Nbytes=%" PRId64 " Ndone=%" PRId64 " Ntodo=%" PRId64 "", nbytes, ndone, ntodo);
1849
1850 if (nbytes != (ndone + ntodo)) {
1851 SDK_RPRINT(SDK_Cache_test, "TSVIONBytesGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1852 SDK_RPRINT(SDK_Cache_test, "TSVIONTodoGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1853 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1854
1855 // no need to continue, return
1856 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1857 return 1;
1858 } else {
1859 SDK_RPRINT(SDK_Cache_test, "TSVIONBytesGet", "TestCase1", TC_PASS, "ok");
1860 SDK_RPRINT(SDK_Cache_test, "TSVIONTodoGet", "TestCase1", TC_PASS, "ok");
1861 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneGet", "TestCase1", TC_PASS, "ok");
1862
1863 TSVIONDoneSet(cache_vconn->read_vio, 0);
1864 if (TSVIONDoneGet(cache_vconn->read_vio) != 0) {
1865 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneSet", "TestCase1", TC_FAIL, "fail to set");
1866
1867 // no need to continue, return
1868 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1869 return 1;
1870 } else {
1871 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneSet", "TestCase1", TC_PASS, "ok");
1872 }
1873
1874 Debug(UTDBG_TAG "_cache_write", "finishing up [i]");
1875
1876 // now waiting for 100ms to make sure the key is
1877 // written in directory remove the content
1878 TSContScheduleOnPool(contp, 100, TS_THREAD_POOL_NET);
1879 }
1880
1881 return 1;
1882
1883 case TS_EVENT_VCONN_READ_READY:
1884 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_VCONN_READ_READY %d %p", event, data);
1885 if (static_cast<TSVIO>(data) != cache_vconn->read_vio) {
1886 SDK_RPRINT(SDK_Cache_test, "TSVConnRead", "TestCase1", TC_FAIL, "read_vio corrupted");
1887
1888 // no need to continue, return
1889 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1890 return 1;
1891 }
1892
1893 nbytes = TSVIONBytesGet(cache_vconn->read_vio);
1894 ntodo = TSVIONTodoGet(cache_vconn->read_vio);
1895 ndone = TSVIONDoneGet(cache_vconn->read_vio);
1896 Debug(UTDBG_TAG "_cache_read", "Nbytes=%" PRId64 " Ndone=%" PRId64 " Ntodo=%" PRId64 "", nbytes, ndone, ntodo);
1897
1898 if (nbytes != (ndone + ntodo)) {
1899 SDK_RPRINT(SDK_Cache_test, "TSVIONBytesGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1900 SDK_RPRINT(SDK_Cache_test, "TSVIONTodoGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1901 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneGet", "TestCase1", TC_FAIL, "read_vio corrupted");
1902
1903 // no need to continue, return
1904 *SDK_Cache_pstatus = REGRESSION_TEST_FAILED;
1905 return 1;
1906 } else {
1907 SDK_RPRINT(SDK_Cache_test, "TSVIONBytesGet", "TestCase1", TC_PASS, "ok");
1908 SDK_RPRINT(SDK_Cache_test, "TSVIONTodoGet", "TestCase1", TC_PASS, "ok");
1909 SDK_RPRINT(SDK_Cache_test, "TSVIONDoneGet", "TestCase1", TC_PASS, "ok");
1910 }
1911
1912 // Fix for bug INKqa12276: Must consume data from iobuffer
1913 nbytes = TSIOBufferReaderAvail(cache_vconn->out_readerp);
1914 TSIOBufferReaderConsume(cache_vconn->out_readerp, nbytes);
1915 TSDebug(UTDBG_TAG "_cache_read", "Consuming %" PRId64 " bytes from cache read VC", nbytes);
1916
1917 TSVIOReenable(cache_vconn->read_vio);
1918 Debug(UTDBG_TAG "_cache_read", "finishing up [j]");
1919 return 1;
1920
1921 case TS_EVENT_TIMEOUT:
1922 Debug(UTDBG_TAG "_cache_event", "TS_EVENT_TIMEOUT %d %p", event, data);
1923 // do remove cached doc
1924 TSCacheRemove(contp, cache_vconn->key);
1925 return 1;
1926
1927 default:
1928 TSReleaseAssert(!"Test SDK_API_TSCache: unexpected event");
1929 }
1930
1931 Debug(UTDBG_TAG "_cache_event", "DONE DONE DONE");
1932
1933 // destroy the data structure
1934 Debug(UTDBG_TAG "_cache_write", "all tests passed [z]");
1935 TSIOBufferDestroy(cache_vconn->bufp);
1936 TSIOBufferDestroy(cache_vconn->out_bufp);
1937 TSCacheKeyDestroy(cache_vconn->key);
1938 TSfree(cache_vconn);
1939 *SDK_Cache_pstatus = REGRESSION_TEST_PASSED;
1940
1941 return 1;
1942 }
1943
REGRESSION_TEST(SDK_API_TSCache)1944 REGRESSION_TEST(SDK_API_TSCache)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
1945 {
1946 *pstatus = REGRESSION_TEST_INPROGRESS;
1947 SDK_Cache_test = test;
1948 SDK_Cache_pstatus = pstatus;
1949 int is_ready = 0;
1950
1951 // Check if Cache is ready
1952 TSCacheReady(&is_ready);
1953 if (!is_ready) {
1954 SDK_RPRINT(test, "TSCacheReady", "TestCase1", TC_FAIL, "cache is not ready");
1955
1956 // no need to continue, return
1957 *pstatus = REGRESSION_TEST_FAILED;
1958 return;
1959 } else {
1960 SDK_RPRINT(test, "TSCacheReady", "TestCase1", TC_PASS, "ok");
1961 }
1962
1963 // Create CacheKey
1964 char key_name[] = "key_for_regression_test";
1965 TSCacheKey key = TSCacheKeyCreate();
1966 TSCacheKey key_cmp = TSCacheKeyCreate();
1967 SDK_RPRINT(test, "TSCacheKeyCreate", "TestCase1", TC_PASS, "ok");
1968 TSCacheKeyDigestSet(key, key_name, strlen(key_name));
1969 TSCacheKeyDigestSet(key_cmp, key_name, strlen(key_name));
1970
1971 // prepare caching content
1972 // string, null-terminated.
1973 for (int i = 0; i < (OBJECT_SIZE - 1); i++) {
1974 content[i] = 'a';
1975 }
1976 content[OBJECT_SIZE - 1] = '\0';
1977
1978 // Write data to cache.
1979 TSCont contp = TSContCreate(cache_handler, TSMutexCreate());
1980 CacheVConnStruct *cache_vconn = static_cast<CacheVConnStruct *>(TSmalloc(sizeof(CacheVConnStruct)));
1981 cache_vconn->key = key;
1982 TSContDataSet(contp, cache_vconn);
1983
1984 TSCacheWrite(contp, key);
1985 }
1986
1987 /* TSfopen */
1988
1989 //////////////////////////////////////////////
1990 // SDK_API_TSfopen
1991 //
1992 // Unit Test for API: TSfopen
1993 // TSclose
1994 // TSfflush
1995 // TSfgets
1996 // TSfread
1997 // TSfwrite
1998 //////////////////////////////////////////////
1999
2000 // Note that for each test, if it fails, we set the error status and return.
REGRESSION_TEST(SDK_API_TSfopen)2001 REGRESSION_TEST(SDK_API_TSfopen)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2002 {
2003 *pstatus = REGRESSION_TEST_INPROGRESS;
2004
2005 char write_file_name[PATH_NAME_MAX];
2006
2007 TSFile source_read_file; // existing file
2008 TSFile write_file; // to be created
2009 TSFile cmp_read_file; // read & compare
2010
2011 char input_buffer[BUFSIZ];
2012 char cmp_buffer[BUFSIZ];
2013 struct stat stat_buffer_pre, stat_buffer_post, stat_buffer_input;
2014 char *ret_val;
2015 int read = 0, wrote = 0;
2016 int64_t read_amount = 0;
2017 char input_file_full_path[BUFSIZ];
2018
2019 // Set full path to file at run time.
2020 // TODO: This can never fail since we are
2021 // returning the char[]
2022 // Better check the dir itself.
2023 //
2024 if (TSInstallDirGet() == nullptr) {
2025 *pstatus = REGRESSION_TEST_FAILED;
2026 return;
2027 }
2028 // Add "etc/trafficserver" to point to config directory
2029 ink_filepath_make(input_file_full_path, sizeof(input_file_full_path), TSConfigDirGet(), ts::filename::PLUGIN);
2030
2031 // open existing file for reading
2032 if (!(source_read_file = TSfopen(input_file_full_path, "r"))) {
2033 SDK_RPRINT(test, "TSfopen", "TestCase1", TC_FAIL, "can't open file for reading");
2034
2035 // no need to continue, return
2036 *pstatus = REGRESSION_TEST_FAILED;
2037 return;
2038 } else {
2039 SDK_RPRINT(test, "TSfopen", "TestCase1", TC_PASS, "ok");
2040 }
2041
2042 // Create unique tmp _file_name_, do not use any TS file_name
2043 snprintf(write_file_name, PATH_NAME_MAX, "/tmp/%sXXXXXX", ts::filename::PLUGIN);
2044 int write_file_fd; // this file will be reopened below
2045 if ((write_file_fd = mkstemp(write_file_name)) <= 0) {
2046 SDK_RPRINT(test, "mkstemp", "std func", TC_FAIL, "can't create file for writing");
2047
2048 // no need to continue, return
2049 *pstatus = REGRESSION_TEST_FAILED;
2050 if (source_read_file != nullptr) {
2051 TSfclose(source_read_file);
2052 }
2053 return;
2054 }
2055 close(write_file_fd);
2056
2057 // open file for writing, the file doesn't have to exist.
2058 if (!(write_file = TSfopen(write_file_name, "w"))) {
2059 SDK_RPRINT(test, "TSfopen", "TestCase2", TC_FAIL, "can't open file for writing");
2060
2061 // no need to continue, return
2062 *pstatus = REGRESSION_TEST_FAILED;
2063 if (source_read_file != nullptr) {
2064 TSfclose(source_read_file);
2065 }
2066 return;
2067 }
2068 SDK_RPRINT(test, "TSfopen", "TestCase2", TC_PASS, "ok");
2069
2070 memset(input_buffer, '\0', BUFSIZ);
2071
2072 // source_read_file and input_file_full_path are the same file
2073 if (stat(input_file_full_path, &stat_buffer_input) != 0) {
2074 SDK_RPRINT(test, "stat", "std func", TC_FAIL, "source file and input file messed up");
2075
2076 // no need to continue, return
2077 *pstatus = REGRESSION_TEST_FAILED;
2078 if (source_read_file != nullptr) {
2079 TSfclose(source_read_file);
2080 }
2081 if (write_file != nullptr) {
2082 TSfclose(write_file);
2083 }
2084 return;
2085 }
2086
2087 read_amount =
2088 (stat_buffer_input.st_size <= static_cast<off_t>(sizeof(input_buffer))) ? (stat_buffer_input.st_size) : (sizeof(input_buffer));
2089
2090 // TSfgets
2091 if ((ret_val = TSfgets(source_read_file, input_buffer, read_amount)) == nullptr) {
2092 SDK_RPRINT(test, "TSfgets", "TestCase1", TC_FAIL, "can't read from file");
2093
2094 // no need to continue, return
2095 *pstatus = REGRESSION_TEST_FAILED;
2096 if (source_read_file != nullptr) {
2097 TSfclose(source_read_file);
2098 }
2099 if (write_file != nullptr) {
2100 TSfclose(write_file);
2101 }
2102 return;
2103 } else {
2104 if (ret_val != input_buffer) {
2105 SDK_RPRINT(test, "TSfgets", "TestCase2", TC_FAIL, "reading error");
2106
2107 // no need to continue, return
2108 *pstatus = REGRESSION_TEST_FAILED;
2109 if (source_read_file != nullptr) {
2110 TSfclose(source_read_file);
2111 }
2112 if (write_file != nullptr) {
2113 TSfclose(write_file);
2114 }
2115 return;
2116 } else {
2117 SDK_RPRINT(test, "TSfgets", "TestCase1", TC_PASS, "ok");
2118 }
2119 }
2120
2121 // TSfwrite
2122 wrote = TSfwrite(write_file, input_buffer, read_amount);
2123 if (wrote != read_amount) {
2124 SDK_RPRINT(test, "TSfwrite", "TestCase1", TC_FAIL, "writing error");
2125
2126 // no need to continue, return
2127 *pstatus = REGRESSION_TEST_FAILED;
2128 if (source_read_file != nullptr) {
2129 TSfclose(source_read_file);
2130 }
2131 if (write_file != nullptr) {
2132 TSfclose(write_file);
2133 }
2134 return;
2135 }
2136
2137 SDK_RPRINT(test, "TSfwrite", "TestCase1", TC_PASS, "ok");
2138
2139 // TSfflush
2140 if (stat(write_file_name, &stat_buffer_pre) != 0) {
2141 SDK_RPRINT(test, "stat", "std func", TC_FAIL, "TSfwrite error");
2142
2143 // no need to continue, return
2144 *pstatus = REGRESSION_TEST_FAILED;
2145 if (source_read_file != nullptr) {
2146 TSfclose(source_read_file);
2147 }
2148 if (write_file != nullptr) {
2149 TSfclose(write_file);
2150 }
2151 return;
2152 }
2153
2154 TSfflush(write_file); // write_file should point to write_file_name
2155
2156 if (stat(write_file_name, &stat_buffer_post) != 0) {
2157 SDK_RPRINT(test, "stat", "std func", TC_FAIL, "TSfflush error");
2158
2159 // no need to continue, return
2160 *pstatus = REGRESSION_TEST_FAILED;
2161 if (source_read_file != nullptr) {
2162 TSfclose(source_read_file);
2163 }
2164 if (write_file != nullptr) {
2165 TSfclose(write_file);
2166 }
2167 return;
2168 }
2169
2170 if ((stat_buffer_pre.st_size == 0) && (stat_buffer_post.st_size == read_amount)) {
2171 SDK_RPRINT(test, "TSfflush", "TestCase1", TC_PASS, "ok");
2172 } else {
2173 SDK_RPRINT(test, "TSfflush", "TestCase1", TC_FAIL, "TSfflush error");
2174
2175 // no need to continue, return
2176 *pstatus = REGRESSION_TEST_FAILED;
2177 if (source_read_file != nullptr) {
2178 TSfclose(source_read_file);
2179 }
2180 if (write_file != nullptr) {
2181 TSfclose(write_file);
2182 }
2183 return;
2184 }
2185
2186 // TSfread
2187 // open again for reading
2188 cmp_read_file = TSfopen(write_file_name, "r");
2189 if (cmp_read_file == nullptr) {
2190 SDK_RPRINT(test, "TSfopen", "TestCase3", TC_FAIL, "can't open file for reading");
2191
2192 // no need to continue, return
2193 *pstatus = REGRESSION_TEST_FAILED;
2194 if (source_read_file != nullptr) {
2195 TSfclose(source_read_file);
2196 }
2197 if (write_file != nullptr) {
2198 TSfclose(write_file);
2199 }
2200 return;
2201 }
2202
2203 read_amount =
2204 (stat_buffer_input.st_size <= static_cast<off_t>(sizeof(cmp_buffer))) ? (stat_buffer_input.st_size) : (sizeof(cmp_buffer));
2205
2206 // TSfread on read file
2207 read = TSfread(cmp_read_file, cmp_buffer, read_amount);
2208 if (read != read_amount) {
2209 SDK_RPRINT(test, "TSfread", "TestCase1", TC_FAIL, "can't reading");
2210
2211 // no need to continue, return
2212 *pstatus = REGRESSION_TEST_FAILED;
2213 if (source_read_file != nullptr) {
2214 TSfclose(source_read_file);
2215 }
2216 if (write_file != nullptr) {
2217 TSfclose(write_file);
2218 }
2219 if (cmp_read_file != nullptr) {
2220 TSfclose(cmp_read_file);
2221 }
2222 return;
2223 } else {
2224 SDK_RPRINT(test, "TSfread", "TestCase1", TC_PASS, "ok");
2225 }
2226
2227 // compare input_buffer and cmp_buffer buffers
2228 if (memcmp(input_buffer, cmp_buffer, read_amount) != 0) {
2229 SDK_RPRINT(test, "TSfread", "TestCase2", TC_FAIL, "reading error");
2230
2231 // no need to continue, return
2232 *pstatus = REGRESSION_TEST_FAILED;
2233 if (source_read_file != nullptr) {
2234 TSfclose(source_read_file);
2235 }
2236 if (write_file != nullptr) {
2237 TSfclose(write_file);
2238 }
2239 if (cmp_read_file != nullptr) {
2240 TSfclose(cmp_read_file);
2241 }
2242 return;
2243 } else {
2244 SDK_RPRINT(test, "TSfread", "TestCase2", TC_PASS, "ok");
2245 }
2246
2247 // remove the tmp file
2248 if (unlink(write_file_name) != 0) {
2249 SDK_RPRINT(test, "unlink", "std func", TC_FAIL, "can't remove temp file");
2250 }
2251 // TSfclose on read file
2252 TSfclose(source_read_file);
2253 SDK_RPRINT(test, "TSfclose", "TestCase1", TC_PASS, "ok");
2254
2255 // TSfclose on write file
2256 TSfclose(write_file);
2257 SDK_RPRINT(test, "TSfclose", "TestCase2", TC_PASS, "ok");
2258
2259 *pstatus = REGRESSION_TEST_PASSED;
2260 if (cmp_read_file != nullptr) {
2261 TSfclose(cmp_read_file);
2262 }
2263 }
2264
2265 /* TSThread */
2266
2267 //////////////////////////////////////////////
2268 // SDK_API_TSThread
2269 //
2270 // Unit Test for API: TSThread
2271 // TSThreadCreate
2272 // TSThreadSelf
2273 //////////////////////////////////////////////
2274 static int thread_err_count = 0;
2275 static RegressionTest *SDK_Thread_test;
2276 static int *SDK_Thread_pstatus;
2277 static void *thread_create_handler(void *arg);
2278
2279 static void *
thread_create_handler(void *)2280 thread_create_handler(void * /* arg ATS_UNUSED */)
2281 {
2282 TSThread athread;
2283 // Fix me: do more useful work
2284 sleep(10);
2285
2286 athread = TSThreadSelf();
2287 if (athread == nullptr) {
2288 thread_err_count++;
2289 SDK_RPRINT(SDK_Thread_test, "TSThreadCreate", "TestCase2", TC_FAIL, "can't get thread");
2290 } else {
2291 SDK_RPRINT(SDK_Thread_test, "TSThreadCreate", "TestCase2", TC_PASS, "ok");
2292 }
2293
2294 if (thread_err_count > 0) {
2295 *SDK_Thread_pstatus = REGRESSION_TEST_FAILED;
2296 } else {
2297 *SDK_Thread_pstatus = REGRESSION_TEST_PASSED;
2298 }
2299
2300 return nullptr;
2301 }
2302
2303 // Fix me: Solaris threads/Win2K threads tests
2304
2305 // Argument data passed to thread init functions
2306 // cannot be allocated on the stack.
2307
REGRESSION_TEST(SDK_API_TSThread)2308 REGRESSION_TEST(SDK_API_TSThread)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2309 {
2310 *pstatus = REGRESSION_TEST_INPROGRESS;
2311 SDK_Thread_test = test;
2312 SDK_Thread_pstatus = pstatus;
2313
2314 TSThread curr_thread = nullptr;
2315 // TSThread created_thread = 0;
2316 pthread_t curr_tid;
2317
2318 curr_tid = pthread_self();
2319
2320 // TSThreadSelf
2321 curr_thread = TSThreadSelf();
2322 if (curr_thread == nullptr) {
2323 SDK_RPRINT(test, "TSThreadSelf", "TestCase1", TC_FAIL, "can't get the current thread");
2324 thread_err_count++;
2325 } else {
2326 SDK_RPRINT(test, "TSThreadSelf", "TestCase1", TC_PASS, "ok");
2327 }
2328
2329 // TSThreadCreate
2330 TSThread created_thread = TSThreadCreate(thread_create_handler, reinterpret_cast<void *>(curr_tid));
2331 if (created_thread == nullptr) {
2332 thread_err_count++;
2333 SDK_RPRINT(test, "TSThreadCreate", "TestCase1", TC_FAIL, "can't create thread");
2334 } else {
2335 SDK_RPRINT(test, "TSThreadCreate", "TestCase1", TC_PASS, "ok");
2336 }
2337
2338 if (created_thread != nullptr) {
2339 TSThreadWait(created_thread);
2340 TSThreadDestroy(created_thread);
2341 }
2342 }
2343
2344 //////////////////////////////////////////////
2345 // SDK_API_TSThread
2346 //
2347 // Unit Test for API: TSThreadInit
2348 // TSThreadDestroy
2349 //////////////////////////////////////////////
2350 static int thread_init_err_count = 0;
2351 static RegressionTest *SDK_ThreadInit_test;
2352 static int *SDK_ThreadInit_pstatus;
2353 static void *pthread_start_func(void *arg);
2354
2355 static void *
pthread_start_func(void *)2356 pthread_start_func(void * /* arg ATS_UNUSED */)
2357 {
2358 TSThread temp_thread = nullptr;
2359
2360 // TSThreadInit
2361 temp_thread = TSThreadInit();
2362
2363 if (!temp_thread) {
2364 SDK_RPRINT(SDK_ThreadInit_test, "TSThreadInit", "TestCase2", TC_FAIL, "can't init thread");
2365 thread_init_err_count++;
2366 } else {
2367 SDK_RPRINT(SDK_ThreadInit_test, "TSThreadInit", "TestCase2", TC_PASS, "ok");
2368 }
2369
2370 // Clean up this thread
2371 if (temp_thread) {
2372 TSThreadDestroy(temp_thread);
2373 }
2374
2375 if (thread_init_err_count > 0) {
2376 *SDK_ThreadInit_pstatus = REGRESSION_TEST_FAILED;
2377 } else {
2378 *SDK_ThreadInit_pstatus = REGRESSION_TEST_PASSED;
2379 }
2380
2381 return nullptr;
2382 }
2383
REGRESSION_TEST(SDK_API_TSThreadInit)2384 REGRESSION_TEST(SDK_API_TSThreadInit)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2385 {
2386 *pstatus = REGRESSION_TEST_INPROGRESS;
2387 SDK_ThreadInit_test = test;
2388 SDK_ThreadInit_pstatus = pstatus;
2389
2390 pthread_t curr_tid, new_tid;
2391
2392 curr_tid = pthread_self();
2393
2394 int ret;
2395 errno = 0;
2396 ret = pthread_create(&new_tid, nullptr, pthread_start_func, reinterpret_cast<void *>(curr_tid));
2397 if (ret != 0) {
2398 thread_init_err_count++;
2399 SDK_RPRINT(test, "TSThreadInit", "TestCase1", TC_FAIL, "can't create pthread");
2400 } else {
2401 SDK_RPRINT(test, "TSThreadInit", "TestCase1", TC_PASS, "ok");
2402 }
2403 }
2404
2405 /* Action */
2406
2407 //////////////////////////////////////////////
2408 // SDK_API_TSAction
2409 //
2410 // Unit Test for API: TSActionCancel
2411 //////////////////////////////////////////////
2412
2413 static RegressionTest *SDK_ActionCancel_test;
2414 static int *SDK_ActionCancel_pstatus;
2415
2416 int
action_cancel_handler(TSCont contp,TSEvent event,void *)2417 action_cancel_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
2418 {
2419 if (event == TS_EVENT_IMMEDIATE) { // called from schedule_imm OK
2420 SDK_RPRINT(SDK_ActionCancel_test, "TSActionCancel", "TestCase1", TC_PASS, "ok");
2421 *SDK_ActionCancel_pstatus = REGRESSION_TEST_PASSED;
2422 } else if (event == TS_EVENT_TIMEOUT) { // called from schedule_in Not OK.
2423 SDK_RPRINT(SDK_ActionCancel_test, "TSActionCancel", "TestCase1", TC_FAIL, "bad action");
2424 *SDK_ActionCancel_pstatus = REGRESSION_TEST_FAILED;
2425 } else { // there is sth wrong
2426 SDK_RPRINT(SDK_ActionCancel_test, "TSActionCancel", "TestCase1", TC_FAIL, "bad event");
2427 *SDK_ActionCancel_pstatus = REGRESSION_TEST_FAILED;
2428 }
2429
2430 TSContDestroy(contp);
2431 return 0;
2432 }
2433
REGRESSION_TEST(SDK_API_TSActionCancel)2434 REGRESSION_TEST(SDK_API_TSActionCancel)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2435 {
2436 *pstatus = REGRESSION_TEST_INPROGRESS;
2437
2438 SDK_ActionCancel_test = test;
2439 SDK_ActionCancel_pstatus = pstatus;
2440
2441 TSMutex cont_mutex = TSMutexCreate();
2442 TSCont contp = TSContCreate(action_cancel_handler, cont_mutex);
2443 TSAction actionp = TSContScheduleOnPool(contp, 10000, TS_THREAD_POOL_NET);
2444
2445 TSMutexLock(cont_mutex);
2446 if (TSActionDone(actionp)) {
2447 *pstatus = REGRESSION_TEST_FAILED;
2448 TSMutexUnlock(cont_mutex);
2449 return;
2450 } else {
2451 TSActionCancel(actionp);
2452 }
2453 TSMutexUnlock(cont_mutex);
2454
2455 TSContScheduleOnPool(contp, 0, TS_THREAD_POOL_NET);
2456 }
2457
2458 //////////////////////////////////////////////
2459 // SDK_API_TSAction
2460 //
2461 // Unit Test for API: TSActionDone
2462 //////////////////////////////////////////////
2463 /* Currently, don't know how to test it because TSAction
2464 is at "done" status only "shortly" after finish
2465 executing action_done_handler. Another possibility is
2466 to use reentrant call. But in both cases it's not
2467 guaranteed to get ActionDone.
2468 */
2469
2470 /* Continuations */
2471
2472 //////////////////////////////////////////////
2473 // SDK_API_TSCont
2474 //
2475 // Unit Test for API: TSContCreate
2476 // TSContCall
2477 //////////////////////////////////////////////
2478
2479 // this is needed for asynchronous APIs
2480 static RegressionTest *SDK_ContCreate_test;
2481 static int *SDK_ContCreate_pstatus;
2482
2483 int
cont_handler(TSCont,TSEvent,void *)2484 cont_handler(TSCont /* contp ATS_UNUSED */, TSEvent /* event ATS_UNUSED */, void * /* edata ATS_UNUSED */)
2485 {
2486 SDK_RPRINT(SDK_ContCreate_test, "TSContCreate", "TestCase1", TC_PASS, "ok");
2487 SDK_RPRINT(SDK_ContCreate_test, "TSContCall", "TestCase1", TC_PASS, "ok");
2488
2489 *SDK_ContCreate_pstatus = REGRESSION_TEST_PASSED;
2490
2491 return 0;
2492 }
2493
REGRESSION_TEST(SDK_API_TSContCreate)2494 REGRESSION_TEST(SDK_API_TSContCreate)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2495 {
2496 *pstatus = REGRESSION_TEST_INPROGRESS;
2497
2498 // For asynchronous APIs, use static vars to store test and pstatus
2499 SDK_ContCreate_test = test;
2500 SDK_ContCreate_pstatus = pstatus;
2501
2502 TSMutex mutexp = TSMutexCreate();
2503 TSCont contp = TSContCreate(cont_handler, mutexp);
2504
2505 if (TS_SUCCESS == TSMutexLockTry(mutexp)) { // Mutex is grabbed successfully
2506 TSContCall(contp, static_cast<TSEvent>(0), nullptr);
2507 TSMutexUnlock(mutexp);
2508 } else { // mutex has problems
2509 SDK_RPRINT(SDK_ContCreate_test, "TSContCreate", "TestCase1", TC_FAIL, "continuation creation has problems");
2510 SDK_RPRINT(SDK_ContCreate_test, "TSContCall", "TestCase1", TC_FAIL, "continuation has problems");
2511
2512 *pstatus = REGRESSION_TEST_FAILED;
2513 }
2514
2515 TSContDestroy(contp);
2516 }
2517
2518 //////////////////////////////////////////////
2519 // SDK_API_TSCont
2520 //
2521 // Unit Test for API: TSContDataGet
2522 // TSContDataSet
2523 //////////////////////////////////////////////
2524
2525 // this is needed for asynchronous APIs
2526 static RegressionTest *SDK_ContData_test;
2527 static int *SDK_ContData_pstatus;
2528
2529 // this is specific for this test
2530 struct MyData {
2531 int data1;
2532 int data2;
2533 };
2534
2535 int
cont_data_handler(TSCont contp,TSEvent,void *)2536 cont_data_handler(TSCont contp, TSEvent /* event ATS_UNUSED */, void * /* edata ATS_UNUSED */)
2537 {
2538 MyData *my_data = static_cast<MyData *>(TSContDataGet(contp));
2539
2540 if (my_data->data1 == 1 && my_data->data2 == 2) {
2541 SDK_RPRINT(SDK_ContData_test, "TSContDataSet", "TestCase1", TC_PASS, "ok");
2542 SDK_RPRINT(SDK_ContData_test, "TSContDataGet", "TestCase1", TC_PASS, "ok");
2543
2544 *SDK_ContData_pstatus = REGRESSION_TEST_PASSED;
2545 } else {
2546 // If we get bad data, it's a failure
2547 SDK_RPRINT(SDK_ContData_test, "TSContDataSet", "TestCase1", TC_FAIL, "bad data");
2548 SDK_RPRINT(SDK_ContData_test, "TSContDataGet", "TestCase1", TC_FAIL, "bad data");
2549
2550 *SDK_ContData_pstatus = REGRESSION_TEST_FAILED;
2551 }
2552
2553 TSfree(my_data);
2554 TSContDestroy(contp);
2555 return 0;
2556 }
2557
REGRESSION_TEST(SDK_API_TSContDataGet)2558 REGRESSION_TEST(SDK_API_TSContDataGet)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2559 {
2560 *pstatus = REGRESSION_TEST_INPROGRESS;
2561
2562 // For asynchronous APIs, use static vars to store test and pstatus
2563 SDK_ContData_test = test;
2564 SDK_ContData_pstatus = pstatus;
2565
2566 TSCont contp = TSContCreate(cont_data_handler, TSMutexCreate());
2567
2568 MyData *my_data = static_cast<MyData *>(TSmalloc(sizeof(MyData)));
2569 my_data->data1 = 1;
2570 my_data->data2 = 2;
2571
2572 TSContDataSet(contp, (void *)my_data);
2573
2574 TSContScheduleOnPool(contp, 0, TS_THREAD_POOL_NET);
2575 }
2576
2577 //////////////////////////////////////////////
2578 // SDK_API_TSCont
2579 //
2580 // Unit Test for API: TSContMutexGet
2581 //////////////////////////////////////////////
2582
REGRESSION_TEST(SDK_API_TSContMutexGet)2583 REGRESSION_TEST(SDK_API_TSContMutexGet)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2584 {
2585 bool test_passed = false;
2586 *pstatus = REGRESSION_TEST_INPROGRESS;
2587
2588 TSMutex mutexp_input;
2589 TSMutex mutexp_output;
2590 TSCont contp;
2591
2592 mutexp_input = TSMutexCreate();
2593 contp = TSContCreate(cont_handler, mutexp_input);
2594
2595 mutexp_output = TSContMutexGet(contp);
2596
2597 if (mutexp_input == mutexp_output) {
2598 SDK_RPRINT(test, "TSContMutexGet", "TestCase1", TC_PASS, "ok");
2599 test_passed = true;
2600 } else {
2601 SDK_RPRINT(test, "TSContMutexGet", "TestCase1", TC_FAIL, "Continuation's mutex corrupted");
2602 }
2603
2604 // Status of the whole test
2605 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2606
2607 TSContDestroy(contp);
2608 }
2609
2610 //////////////////////////////////////////////
2611 // SDK_API_TSCont
2612 //
2613 // Unit Test for API: TSContScheduleOnPool
2614 //////////////////////////////////////////////
2615
2616 // this is needed for asynchronous APIs
2617 static RegressionTest *SDK_ContSchedule_test;
2618 static int *SDK_ContSchedule_pstatus;
2619
2620 // this is specific for this test
2621 static int tc1_count = 0;
2622 static int tc2_count = 0;
2623
2624 int
cont_schedule_handler(TSCont contp,TSEvent event,void *)2625 cont_schedule_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
2626 {
2627 if (event == TS_EVENT_IMMEDIATE) {
2628 // Test Case 1
2629 SDK_RPRINT(SDK_ContSchedule_test, "TSContScheduleOnPool", "TestCase1", TC_PASS, "ok");
2630 tc1_count++;
2631 } else if (event == TS_EVENT_TIMEOUT) {
2632 // Test Case 2
2633 SDK_RPRINT(SDK_ContSchedule_test, "TSContScheduleOnPool", "TestCase2", TC_PASS, "ok");
2634 tc2_count++;
2635 } else {
2636 // If we receive a bad event, it's a failure
2637 SDK_RPRINT(SDK_ContSchedule_test, "TSContScheduleOnPool", "TestCase1|2", TC_FAIL, "received unexpected event number %d", event);
2638 *SDK_ContSchedule_pstatus = REGRESSION_TEST_FAILED;
2639 return 0;
2640 }
2641
2642 // We expect to be called once for TC1 and once for TC2
2643 if ((tc1_count == 1) && (tc2_count == 1)) {
2644 *SDK_ContSchedule_pstatus = REGRESSION_TEST_PASSED;
2645 }
2646 // If TC1 or TC2 executed more than once, something is fishy..
2647 else if (tc1_count + tc2_count >= 2) {
2648 *SDK_ContSchedule_pstatus = REGRESSION_TEST_FAILED;
2649 }
2650
2651 TSContDestroy(contp);
2652 return 0;
2653 }
2654
2655 /* Mutex */
2656
2657 /*
2658 Fix me: test for grabbing the mutex from two
2659 different threads.
2660 */
2661
2662 //////////////////////////////////////////////
2663 // SDK_API_TSMutex
2664 //
2665 // Unit Test for API: TSMutexCreate
2666 // TSMutexLock
2667 // TSMutexUnLock
2668 //////////////////////////////////////////////
2669
REGRESSION_TEST(SDK_API_TSMutexCreate)2670 REGRESSION_TEST(SDK_API_TSMutexCreate)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2671 {
2672 bool test_passed = false;
2673 *pstatus = REGRESSION_TEST_INPROGRESS;
2674
2675 TSMutex mutexp = TSMutexCreate();
2676
2677 TSMutexLock(mutexp);
2678
2679 /* This is normal because all locking is from the same thread */
2680 TSReturnCode lock1 = TS_ERROR;
2681 TSReturnCode lock2 = TS_ERROR;
2682
2683 lock1 = TSMutexLockTry(mutexp);
2684 lock2 = TSMutexLockTry(mutexp);
2685
2686 if (TS_SUCCESS == lock1 && TS_SUCCESS == lock2) {
2687 SDK_RPRINT(test, "TSMutexCreate", "TestCase1", TC_PASS, "ok");
2688 SDK_RPRINT(test, "TSMutexLock", "TestCase1", TC_PASS, "ok");
2689 SDK_RPRINT(test, "TSMutexLockTry", "TestCase1", TC_PASS, "ok");
2690 test_passed = true;
2691 } else {
2692 SDK_RPRINT(test, "TSMutexCreate", "TestCase1", TC_FAIL, "mutex can't be grabbed twice from the same thread");
2693 SDK_RPRINT(test, "TSMutexLock", "TestCase1", TC_FAIL, "mutex can't be grabbed twice from the same thread");
2694 SDK_RPRINT(test, "TSMutexLockTry", "TestCase1", TC_FAIL, "mutex can't be grabbed twice from the same thread");
2695 }
2696
2697 TSMutexUnlock(mutexp);
2698 SDK_RPRINT(test, "TSMutexUnLock", "TestCase1", TC_PASS, "ok");
2699
2700 if (test_passed) {
2701 *pstatus = REGRESSION_TEST_PASSED;
2702 } else {
2703 *pstatus = REGRESSION_TEST_FAILED;
2704 }
2705 }
2706
2707 /* IOBuffer */
2708
2709 //////////////////////////////////////////////
2710 // SDK_API_TSIOBuffer
2711 //
2712 // Unit Test for API: TSIOBufferCreate
2713 // TSIOBufferWaterMarkGet
2714 // TSIOBufferWaterMarkSet
2715 //////////////////////////////////////////////
2716
REGRESSION_TEST(SDK_API_TSIOBufferCreate)2717 REGRESSION_TEST(SDK_API_TSIOBufferCreate)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2718 {
2719 bool test_passed = false;
2720 *pstatus = REGRESSION_TEST_INPROGRESS;
2721
2722 int64_t watermark = 1000;
2723
2724 TSIOBuffer bufp = TSIOBufferCreate();
2725
2726 TSIOBufferWaterMarkSet(bufp, watermark);
2727 watermark = TSIOBufferWaterMarkGet(bufp);
2728
2729 if (watermark == 1000) {
2730 SDK_RPRINT(test, "TSIOBufferCreate", "TestCase1", TC_PASS, "ok");
2731 SDK_RPRINT(test, "TSIOBufferWaterMarkGet", "TestCase1", TC_PASS, "ok");
2732 SDK_RPRINT(test, "TSIOBufferWaterMarkSet", "TestCase1", TC_PASS, "ok");
2733 test_passed = true;
2734 } else {
2735 SDK_RPRINT(test, "TSIOBufferCreate", "TestCase1", TC_FAIL, "watermark failed");
2736 SDK_RPRINT(test, "TSIOBufferWaterMarkGet", "TestCase1", TC_FAIL, "watermark failed");
2737 SDK_RPRINT(test, "TSIOBufferWaterMarkSet", "TestCase1", TC_FAIL, "watermark failed");
2738 }
2739
2740 TSIOBufferDestroy(bufp);
2741
2742 // Status of the whole test
2743 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2744 return;
2745 }
2746
2747 //////////////////////////////////////////////
2748 // SDK_API_TSIOBuffer
2749 //
2750 // Unit Test for API: TSIOBufferSizedCreate
2751 // TSIOBufferProduce
2752 // TSIOBufferReaderAlloc
2753 // TSIOBufferReaderAvail
2754 //////////////////////////////////////////////
2755
REGRESSION_TEST(SDK_API_TSIOBufferProduce)2756 REGRESSION_TEST(SDK_API_TSIOBufferProduce)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2757 {
2758 bool test_passed = false;
2759 *pstatus = REGRESSION_TEST_INPROGRESS;
2760
2761 TSIOBuffer bufp = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K); // size is 4096
2762
2763 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2764
2765 TSIOBufferProduce(bufp, 10);
2766
2767 int64_t reader_avail = TSIOBufferReaderAvail(readerp);
2768 if (reader_avail == 10) {
2769 SDK_RPRINT(test, "TSIOBufferProduce", "TestCase1", TC_PASS, "ok");
2770 SDK_RPRINT(test, "TSIOBufferReaderAlloc", "TestCase1", TC_PASS, "ok");
2771 SDK_RPRINT(test, "TSIOBufferReaderAvail", "TestCase1", TC_PASS, "ok");
2772 test_passed = true;
2773 } else {
2774 SDK_RPRINT(test, "TSIOBufferProduce", "TestCase1", TC_FAIL, "failed");
2775 SDK_RPRINT(test, "TSIOBufferReaderAlloc", "TestCase1", TC_FAIL, "failed");
2776 SDK_RPRINT(test, "TSIOBufferReaderAvail", "TestCase1", TC_FAIL, "failed");
2777 }
2778
2779 // Status of the whole test
2780 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2781 return;
2782 }
2783
2784 //////////////////////////////////////////////
2785 // SDK_API_TSIOBuffer
2786 //
2787 // Unit Test for API: TSIOBufferReaderConsume
2788 //////////////////////////////////////////////
2789
REGRESSION_TEST(SDK_API_TSIOBufferReaderConsume)2790 REGRESSION_TEST(SDK_API_TSIOBufferReaderConsume)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2791 {
2792 bool test_passed = false;
2793 *pstatus = REGRESSION_TEST_INPROGRESS;
2794
2795 TSIOBuffer bufp = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K);
2796
2797 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2798
2799 TSIOBufferProduce(bufp, 10);
2800 TSIOBufferReaderConsume(readerp, 10);
2801
2802 int64_t reader_avail = TSIOBufferReaderAvail(readerp);
2803 if (reader_avail == 0) {
2804 SDK_RPRINT(test, "TSIOBufferReaderConsume", "TestCase1", TC_PASS, "ok");
2805 test_passed = true;
2806 } else {
2807 SDK_RPRINT(test, "TSIOBufferReaderConsume", "TestCase1", TC_FAIL, "failed");
2808 }
2809
2810 // Status of the whole test
2811 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2812 return;
2813 }
2814
2815 //////////////////////////////////////////////
2816 // SDK_API_TSIOBuffer
2817 //
2818 // Unit Test for API: TSIOBufferReaderClone
2819 //////////////////////////////////////////////
2820
REGRESSION_TEST(SDK_API_TSIOBufferReaderClone)2821 REGRESSION_TEST(SDK_API_TSIOBufferReaderClone)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2822 {
2823 bool test_passed = false;
2824 *pstatus = REGRESSION_TEST_INPROGRESS;
2825
2826 TSIOBuffer bufp = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K);
2827 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2828
2829 TSIOBufferProduce(bufp, 10);
2830 TSIOBufferReaderConsume(readerp, 5);
2831
2832 TSIOBufferReader readerp2 = TSIOBufferReaderClone(readerp);
2833
2834 int64_t reader_avail = TSIOBufferReaderAvail(readerp2);
2835 if (reader_avail == 5) {
2836 SDK_RPRINT(test, "TSIOBufferReaderClone", "TestCase1", TC_PASS, "ok");
2837 test_passed = true;
2838 } else {
2839 SDK_RPRINT(test, "TSIOBufferReaderClone", "TestCase1", TC_FAIL, "failed");
2840 }
2841
2842 // Status of the whole test
2843 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2844 return;
2845 }
2846
2847 //////////////////////////////////////////////
2848 // SDK_API_TSIOBuffer
2849 //
2850 // Unit Test for API: TSIOBufferStart
2851 // TSIOBufferReaderStart
2852 //////////////////////////////////////////////
2853
REGRESSION_TEST(SDK_API_TSIOBufferStart)2854 REGRESSION_TEST(SDK_API_TSIOBufferStart)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2855 {
2856 bool test_passed = false;
2857 *pstatus = REGRESSION_TEST_INPROGRESS;
2858
2859 TSIOBuffer bufp = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K);
2860
2861 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2862
2863 if (TSIOBufferStart(bufp) == TSIOBufferReaderStart(readerp)) {
2864 SDK_RPRINT(test, "TSIOBufferStart", "TestCase1", TC_PASS, "ok");
2865 SDK_RPRINT(test, "TSIOBufferReaderStart", "TestCase1", TC_PASS, "ok");
2866 test_passed = true;
2867 } else {
2868 SDK_RPRINT(test, "TSIOBufferStart", "TestCase1", TC_FAIL, "failed");
2869 SDK_RPRINT(test, "TSIOBufferReaderStart", "TestCase1", TC_FAIL, "failed");
2870 }
2871
2872 // Status of the whole test
2873 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2874 return;
2875 }
2876
2877 //////////////////////////////////////////////
2878 // SDK_API_TSIOBuffer
2879 //
2880 // Unit Test for API: TSIOBufferCopy
2881 // TSIOBufferWrite
2882 // TSIOBufferReaderCopy
2883 //////////////////////////////////////////////
2884
REGRESSION_TEST(SDK_API_TSIOBufferCopy)2885 REGRESSION_TEST(SDK_API_TSIOBufferCopy)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2886 {
2887 bool test_passed = false;
2888 *pstatus = REGRESSION_TEST_INPROGRESS;
2889
2890 char input_buf[] = "This is the test for TSIOBufferCopy, TSIOBufferWrite, TSIOBufferReaderCopy";
2891 char output_buf[1024];
2892 TSIOBuffer bufp = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K);
2893 TSIOBuffer bufp2 = TSIOBufferSizedCreate(TS_IOBUFFER_SIZE_INDEX_4K);
2894
2895 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2896 TSIOBufferWrite(bufp, input_buf, (strlen(input_buf) + 1));
2897 TSIOBufferCopy(bufp2, readerp, (strlen(input_buf) + 1), 0);
2898 TSIOBufferReaderCopy(readerp, output_buf, (strlen(input_buf) + 1));
2899
2900 if (strcmp(input_buf, output_buf) == 0) {
2901 SDK_RPRINT(test, "TSIOBufferWrite", "TestCase1", TC_PASS, "ok");
2902 SDK_RPRINT(test, "TSIOBufferCopy", "TestCase1", TC_PASS, "ok");
2903 SDK_RPRINT(test, "TSIOBufferReaderCopy", "TestCase1", TC_PASS, "ok");
2904 test_passed = true;
2905 } else {
2906 SDK_RPRINT(test, "TSIOBufferWrite", "TestCase1", TC_FAIL, "failed");
2907 SDK_RPRINT(test, "TSIOBufferCopy", "TestCase1", TC_FAIL, "failed");
2908 SDK_RPRINT(test, "TSIOBufferReaderCopy", "TestCase1", TC_FAIL, "failed");
2909 }
2910
2911 // Status of the whole test
2912 *pstatus = ((test_passed == true) ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
2913 return;
2914 }
2915
2916 //////////////////////////////////////////////
2917 // SDK_API_TSIOBuffer
2918 //
2919 // Unit Test for API: TSIOBuffer
2920 // TSIOBufferWrite
2921 // TSIOBufferReaderCopy
2922 //////////////////////////////////////////////
2923
REGRESSION_TEST(SDK_API_TSIOBufferBlockReadAvail)2924 REGRESSION_TEST(SDK_API_TSIOBufferBlockReadAvail)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2925 {
2926 bool test_passed_1 = false;
2927 bool test_passed_2 = false;
2928 *pstatus = REGRESSION_TEST_INPROGRESS;
2929
2930 int i = 10000;
2931 TSIOBuffer bufp = TSIOBufferCreate();
2932 TSIOBufferWrite(bufp, reinterpret_cast<char *>(&i), sizeof(int));
2933 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2934
2935 int64_t avail_write, avail_read;
2936
2937 // TODO: This is probably not correct any more.
2938 TSIOBufferBlock blockp = TSIOBufferStart(bufp);
2939
2940 if ((TSIOBufferBlockWriteStart(blockp, &avail_write) - TSIOBufferBlockReadStart(blockp, readerp, &avail_read)) == sizeof(int)) {
2941 SDK_RPRINT(test, "TSIOBufferBlockReadStart", "TestCase1", TC_PASS, "ok");
2942 SDK_RPRINT(test, "TSIOBufferBlockWriteStart", "TestCase1", TC_PASS, "ok");
2943 test_passed_1 = true;
2944 } else {
2945 SDK_RPRINT(test, "TSIOBufferBlockReadStart", "TestCase1", TC_FAIL, "failed");
2946 SDK_RPRINT(test, "TSIOBufferBlockWriteStart", "TestCase1", TC_FAIL, "failed");
2947 }
2948
2949 if ((TSIOBufferBlockReadAvail(blockp, readerp) + TSIOBufferBlockWriteAvail(blockp)) == 32768) {
2950 SDK_RPRINT(test, "TSIOBufferBlockReadAvail", "TestCase1", TC_PASS, "ok");
2951 SDK_RPRINT(test, "TSIOBufferBlockWriteAvail", "TestCase1", TC_PASS, "ok");
2952 test_passed_2 = true;
2953 } else {
2954 SDK_RPRINT(test, "TSIOBufferBlockReadAvail", "TestCase1", TC_FAIL, "failed");
2955 SDK_RPRINT(test, "TSIOBufferBlockWriteAvail", "TestCase1", TC_FAIL, "failed");
2956 }
2957
2958 if (test_passed_1 && test_passed_2) {
2959 *pstatus = REGRESSION_TEST_PASSED;
2960 } else {
2961 *pstatus = REGRESSION_TEST_FAILED;
2962 }
2963
2964 return;
2965 }
2966
2967 //////////////////////////////////////////////////
2968 // SDK_API_TSIOBuffer
2969 //
2970 // Unit Test for API: TSIOBufferBlockNext
2971 //////////////////////////////////////////////////
2972
REGRESSION_TEST(SDK_API_TSIOBufferBlockNext)2973 REGRESSION_TEST(SDK_API_TSIOBufferBlockNext)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
2974 {
2975 bool test_passed = false;
2976 *pstatus = REGRESSION_TEST_INPROGRESS;
2977
2978 int i = 10000;
2979 TSIOBuffer bufp = TSIOBufferCreate();
2980 TSIOBufferWrite(bufp, reinterpret_cast<char *>(&i), sizeof(int));
2981
2982 TSIOBufferReader readerp = TSIOBufferReaderAlloc(bufp);
2983 TSIOBufferBlock blockp = TSIOBufferReaderStart(readerp);
2984
2985 // TODO: This is probably not the best of regression tests right now ...
2986 // Note that this assumes block size is > sizeof(int) bytes.
2987 if (TSIOBufferBlockNext(blockp) == nullptr) {
2988 SDK_RPRINT(test, "TSIOBufferBlockNext", "TestCase1", TC_PASS, "ok");
2989 test_passed = true;
2990 } else {
2991 SDK_RPRINT(test, "TSIOBufferBlockNext", "TestCase1", TC_FAIL, "fail");
2992 }
2993
2994 if (test_passed) {
2995 *pstatus = REGRESSION_TEST_PASSED;
2996 } else {
2997 *pstatus = REGRESSION_TEST_FAILED;
2998 }
2999
3000 return;
3001 }
3002
REGRESSION_TEST(SDK_API_TSContSchedule)3003 REGRESSION_TEST(SDK_API_TSContSchedule)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
3004 {
3005 *pstatus = REGRESSION_TEST_INPROGRESS;
3006
3007 // For asynchronous APIs, use static vars to store test and pstatus
3008 SDK_ContSchedule_test = test;
3009 SDK_ContSchedule_pstatus = pstatus;
3010
3011 TSCont contp = TSContCreate(cont_schedule_handler, TSMutexCreate());
3012 TSCont contp2 = TSContCreate(cont_schedule_handler, TSMutexCreate());
3013
3014 // Test Case 1: schedule immediate
3015 TSContScheduleOnPool(contp, 0, TS_THREAD_POOL_NET);
3016
3017 // Test Case 2: schedule in 10ms
3018 TSContScheduleOnPool(contp2, 10, TS_THREAD_POOL_NET);
3019 }
3020
3021 //////////////////////////////////////////////////////////////////////////////
3022 // SDK_API_HttpHookAdd
3023 //
3024 // Unit Test for API: TSHttpHookAdd
3025 // TSHttpTxnReenable
3026 // TSHttpTxnClientIPGet
3027 // TSHttpTxnServerIPGet
3028 // TSHttpTxnIncomingAddrGet
3029 // TSHttpTxnClientAddrGet
3030 // TSHttpTxnClientReqGet
3031 // TSHttpTxnClientRespGet
3032 // TSHttpTxnServerReqGet
3033 // TSHttpTxnServerRespGet
3034 // TSHttpTxnNextHopAddrGet
3035 // TSHttpTxnClientProtocolStackGet
3036 // TSHttpTxnClientProtocolStackContains
3037 // TSHttpTxnServerSsnTransactionCount
3038 //////////////////////////////////////////////////////////////////////////////
3039
3040 #define HTTP_HOOK_TEST_REQUEST_ID 1
3041
3042 struct SocketTest {
3043 RegressionTest *regtest;
3044 int *pstatus;
3045 SocketServer *os;
3046 ClientTxn *browser;
3047 int hook_mask;
3048 int reenable_mask;
3049 bool test_client_ip_get;
3050 bool test_client_incoming_port_get;
3051 bool test_client_remote_port_get;
3052 bool test_client_req_get;
3053 bool test_client_resp_get;
3054 bool test_server_ip_get;
3055 bool test_server_req_get;
3056 bool test_server_resp_get;
3057 bool test_next_hop_ip_get;
3058 bool test_client_protocol_stack_get;
3059 bool test_client_protocol_stack_contains;
3060
3061 unsigned int magic;
3062 };
3063
3064 // This func is called by us from mytest_handler to test TSHttpTxnClientIPGet
3065 static int
checkHttpTxnClientIPGet(SocketTest * test,void * data)3066 checkHttpTxnClientIPGet(SocketTest *test, void *data)
3067 {
3068 sockaddr const *ptr;
3069 in_addr_t ip;
3070 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3071 in_addr_t actual_ip = htonl(INADDR_LOOPBACK); /* 127.0.0.1 is expected because the client is on the same machine */
3072
3073 ptr = TSHttpTxnClientAddrGet(txnp);
3074 if (ptr == nullptr || INADDR_ANY == (ip = ats_ip4_addr_cast(ptr))) {
3075 test->test_client_ip_get = false;
3076 SDK_RPRINT(test->regtest, "TSHttpTxnClientIPGet", "TestCase1", TC_FAIL, "TSHttpTxnClientIPGet returns 0 %s",
3077 ptr ? "address" : "pointer");
3078 return TS_EVENT_CONTINUE;
3079 }
3080
3081 if (ip == actual_ip) {
3082 test->test_client_ip_get = true;
3083 SDK_RPRINT(test->regtest, "TSHttpTxnClientIPGet", "TestCase1", TC_PASS, "ok [%0.8x]", ip);
3084 } else {
3085 test->test_client_ip_get = false;
3086 SDK_RPRINT(test->regtest, "TSHttpTxnClientIPGet", "TestCase1", TC_FAIL, "Value's Mismatch [expected %.8x got %.8x]", actual_ip,
3087 ip);
3088 }
3089 return TS_EVENT_CONTINUE;
3090 }
3091
3092 // This func is called by us from mytest_handler to check for TSHttpTxnClientProtocolStackGet
3093 static int
checkHttpTxnClientProtocolStackGet(SocketTest * test,void * data)3094 checkHttpTxnClientProtocolStackGet(SocketTest *test, void *data)
3095 {
3096 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3097 const char *results[10];
3098 int count = 0;
3099 TSHttpTxnClientProtocolStackGet(txnp, 10, results, &count);
3100 // Should return results[0] = "http/1.0", results[1] = "tcp", results[2] = "ipv4"
3101 test->test_client_protocol_stack_get = true;
3102 if (count != 3) {
3103 test->test_client_protocol_stack_get = false;
3104 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackGet", "TestCase1", TC_FAIL, "count should be 3 is %d", count);
3105 } else if (strcmp(results[0], "http/1.0") != 0) {
3106 test->test_client_protocol_stack_get = false;
3107 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackGet", "TestCase1", TC_FAIL, "results[0] should be http/1.0 is %s",
3108 results[0]);
3109 } else if (strcmp(results[1], "tcp") != 0) {
3110 test->test_client_protocol_stack_get = false;
3111 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackGet", "TestCase1", TC_FAIL, "results[1] should be tcp is %s",
3112 results[1]);
3113 } else if (strcmp(results[2], "ipv4") != 0) {
3114 test->test_client_protocol_stack_get = false;
3115 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackGet", "TestCase1", TC_FAIL, "results[2] should be ipv4 is %s",
3116 results[2]);
3117 } else {
3118 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackGet", "TestCase1", TC_PASS, "ok stack_size=%d", count);
3119 }
3120 return TS_EVENT_CONTINUE;
3121 }
3122
3123 // This func is called by us from mytest_handler to check for TSHttpTxnClientProtocolStackContains
3124 static int
checkHttpTxnClientProtocolStackContains(SocketTest * test,void * data)3125 checkHttpTxnClientProtocolStackContains(SocketTest *test, void *data)
3126 {
3127 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3128 const char *ret_tag = TSHttpTxnClientProtocolStackContains(txnp, "tcp");
3129 test->test_client_protocol_stack_contains = true;
3130 if (ret_tag) {
3131 const char *normalized_tag = TSNormalizedProtocolTag("tcp");
3132 if (normalized_tag != ret_tag) {
3133 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackContains", "TestCase1", TC_FAIL,
3134 "contains tcp, but normalized tag is wrong");
3135 } else {
3136 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackContains", "TestCase1", TC_PASS, "ok tcp");
3137 }
3138 } else {
3139 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackContains", "TestCase1", TC_FAIL, "missing tcp");
3140 test->test_client_protocol_stack_contains = false;
3141 }
3142 ret_tag = TSHttpTxnClientProtocolStackContains(txnp, "udp");
3143 if (!ret_tag) {
3144 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackContains", "TestCase2", TC_PASS, "ok no udp");
3145 } else {
3146 SDK_RPRINT(test->regtest, "TSHttpTxnClientProtocolStackContains", "TestCase2", TC_FAIL, "faulty udp report");
3147 test->test_client_protocol_stack_contains = false;
3148 }
3149 return TS_EVENT_CONTINUE;
3150 }
3151
3152 // This func is called by us from mytest_handler to check for TSHttpTxnNextHopIPGet
3153 static int
checkHttpTxnNextHopIPGet(SocketTest * test,void * data)3154 checkHttpTxnNextHopIPGet(SocketTest *test, void *data)
3155 {
3156 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3157 in_addr_t actual_ip = htonl(INADDR_LOOPBACK); /* 127.0.0.1 is expected because the client is on the same machine */
3158 sockaddr const *ptr;
3159 in_addr_t nexthopip;
3160
3161 ptr = TSHttpTxnNextHopAddrGet(txnp);
3162 if (ptr == nullptr || (nexthopip = ats_ip4_addr_cast(ptr)) == 0) {
3163 test->test_next_hop_ip_get = false;
3164 SDK_RPRINT(test->regtest, "TSHttpTxnNextHopIPGet", "TestCase1", TC_FAIL, "TSHttpTxnNextHopIPGet returns 0 %s",
3165 ptr ? "address" : "pointer");
3166 return TS_EVENT_CONTINUE;
3167 }
3168
3169 if (nexthopip == actual_ip) {
3170 test->test_next_hop_ip_get = true;
3171 SDK_RPRINT(test->regtest, "TSHttpTxnNextHopIPGet", "TestCase1", TC_PASS, "ok");
3172 } else {
3173 test->test_next_hop_ip_get = false;
3174 SDK_RPRINT(test->regtest, "TSHttpTxnNextHopIPGet", "TestCase1", TC_FAIL, "Value's Mismatch [expected %0.8x got %0.8x]",
3175 actual_ip, nexthopip);
3176 }
3177
3178 return TS_EVENT_CONTINUE;
3179 }
3180
3181 // This func is called by us from mytest_handler to test TSHttpTxnServerIPGet
3182 static int
checkHttpTxnServerIPGet(SocketTest * test,void * data)3183 checkHttpTxnServerIPGet(SocketTest *test, void *data)
3184 {
3185 sockaddr const *ptr;
3186 in_addr_t ip;
3187 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3188 in_addr_t actual_ip = htonl(INADDR_LOOPBACK); /* 127.0.0.1 is expected because the client is on the same machine */
3189
3190 ptr = TSHttpTxnServerAddrGet(txnp);
3191 if (nullptr == ptr || 0 == (ip = ats_ip4_addr_cast(ptr))) {
3192 test->test_server_ip_get = false;
3193 SDK_RPRINT(test->regtest, "TSHttpTxnServerIPGet", "TestCase1", TC_FAIL, "TSHttpTxnServerIPGet returns 0 %s",
3194 ptr ? "address" : "pointer");
3195 return TS_EVENT_CONTINUE;
3196 }
3197
3198 if (ip == actual_ip) {
3199 test->test_server_ip_get = true;
3200 SDK_RPRINT(test->regtest, "TSHttpTxnServerIPGet", "TestCase1", TC_PASS, "ok");
3201 } else {
3202 test->test_server_ip_get = false;
3203 SDK_RPRINT(test->regtest, "TSHttpTxnServerIPGet", "TestCase1", TC_FAIL, "Value's Mismatch");
3204 }
3205
3206 return TS_EVENT_CONTINUE;
3207 }
3208
3209 // This func is called by us from mytest_handler to test TSHttpTxnIncomingAddrGet
3210 static int
checkHttpTxnIncomingAddrGet(SocketTest * test,void * data)3211 checkHttpTxnIncomingAddrGet(SocketTest *test, void *data)
3212 {
3213 uint16_t port;
3214 const HttpProxyPort *proxy_port = HttpProxyPort::findHttp(AF_INET);
3215 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3216 sockaddr const *ptr = TSHttpTxnIncomingAddrGet(txnp);
3217
3218 if (nullptr == proxy_port) {
3219 SDK_RPRINT(test->regtest, "TSHttpTxnIncomingPortGet", "TestCase1", TC_FAIL,
3220 "TSHttpTxnIncomingAddrGet failed to find configured HTTP port.");
3221 test->test_client_incoming_port_get = false;
3222 return TS_EVENT_CONTINUE;
3223 }
3224 if (nullptr == ptr) {
3225 SDK_RPRINT(test->regtest, "TSHttpTxnIncomingPortGet", "TestCase1", TC_FAIL, "TSHttpTxnIncomingAddrGet returns 0 pointer");
3226 test->test_client_incoming_port_get = false;
3227 return TS_EVENT_CONTINUE;
3228 }
3229 port = ats_ip_port_host_order(ptr);
3230
3231 TSDebug(UTDBG_TAG, "TS HTTP port = %x, Txn incoming client port %x", proxy_port->m_port, port);
3232
3233 if (port == proxy_port->m_port) {
3234 SDK_RPRINT(test->regtest, "TSHttpTxnIncomingAddrGet", "TestCase1", TC_PASS, "ok");
3235 test->test_client_incoming_port_get = true;
3236 } else {
3237 SDK_RPRINT(test->regtest, "TSHttpTxnIncomingAddrGet", "TestCase1", TC_FAIL,
3238 "Value's Mismatch. From Function: %d Expected value: %d", port, proxy_port->m_port);
3239 test->test_client_incoming_port_get = false;
3240 }
3241 return TS_EVENT_CONTINUE;
3242 }
3243
3244 // This func is called by us from mytest_handler to test TSHttpTxnClientAddrGet
3245 static int
checkHttpTxnClientAddrGet(SocketTest * test,void * data)3246 checkHttpTxnClientAddrGet(SocketTest *test, void *data)
3247 {
3248 uint16_t port;
3249 uint16_t browser_port;
3250 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3251 sockaddr const *ptr = TSHttpTxnClientAddrGet(txnp);
3252
3253 browser_port = test->browser->local_port;
3254
3255 if (nullptr == ptr) {
3256 SDK_RPRINT(test->regtest, "TSHttpTxnClientClientAddrGet", "TestCase2", TC_FAIL, "TSHttpTxnClientAddrGet returned 0 pointer.");
3257 test->test_client_remote_port_get = false;
3258 return TS_EVENT_CONTINUE;
3259 }
3260
3261 port = ats_ip_port_host_order(ptr);
3262 TSDebug(UTDBG_TAG, "Browser port = %x, Txn remote port = %x", browser_port, port);
3263
3264 if (port == browser_port) {
3265 SDK_RPRINT(test->regtest, "TSHttpTxnClientAddrGet", "TestCase1", TC_PASS, "ok");
3266 test->test_client_remote_port_get = true;
3267 } else {
3268 SDK_RPRINT(test->regtest, "TSHttpTxnClientAddrGet", "TestCase1", TC_FAIL,
3269 "Value's Mismatch. From Function: %d Expected Value: %d", port, browser_port);
3270 test->test_client_remote_port_get = false;
3271 }
3272 return TS_EVENT_CONTINUE;
3273 }
3274
3275 // This func is called by us from mytest_handler to test TSHttpTxnClientReqGet
3276 static int
checkHttpTxnClientReqGet(SocketTest * test,void * data)3277 checkHttpTxnClientReqGet(SocketTest *test, void *data)
3278 {
3279 TSMBuffer bufp;
3280 TSMLoc mloc;
3281 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3282
3283 if (TSHttpTxnClientReqGet(txnp, &bufp, &mloc) != TS_SUCCESS) {
3284 test->test_client_req_get = false;
3285 SDK_RPRINT(test->regtest, "TSHttpTxnClientReqGet", "TestCase1", TC_FAIL, "Unable to get handle to client request");
3286 return TS_EVENT_CONTINUE;
3287 }
3288
3289 if ((bufp == reinterpret_cast<TSMBuffer>(&((HttpSM *)txnp)->t_state.hdr_info.client_request)) &&
3290 (mloc == reinterpret_cast<TSMLoc>(((HttpSM *)txnp)->t_state.hdr_info.client_request.m_http))) {
3291 test->test_client_req_get = true;
3292 SDK_RPRINT(test->regtest, "TSHttpTxnClientReqGet", "TestCase1", TC_PASS, "ok");
3293 } else {
3294 test->test_client_req_get = false;
3295 SDK_RPRINT(test->regtest, "TSHttpTxnClientReqGet", "TestCase1", TC_FAIL, "Value's Mismatch");
3296 }
3297
3298 return TS_EVENT_CONTINUE;
3299 }
3300
3301 // This func is called by us from mytest_handler to test TSHttpTxnClientRespGet
3302 static int
checkHttpTxnClientRespGet(SocketTest * test,void * data)3303 checkHttpTxnClientRespGet(SocketTest *test, void *data)
3304 {
3305 TSMBuffer bufp;
3306 TSMLoc mloc;
3307 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3308
3309 if (TSHttpTxnClientRespGet(txnp, &bufp, &mloc) != TS_SUCCESS) {
3310 test->test_client_resp_get = false;
3311 SDK_RPRINT(test->regtest, "TSHttpTxnClientRespGet", "TestCase1", TC_FAIL, "Unable to get handle to client response");
3312 return TS_EVENT_CONTINUE;
3313 }
3314
3315 if ((bufp == reinterpret_cast<TSMBuffer>(&((HttpSM *)txnp)->t_state.hdr_info.client_response)) &&
3316 (mloc == reinterpret_cast<TSMLoc>(((HttpSM *)txnp)->t_state.hdr_info.client_response.m_http))) {
3317 test->test_client_resp_get = true;
3318 SDK_RPRINT(test->regtest, "TSHttpTxnClientRespGet", "TestCase1", TC_PASS, "ok");
3319 } else {
3320 test->test_client_resp_get = false;
3321 SDK_RPRINT(test->regtest, "TSHttpTxnClientRespGet", "TestCase1", TC_FAIL, "Value's Mismatch");
3322 }
3323
3324 return TS_EVENT_CONTINUE;
3325 }
3326
3327 // This func is called by us from mytest_handler to test TSHttpTxnServerReqGet
3328 static int
checkHttpTxnServerReqGet(SocketTest * test,void * data)3329 checkHttpTxnServerReqGet(SocketTest *test, void *data)
3330 {
3331 TSMBuffer bufp;
3332 TSMLoc mloc;
3333 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3334
3335 if (TSHttpTxnServerReqGet(txnp, &bufp, &mloc) != TS_SUCCESS) {
3336 test->test_server_req_get = false;
3337 SDK_RPRINT(test->regtest, "TSHttpTxnServerReqGet", "TestCase1", TC_FAIL, "Unable to get handle to server request");
3338 return TS_EVENT_CONTINUE;
3339 }
3340
3341 if ((bufp == reinterpret_cast<TSMBuffer>(&((HttpSM *)txnp)->t_state.hdr_info.server_request)) &&
3342 (mloc == reinterpret_cast<TSMLoc>(((HttpSM *)txnp)->t_state.hdr_info.server_request.m_http))) {
3343 test->test_server_req_get = true;
3344 SDK_RPRINT(test->regtest, "TSHttpTxnServerReqGet", "TestCase1", TC_PASS, "ok");
3345 } else {
3346 test->test_server_req_get = false;
3347 SDK_RPRINT(test->regtest, "TSHttpTxnServerReqGet", "TestCase1", TC_FAIL, "Value's Mismatch");
3348 }
3349
3350 return TS_EVENT_CONTINUE;
3351 }
3352
3353 // This func is called by us from mytest_handler to test TSHttpTxnServerRespGet
3354 static int
checkHttpTxnServerRespGet(SocketTest * test,void * data)3355 checkHttpTxnServerRespGet(SocketTest *test, void *data)
3356 {
3357 TSMBuffer bufp;
3358 TSMLoc mloc;
3359 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3360
3361 if (TSHttpTxnServerRespGet(txnp, &bufp, &mloc) != TS_SUCCESS) {
3362 test->test_server_resp_get = false;
3363 SDK_RPRINT(test->regtest, "TSHttpTxnServerRespGet", "TestCase1", TC_FAIL, "Unable to get handle to server response");
3364 return TS_EVENT_CONTINUE;
3365 }
3366
3367 if ((bufp == reinterpret_cast<TSMBuffer>(&((HttpSM *)txnp)->t_state.hdr_info.server_response)) &&
3368 (mloc == reinterpret_cast<TSMLoc>(((HttpSM *)txnp)->t_state.hdr_info.server_response.m_http))) {
3369 test->test_server_resp_get = true;
3370 SDK_RPRINT(test->regtest, "TSHttpTxnServerRespGet", "TestCase1", TC_PASS, "ok");
3371 } else {
3372 test->test_server_resp_get = false;
3373 SDK_RPRINT(test->regtest, "TSHttpTxnServerRespGet", "TestCase1", TC_FAIL, "Value's Mismatch");
3374 }
3375
3376 return TS_EVENT_CONTINUE;
3377 }
3378
3379 // This func is called by us from mytest_handler to test TSHttpTxnServerSsnTransactionCount
3380 static int
checkHttpTxnServerSsnTransactionCount(SocketTest * test,void * data)3381 checkHttpTxnServerSsnTransactionCount(SocketTest *test, void *data)
3382 {
3383 TSHttpTxn txnp = static_cast<TSHttpTxn>(data);
3384
3385 int count = TSHttpTxnServerSsnTransactionCount(txnp);
3386 if (count < 0) {
3387 SDK_RPRINT(test->regtest, "TSHttpTxnServerSsnTransactionCount", "TestCase1", TC_FAIL, "invalid count value '%d'", count);
3388 } else {
3389 SDK_RPRINT(test->regtest, "TSHttpTxnServerSsnTransactionCount", "TestCase1", TC_PASS, "ok - count='%d'", count);
3390 }
3391
3392 return count;
3393 }
3394
3395 // This func is called both by us when scheduling EVENT_IMMEDIATE
3396 // And by HTTP SM for registered hooks
3397 // Depending on the timing of the DNS response, OS_DNS can happen before or after CACHE_LOOKUP.
3398 static int
mytest_handler(TSCont contp,TSEvent event,void * data)3399 mytest_handler(TSCont contp, TSEvent event, void *data)
3400 {
3401 SocketTest *test = static_cast<SocketTest *>(TSContDataGet(contp));
3402 if (test == nullptr) {
3403 if ((event == TS_EVENT_IMMEDIATE) || (event == TS_EVENT_TIMEOUT)) {
3404 return 0;
3405 }
3406 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3407 return 0;
3408 }
3409 TSAssert(test->magic == MAGIC_ALIVE);
3410 TSAssert(test->browser->magic == MAGIC_ALIVE);
3411
3412 switch (event) {
3413 case TS_EVENT_HTTP_TXN_START:
3414 if (test->hook_mask == 0) {
3415 test->hook_mask |= 1;
3416 }
3417
3418 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3419 test->reenable_mask |= 1;
3420 break;
3421
3422 case TS_EVENT_HTTP_READ_REQUEST_HDR:
3423 if (test->hook_mask == 1) {
3424 test->hook_mask |= 2;
3425 }
3426 TSSkipRemappingSet(static_cast<TSHttpTxn>(data), 1);
3427 checkHttpTxnClientReqGet(test, data);
3428
3429 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3430 test->reenable_mask |= 2;
3431 break;
3432
3433 case TS_EVENT_HTTP_OS_DNS:
3434 if (test->hook_mask == 3 || test->hook_mask == 7) {
3435 test->hook_mask |= 8;
3436 }
3437
3438 checkHttpTxnIncomingAddrGet(test, data);
3439 checkHttpTxnClientAddrGet(test, data);
3440
3441 checkHttpTxnClientIPGet(test, data);
3442 checkHttpTxnServerIPGet(test, data);
3443
3444 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3445 test->reenable_mask |= 8;
3446 break;
3447
3448 case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
3449 if (test->hook_mask == 3 || test->hook_mask == 11) {
3450 test->hook_mask |= 4;
3451 }
3452 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3453 test->reenable_mask |= 4;
3454 break;
3455
3456 case TS_EVENT_HTTP_SEND_REQUEST_HDR:
3457 if (test->hook_mask == 15) {
3458 test->hook_mask |= 16;
3459 }
3460
3461 checkHttpTxnServerReqGet(test, data);
3462 checkHttpTxnNextHopIPGet(test, data);
3463 checkHttpTxnClientProtocolStackContains(test, data);
3464 checkHttpTxnClientProtocolStackGet(test, data);
3465
3466 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3467 test->reenable_mask |= 16;
3468 break;
3469
3470 case TS_EVENT_HTTP_READ_RESPONSE_HDR:
3471 if (test->hook_mask == 31) {
3472 test->hook_mask |= 32;
3473 }
3474 checkHttpTxnServerRespGet(test, data);
3475 checkHttpTxnServerSsnTransactionCount(test, data);
3476
3477 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3478 test->reenable_mask |= 32;
3479 break;
3480
3481 case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
3482 if (test->hook_mask == 63) {
3483 test->hook_mask |= 64;
3484 }
3485
3486 checkHttpTxnClientRespGet(test, data);
3487 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3488 test->reenable_mask |= 64;
3489 break;
3490
3491 case TS_EVENT_HTTP_TXN_CLOSE:
3492 if (test->hook_mask == 127) {
3493 test->hook_mask |= 128;
3494 }
3495
3496 TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
3497 test->reenable_mask |= 128;
3498 break;
3499
3500 case TS_EVENT_IMMEDIATE:
3501 case TS_EVENT_TIMEOUT:
3502 /* Browser still waiting the response ? */
3503 if (test->browser->status == REQUEST_INPROGRESS) {
3504 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
3505 }
3506 /* Browser got the response. test is over. clean up */
3507 else {
3508 /* Note: response is available using test->browser->response pointer */
3509 if ((test->browser->status == REQUEST_SUCCESS) && (test->hook_mask == 255)) {
3510 *(test->pstatus) = REGRESSION_TEST_PASSED;
3511 SDK_RPRINT(test->regtest, "TSHttpHookAdd", "TestCase1", TC_PASS, "ok");
3512
3513 } else {
3514 *(test->pstatus) = REGRESSION_TEST_FAILED;
3515 SDK_RPRINT(test->regtest, "TSHttpHookAdd", "TestCase1", TC_FAIL, "Hooks not called or request failure. Hook mask = %d\n %s",
3516 test->hook_mask, test->browser->response);
3517 }
3518
3519 if (test->reenable_mask == 255) {
3520 SDK_RPRINT(test->regtest, "TSHttpTxnReenable", "TestCase1", TC_PASS, "ok");
3521
3522 } else {
3523 *(test->pstatus) = REGRESSION_TEST_FAILED;
3524 SDK_RPRINT(test->regtest, "TSHttpTxnReenable", "TestCase1", TC_FAIL, "Txn not re-enabled properly");
3525 }
3526
3527 if ((test->test_client_ip_get != true) || (test->test_client_incoming_port_get != true) ||
3528 (test->test_client_remote_port_get != true) || (test->test_client_req_get != true) ||
3529 (test->test_client_resp_get != true) || (test->test_server_ip_get != true) || (test->test_server_req_get != true) ||
3530 (test->test_server_resp_get != true) || (test->test_next_hop_ip_get != true)) {
3531 *(test->pstatus) = REGRESSION_TEST_FAILED;
3532 }
3533 // transaction is over. clean up.
3534 synclient_txn_delete(test->browser);
3535 synserver_delete(test->os);
3536 test->os = nullptr;
3537
3538 test->magic = MAGIC_DEAD;
3539 TSfree(test);
3540 TSContDataSet(contp, nullptr);
3541 }
3542 break;
3543
3544 default:
3545 *(test->pstatus) = REGRESSION_TEST_FAILED;
3546 SDK_RPRINT(test->regtest, "TSHttpHookAdd", "TestCase1", TC_FAIL, "Unexpected event %d", event);
3547 break;
3548 }
3549
3550 return TS_EVENT_IMMEDIATE;
3551 }
3552
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpHookAdd)3553 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpHookAdd)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
3554 {
3555 *pstatus = REGRESSION_TEST_INPROGRESS;
3556
3557 TSCont cont = TSContCreate(mytest_handler, TSMutexCreate());
3558 SocketTest *socktest = static_cast<SocketTest *>(TSmalloc(sizeof(SocketTest)));
3559
3560 socktest->regtest = test;
3561 socktest->pstatus = pstatus;
3562 socktest->hook_mask = 0;
3563 socktest->reenable_mask = 0;
3564 socktest->test_client_ip_get = false;
3565 socktest->test_client_incoming_port_get = false;
3566 socktest->test_client_req_get = false;
3567 socktest->test_client_resp_get = false;
3568 socktest->test_server_ip_get = false;
3569 socktest->test_server_req_get = false;
3570 socktest->test_server_resp_get = false;
3571 socktest->test_next_hop_ip_get = false;
3572 socktest->magic = MAGIC_ALIVE;
3573 TSContDataSet(cont, socktest);
3574
3575 /* Register to HTTP hooks that are called in case of a cache MISS */
3576 TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, cont);
3577 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
3578 TSHttpHookAdd(TS_HTTP_OS_DNS_HOOK, cont);
3579 TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont);
3580 TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, cont);
3581 TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, cont);
3582 TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont);
3583 TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, cont);
3584
3585 /* Create a new synthetic server */
3586 socktest->os = synserver_create(SYNSERVER_LISTEN_PORT);
3587 synserver_start(socktest->os);
3588
3589 /* Create a client transaction */
3590 socktest->browser = synclient_txn_create();
3591 char *request = generate_request(HTTP_HOOK_TEST_REQUEST_ID); // this request has a no-cache that prevents caching
3592 synclient_txn_send_request(socktest->browser, request);
3593 TSfree(request);
3594
3595 /* Wait until transaction is done */
3596 if (socktest->browser->status == REQUEST_INPROGRESS) {
3597 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
3598 }
3599
3600 return;
3601 }
3602
3603 //////////////////////////////////////////////
3604 // SDK_API_TSUrl
3605 //
3606 // Unit Test for API: TSUrlCreate
3607 // TSUrlSchemeGet
3608 // TSUrlSchemeSet
3609 // TSUrlUserGet
3610 // TSUrlUserSet
3611 // TSUrlPasswordGet
3612 // TSUrlPasswordSet
3613 // TSUrlHostGet
3614 // TSUrlHostSet
3615 // TSUrlPortGet
3616 // TSUrlPortSet
3617 // TSUrlPathGet
3618 // TSUrlPathSet
3619 // TSUrlHttpParamsGet
3620 // TSUrlHttpParamsSet
3621 // TSUrlHttpQueryGet
3622 // TSUrlHttpQuerySet
3623 // TSUrlHttpFragmentGet
3624 // TSUrlHttpFragmentSet
3625 // TSUrlCopy
3626 // TSUrlClone
3627 // TSUrlStringGet
3628 // TSUrlPrint
3629 // TSUrlLengthGet
3630 // TSUrlFtpTypeGet
3631 // TSUrlFtpTypeSet
3632 //////////////////////////////////////////////
3633
3634 char *
test_url_print(TSMBuffer bufp,TSMLoc hdr_loc)3635 test_url_print(TSMBuffer bufp, TSMLoc hdr_loc)
3636 {
3637 TSIOBuffer output_buffer;
3638 TSIOBufferReader reader;
3639 int64_t total_avail;
3640
3641 TSIOBufferBlock block;
3642 const char *block_start;
3643 int64_t block_avail;
3644
3645 char *output_string;
3646 int output_len;
3647
3648 output_buffer = TSIOBufferCreate();
3649
3650 if (!output_buffer) {
3651 TSError("[InkAPITest] couldn't allocate IOBuffer");
3652 }
3653
3654 reader = TSIOBufferReaderAlloc(output_buffer);
3655
3656 /* This will print just MIMEFields and not
3657 the http request line */
3658 TSUrlPrint(bufp, hdr_loc, output_buffer);
3659
3660 /* Find out how the big the complete header is by
3661 seeing the total bytes in the buffer. We need to
3662 look at the buffer rather than the first block to
3663 see the size of the entire header */
3664 total_avail = TSIOBufferReaderAvail(reader);
3665
3666 /* Allocate the string with an extra byte for the string
3667 terminator */
3668 output_string = static_cast<char *>(TSmalloc(total_avail + 1));
3669 output_len = 0;
3670
3671 /* We need to loop over all the buffer blocks to make
3672 sure we get the complete header since the header can
3673 be in multiple blocks */
3674 block = TSIOBufferReaderStart(reader);
3675 while (block) {
3676 block_start = TSIOBufferBlockReadStart(block, reader, &block_avail);
3677
3678 /* We'll get a block pointer back even if there is no data
3679 left to read so check for this condition and break out of
3680 the loop. A block with no data to read means we've exhausted
3681 buffer of data since if there was more data on a later
3682 block in the chain, this block would have been skipped over */
3683 if (block_avail == 0) {
3684 break;
3685 }
3686
3687 memcpy(output_string + output_len, block_start, block_avail);
3688 output_len += block_avail;
3689
3690 /* Consume the data so that we get to the next block */
3691 TSIOBufferReaderConsume(reader, block_avail);
3692
3693 /* Get the next block now that we've consumed the
3694 data off the last block */
3695 block = TSIOBufferReaderStart(reader);
3696 }
3697
3698 /* Terminate the string */
3699 output_string[output_len] = '\0';
3700 output_len++;
3701
3702 /* Free up the TSIOBuffer that we used to print out the header */
3703 TSIOBufferReaderFree(reader);
3704 TSIOBufferDestroy(output_buffer);
3705
3706 return output_string;
3707 }
3708
REGRESSION_TEST(SDK_API_TSUrl)3709 REGRESSION_TEST(SDK_API_TSUrl)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
3710 {
3711 TSMBuffer bufp1 = (TSMBuffer) nullptr;
3712 TSMBuffer bufp2 = (TSMBuffer) nullptr;
3713 TSMBuffer bufp3 = (TSMBuffer) nullptr;
3714 TSMLoc url_loc1;
3715 TSMLoc url_loc2;
3716 TSMLoc url_loc3;
3717 const char *scheme = TS_URL_SCHEME_HTTP;
3718 const char *scheme_get;
3719 const char *user = "yyy";
3720 const char *user_get;
3721 const char *password = "xxx";
3722 const char *password_get;
3723 const char *host = "www.example.com";
3724 const char *host_get;
3725 int port = 2021;
3726 char port_char[10];
3727 int port_get = 80;
3728 const char *path = "about/overview.html";
3729 const char *path_get;
3730 const char *params = "abcdef";
3731 const char *params_get;
3732 const char *query = "name=xxx";
3733 const char *query_get;
3734 const char *fragment = "yyy";
3735 const char *fragment_get;
3736 char *url_expected_string;
3737 char *url_string_from_1 = (char *)nullptr;
3738 char *url_string_from_2 = (char *)nullptr;
3739 char *url_string_from_3 = (char *)nullptr;
3740 char *url_string_from_print = (char *)nullptr;
3741 int url_expected_length;
3742 int url_length_from_1;
3743 int url_length_from_2;
3744 int type = 'a';
3745 int type_get;
3746 int tmp_len;
3747
3748 bool test_passed_create = false;
3749 bool test_passed_scheme = false;
3750 bool test_passed_user = false;
3751 bool test_passed_password = false;
3752 bool test_passed_host = false;
3753 bool test_passed_port = false;
3754 bool test_passed_path = false;
3755 bool test_passed_params = false;
3756 bool test_passed_query = false;
3757 bool test_passed_fragment = false;
3758 bool test_passed_copy = false;
3759 bool test_passed_clone = false;
3760 bool test_passed_string1 = false;
3761 bool test_passed_string2 = false;
3762 bool test_passed_print = false;
3763 bool test_passed_length1 = false;
3764 bool test_passed_length2 = false;
3765 bool test_passed_type = false;
3766
3767 int length;
3768
3769 *pstatus = REGRESSION_TEST_INPROGRESS;
3770
3771 // Initialization
3772 memset(port_char, 0, 10);
3773 snprintf(port_char, sizeof(port_char), "%d", port);
3774
3775 // HTTP URL
3776
3777 url_expected_length =
3778 strlen(scheme) + strlen("://") + ((user == nullptr) ? 0 : strlen(user)) +
3779 ((password == nullptr) ? ((user == nullptr) ? 0 : strlen("@")) : strlen(":") + strlen(password) + strlen("@")) + strlen(host) +
3780 ((port == 80) ? 0 : strlen(port_char) + strlen(":")) + strlen("/") + strlen(path) +
3781 ((params == nullptr) ? 0 : strlen(";") + strlen(params)) + ((query == nullptr) ? 0 : strlen("?") + strlen(query)) +
3782 ((fragment == nullptr) ? 0 : strlen("#") + strlen(fragment));
3783
3784 size_t len = url_expected_length + 1;
3785 url_expected_string = static_cast<char *>(TSmalloc(len * sizeof(char)));
3786 memset(url_expected_string, 0, url_expected_length + 1);
3787 snprintf(url_expected_string, len, "%s://%s%s%s%s%s%s%s/%s%s%s%s%s%s%s", scheme, ((user == nullptr) ? "" : user),
3788 ((password == nullptr) ? "" : ":"), ((password == nullptr) ? "" : password),
3789 (((user == nullptr) && (password == nullptr)) ? "" : "@"), host, ((port == 80) ? "" : ":"),
3790 ((port == 80) ? "" : port_char), ((path == nullptr) ? "" : path), ((params == nullptr) ? "" : ";"),
3791 ((params == nullptr) ? "" : params), ((query == nullptr) ? "" : "?"), ((query == nullptr) ? "" : query),
3792 ((fragment == nullptr) ? "" : "#"), ((fragment == nullptr) ? "" : fragment));
3793
3794 // Set Functions
3795
3796 bufp1 = TSMBufferCreate();
3797 if (TSUrlCreate(bufp1, &url_loc1) != TS_SUCCESS) {
3798 // Cannot proceed with tests.
3799 SDK_RPRINT(test, "TSUrlCreate", "TestCase1", TC_FAIL, "unable to create URL within buffer.");
3800 goto print_results;
3801 }
3802 // Scheme
3803 if (TSUrlSchemeSet(bufp1, url_loc1, scheme, -1) != TS_SUCCESS) {
3804 SDK_RPRINT(test, "TSUrlSchemeSet", "TestCase1", TC_FAIL, "TSUrlSchemeSet Returned TS_ERROR");
3805 } else {
3806 scheme_get = TSUrlSchemeGet(bufp1, url_loc1, &length);
3807 if (scheme_get != nullptr && strncmp(scheme_get, scheme, length) == 0) {
3808 SDK_RPRINT(test, "TSUrlSchemeSet&Get", "TestCase1", TC_PASS, "ok");
3809 test_passed_scheme = true;
3810 } else {
3811 SDK_RPRINT(test, "TSUrlSchemeSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3812 }
3813 }
3814
3815 // User
3816 if (TSUrlUserSet(bufp1, url_loc1, user, -1) != TS_SUCCESS) {
3817 SDK_RPRINT(test, "TSUrlUserSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3818 } else {
3819 user_get = TSUrlUserGet(bufp1, url_loc1, &length);
3820 if (user_get != nullptr && strncmp(user_get, user, length) == 0) {
3821 SDK_RPRINT(test, "TSUrlUserSet&Get", "TestCase1", TC_PASS, "ok");
3822 test_passed_user = true;
3823 } else {
3824 SDK_RPRINT(test, "TSUrlUserSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3825 }
3826 }
3827
3828 // Password
3829 if (TSUrlPasswordSet(bufp1, url_loc1, password, -1) != TS_SUCCESS) {
3830 SDK_RPRINT(test, "TSUrlPasswordSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3831 } else {
3832 password_get = TSUrlPasswordGet(bufp1, url_loc1, &length);
3833 if (password_get != nullptr && strncmp(password_get, password, length) == 0) {
3834 SDK_RPRINT(test, "TSUrlPasswordSet&Get", "TestCase1", TC_PASS, "ok");
3835 test_passed_password = true;
3836 } else {
3837 SDK_RPRINT(test, "TSUrlPasswordSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3838 }
3839 }
3840
3841 // Host
3842 if (TSUrlHostSet(bufp1, url_loc1, host, -1) != TS_SUCCESS) {
3843 SDK_RPRINT(test, "TSUrlHostSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3844 } else {
3845 host_get = TSUrlHostGet(bufp1, url_loc1, &length);
3846 if (host_get != nullptr && strncmp(host_get, host, length) == 0) {
3847 SDK_RPRINT(test, "TSUrlHostSet&Get", "TestCase1", TC_PASS, "ok");
3848 test_passed_host = true;
3849 } else {
3850 SDK_RPRINT(test, "TSUrlHostSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3851 }
3852 }
3853
3854 // Port
3855 if (TSUrlPortSet(bufp1, url_loc1, port) != TS_SUCCESS) {
3856 SDK_RPRINT(test, "TSUrlPortSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3857 } else {
3858 port_get = TSUrlPortGet(bufp1, url_loc1);
3859 if (port_get == port) {
3860 SDK_RPRINT(test, "TSUrlPortSet&Get", "TestCase1", TC_PASS, "ok");
3861 test_passed_port = true;
3862 } else {
3863 SDK_RPRINT(test, "TSUrlPortSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3864 }
3865 }
3866
3867 // Path
3868 if (TSUrlPathSet(bufp1, url_loc1, path, -1) != TS_SUCCESS) {
3869 SDK_RPRINT(test, "TSUrlPathSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3870 } else {
3871 path_get = TSUrlPathGet(bufp1, url_loc1, &length);
3872 if (path_get != nullptr && strncmp(path, path_get, length) == 0) {
3873 SDK_RPRINT(test, "TSUrlPathSet&Get", "TestCase1", TC_PASS, "ok");
3874 test_passed_path = true;
3875 } else {
3876 SDK_RPRINT(test, "TSUrlPathSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3877 }
3878 }
3879
3880 // Params
3881 if (TSUrlHttpParamsSet(bufp1, url_loc1, params, -1) != TS_SUCCESS) {
3882 SDK_RPRINT(test, "TSUrlHttpParamsSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3883 } else {
3884 params_get = TSUrlHttpParamsGet(bufp1, url_loc1, &length);
3885 if (params_get != nullptr && strncmp(params, params_get, length) == 0) {
3886 SDK_RPRINT(test, "TSUrlHttpParamsSet&Get", "TestCase1", TC_PASS, "ok");
3887 test_passed_params = true;
3888 } else {
3889 SDK_RPRINT(test, "TSUrlHttpParamsSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3890 }
3891 }
3892
3893 // Query
3894 if (TSUrlHttpQuerySet(bufp1, url_loc1, query, -1) != TS_SUCCESS) {
3895 SDK_RPRINT(test, "TSUrlHttpQuerySet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3896 } else {
3897 query_get = TSUrlHttpQueryGet(bufp1, url_loc1, &length);
3898 if (query_get != nullptr && strncmp(query, query_get, length) == 0) {
3899 SDK_RPRINT(test, "TSUrlHttpQuerySet&Get", "TestCase1", TC_PASS, "ok");
3900 test_passed_query = true;
3901 } else {
3902 SDK_RPRINT(test, "TSUrlHttpQuerySet&Get", "TestCase1", TC_FAIL, "Values don't match");
3903 }
3904 }
3905
3906 // Fragments
3907 if (TSUrlHttpFragmentSet(bufp1, url_loc1, fragment, -1) != TS_SUCCESS) {
3908 SDK_RPRINT(test, "TSUrlHttpFragmentSet", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3909 } else {
3910 fragment_get = TSUrlHttpFragmentGet(bufp1, url_loc1, &length);
3911 if (fragment_get != nullptr && strncmp(fragment, fragment_get, length) == 0) {
3912 SDK_RPRINT(test, "TSUrlHttpFragmentSet&Get", "TestCase1", TC_PASS, "ok");
3913 test_passed_fragment = true;
3914 } else {
3915 SDK_RPRINT(test, "TSUrlHttpFragmentSet&Get", "TestCase1", TC_FAIL, "Values don't match");
3916 }
3917 }
3918
3919 // Length
3920 url_length_from_1 = TSUrlLengthGet(bufp1, url_loc1);
3921 if (url_length_from_1 == url_expected_length) {
3922 SDK_RPRINT(test, "TSUrlLengthGet", "TestCase1", TC_PASS, "ok");
3923 test_passed_length1 = true;
3924 } else {
3925 SDK_RPRINT(test, "TSUrlLengthGet", "TestCase1", TC_FAIL, "Values don't match");
3926 }
3927
3928 // String
3929 url_string_from_1 = TSUrlStringGet(bufp1, url_loc1, &tmp_len);
3930 if (strcmp(url_string_from_1, url_expected_string) == 0) {
3931 SDK_RPRINT(test, "TSUrlStringGet", "TestCase1", TC_PASS, "ok");
3932 test_passed_string1 = true;
3933 } else {
3934 SDK_RPRINT(test, "TSUrlStringGet", "TestCase1", TC_FAIL, "Values don't match");
3935 }
3936
3937 // Copy
3938 bufp2 = TSMBufferCreate();
3939 if (TSUrlCreate(bufp2, &url_loc2) != TS_SUCCESS) {
3940 // Cannot proceed with tests.
3941 SDK_RPRINT(test, "TSUrlCreate", "TestCase2", TC_FAIL, "unable to create URL within buffer for TSUrlCopy.");
3942 goto print_results;
3943 }
3944 if (TSUrlCopy(bufp2, url_loc2, bufp1, url_loc1) == TS_ERROR) {
3945 SDK_RPRINT(test, "TSUrlCopy", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3946 } else {
3947 // Length Test Case 2
3948 url_length_from_2 = TSUrlLengthGet(bufp2, url_loc2);
3949 if (url_length_from_2 == url_expected_length) {
3950 SDK_RPRINT(test, "TSUrlLengthGet", "TestCase2", TC_PASS, "ok");
3951 test_passed_length2 = true;
3952 } else {
3953 SDK_RPRINT(test, "TSUrlCopy", "TestCase1", TC_FAIL, "Values don't match");
3954 }
3955
3956 // String Test Case 2
3957 url_string_from_2 = TSUrlStringGet(bufp2, url_loc2, &tmp_len);
3958 if (strcmp(url_string_from_2, url_expected_string) == 0) {
3959 SDK_RPRINT(test, "TSUrlStringGet", "TestCase2", TC_PASS, "ok");
3960 test_passed_string2 = true;
3961 } else {
3962 SDK_RPRINT(test, "TSUrlStringGet", "TestCase2", TC_FAIL, "Values don't match");
3963 }
3964
3965 // Copy Test Case
3966 if (strcmp(url_string_from_1, url_string_from_2) == 0) {
3967 SDK_RPRINT(test, "TSUrlCopy", "TestCase1", TC_PASS, "ok");
3968 test_passed_copy = true;
3969 } else {
3970 SDK_RPRINT(test, "TSUrlCopy", "TestCase1", TC_FAIL, "Values Don't Match");
3971 }
3972 }
3973
3974 // Clone
3975 bufp3 = TSMBufferCreate();
3976 if (TSUrlClone(bufp3, bufp1, url_loc1, &url_loc3) != TS_SUCCESS) {
3977 SDK_RPRINT(test, "TSUrlClone", "TestCase1", TC_FAIL, "Returned TS_ERROR");
3978 } else {
3979 // String Test Case 2
3980 url_string_from_3 = TSUrlStringGet(bufp3, url_loc3, &tmp_len);
3981 // Copy Test Case
3982 if (strcmp(url_string_from_1, url_string_from_3) == 0) {
3983 SDK_RPRINT(test, "TSUrlClone", "TestCase1", TC_PASS, "ok");
3984 test_passed_clone = true;
3985 } else {
3986 SDK_RPRINT(test, "TSUrlClone", "TestCase1", TC_FAIL, "Values Don't Match");
3987 }
3988 }
3989
3990 // UrlPrint
3991 url_string_from_print = test_url_print(bufp1, url_loc1);
3992 if (url_string_from_print == nullptr) {
3993 SDK_RPRINT(test, "TSUrlPrint", "TestCase1", TC_FAIL, "TSUrlPrint doesn't return TS_SUCCESS");
3994 } else {
3995 if (strcmp(url_string_from_print, url_expected_string) == 0) {
3996 SDK_RPRINT(test, "TSUrlPrint", "TestCase1", TC_PASS, "ok");
3997 test_passed_print = true;
3998 } else {
3999 SDK_RPRINT(test, "TSUrlPrint", "TestCase1", TC_FAIL, "TSUrlPrint doesn't return TS_SUCCESS");
4000 }
4001 TSfree(url_string_from_print);
4002 }
4003
4004 if (TSUrlFtpTypeSet(bufp1, url_loc1, type) != TS_SUCCESS) {
4005 SDK_RPRINT(test, "TSUrlFtpTypeSet", "TestCase1", TC_FAIL, "TSUrlFtpTypeSet Returned TS_ERROR");
4006 } else {
4007 type_get = TSUrlFtpTypeGet(bufp1, url_loc1);
4008 if (type_get == type) {
4009 SDK_RPRINT(test, "TSUrlFtpTypeSet&Get", "TestCase1", TC_PASS, "ok");
4010 test_passed_type = true;
4011 } else {
4012 SDK_RPRINT(test, "TSUrlFtpTypeSet&Get", "TestCase1", TC_FAIL, "Values don't match");
4013 }
4014 }
4015
4016 SDK_RPRINT(test, "TSUrlCreate", "TestCase1&2", TC_PASS, "ok");
4017 TSHandleMLocRelease(bufp1, TS_NULL_MLOC, url_loc1);
4018 TSHandleMLocRelease(bufp2, TS_NULL_MLOC, url_loc2);
4019 TSHandleMLocRelease(bufp3, TS_NULL_MLOC, url_loc3);
4020 test_passed_create = true;
4021
4022 print_results:
4023 TSfree(url_expected_string);
4024 if (url_string_from_1 != nullptr) {
4025 TSfree(url_string_from_1);
4026 }
4027 if (url_string_from_2 != nullptr) {
4028 TSfree(url_string_from_2);
4029 }
4030 if (url_string_from_3 != nullptr) {
4031 TSfree(url_string_from_3);
4032 }
4033 if (bufp1 != nullptr) {
4034 TSMBufferDestroy(bufp1);
4035 }
4036 if (bufp2 != nullptr) {
4037 TSMBufferDestroy(bufp2);
4038 }
4039 if (bufp3 != nullptr) {
4040 TSMBufferDestroy(bufp3);
4041 }
4042 if ((test_passed_create == false) || (test_passed_scheme == false) || (test_passed_user == false) ||
4043 (test_passed_password == false) || (test_passed_host == false) || (test_passed_port == false) ||
4044 (test_passed_path == false) || (test_passed_params == false) || (test_passed_query == false) ||
4045 (test_passed_fragment == false) || (test_passed_copy == false) || (test_passed_clone == false) ||
4046 (test_passed_string1 == false) || (test_passed_string2 == false) || (test_passed_print == false) ||
4047 (test_passed_length1 == false) || (test_passed_length2 == false) || (test_passed_type == false)) {
4048 /*** Debugging the test itself....
4049 (test_passed_create == false)?printf("test_passed_create is false\n"):printf("");
4050 (test_passed_destroy == false)?printf("test_passed_destroy is false\n"):printf("");
4051 (test_passed_user == false)?printf("test_passed_user is false\n"):printf("");
4052 (test_passed_password == false)?printf("test_passed_password is false\n"):printf("");
4053 (test_passed_host == false)?printf("test_passed_host is false\n"):printf("");
4054 (test_passed_port == false)?printf("test_passed_port is false\n"):printf("");
4055 (test_passed_path == false)?printf("test_passed_path is false\n"):printf("");
4056 (test_passed_params == false)?printf("test_passed_params is false\n"):printf("");
4057 (test_passed_query == false)?printf("test_passed_query is false\n"):printf("");
4058 (test_passed_fragment == false)?printf("test_passed_fragment is false\n"):printf("");
4059 (test_passed_copy == false)?printf("test_passed_copy is false\n"):printf("");
4060 (test_passed_string1 == false)?printf("test_passed_string1 is false\n"):printf("");
4061 (test_passed_string2 == false)?printf("test_passed_string2 is false\n"):printf("");
4062 (test_passed_length1 == false)?printf("test_passed_length1 is false\n"):printf("");
4063 (test_passed_length2 == false)?printf("test_passed_length2 is false\n"):printf("");
4064 (test_passed_type == false)?printf("test_passed_type is false\n"):printf("");
4065 .....***********/
4066 *pstatus = REGRESSION_TEST_FAILED;
4067 } else {
4068 *pstatus = REGRESSION_TEST_PASSED;
4069 }
4070 }
4071
4072 //////////////////////////////////////////////
4073 // SDK_API_TSHttpHdr
4074 //
4075 // Unit Test for API: TSHttpHdrCreate
4076 // TSHttpHdrCopy
4077 // TSHttpHdrClone
4078 // TSHttpHdrDestroy
4079 // TSHttpHdrLengthGet
4080 // TSHttpHdrMethodGet
4081 // TSHttpHdrMethodSet
4082 // TSHttpHdrPrint
4083 // TSHttpHdrReasonGet
4084 // TSHttpHdrReasonLookup
4085 // TSHttpHdrReasonSet
4086 // TSHttpHdrStatusGet
4087 // TSHttpHdrStatusSet
4088 // TSHttpHdrTypeGet
4089 // TSHttpHdrUrlGet
4090 // TSHttpHdrUrlSet
4091 //////////////////////////////////////////////
4092
4093 /**
4094 * If you change value of any constant in this function then reflect that change in variable expected_iobuf.
4095 */
REGRESSION_TEST(SDK_API_TSHttpHdr)4096 REGRESSION_TEST(SDK_API_TSHttpHdr)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
4097 {
4098 TSMBuffer bufp1 = (TSMBuffer) nullptr;
4099 TSMBuffer bufp2 = (TSMBuffer) nullptr;
4100 TSMBuffer bufp3 = (TSMBuffer) nullptr;
4101 TSMBuffer bufp4 = (TSMBuffer) nullptr;
4102
4103 TSMLoc hdr_loc1 = (TSMLoc) nullptr;
4104 TSMLoc hdr_loc2 = (TSMLoc) nullptr;
4105 TSMLoc hdr_loc3 = (TSMLoc) nullptr;
4106 TSMLoc hdr_loc4 = (TSMLoc) nullptr;
4107
4108 TSHttpType hdr1type;
4109 TSHttpType hdr2type;
4110
4111 const char *methodGet;
4112
4113 TSMLoc url_loc;
4114 TSMLoc url_loc_Get;
4115 const char *url_host = "www.example.com";
4116 int url_port = 2345;
4117 const char *url_path = "abcd/efg/hij.htm";
4118
4119 const char *response_reason = "aefa";
4120 const char *response_reason_get;
4121
4122 TSHttpStatus status_get;
4123
4124 int version_major = 2;
4125 int version_minor = 1;
4126 int version_get;
4127
4128 /* TSHttpType type1; unused: lv */
4129 /* TSHttpType type2; unused: lv */
4130 const char *method1;
4131 const char *method2;
4132 int length1;
4133 int length2;
4134 TSMLoc url_loc1;
4135 TSMLoc url_loc2;
4136 /* int version1; unused: lv */
4137 /* int version2; unused: lv */
4138
4139 int length;
4140 const char *expected_iobuf = "GET http://www.example.com:2345/abcd/efg/hij.htm HTTP/2.1\r\n\r\n";
4141 int actual_length;
4142 int expected_length;
4143 bool test_passed_Http_Hdr_Create = false;
4144 bool test_passed_Http_Hdr_Type = false;
4145 bool test_passed_Http_Hdr_Method = false;
4146 bool test_passed_Http_Hdr_Url = false;
4147 bool test_passed_Http_Hdr_Status = false;
4148 bool test_passed_Http_Hdr_Reason = false;
4149 bool test_passed_Http_Hdr_Reason_Lookup = false;
4150 bool test_passed_Http_Hdr_Version = false;
4151 bool test_passed_Http_Hdr_Copy = false;
4152 bool test_passed_Http_Hdr_Clone = false;
4153 bool test_passed_Http_Hdr_Length = false;
4154 bool test_passed_Http_Hdr_Print = false;
4155 bool test_passed_Http_Hdr_Destroy = false;
4156 bool try_print_function = true;
4157 bool test_buffer_created = true;
4158
4159 *pstatus = REGRESSION_TEST_INPROGRESS;
4160
4161 bufp1 = TSMBufferCreate();
4162 bufp2 = TSMBufferCreate();
4163 bufp3 = TSMBufferCreate();
4164 bufp4 = TSMBufferCreate();
4165
4166 // Create
4167 if (test_buffer_created == true) {
4168 hdr_loc1 = TSHttpHdrCreate(bufp1);
4169 hdr_loc2 = TSHttpHdrCreate(bufp2);
4170 hdr_loc3 = TSHttpHdrCreate(bufp3);
4171 SDK_RPRINT(test, "TSHttpHdrCreate", "TestCase1&2&3", TC_PASS, "ok");
4172 test_passed_Http_Hdr_Create = true;
4173 } else {
4174 SDK_RPRINT(test, "TSHttpHdrCreate", "All Test Cases", TC_FAIL, "Cannot run test as unable to allocate MBuffers");
4175 }
4176
4177 // Type
4178 if (test_passed_Http_Hdr_Create == true) {
4179 if ((TSHttpHdrTypeSet(bufp1, hdr_loc1, TS_HTTP_TYPE_REQUEST) == TS_ERROR) ||
4180 (TSHttpHdrTypeSet(bufp2, hdr_loc2, TS_HTTP_TYPE_RESPONSE) == TS_ERROR)) {
4181 SDK_RPRINT(test, "TSHttpHdrTypeSet", "TestCase1|2", TC_FAIL, "TSHttpHdrTypeSet returns TS_ERROR");
4182 } else {
4183 hdr1type = TSHttpHdrTypeGet(bufp1, hdr_loc1);
4184 hdr2type = TSHttpHdrTypeGet(bufp2, hdr_loc2);
4185 if ((hdr1type == TS_HTTP_TYPE_REQUEST) && (hdr2type == TS_HTTP_TYPE_RESPONSE)) {
4186 SDK_RPRINT(test, "TSHttpHdrTypeSet&Get", "TestCase1&2", TC_PASS, "ok");
4187 test_passed_Http_Hdr_Type = true;
4188 } else {
4189 SDK_RPRINT(test, "TSHttpHdrTypeSet&Get", "TestCase1&2", TC_FAIL, "Values mismatch");
4190 }
4191 }
4192 } else {
4193 SDK_RPRINT(test, "TSHttpHdrTypeSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header Creation Test failed");
4194 }
4195
4196 // Method
4197 if (test_passed_Http_Hdr_Type == true) {
4198 if (TSHttpHdrMethodSet(bufp1, hdr_loc1, TS_HTTP_METHOD_GET, -1) == TS_ERROR) {
4199 SDK_RPRINT(test, "TSHttpHdrMethodSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrMethodSet returns TS_ERROR");
4200 } else {
4201 methodGet = TSHttpHdrMethodGet(bufp1, hdr_loc1, &length);
4202 if ((strncmp(methodGet, TS_HTTP_METHOD_GET, length) == 0) && (length == static_cast<int>(strlen(TS_HTTP_METHOD_GET)))) {
4203 SDK_RPRINT(test, "TSHttpHdrMethodSet&Get", "TestCase1", TC_PASS, "ok");
4204 test_passed_Http_Hdr_Method = true;
4205 } else {
4206 SDK_RPRINT(test, "TSHttpHdrMethodSet&Get", "TestCase1", TC_FAIL, "Value's mismatch");
4207 }
4208 }
4209 } else {
4210 SDK_RPRINT(test, "TSHttpHdrMethodSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header's Type cannot be set");
4211 }
4212
4213 // Url
4214 if (test_passed_Http_Hdr_Type == true) {
4215 if (TSUrlCreate(bufp1, &url_loc) != TS_SUCCESS) {
4216 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "TestCase1", TC_FAIL, "Cannot run test as TSUrlCreate returns TS_ERROR");
4217 } else {
4218 if (TSHttpHdrUrlSet(bufp1, hdr_loc1, url_loc) == TS_ERROR) {
4219 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrUrlSet returns TS_ERROR");
4220 } else {
4221 if (TSHttpHdrUrlGet(bufp1, hdr_loc1, &url_loc_Get) != TS_SUCCESS) {
4222 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrUrlGet returns TS_ERROR");
4223 } else {
4224 if (url_loc == url_loc_Get) {
4225 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "TestCase1", TC_PASS, "ok");
4226 test_passed_Http_Hdr_Url = true;
4227 } else {
4228 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "TestCase1", TC_FAIL, "Value's mismatch");
4229 }
4230 if (TSHandleMLocRelease(bufp1, hdr_loc1, url_loc_Get) == TS_ERROR) {
4231 SDK_RPRINT(test, "TSHandleMLocRelease", "", TC_FAIL, "Unable to release handle to URL");
4232 }
4233 }
4234 }
4235
4236 // Fill up the URL for Copy Test Case.
4237 if (TSUrlSchemeSet(bufp1, url_loc, TS_URL_SCHEME_HTTP, -1) == TS_ERROR) {
4238 SDK_RPRINT(test, "TSUrlSchemeSet", "", TC_FAIL, "Unable to set scheme in URL in the HTTP Header");
4239 try_print_function = false;
4240 }
4241 if (TSUrlHostSet(bufp1, url_loc, url_host, -1) == TS_ERROR) {
4242 SDK_RPRINT(test, "TSUrlHostSet", "", TC_FAIL, "Unable to set host in URL in the HTTP Header");
4243 try_print_function = false;
4244 }
4245 if (TSUrlPortSet(bufp1, url_loc, url_port) == TS_ERROR) {
4246 SDK_RPRINT(test, "TSUrlPortSet", "", TC_FAIL, "Unable to set port in URL in the HTTP Header");
4247 try_print_function = false;
4248 }
4249 if (TSUrlPathSet(bufp1, url_loc, url_path, -1) == TS_ERROR) {
4250 SDK_RPRINT(test, "TSUrlPathSet", "", TC_FAIL, "Unable to set path in URL in the HTTP Header");
4251 try_print_function = false;
4252 }
4253 if (TSHandleMLocRelease(bufp1, hdr_loc1, url_loc) == TS_ERROR) {
4254 SDK_RPRINT(test, "TSHandleMLocRelease", "", TC_FAIL, "Unable to release handle to URL");
4255 }
4256 }
4257 } else {
4258 SDK_RPRINT(test, "TSHttpHdrUrlSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header's Type cannot be set");
4259 }
4260
4261 // Reason
4262 if (test_passed_Http_Hdr_Type == true) {
4263 if (TSHttpHdrReasonSet(bufp2, hdr_loc2, response_reason, -1) == TS_ERROR) {
4264 SDK_RPRINT(test, "TSHttpHdrReasonSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrReasonSet returns TS_ERROR");
4265 } else {
4266 response_reason_get = TSHttpHdrReasonGet(bufp2, hdr_loc2, &length);
4267 if ((strncmp(response_reason_get, response_reason, length) == 0) && (length == static_cast<int>(strlen(response_reason)))) {
4268 SDK_RPRINT(test, "TSHttpHdrReasonSet&Get", "TestCase1", TC_PASS, "ok");
4269 test_passed_Http_Hdr_Reason = true;
4270 } else {
4271 SDK_RPRINT(test, "TSHttpHdrReasonSet&Get", "TestCase1", TC_FAIL, "Value's mismatch");
4272 }
4273 }
4274 } else {
4275 SDK_RPRINT(test, "TSHttpHdrReasonSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header's Type cannot be set");
4276 }
4277
4278 // Status
4279 if (test_passed_Http_Hdr_Type == true) {
4280 if (TSHttpHdrStatusSet(bufp2, hdr_loc2, TS_HTTP_STATUS_OK) == TS_ERROR) {
4281 SDK_RPRINT(test, "TSHttpHdrStatusSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrStatusSet returns TS_ERROR");
4282 } else {
4283 status_get = TSHttpHdrStatusGet(bufp2, hdr_loc2);
4284 if (status_get == TS_HTTP_STATUS_OK) {
4285 SDK_RPRINT(test, "TSHttpHdrStatusSet&Get", "TestCase1", TC_PASS, "ok");
4286 test_passed_Http_Hdr_Status = true;
4287 } else {
4288 SDK_RPRINT(test, "TSHttpHdrStatusSet&Get", "TestCase1", TC_FAIL, "Value's mismatch");
4289 }
4290 }
4291 } else {
4292 SDK_RPRINT(test, "TSHttpHdrStatusSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header's Type cannot be set");
4293 }
4294
4295 // Version
4296 if (test_passed_Http_Hdr_Type == true) {
4297 if (TSHttpHdrVersionSet(bufp1, hdr_loc1, TS_HTTP_VERSION(version_major, version_minor)) == TS_ERROR) {
4298 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase1", TC_FAIL, "TSHttpHdrVersionSet returns TS_ERROR");
4299 } else {
4300 version_get = TSHttpHdrVersionGet(bufp1, hdr_loc1);
4301 if ((version_major == TS_HTTP_MAJOR(version_get)) && (version_minor == TS_HTTP_MINOR(version_get))) {
4302 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase1", TC_PASS, "ok");
4303 test_passed_Http_Hdr_Version = true;
4304 } else {
4305 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase1", TC_FAIL, "Value's mismatch");
4306 }
4307 }
4308 } else {
4309 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "All Test Case", TC_FAIL, "Cannot run test as Header's Type cannot be set");
4310 }
4311
4312 if (test_passed_Http_Hdr_Version == true) {
4313 if (TSHttpHdrVersionSet(bufp2, hdr_loc2, TS_HTTP_VERSION(version_major, version_minor)) == TS_ERROR) {
4314 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase2", TC_FAIL, "TSHttpHdrVersionSet returns TS_ERROR");
4315 test_passed_Http_Hdr_Version = false;
4316 } else {
4317 version_get = TSHttpHdrVersionGet(bufp2, hdr_loc2);
4318 if ((version_major == TS_HTTP_MAJOR(version_get)) && (version_minor == TS_HTTP_MINOR(version_get))) {
4319 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase2", TC_PASS, "ok");
4320 } else {
4321 SDK_RPRINT(test, "TSHttpHdrVersionSet&Get", "TestCase2", TC_FAIL, "Value's mismatch");
4322 test_passed_Http_Hdr_Version = false;
4323 }
4324 }
4325 }
4326 // Reason Lookup
4327 if (strcmp("None", TSHttpHdrReasonLookup(TS_HTTP_STATUS_NONE)) != 0) {
4328 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase1", TC_FAIL, "TSHttpHdrReasonLookup returns Value's mismatch");
4329 } else {
4330 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase1", TC_PASS, "ok");
4331 test_passed_Http_Hdr_Reason_Lookup = true;
4332 }
4333
4334 if (strcmp("OK", TSHttpHdrReasonLookup(TS_HTTP_STATUS_OK)) != 0) {
4335 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase2", TC_FAIL, "TSHttpHdrReasonLookup returns Value's mismatch");
4336 if (test_passed_Http_Hdr_Reason_Lookup == true) {
4337 test_passed_Http_Hdr_Reason_Lookup = false;
4338 }
4339 } else {
4340 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase2", TC_PASS, "ok");
4341 }
4342
4343 if (strcmp("Continue", TSHttpHdrReasonLookup(TS_HTTP_STATUS_CONTINUE)) != 0) {
4344 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase3", TC_FAIL, "TSHttpHdrReasonLookup returns Value's mismatch");
4345 if (test_passed_Http_Hdr_Reason_Lookup == true) {
4346 test_passed_Http_Hdr_Reason_Lookup = false;
4347 }
4348 } else {
4349 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase3", TC_PASS, "ok");
4350 }
4351
4352 if (strcmp("Not Modified", TSHttpHdrReasonLookup(TS_HTTP_STATUS_NOT_MODIFIED)) != 0) {
4353 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase4", TC_FAIL, "TSHttpHdrReasonLookup returns Value's mismatch");
4354 if (test_passed_Http_Hdr_Reason_Lookup == true) {
4355 test_passed_Http_Hdr_Reason_Lookup = false;
4356 }
4357 } else {
4358 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase4", TC_PASS, "ok");
4359 }
4360
4361 if (strcmp("Early Hints", TSHttpHdrReasonLookup(TS_HTTP_STATUS_EARLY_HINTS)) != 0) {
4362 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase5", TC_FAIL, "TSHttpHdrReasonLookup returns Value's mismatch");
4363 if (test_passed_Http_Hdr_Reason_Lookup == true) {
4364 test_passed_Http_Hdr_Reason_Lookup = false;
4365 }
4366 } else {
4367 SDK_RPRINT(test, "TSHttpHdrReasonLookup", "TestCase5", TC_PASS, "ok");
4368 }
4369
4370 // Copy
4371 if (test_passed_Http_Hdr_Create == true) {
4372 if (TSHttpHdrCopy(bufp3, hdr_loc3, bufp1, hdr_loc1) == TS_ERROR) {
4373 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "TSHttpHdrCopy returns TS_ERROR");
4374 } else {
4375 bool flag = true;
4376 // Check the type
4377 if (flag == true) {
4378 TSHttpType type1 = TSHttpHdrTypeGet(bufp1, hdr_loc1);
4379 TSHttpType type2 = TSHttpHdrTypeGet(bufp3, hdr_loc3);
4380
4381 if (type1 != type2) {
4382 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Type mismatch in both headers");
4383 flag = false;
4384 }
4385 }
4386 // Check the Version
4387 if (flag == true) {
4388 int version1 = TSHttpHdrVersionGet(bufp1, hdr_loc1);
4389 int version2 = TSHttpHdrVersionGet(bufp3, hdr_loc3);
4390
4391 if (version1 != version2) {
4392 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Version mismatch in both headers");
4393 flag = false;
4394 }
4395 }
4396 // Check the Method
4397 if (flag == true) {
4398 method1 = TSHttpHdrMethodGet(bufp1, hdr_loc1, &length1);
4399 method2 = TSHttpHdrMethodGet(bufp3, hdr_loc3, &length2);
4400 if ((length1 != length2) || (strncmp(method1, method2, length1) != 0)) {
4401 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Method mismatch in both headers");
4402 flag = false;
4403 }
4404 }
4405 // Check the URL
4406 if (flag == true) {
4407 if ((TSHttpHdrUrlGet(bufp1, hdr_loc1, &url_loc1) != TS_SUCCESS) ||
4408 (TSHttpHdrUrlGet(bufp3, hdr_loc3, &url_loc2) != TS_SUCCESS)) {
4409 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "TSHttpVersionGet returns TS_ERROR");
4410 } else {
4411 const char *scheme1;
4412 const char *scheme2;
4413
4414 const char *host1;
4415 const char *host2;
4416
4417 int port1;
4418 int port2;
4419
4420 const char *path1;
4421 const char *path2;
4422
4423 // URL Scheme
4424 scheme1 = TSUrlSchemeGet(bufp1, url_loc1, &length1);
4425 scheme2 = TSUrlSchemeGet(bufp3, url_loc2, &length2);
4426 if ((length1 != length2) || (strncmp(scheme1, scheme2, length1) != 0)) {
4427 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Scheme has different values in both headers");
4428 flag = false;
4429 }
4430
4431 // URL Host
4432 if (flag == true) {
4433 host1 = TSUrlHostGet(bufp1, url_loc1, &length1);
4434 host2 = TSUrlHostGet(bufp3, url_loc2, &length2);
4435 if ((length1 != length2) || (strncmp(host1, host2, length1) != 0)) {
4436 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Host has different values in both headers");
4437 flag = false;
4438 }
4439 }
4440 // URL Port
4441 if (flag == true) {
4442 port1 = TSUrlPortGet(bufp1, url_loc1);
4443 port2 = TSUrlPortGet(bufp3, url_loc2);
4444 if (port1 != port2) {
4445 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Port has different values in both headers");
4446 flag = false;
4447 }
4448 }
4449 // URL Path
4450 if (flag == true) {
4451 path1 = TSUrlPathGet(bufp1, url_loc1, &length1);
4452 path2 = TSUrlPathGet(bufp3, url_loc2, &length2);
4453 if ((path1 != nullptr) && (path2 != nullptr)) {
4454 if ((length1 != length2) || (strncmp(path1, path2, length1) != 0)) {
4455 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Path has different values in both headers");
4456 flag = false;
4457 }
4458 } else {
4459 if (path1 != path2) {
4460 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Host has different values in both headers");
4461 flag = false;
4462 }
4463 }
4464 if ((TSHandleMLocRelease(bufp1, hdr_loc1, url_loc1) == TS_ERROR) ||
4465 (TSHandleMLocRelease(bufp3, hdr_loc3, url_loc2) == TS_ERROR)) {
4466 SDK_RPRINT(test, "TSHandleMLocRelease", "", TC_FAIL, "Unable to release Handle acquired by TSHttpHdrUrlGet");
4467 }
4468 }
4469
4470 if (flag == true) {
4471 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_PASS, "ok");
4472 test_passed_Http_Hdr_Copy = true;
4473 }
4474 }
4475 }
4476 }
4477 } else {
4478 SDK_RPRINT(test, "TSHttpHdrCopy", "All Test Cases", TC_PASS, "Cannot run test as TSHttpHdrCreate has failed");
4479 }
4480
4481 // Clone
4482 if (test_passed_Http_Hdr_Create == true) {
4483 if (TSHttpHdrClone(bufp4, bufp1, hdr_loc1, &hdr_loc4) != TS_SUCCESS) {
4484 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "TSHttpHdrClone returns TS_ERROR");
4485 } else {
4486 bool flag = true;
4487 // Check the type
4488 if (flag == true) {
4489 TSHttpType type1 = TSHttpHdrTypeGet(bufp1, hdr_loc1);
4490 TSHttpType type2 = TSHttpHdrTypeGet(bufp4, hdr_loc4);
4491
4492 if (type1 != type2) {
4493 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Type mismatch in both headers");
4494 flag = false;
4495 }
4496 }
4497 // Check the Version
4498 if (flag == true) {
4499 int version1 = TSHttpHdrVersionGet(bufp1, hdr_loc1);
4500 int version2 = TSHttpHdrVersionGet(bufp4, hdr_loc4);
4501
4502 if (version1 != version2) {
4503 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Version mismatch in both headers");
4504 flag = false;
4505 }
4506 }
4507 // Check the Method
4508 if (flag == true) {
4509 method1 = TSHttpHdrMethodGet(bufp1, hdr_loc1, &length1);
4510 method2 = TSHttpHdrMethodGet(bufp4, hdr_loc4, &length2);
4511 if ((length1 != length2) || (strncmp(method1, method2, length1) != 0)) {
4512 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Method mismatch in both headers");
4513 flag = false;
4514 }
4515 }
4516 // Check the URL
4517 if (flag == true) {
4518 if ((TSHttpHdrUrlGet(bufp1, hdr_loc1, &url_loc1) != TS_SUCCESS) ||
4519 (TSHttpHdrUrlGet(bufp4, hdr_loc4, &url_loc2) != TS_SUCCESS)) {
4520 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "TSHttpVersionGet returns TS_ERROR");
4521 } else {
4522 const char *scheme1;
4523 const char *scheme2;
4524
4525 const char *host1;
4526 const char *host2;
4527
4528 int port1;
4529 int port2;
4530
4531 const char *path1;
4532 const char *path2;
4533
4534 // URL Scheme
4535 scheme1 = TSUrlSchemeGet(bufp1, url_loc1, &length1);
4536 scheme2 = TSUrlSchemeGet(bufp4, url_loc2, &length2);
4537 if ((length1 != length2) || (strncmp(scheme1, scheme2, length1) != 0)) {
4538 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Url Scheme has different values in both headers");
4539 flag = false;
4540 }
4541
4542 // URL Host
4543 if (flag == true) {
4544 host1 = TSUrlHostGet(bufp1, url_loc1, &length1);
4545 host2 = TSUrlHostGet(bufp4, url_loc2, &length2);
4546 if ((length1 != length2) || (strncmp(host1, host2, length1) != 0)) {
4547 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Url Host has different values in both headers");
4548 flag = false;
4549 }
4550 }
4551 // URL Port
4552 if (flag == true) {
4553 port1 = TSUrlPortGet(bufp1, url_loc1);
4554 port2 = TSUrlPortGet(bufp4, url_loc2);
4555 if (port1 != port2) {
4556 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_FAIL, "Url Port has different values in both headers");
4557 flag = false;
4558 }
4559 }
4560 // URL Path
4561 if (flag == true) {
4562 path1 = TSUrlPathGet(bufp1, url_loc1, &length1);
4563 path2 = TSUrlPathGet(bufp4, url_loc2, &length2);
4564 if ((path1 != nullptr) && (path2 != nullptr)) {
4565 if ((length1 != length2) || (strncmp(path1, path2, length1) != 0)) {
4566 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Path has different values in both headers");
4567 flag = false;
4568 }
4569 } else {
4570 if (path1 != path2) {
4571 SDK_RPRINT(test, "TSHttpHdrCopy", "TestCase1", TC_FAIL, "Url Host has different values in both headers");
4572 flag = false;
4573 }
4574 }
4575 if ((TSHandleMLocRelease(bufp1, hdr_loc1, url_loc1) == TS_ERROR) ||
4576 (TSHandleMLocRelease(bufp4, hdr_loc4, url_loc2) == TS_ERROR)) {
4577 SDK_RPRINT(test, "TSHandleMLocRelease", "", TC_FAIL, "Unable to release Handle acquired by TSHttpHdrUrlGet");
4578 }
4579 }
4580
4581 if (flag == true) {
4582 SDK_RPRINT(test, "TSHttpHdrClone", "TestCase1", TC_PASS, "ok");
4583 test_passed_Http_Hdr_Clone = true;
4584 }
4585 }
4586 }
4587 }
4588 } else {
4589 SDK_RPRINT(test, "TSHttpHdrClone", "All Test Cases", TC_PASS, "Cannot run test as TSHttpHdrCreate has failed");
4590 }
4591
4592 // LengthGet
4593 if (test_passed_Http_Hdr_Create == true) {
4594 actual_length = TSHttpHdrLengthGet(bufp1, hdr_loc1);
4595 TSIOBuffer iobuf = TSIOBufferCreate();
4596 TSHttpHdrPrint(bufp1, hdr_loc1, iobuf);
4597 TSIOBufferReader iobufreader = TSIOBufferReaderAlloc(iobuf);
4598
4599 expected_length = TSIOBufferReaderAvail(iobufreader);
4600 if (actual_length == expected_length) {
4601 SDK_RPRINT(test, "TSHttpHdrLengthGet", "TestCase1", TC_PASS, "ok");
4602 test_passed_Http_Hdr_Length = true;
4603 } else {
4604 SDK_RPRINT(test, "TSHttpHdrLengthGet", "TestCase1", TC_FAIL, "Incorrect value returned.");
4605 }
4606
4607 // Print.
4608 if ((test_passed_Http_Hdr_Method == true) && (test_passed_Http_Hdr_Url == true) && (test_passed_Http_Hdr_Version == true) &&
4609 (test_passed_Http_Hdr_Length == true) && (try_print_function == true)) {
4610 char *actual_iobuf = nullptr;
4611
4612 actual_iobuf = static_cast<char *>(TSmalloc((actual_length + 1) * sizeof(char)));
4613
4614 if (actual_iobuf == nullptr) {
4615 SDK_RPRINT(test, "TSHttpHdrPrint", "TestCase1", TC_FAIL, "Unable to allocate memory");
4616 } else {
4617 TSIOBufferBlock iobufblock;
4618 int64_t bytes_read;
4619
4620 memset(actual_iobuf, 0, (actual_length + 1) * sizeof(char));
4621 bytes_read = 0;
4622
4623 iobufblock = TSIOBufferReaderStart(iobufreader);
4624
4625 while (iobufblock != nullptr) {
4626 const char *block_start;
4627 int64_t block_size;
4628
4629 block_start = TSIOBufferBlockReadStart(iobufblock, iobufreader, &block_size);
4630 if (block_size <= 0) {
4631 break;
4632 }
4633
4634 memcpy(actual_iobuf + bytes_read, block_start, block_size);
4635 bytes_read += block_size;
4636 TSIOBufferReaderConsume(iobufreader, block_size);
4637 iobufblock = TSIOBufferReaderStart(iobufreader);
4638 }
4639 if (strcmp(actual_iobuf, expected_iobuf) == 0) {
4640 SDK_RPRINT(test, "TSHttpHdrPrint", "TestCase1", TC_PASS, "ok");
4641 test_passed_Http_Hdr_Print = true;
4642 } else {
4643 SDK_RPRINT(test, "TSHttpHdrPrint", "TestCase1", TC_FAIL, "Value's mismatch");
4644 }
4645
4646 TSfree(actual_iobuf);
4647 TSIOBufferReaderFree(iobufreader);
4648 TSIOBufferDestroy(iobuf);
4649 }
4650 } else {
4651 SDK_RPRINT(test, "TSHttpHdrPrint", "TestCase1", TC_FAIL, "Unable to run test for TSHttpHdrPrint");
4652 }
4653 } else {
4654 SDK_RPRINT(test, "TSHttpHdrLengthGet", "All Test Cases", TC_PASS, "Cannot run test as TSHttpHdrCreate has failed");
4655 }
4656
4657 // Destroy
4658 if (test_passed_Http_Hdr_Create == true) {
4659 TSHttpHdrDestroy(bufp1, hdr_loc1);
4660 TSHttpHdrDestroy(bufp2, hdr_loc2);
4661 TSHttpHdrDestroy(bufp3, hdr_loc3);
4662 TSHttpHdrDestroy(bufp4, hdr_loc4);
4663 if ((TSHandleMLocRelease(bufp1, TS_NULL_MLOC, hdr_loc1) == TS_ERROR) ||
4664 (TSHandleMLocRelease(bufp2, TS_NULL_MLOC, hdr_loc2) == TS_ERROR) ||
4665 (TSHandleMLocRelease(bufp3, TS_NULL_MLOC, hdr_loc3) == TS_ERROR) ||
4666 (TSHandleMLocRelease(bufp4, TS_NULL_MLOC, hdr_loc4) == TS_ERROR)) {
4667 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase1|2|3|4", TC_FAIL, "Unable to release the handle to headers");
4668 }
4669 SDK_RPRINT(test, "TSHttpHdrDestroy", "TestCase1&2&3&4", TC_PASS, "ok");
4670 test_passed_Http_Hdr_Destroy = true;
4671 } else {
4672 SDK_RPRINT(test, "TSHttpHdrDestroy", "All Test Cases", TC_FAIL, "Cannot run test as header was not created");
4673 }
4674
4675 if (bufp1) {
4676 if (TSMBufferDestroy(bufp1) == TS_ERROR) {
4677 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase1", TC_FAIL, "Unable to destroy MBuffer");
4678 }
4679 }
4680
4681 if (bufp2) {
4682 if (TSMBufferDestroy(bufp2) == TS_ERROR) {
4683 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase2", TC_FAIL, "Unable to destroy MBuffer");
4684 }
4685 }
4686
4687 if (bufp3) {
4688 if (TSMBufferDestroy(bufp3) == TS_ERROR) {
4689 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase3", TC_FAIL, "Unable to destroy MBuffer");
4690 }
4691 }
4692
4693 if (bufp4) {
4694 if (TSMBufferDestroy(bufp4) == TS_ERROR) {
4695 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase4", TC_FAIL, "Unable to destroy MBuffer");
4696 }
4697 }
4698
4699 if ((test_passed_Http_Hdr_Create == true) && (test_passed_Http_Hdr_Type == true) && (test_passed_Http_Hdr_Method == true) &&
4700 (test_passed_Http_Hdr_Url == true) && (test_passed_Http_Hdr_Status == true) && (test_passed_Http_Hdr_Reason == true) &&
4701 (test_passed_Http_Hdr_Reason_Lookup == true) && (test_passed_Http_Hdr_Version == true) &&
4702 (test_passed_Http_Hdr_Copy == true) && (test_passed_Http_Hdr_Clone == true) && (test_passed_Http_Hdr_Length == true) &&
4703 (test_passed_Http_Hdr_Print == true) && (test_passed_Http_Hdr_Destroy == true)) {
4704 *pstatus = REGRESSION_TEST_PASSED;
4705 } else {
4706 *pstatus = REGRESSION_TEST_FAILED;
4707 }
4708
4709 return;
4710 }
4711
4712 //////////////////////////////////////////////
4713 // SDK_API_TSMimeHdrField
4714 //
4715 // Unit Test for API: TSMBufferCreate
4716 // TSMBufferDestroy
4717 // TSMimeHdrCreate
4718 // TSMimeHdrDestroy
4719 // TSMimeHdrFieldCreate
4720 // TSMimeHdrFieldDestroy
4721 // TSMimeHdrFieldFind
4722 // TSMimeHdrFieldGet
4723 // TSMimeHdrFieldAppend
4724 // TSMimeHdrFieldNameGet
4725 // TSMimeHdrFieldNameSet
4726 // TSMimeHdrFieldNext
4727 // TSMimeHdrFieldsClear
4728 // TSMimeHdrFieldsCount
4729 // TSMimeHdrFieldValueAppend
4730 // TSMimeHdrFieldValueDelete
4731 // TSMimeHdrFieldValueStringGet
4732 // TSMimeHdrFieldValueDateGet
4733 // TSMimeHdrFieldValueIntGet
4734 // TSMimeHdrFieldValueUintGet
4735 // TSMimeHdrFieldValueStringInsert
4736 // TSMimeHdrFieldValueDateInsert
4737 // TSMimeHdrFieldValueIntInsert
4738 // TSMimeHdrFieldValueUintInsert
4739 // TSMimeHdrFieldValuesClear
4740 // TSMimeHdrFieldValuesCount
4741 // TSMimeHdrFieldValueStringSet
4742 // TSMimeHdrFieldValueDateSet
4743 // TSMimeHdrFieldValueIntSet
4744 // TSMimeHdrFieldValueUintSet
4745 // TSMimeHdrLengthGet
4746 // TSMimeHdrPrint
4747 //////////////////////////////////////////////
4748
4749 TSReturnCode
compare_field_names(RegressionTest *,TSMBuffer bufp1,TSMLoc mime_loc1,TSMLoc field_loc1,TSMBuffer bufp2,TSMLoc mime_loc2,TSMLoc field_loc2)4750 compare_field_names(RegressionTest * /* test ATS_UNUSED */, TSMBuffer bufp1, TSMLoc mime_loc1, TSMLoc field_loc1, TSMBuffer bufp2,
4751 TSMLoc mime_loc2, TSMLoc field_loc2)
4752 {
4753 const char *name1;
4754 const char *name2;
4755 int length1;
4756 int length2;
4757
4758 name1 = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc1, &length1);
4759 name2 = TSMimeHdrFieldNameGet(bufp2, mime_loc2, field_loc2, &length2);
4760
4761 if ((length1 == length2) && (strncmp(name1, name2, length1) == 0)) {
4762 return TS_SUCCESS;
4763 } else {
4764 return TS_ERROR;
4765 }
4766 }
4767
REGRESSION_TEST(SDK_API_TSMimeHdrField)4768 REGRESSION_TEST(SDK_API_TSMimeHdrField)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
4769 {
4770 TSMBuffer bufp1 = (TSMBuffer) nullptr;
4771
4772 TSMLoc mime_loc1 = (TSMLoc) nullptr;
4773
4774 TSMLoc field_loc11 = (TSMLoc) nullptr;
4775 TSMLoc field_loc12 = (TSMLoc) nullptr;
4776 TSMLoc field_loc13 = (TSMLoc) nullptr;
4777 TSMLoc field_loc14 = (TSMLoc) nullptr;
4778 TSMLoc field_loc15 = (TSMLoc) nullptr;
4779
4780 const char *field1Name = "field1";
4781 const char *field2Name = "field2";
4782 const char *field3Name = "field3";
4783 const char *field4Name = "field4";
4784 const char *field5Name = "field5";
4785
4786 const char *field1NameGet;
4787 const char *field2NameGet;
4788 const char *field3NameGet;
4789 const char *field4NameGet;
4790 const char *field5NameGet;
4791
4792 int field1NameGetLength;
4793 int field2NameGetLength;
4794 int field3NameGetLength;
4795 int field4NameGetLength;
4796 int field5NameGetLength;
4797
4798 int field1_length;
4799 int field2_length;
4800 int field3_length;
4801 int field4_length;
4802 /* int field5_length; unused: lv */
4803
4804 TSMLoc test_field_loc11 = (TSMLoc) nullptr;
4805 TSMLoc test_field_loc12 = (TSMLoc) nullptr;
4806 TSMLoc test_field_loc13 = (TSMLoc) nullptr;
4807 TSMLoc test_field_loc14 = (TSMLoc) nullptr;
4808 TSMLoc test_field_loc15 = (TSMLoc) nullptr;
4809
4810 int actualNumberOfFields;
4811 int numberOfFields;
4812
4813 const char *field1Value1 = "field1Value1";
4814 const char *field1Value2 = "field1Value2";
4815 const char *field1Value3 = "field1Value3";
4816 const char *field1Value4 = "field1Value4";
4817 const char *field1Value5 = "field1Value5";
4818 const char *field1ValueNew = "newfieldValue";
4819
4820 const char *field1Value1Get;
4821 const char *field1Value2Get;
4822 const char *field1Value3Get;
4823 const char *field1Value4Get;
4824 const char *field1Value5Get;
4825 const char *field1ValueAllGet;
4826 const char *field1ValueNewGet;
4827
4828 int lengthField1Value1;
4829 int lengthField1Value2;
4830 int lengthField1Value3;
4831 int lengthField1Value4;
4832 int lengthField1Value5;
4833 int lengthField1ValueAll;
4834 int lengthField1ValueNew;
4835
4836 time_t field2Value1 = time(nullptr);
4837 time_t field2Value1Get;
4838 time_t field2ValueNew;
4839 time_t field2ValueNewGet;
4840
4841 int field3Value1 = 31;
4842 int field3Value2 = 32;
4843 int field3Value3 = 33;
4844 int field3Value4 = 34;
4845 int field3Value5 = 35;
4846 int field3ValueNew = 30;
4847
4848 int field3Value1Get;
4849 int field3Value2Get;
4850 int field3Value3Get;
4851 int field3Value4Get;
4852 int field3Value5Get;
4853 int field3ValueNewGet;
4854
4855 unsigned int field4Value1 = 41;
4856 unsigned int field4Value2 = 42;
4857 unsigned int field4Value3 = 43;
4858 unsigned int field4Value4 = 44;
4859 unsigned int field4Value5 = 45;
4860 unsigned int field4ValueNew = 40;
4861
4862 unsigned int field4Value1Get;
4863 unsigned int field4Value2Get;
4864 unsigned int field4Value3Get;
4865 unsigned int field4Value4Get;
4866 unsigned int field4Value5Get;
4867 unsigned int field4ValueNewGet;
4868
4869 const char *field5Value1 = "field5Value1";
4870 const char *field5Value1Append = "AppendedValue";
4871 const char *fieldValueAppendGet;
4872 int lengthFieldValueAppended;
4873 int field5Value2 = 52;
4874 const char *field5Value3 = "DeleteValue";
4875 const char *fieldValueDeleteGet;
4876 int lengthFieldValueDeleteGet;
4877 unsigned int field5Value4 = 54;
4878 int numberOfValueInField;
4879
4880 TSMLoc field_loc;
4881
4882 bool test_passed_MBuffer_Create = false;
4883 bool test_passed_Mime_Hdr_Create = false;
4884 bool test_passed_Mime_Hdr_Field_Create = false;
4885 bool test_passed_Mime_Hdr_Field_Name = false;
4886 bool test_passed_Mime_Hdr_Field_Append = false;
4887 bool test_passed_Mime_Hdr_Field_Get = false;
4888 bool test_passed_Mime_Hdr_Field_Next = false;
4889 bool test_passed_Mime_Hdr_Fields_Count = false;
4890 bool test_passed_Mime_Hdr_Field_Value_String_Insert = false;
4891 bool test_passed_Mime_Hdr_Field_Value_String_Get = false;
4892 bool test_passed_Mime_Hdr_Field_Value_String_Set = false;
4893 bool test_passed_Mime_Hdr_Field_Value_Date_Insert = false;
4894 bool test_passed_Mime_Hdr_Field_Value_Date_Get = false;
4895 bool test_passed_Mime_Hdr_Field_Value_Date_Set = false;
4896 bool test_passed_Mime_Hdr_Field_Value_Int_Insert = false;
4897 bool test_passed_Mime_Hdr_Field_Value_Int_Get = false;
4898 bool test_passed_Mime_Hdr_Field_Value_Int_Set = false;
4899 bool test_passed_Mime_Hdr_Field_Value_Uint_Insert = false;
4900 bool test_passed_Mime_Hdr_Field_Value_Uint_Get = false;
4901 bool test_passed_Mime_Hdr_Field_Value_Uint_Set = false;
4902 bool test_passed_Mime_Hdr_Field_Value_Append = false;
4903 bool test_passed_Mime_Hdr_Field_Value_Delete = false;
4904 bool test_passed_Mime_Hdr_Field_Values_Clear = false;
4905 bool test_passed_Mime_Hdr_Field_Values_Count = false;
4906 bool test_passed_Mime_Hdr_Field_Destroy = false;
4907 bool test_passed_Mime_Hdr_Fields_Clear = false;
4908 bool test_passed_Mime_Hdr_Destroy = false;
4909 bool test_passed_MBuffer_Destroy = false;
4910 bool test_passed_Mime_Hdr_Field_Length_Get = false;
4911
4912 *pstatus = REGRESSION_TEST_INPROGRESS;
4913
4914 // TSMBufferCreate
4915 bufp1 = TSMBufferCreate();
4916 SDK_RPRINT(test, "TSMBufferCreate", "TestCase1", TC_PASS, "ok");
4917 test_passed_MBuffer_Create = true;
4918
4919 // TSMimeHdrCreate
4920 if (test_passed_MBuffer_Create == true) {
4921 if (TSMimeHdrCreate(bufp1, &mime_loc1) != TS_SUCCESS) {
4922 SDK_RPRINT(test, "TSMimeHdrCreate", "TestCase1", TC_FAIL, "TSMimeHdrCreate Returns TS_ERROR");
4923 } else {
4924 SDK_RPRINT(test, "TSMimeHdrCreate", "TestCase1", TC_PASS, "ok");
4925 test_passed_Mime_Hdr_Create = true;
4926 }
4927 } else {
4928 SDK_RPRINT(test, "TSMimeHdrCreate", "TestCase1", TC_FAIL, "Cannot run test as Test for TSMBufferCreate Failed");
4929 }
4930
4931 // TSMimeHdrFieldCreate
4932 if (test_passed_Mime_Hdr_Create == true) {
4933 if ((TSMimeHdrFieldCreate(bufp1, mime_loc1, &field_loc11) != TS_SUCCESS) ||
4934 (TSMimeHdrFieldCreate(bufp1, mime_loc1, &field_loc12) != TS_SUCCESS) ||
4935 (TSMimeHdrFieldCreate(bufp1, mime_loc1, &field_loc13) != TS_SUCCESS) ||
4936 (TSMimeHdrFieldCreate(bufp1, mime_loc1, &field_loc14) != TS_SUCCESS) ||
4937 (TSMimeHdrFieldCreate(bufp1, mime_loc1, &field_loc15) != TS_SUCCESS)) {
4938 SDK_RPRINT(test, "TSMimeHdrFieldCreate", "TestCase1|2|3|4|5", TC_FAIL, "TSMimeHdrFieldCreate Returns TS_ERROR");
4939 } else {
4940 SDK_RPRINT(test, "TSMimeHdrFieldCreate", "TestCase1|2|3|4|5", TC_PASS, "ok");
4941 test_passed_Mime_Hdr_Field_Create = true;
4942 }
4943 } else {
4944 SDK_RPRINT(test, "TSMimeHdrFieldCreate", "All Test Case", TC_FAIL, "Cannot run test as Test for TSMimeHdrCreate Failed");
4945 }
4946
4947 // TSMimeHdrFieldNameGet&Set
4948 if (test_passed_Mime_Hdr_Field_Create == true) {
4949 if ((TSMimeHdrFieldNameSet(bufp1, mime_loc1, field_loc11, field1Name, -1) == TS_ERROR) ||
4950 (TSMimeHdrFieldNameSet(bufp1, mime_loc1, field_loc12, field2Name, -1) == TS_ERROR) ||
4951 (TSMimeHdrFieldNameSet(bufp1, mime_loc1, field_loc13, field3Name, -1) == TS_ERROR) ||
4952 (TSMimeHdrFieldNameSet(bufp1, mime_loc1, field_loc14, field4Name, -1) == TS_ERROR) ||
4953 (TSMimeHdrFieldNameSet(bufp1, mime_loc1, field_loc15, field5Name, -1) == TS_ERROR)) {
4954 SDK_RPRINT(test, "TSMimeHdrFieldNameSet", "TestCase1|2|3|4|5", TC_FAIL, "TSMimeHdrFieldNameSet Returns TS_ERROR");
4955 } else {
4956 field1NameGet = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc11, &field1NameGetLength);
4957 field2NameGet = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc12, &field2NameGetLength);
4958 field3NameGet = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc13, &field3NameGetLength);
4959 field4NameGet = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc14, &field4NameGetLength);
4960 field5NameGet = TSMimeHdrFieldNameGet(bufp1, mime_loc1, field_loc15, &field5NameGetLength);
4961 if (((strncmp(field1NameGet, field1Name, field1NameGetLength) == 0) &&
4962 (field1NameGetLength == static_cast<int>(strlen(field1Name)))) &&
4963 ((strncmp(field2NameGet, field2Name, field2NameGetLength) == 0) &&
4964 (field2NameGetLength == static_cast<int>(strlen(field2Name)))) &&
4965 ((strncmp(field3NameGet, field3Name, field3NameGetLength) == 0) &&
4966 (field3NameGetLength == static_cast<int>(strlen(field3Name)))) &&
4967 ((strncmp(field4NameGet, field4Name, field4NameGetLength) == 0) &&
4968 (field4NameGetLength == static_cast<int>(strlen(field4Name)))) &&
4969 ((strncmp(field5NameGet, field5Name, field5NameGetLength) == 0) &&
4970 field5NameGetLength == static_cast<int>(strlen(field5Name)))) {
4971 SDK_RPRINT(test, "TSMimeHdrFieldNameGet&Set", "TestCase1&2&3&4&5", TC_PASS, "ok");
4972 test_passed_Mime_Hdr_Field_Name = true;
4973 } else {
4974 SDK_RPRINT(test, "TSMimeHdrFieldNameGet&Set", "TestCase1|2|3|4|5", TC_FAIL, "Values Don't Match");
4975 }
4976 }
4977 } else {
4978 SDK_RPRINT(test, "TSMimeHdrFieldNameGet&Set", "All Test Case", TC_FAIL,
4979 "Cannot run test as Test for TSMBufferFieldCreate Failed");
4980 }
4981
4982 // TSMimeHdrFieldAppend, TSMimeHdrFieldGet, TSMimeHdrFieldNext
4983 if (test_passed_Mime_Hdr_Field_Name == true) {
4984 if ((TSMimeHdrFieldAppend(bufp1, mime_loc1, field_loc11) != TS_SUCCESS) ||
4985 (TSMimeHdrFieldAppend(bufp1, mime_loc1, field_loc12) != TS_SUCCESS) ||
4986 (TSMimeHdrFieldAppend(bufp1, mime_loc1, field_loc13) != TS_SUCCESS) ||
4987 (TSMimeHdrFieldAppend(bufp1, mime_loc1, field_loc14) != TS_SUCCESS) ||
4988 (TSMimeHdrFieldAppend(bufp1, mime_loc1, field_loc15) != TS_SUCCESS)) {
4989 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase1|2|3|4|5", TC_FAIL, "TSMimeHdrFieldAppend Returns TS_ERROR");
4990 } else {
4991 if (TS_NULL_MLOC == (test_field_loc11 = TSMimeHdrFieldGet(bufp1, mime_loc1, 0))) {
4992 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase1|2|3|4|5", TC_FAIL, "TSMimeHdrFieldGet Returns TS_NULL_MLOC");
4993 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase1", TC_FAIL,
4994 "Cannot Test TSMimeHdrFieldNext as TSMimeHdrFieldGet Returns TS_NULL_MLOC");
4995 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase1", TC_FAIL, "TSMimeHdrFieldGet Returns TS_NULL_MLOC");
4996 } else {
4997 if (compare_field_names(test, bufp1, mime_loc1, field_loc11, bufp1, mime_loc1, test_field_loc11) == TS_ERROR) {
4998 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase1", TC_FAIL, "Values Don't match");
4999 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase1", TC_FAIL, "Cannot Test TSMimeHdrFieldNext as Values don't match");
5000 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase1", TC_FAIL, "Values Don't match");
5001 } else {
5002 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase1", TC_PASS, "ok");
5003 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase1", TC_PASS, "ok");
5004 test_passed_Mime_Hdr_Field_Append = true;
5005 test_passed_Mime_Hdr_Field_Get = true;
5006 }
5007 }
5008
5009 if (test_passed_Mime_Hdr_Field_Append == true) {
5010 test_field_loc12 = TSMimeHdrFieldNext(bufp1, mime_loc1, test_field_loc11);
5011 if (compare_field_names(test, bufp1, mime_loc1, field_loc12, bufp1, mime_loc1, test_field_loc12) == TS_ERROR) {
5012 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase2", TC_PASS, "Values Don't match");
5013 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase2", TC_PASS, "Values Don't match");
5014 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase2", TC_PASS, "Values Don't match");
5015 test_passed_Mime_Hdr_Field_Append = false;
5016 test_passed_Mime_Hdr_Field_Next = false;
5017 test_passed_Mime_Hdr_Field_Get = false;
5018 } else {
5019 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase2", TC_PASS, "ok");
5020 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase2", TC_PASS, "ok");
5021 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase2", TC_PASS, "ok");
5022 test_passed_Mime_Hdr_Field_Next = true;
5023 }
5024 }
5025
5026 if (test_passed_Mime_Hdr_Field_Append == true) {
5027 test_field_loc13 = TSMimeHdrFieldNext(bufp1, mime_loc1, test_field_loc12);
5028 if (compare_field_names(test, bufp1, mime_loc1, field_loc13, bufp1, mime_loc1, test_field_loc13) == TS_ERROR) {
5029 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase3", TC_FAIL, "Values Don't match");
5030 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase3", TC_FAIL, "Values Don't match");
5031 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase3", TC_FAIL, "Values Don't match");
5032 test_passed_Mime_Hdr_Field_Append = false;
5033 test_passed_Mime_Hdr_Field_Next = false;
5034 test_passed_Mime_Hdr_Field_Get = false;
5035 } else {
5036 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase3", TC_PASS, "ok");
5037 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase3", TC_PASS, "ok");
5038 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase3", TC_PASS, "ok");
5039 }
5040 }
5041
5042 if (test_passed_Mime_Hdr_Field_Append == true) {
5043 test_field_loc14 = TSMimeHdrFieldNext(bufp1, mime_loc1, test_field_loc13);
5044 if (compare_field_names(test, bufp1, mime_loc1, field_loc14, bufp1, mime_loc1, test_field_loc14) == TS_ERROR) {
5045 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase4", TC_FAIL, "Values Don't match");
5046 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase4", TC_FAIL, "Values Don't match");
5047 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase4", TC_FAIL, "Values Don't match");
5048 test_passed_Mime_Hdr_Field_Append = false;
5049 test_passed_Mime_Hdr_Field_Next = false;
5050 test_passed_Mime_Hdr_Field_Get = false;
5051 } else {
5052 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase4", TC_PASS, "ok");
5053 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase4", TC_PASS, "ok");
5054 SDK_RPRINT(test, "TSMimeHdrFieldGet", "TestCase4", TC_PASS, "ok");
5055 }
5056 }
5057
5058 if (test_passed_Mime_Hdr_Field_Append == true) {
5059 test_field_loc15 = TSMimeHdrFieldNext(bufp1, mime_loc1, test_field_loc14);
5060 if (compare_field_names(test, bufp1, mime_loc1, field_loc15, bufp1, mime_loc1, test_field_loc15) == TS_ERROR) {
5061 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase5", TC_FAIL, "Values Don't match");
5062 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase5", TC_FAIL, "Values Don't match");
5063 test_passed_Mime_Hdr_Field_Append = false;
5064 test_passed_Mime_Hdr_Field_Next = false;
5065 test_passed_Mime_Hdr_Field_Get = false;
5066 } else {
5067 SDK_RPRINT(test, "TSMimeHdrFieldAppend", "TestCase5", TC_PASS, "ok");
5068 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase5", TC_PASS, "ok");
5069 }
5070 }
5071
5072 if ((TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc11) == TS_ERROR) ||
5073 (TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc12) == TS_ERROR) ||
5074 (TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc13) == TS_ERROR) ||
5075 (TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc14) == TS_ERROR) ||
5076 (TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc15) == TS_ERROR)) {
5077 SDK_RPRINT(test, "TSMimeHdrFieldAppend/Next/Get", "", TC_FAIL,
5078 "Unable to release handle using TSHandleMLocRelease. Can be bad handle.");
5079 }
5080 }
5081 } else {
5082 SDK_RPRINT(test, "TSMimeHdrFieldAppend & TSMimeHdrFieldNext", "All Test Case", TC_FAIL,
5083 "Cannot run test as Test for TSMimeHdrFieldNameGet&Set Failed");
5084 }
5085
5086 // TSMimeHdrFieldsCount
5087 if (test_passed_Mime_Hdr_Field_Create == true) {
5088 if ((numberOfFields = TSMimeHdrFieldsCount(bufp1, mime_loc1)) < 0) {
5089 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_FAIL, "TSMimeHdrFieldsCount Returns TS_ERROR");
5090 } else {
5091 actualNumberOfFields = 0;
5092 if ((field_loc = TSMimeHdrFieldGet(bufp1, mime_loc1, actualNumberOfFields)) == TS_NULL_MLOC) {
5093 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_FAIL, "TSMimeHdrFieldGet Returns TS_NULL_MLOC");
5094 } else {
5095 while (field_loc != nullptr) {
5096 TSMLoc next_field_loc;
5097
5098 actualNumberOfFields++;
5099 next_field_loc = TSMimeHdrFieldNext(bufp1, mime_loc1, field_loc);
5100 if (TSHandleMLocRelease(bufp1, mime_loc1, field_loc) == TS_ERROR) {
5101 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_FAIL, "Unable to release handle using TSHandleMLocRelease");
5102 }
5103 field_loc = next_field_loc;
5104 next_field_loc = nullptr;
5105 }
5106 if (actualNumberOfFields == numberOfFields) {
5107 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_PASS, "ok");
5108 test_passed_Mime_Hdr_Fields_Count = true;
5109 } else {
5110 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_FAIL, "Values don't match");
5111 }
5112 }
5113 }
5114 } else {
5115 SDK_RPRINT(test, "TSMimeHdrFieldsCount", "TestCase1", TC_FAIL, "Cannot run Test as TSMimeHdrFieldCreate failed");
5116 }
5117
5118 // TSMimeHdrFieldValueStringInsert, TSMimeHdrFieldValueStringGet, TSMimeHdrFieldValueStringSet
5119 if (test_passed_Mime_Hdr_Field_Create == true) {
5120 if ((TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc11, -1, field1Value2, -1) == TS_ERROR) ||
5121 (TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc11, 0, field1Value1, -1) == TS_ERROR) ||
5122 (TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc11, -1, field1Value5, -1) == TS_ERROR) ||
5123 (TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc11, 2, field1Value4, -1) == TS_ERROR) ||
5124 (TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc11, 2, field1Value3, -1) == TS_ERROR)) {
5125 SDK_RPRINT(test, "TSMimeHdrFieldValueStringInsert", "TestCase1|2|3|4|5", TC_FAIL,
5126 "TSMimeHdrFieldValueStringInsert Returns TS_ERROR");
5127 SDK_RPRINT(test, "TSMimeHdrFieldValueStringGet", "TestCase1&2&3&4&5", TC_FAIL,
5128 "Cannot run Test as TSMimeHdrFieldValueStringInsert returns TS_ERROR");
5129 SDK_RPRINT(test, "TSMimeHdrFieldValueStringSet", "TestCase1", TC_FAIL,
5130 "Cannot run Test as TSMimeHdrFieldValueStringInsert returns TS_ERROR");
5131 } else {
5132 field1Value1Get = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 0, &lengthField1Value1);
5133 field1Value2Get = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 1, &lengthField1Value2);
5134 field1Value3Get = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 2, &lengthField1Value3);
5135 field1Value4Get = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 3, &lengthField1Value4);
5136 field1Value5Get = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 4, &lengthField1Value5);
5137 field1ValueAllGet = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, -1, &lengthField1ValueAll);
5138 if (((strncmp(field1Value1Get, field1Value1, lengthField1Value1) == 0) &&
5139 lengthField1Value1 == static_cast<int>(strlen(field1Value1))) &&
5140 ((strncmp(field1Value2Get, field1Value2, lengthField1Value2) == 0) &&
5141 lengthField1Value2 == static_cast<int>(strlen(field1Value2))) &&
5142 ((strncmp(field1Value3Get, field1Value3, lengthField1Value3) == 0) &&
5143 lengthField1Value3 == static_cast<int>(strlen(field1Value3))) &&
5144 ((strncmp(field1Value4Get, field1Value4, lengthField1Value4) == 0) &&
5145 lengthField1Value4 == static_cast<int>(strlen(field1Value4))) &&
5146 ((strncmp(field1Value5Get, field1Value5, lengthField1Value5) == 0) &&
5147 lengthField1Value5 == static_cast<int>(strlen(field1Value5))) &&
5148 (strstr(field1ValueAllGet, field1Value1Get) == field1Value1Get) &&
5149 (strstr(field1ValueAllGet, field1Value2Get) == field1Value2Get) &&
5150 (strstr(field1ValueAllGet, field1Value3Get) == field1Value3Get) &&
5151 (strstr(field1ValueAllGet, field1Value4Get) == field1Value4Get) &&
5152 (strstr(field1ValueAllGet, field1Value5Get) == field1Value5Get)) {
5153 SDK_RPRINT(test, "TSMimeHdrFieldValueStringInsert", "TestCase1&2&3&4&5", TC_PASS, "ok");
5154 SDK_RPRINT(test, "TSMimeHdrFieldValueStringGet", "TestCase1&2&3&4&5", TC_PASS, "ok");
5155 SDK_RPRINT(test, "TSMimeHdrFieldValueStringGet with IDX=-1", "TestCase1&2&3&4&5", TC_PASS, "ok");
5156 test_passed_Mime_Hdr_Field_Value_String_Insert = true;
5157 test_passed_Mime_Hdr_Field_Value_String_Get = true;
5158
5159 if ((TSMimeHdrFieldValueStringSet(bufp1, mime_loc1, field_loc11, 3, field1ValueNew, -1)) == TS_ERROR) {
5160 SDK_RPRINT(test, "TSMimeHdrFieldValueStringSet", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueStringSet returns TS_ERROR");
5161 } else {
5162 field1ValueNewGet = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc11, 3, &lengthField1ValueNew);
5163 if ((strncmp(field1ValueNewGet, field1ValueNew, lengthField1ValueNew) == 0) &&
5164 (lengthField1ValueNew == static_cast<int>(strlen(field1ValueNew)))) {
5165 SDK_RPRINT(test, "TSMimeHdrFieldValueStringSet", "TestCase1", TC_PASS, "ok");
5166 test_passed_Mime_Hdr_Field_Value_String_Set = true;
5167 } else {
5168 SDK_RPRINT(test, "TSMimeHdrFieldValueStringSet", "TestCase1", TC_FAIL, "Value's Don't match");
5169 }
5170 }
5171 } else {
5172 SDK_RPRINT(test, "TSMimeHdrFieldValueStringInsert", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5173 SDK_RPRINT(test, "TSMimeHdrFieldValueStringGet", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5174 SDK_RPRINT(test, "TSMimeHdrFieldValueStringSet", "TestCase1", TC_FAIL,
5175 "TSMimeHdrFieldValueStringSet cannot be tested as TSMimeHdrFieldValueStringInsert|Get failed");
5176 }
5177 }
5178 } else {
5179 SDK_RPRINT(test, "TSMimeHdrFieldValueStringInsert&Set&Get", "All", TC_FAIL, "Cannot run Test as TSMimeHdrFieldCreate failed");
5180 }
5181
5182 // TSMimeHdrFieldValueDateInsert, TSMimeHdrFieldValueDateGet, TSMimeHdrFieldValueDateSet
5183 if (test_passed_Mime_Hdr_Field_Create == true) {
5184 if (TSMimeHdrFieldValueDateInsert(bufp1, mime_loc1, field_loc12, field2Value1) == TS_ERROR) {
5185 SDK_RPRINT(test, "TSMimeHdrFieldValueDateInsert", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueDateInsert Returns TS_ERROR");
5186 SDK_RPRINT(test, "TSMimeHdrFieldValueDateGet", "TestCase1", TC_FAIL,
5187 "Cannot run Test as TSMimeHdrFieldValueDateInsert returns TS_ERROR");
5188 SDK_RPRINT(test, "TSMimeHdrFieldValueDateSet", "TestCase1", TC_FAIL,
5189 "Cannot run Test as TSMimeHdrFieldValueDateInsert returns TS_ERROR");
5190 } else {
5191 field2Value1Get = TSMimeHdrFieldValueDateGet(bufp1, mime_loc1, field_loc12);
5192 if (field2Value1Get == field2Value1) {
5193 SDK_RPRINT(test, "TSMimeHdrFieldValueDateInsert", "TestCase1", TC_PASS, "ok");
5194 SDK_RPRINT(test, "TSMimeHdrFieldValueDateGet", "TestCase1", TC_PASS, "ok");
5195 test_passed_Mime_Hdr_Field_Value_Date_Insert = true;
5196 test_passed_Mime_Hdr_Field_Value_Date_Get = true;
5197 field2ValueNew = time(nullptr);
5198 if ((TSMimeHdrFieldValueDateSet(bufp1, mime_loc1, field_loc12, field2ValueNew)) == TS_ERROR) {
5199 SDK_RPRINT(test, "TSMimeHdrFieldValueDateSet", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueDateSet returns TS_ERROR");
5200 } else {
5201 field2ValueNewGet = TSMimeHdrFieldValueDateGet(bufp1, mime_loc1, field_loc12);
5202 if (field2ValueNewGet == field2ValueNew) {
5203 SDK_RPRINT(test, "TSMimeHdrFieldValueDateSet", "TestCase1", TC_PASS, "ok");
5204 test_passed_Mime_Hdr_Field_Value_Date_Set = true;
5205 } else {
5206 SDK_RPRINT(test, "TSMimeHdrFieldValueDateSet", "TestCase1", TC_FAIL, "Value's Don't match");
5207 }
5208 }
5209 } else {
5210 SDK_RPRINT(test, "TSMimeHdrFieldValueDateInsert", "TestCase1", TC_PASS, "Value's Don't Match");
5211 SDK_RPRINT(test, "TSMimeHdrFieldValueDateGet", "TestCase1", TC_PASS, "Value's Don't Match");
5212 SDK_RPRINT(test, "TSMimeHdrFieldValueDateSet", "TestCase1", TC_FAIL,
5213 "TSMimeHdrFieldValueDateSet cannot be tested as TSMimeHdrFieldValueDateInsert|Get failed");
5214 }
5215 }
5216 } else {
5217 SDK_RPRINT(test, "TSMimeHdrFieldValueDateInsert&Set&Get", "TestCase1", TC_FAIL,
5218 "Cannot run Test as TSMimeHdrFieldCreate failed");
5219 }
5220
5221 // TSMimeHdrFieldValueIntInsert, TSMimeHdrFieldValueIntGet, TSMimeHdrFieldValueIntSet
5222 if (test_passed_Mime_Hdr_Field_Create == true) {
5223 if ((TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc13, -1, field3Value2) == TS_ERROR) ||
5224 (TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc13, 0, field3Value1) == TS_ERROR) ||
5225 (TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc13, -1, field3Value5) == TS_ERROR) ||
5226 (TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc13, 2, field3Value4) == TS_ERROR) ||
5227 (TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc13, 2, field3Value3) == TS_ERROR)) {
5228 SDK_RPRINT(test, "TSMimeHdrFieldValueIntInsert", "TestCase1|2|3|4|5", TC_FAIL,
5229 "TSMimeHdrFieldValueIntInsert Returns TS_ERROR");
5230 SDK_RPRINT(test, "TSMimeHdrFieldValueIntGet", "TestCase1&2&3&4&5", TC_FAIL,
5231 "Cannot run Test as TSMimeHdrFieldValueIntInsert returns TS_ERROR");
5232 SDK_RPRINT(test, "TSMimeHdrFieldValueIntSet", "TestCase1", TC_FAIL,
5233 "Cannot run Test as TSMimeHdrFieldValueIntInsert returns TS_ERROR");
5234 } else {
5235 field3Value1Get = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 0);
5236 field3Value2Get = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 1);
5237 field3Value3Get = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 2);
5238 field3Value4Get = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 3);
5239 field3Value5Get = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 4);
5240 if ((field3Value1Get == field3Value1) && (field3Value2Get == field3Value2) && (field3Value3Get == field3Value3) &&
5241 (field3Value4Get == field3Value4) && (field3Value5Get == field3Value5)) {
5242 SDK_RPRINT(test, "TSMimeHdrFieldValueIntInsert", "TestCase1&2&3&4&5", TC_PASS, "ok");
5243 SDK_RPRINT(test, "TSMimeHdrFieldValueIntGet", "TestCase1&2&3&4&5", TC_PASS, "ok");
5244 test_passed_Mime_Hdr_Field_Value_Int_Insert = true;
5245 test_passed_Mime_Hdr_Field_Value_Int_Get = true;
5246 if ((TSMimeHdrFieldValueIntSet(bufp1, mime_loc1, field_loc13, 3, field3ValueNew)) == TS_ERROR) {
5247 SDK_RPRINT(test, "TSMimeHdrFieldValueIntSet", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueIntSet returns TS_ERROR");
5248 } else {
5249 field3ValueNewGet = TSMimeHdrFieldValueIntGet(bufp1, mime_loc1, field_loc13, 3);
5250 if (field3ValueNewGet == field3ValueNew) {
5251 SDK_RPRINT(test, "TSMimeHdrFieldValueIntSet", "TestCase1", TC_PASS, "ok");
5252 test_passed_Mime_Hdr_Field_Value_Int_Set = true;
5253 } else {
5254 SDK_RPRINT(test, "TSMimeHdrFieldValueIntSet", "TestCase1", TC_FAIL, "Value's Don't match");
5255 }
5256 }
5257 } else {
5258 SDK_RPRINT(test, "TSMimeHdrFieldValueIntInsert", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5259 SDK_RPRINT(test, "TSMimeHdrFieldValueIntGet", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5260 SDK_RPRINT(test, "TSMimeHdrFieldValueIntSet", "TestCase1", TC_FAIL,
5261 "TSMimeHdrFieldValueIntSet cannot be tested as TSMimeHdrFieldValueIntInsert|Get failed");
5262 }
5263 }
5264 } else {
5265 SDK_RPRINT(test, "TSMimeHdrFieldValueIntInsert&Set&Get", "All", TC_FAIL, "Cannot run Test as TSMimeHdrFieldCreate failed");
5266 }
5267
5268 // TSMimeHdrFieldValueUintInsert, TSMimeHdrFieldValueUintGet, TSMimeHdrFieldValueUintSet
5269 if (test_passed_Mime_Hdr_Field_Create == true) {
5270 if ((TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc14, -1, field4Value2) == TS_ERROR) ||
5271 (TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc14, 0, field4Value1) == TS_ERROR) ||
5272 (TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc14, -1, field4Value5) == TS_ERROR) ||
5273 (TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc14, 2, field4Value4) == TS_ERROR) ||
5274 (TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc14, 2, field4Value3) == TS_ERROR)) {
5275 SDK_RPRINT(test, "TSMimeHdrFieldValueUintInsert", "TestCase1|2|3|4|5", TC_FAIL,
5276 "TSMimeHdrFieldValueUintInsert Returns TS_ERROR");
5277 SDK_RPRINT(test, "TSMimeHdrFieldValueUintGet", "TestCase1&2&3&4&5", TC_FAIL,
5278 "Cannot run Test as TSMimeHdrFieldValueUintInsert returns TS_ERROR");
5279 SDK_RPRINT(test, "TSMimeHdrFieldValueUintSet", "TestCase1", TC_FAIL,
5280 "Cannot run Test as TSMimeHdrFieldValueUintInsert returns TS_ERROR");
5281 } else {
5282 field4Value1Get = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 0);
5283 field4Value2Get = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 1);
5284 field4Value3Get = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 2);
5285 field4Value4Get = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 3);
5286 field4Value5Get = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 4);
5287 if ((field4Value1Get == field4Value1) && (field4Value2Get == field4Value2) && (field4Value3Get == field4Value3) &&
5288 (field4Value4Get == field4Value4) && (field4Value5Get == field4Value5)) {
5289 SDK_RPRINT(test, "TSMimeHdrFieldValueUintInsert", "TestCase1&2&3&4&5", TC_PASS, "ok");
5290 SDK_RPRINT(test, "TSMimeHdrFieldValueUintGet", "TestCase1&2&3&4&5", TC_PASS, "ok");
5291 test_passed_Mime_Hdr_Field_Value_Uint_Insert = true;
5292 test_passed_Mime_Hdr_Field_Value_Uint_Get = true;
5293 if ((TSMimeHdrFieldValueUintSet(bufp1, mime_loc1, field_loc14, 3, field4ValueNew)) == TS_ERROR) {
5294 SDK_RPRINT(test, "TSMimeHdrFieldValueUintSet", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueUintSet returns TS_ERROR");
5295 } else {
5296 field4ValueNewGet = TSMimeHdrFieldValueUintGet(bufp1, mime_loc1, field_loc14, 3);
5297 if (field4ValueNewGet == field4ValueNew) {
5298 SDK_RPRINT(test, "TSMimeHdrFieldValueUintSet", "TestCase1", TC_PASS, "ok");
5299 test_passed_Mime_Hdr_Field_Value_Uint_Set = true;
5300 } else {
5301 SDK_RPRINT(test, "TSMimeHdrFieldValueUintSet", "TestCase1", TC_FAIL, "Value's Don't match");
5302 }
5303 }
5304 } else {
5305 SDK_RPRINT(test, "TSMimeHdrFieldValueUintInsert", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5306 SDK_RPRINT(test, "TSMimeHdrFieldValueUintGet", "TestCase1|2|3|4|5", TC_PASS, "Value's Don't Match");
5307 SDK_RPRINT(test, "TSMimeHdrFieldValueUintSet", "TestCase1", TC_FAIL,
5308 "TSMimeHdrFieldValueUintSet cannot be tested as TSMimeHdrFieldValueUintInsert|Get failed");
5309 }
5310 }
5311 } else {
5312 SDK_RPRINT(test, "TSMimeHdrFieldValueUintInsert&Set&Get", "All", TC_FAIL, "Cannot run Test as TSMimeHdrFieldCreate failed");
5313 }
5314
5315 // TSMimeHdrFieldLengthGet
5316 field1_length = TSMimeHdrFieldLengthGet(bufp1, mime_loc1, field_loc11);
5317 field2_length = TSMimeHdrFieldLengthGet(bufp1, mime_loc1, field_loc12);
5318 field3_length = TSMimeHdrFieldLengthGet(bufp1, mime_loc1, field_loc13);
5319 field4_length = TSMimeHdrFieldLengthGet(bufp1, mime_loc1, field_loc14);
5320 if ((field1_length == 0) || (field2_length == 0) || (field3_length == 0) || (field4_length == 0)) {
5321 SDK_RPRINT(test, "TSMimeHdrFieldLengthGet", "TestCase1", TC_FAIL, "Returned bad length");
5322 test_passed_Mime_Hdr_Field_Length_Get = false;
5323 } else {
5324 SDK_RPRINT(test, "TSMimeHdrFieldLengthGet", "TestCase1", TC_PASS, "ok");
5325 test_passed_Mime_Hdr_Field_Length_Get = true;
5326 }
5327
5328 // TSMimeHdrFieldValueAppend, TSMimeHdrFieldValueDelete, TSMimeHdrFieldValuesCount, TSMimeHdrFieldValuesClear
5329
5330 if (test_passed_Mime_Hdr_Field_Create == true) {
5331 if ((TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc15, -1, field5Value1, -1) == TS_ERROR) ||
5332 (TSMimeHdrFieldValueIntInsert(bufp1, mime_loc1, field_loc15, -1, field5Value2) == TS_ERROR) ||
5333 (TSMimeHdrFieldValueStringInsert(bufp1, mime_loc1, field_loc15, -1, field5Value3, -1) == TS_ERROR) ||
5334 (TSMimeHdrFieldValueUintInsert(bufp1, mime_loc1, field_loc15, -1, field5Value4) == TS_ERROR)) {
5335 SDK_RPRINT(test, "TSMimeHdrFieldValueAppend", "TestCase1", TC_FAIL,
5336 "TSMimeHdrFieldValueString|Int|UintInsert returns TS_ERROR. Cannot create field for testing.");
5337 SDK_RPRINT(test, "TSMimeHdrFieldValueDelete", "TestCase1", TC_FAIL,
5338 "TSMimeHdrFieldValueString|Int|UintInsert returns TS_ERROR. Cannot create field for testing.");
5339 SDK_RPRINT(test, "TSMimeHdrFieldValuesCount", "TestCase1", TC_FAIL,
5340 "TSMimeHdrFieldValueString|Int|UintInsert returns TS_ERROR. Cannot create field for testing.");
5341 SDK_RPRINT(test, "TSMimeHdrFieldValuesClear", "TestCase1", TC_FAIL,
5342 "TSMimeHdrFieldValueString|Int|UintInsert returns TS_ERROR. Cannot create field for testing.");
5343 } else {
5344 if (TSMimeHdrFieldValueAppend(bufp1, mime_loc1, field_loc15, 0, field5Value1Append, -1) == TS_ERROR) {
5345 SDK_RPRINT(test, "TSMimeHdrFieldValueAppend", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueAppend returns TS_ERROR");
5346 } else {
5347 fieldValueAppendGet = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc15, 0, &lengthFieldValueAppended);
5348 char *expected_value;
5349 size_t len = strlen(field5Value1) + strlen(field5Value1Append) + 1;
5350 expected_value = static_cast<char *>(TSmalloc(len));
5351 memset(expected_value, 0, len);
5352 ink_strlcpy(expected_value, field5Value1, len);
5353 ink_strlcat(expected_value, field5Value1Append, len);
5354 if ((strncmp(fieldValueAppendGet, expected_value, lengthFieldValueAppended) == 0) &&
5355 (lengthFieldValueAppended = strlen(expected_value))) {
5356 SDK_RPRINT(test, "TSMimeHdrFieldValueAppend", "TestCase1", TC_PASS, "ok");
5357 test_passed_Mime_Hdr_Field_Value_Append = true;
5358 } else {
5359 SDK_RPRINT(test, "TSMimeHdrFieldValueAppend", "TestCase1", TC_FAIL, "Values mismatch");
5360 }
5361 TSfree(expected_value);
5362 }
5363
5364 numberOfValueInField = TSMimeHdrFieldValuesCount(bufp1, mime_loc1, field_loc15);
5365 if (numberOfValueInField == 4) {
5366 SDK_RPRINT(test, "TSMimeHdrFieldValuesCount", "TestCase1", TC_PASS, "ok");
5367 test_passed_Mime_Hdr_Field_Values_Count = true;
5368 } else {
5369 SDK_RPRINT(test, "TSMimeHdrFieldValuesCount", "TestCase1", TC_FAIL, "Values don't match");
5370 }
5371
5372 if (TSMimeHdrFieldValueDelete(bufp1, mime_loc1, field_loc15, 2) == TS_ERROR) {
5373 SDK_RPRINT(test, "TSMimeHdrFieldValueDelete", "TestCase1", TC_FAIL, "TSMimeHdrFieldValueDelete Returns TS_ERROR");
5374 } else {
5375 fieldValueDeleteGet = TSMimeHdrFieldValueStringGet(bufp1, mime_loc1, field_loc15, 2, &lengthFieldValueDeleteGet);
5376 if ((strncmp(fieldValueDeleteGet, field5Value3, lengthFieldValueDeleteGet) == 0) &&
5377 (lengthFieldValueDeleteGet == static_cast<int>(strlen(field5Value3)))) {
5378 SDK_RPRINT(test, "TSMimeHdrFieldValueDelete", "TestCase1", TC_FAIL,
5379 "Value not deleted from field or incorrect index deleted from field.");
5380 } else {
5381 SDK_RPRINT(test, "TSMimeHdrFieldValueDelete", "TestCase1", TC_PASS, "ok");
5382 test_passed_Mime_Hdr_Field_Value_Delete = true;
5383 }
5384 }
5385
5386 if (TSMimeHdrFieldValuesClear(bufp1, mime_loc1, field_loc15) == TS_ERROR) {
5387 SDK_RPRINT(test, "TSMimeHdrFieldValuesClear", "TestCase1", TC_FAIL, "TSMimeHdrFieldValuesClear returns TS_ERROR");
5388 } else {
5389 numberOfValueInField = TSMimeHdrFieldValuesCount(bufp1, mime_loc1, field_loc15);
5390 if (numberOfValueInField == 0) {
5391 SDK_RPRINT(test, "TSMimeHdrFieldValuesClear", "TestCase1", TC_PASS, "ok");
5392 test_passed_Mime_Hdr_Field_Values_Clear = true;
5393 } else {
5394 SDK_RPRINT(test, "TSMimeHdrFieldValuesClear", "TestCase1", TC_FAIL, "Values don't match");
5395 }
5396 }
5397 }
5398
5399 // TSMimeHdrFieldDestroy
5400 if (TSMimeHdrFieldDestroy(bufp1, mime_loc1, field_loc15) != TS_SUCCESS) {
5401 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase1", TC_FAIL, "TSMimeHdrFieldDestroy returns TS_ERROR");
5402 } else {
5403 if ((test_field_loc15 = TSMimeHdrFieldFind(bufp1, mime_loc1, field5Name, -1)) == TS_NULL_MLOC) {
5404 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase1", TC_PASS, "ok");
5405 test_passed_Mime_Hdr_Field_Destroy = true;
5406 } else {
5407 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase1", TC_FAIL, "Field not destroyed");
5408 if (TSHandleMLocRelease(bufp1, mime_loc1, test_field_loc15) == TS_ERROR) {
5409 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase1", TC_FAIL, "Unable to release handle using TSHandleMLocRelease");
5410 }
5411 }
5412 if (TSHandleMLocRelease(bufp1, mime_loc1, field_loc15) == TS_ERROR) {
5413 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase2", TC_FAIL, "Unable to release handle using TSHandleMLocRelease");
5414 }
5415 }
5416 } else {
5417 SDK_RPRINT(test, "TSMimeHdrFieldValueAppend", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrFieldCreate has failed");
5418 SDK_RPRINT(test, "TSMimeHdrFieldValueDelete", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrFieldCreate has failed");
5419 SDK_RPRINT(test, "TSMimeHdrFieldValuesCount", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrFieldCreate has failed");
5420 SDK_RPRINT(test, "TSMimeHdrFieldValuesClear", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrFieldCreate has failed");
5421 SDK_RPRINT(test, "TSMimeHdrFieldDestroy", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrFieldCreate has failed");
5422 }
5423
5424 // Mime Hdr Fields Clear
5425 if (test_passed_Mime_Hdr_Field_Append == true) {
5426 if (TSMimeHdrFieldsClear(bufp1, mime_loc1) != TS_SUCCESS) {
5427 SDK_RPRINT(test, "TSMimeHdrFieldsClear", "TestCase1", TC_FAIL, "TSMimeHdrFieldsClear returns TS_ERROR");
5428 } else {
5429 if ((numberOfFields = TSMimeHdrFieldsCount(bufp1, mime_loc1)) < 0) {
5430 SDK_RPRINT(test, "TSMimeHdrFieldsClear", "TestCase1", TC_FAIL, "TSMimeHdrFieldsCount returns TS_ERROR");
5431 } else {
5432 if (numberOfFields == 0) {
5433 SDK_RPRINT(test, "TSMimeHdrFieldsClear", "TestCase1", TC_PASS, "ok");
5434 test_passed_Mime_Hdr_Fields_Clear = true;
5435 } else {
5436 SDK_RPRINT(test, "TSMimeHdrFieldsClear", "TestCase1", TC_FAIL, "Fields still exist");
5437 }
5438 }
5439 if ((TSHandleMLocRelease(bufp1, mime_loc1, field_loc11) == TS_ERROR) ||
5440 (TSHandleMLocRelease(bufp1, mime_loc1, field_loc12) == TS_ERROR) ||
5441 (TSHandleMLocRelease(bufp1, mime_loc1, field_loc13) == TS_ERROR) ||
5442 (TSHandleMLocRelease(bufp1, mime_loc1, field_loc14) == TS_ERROR)) {
5443 SDK_RPRINT(test, "TSMimeHdrFieldsDestroy", "", TC_FAIL, "Unable to release handle using TSHandleMLocRelease");
5444 }
5445 }
5446 } else {
5447 SDK_RPRINT(test, "TSMimeHdrFieldsClear", "TestCase1", TC_FAIL,
5448 "Cannot run test as Fields have not been inserted in the mime header");
5449 }
5450
5451 // Mime Hdr Destroy
5452 if (test_passed_Mime_Hdr_Create == true) {
5453 if (TSMimeHdrDestroy(bufp1, mime_loc1) == TS_ERROR) {
5454 SDK_RPRINT(test, "TSMimeHdrDestroy", "TestCase1", TC_FAIL, "TSMimeHdrDestroy return TS_ERROR");
5455 SDK_RPRINT(test, "TSMimeHdrDestroy", "TestCase1", TC_FAIL, "Probably TSMimeHdrCreate failed.");
5456 } else {
5457 SDK_RPRINT(test, "TSMimeHdrDestroy", "TestCase1", TC_PASS, "ok");
5458 test_passed_Mime_Hdr_Destroy = true;
5459 }
5460 /** Commented out as Traffic Server was crashing. Will have to look into it. */
5461 /*
5462 if (TSHandleMLocRelease(bufp1,TS_NULL_MLOC,mime_loc1)==TS_ERROR) {
5463 SDK_RPRINT(test,"TSHandleMLocRelease","TSMimeHdrDestroy",TC_FAIL,"unable to release handle using TSHandleMLocRelease");
5464 }
5465 */
5466 } else {
5467 SDK_RPRINT(test, "TSMimeHdrDestroy", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrCreate failed");
5468 }
5469
5470 // MBuffer Destroy
5471 if (test_passed_MBuffer_Create == true) {
5472 if (TSMBufferDestroy(bufp1) == TS_ERROR) {
5473 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase1", TC_FAIL, "TSMBufferDestroy return TS_ERROR");
5474 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase1", TC_FAIL, "Probably TSMBufferCreate failed.");
5475 } else {
5476 SDK_RPRINT(test, "TSMBufferDestroy", "TestCase1", TC_PASS, "ok");
5477 test_passed_MBuffer_Destroy = true;
5478 }
5479 } else {
5480 SDK_RPRINT(test, "TSMimeHdrDestroy", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrCreate failed");
5481 }
5482
5483 if ((test_passed_MBuffer_Create == true) && (test_passed_Mime_Hdr_Create == true) &&
5484 (test_passed_Mime_Hdr_Field_Create == true) && (test_passed_Mime_Hdr_Field_Name == true) &&
5485 (test_passed_Mime_Hdr_Field_Append == true) && (test_passed_Mime_Hdr_Field_Get == true) &&
5486 (test_passed_Mime_Hdr_Field_Next == true) && (test_passed_Mime_Hdr_Fields_Count == true) &&
5487 (test_passed_Mime_Hdr_Field_Value_String_Insert == true) && (test_passed_Mime_Hdr_Field_Value_String_Get == true) &&
5488 (test_passed_Mime_Hdr_Field_Value_String_Set == true) && (test_passed_Mime_Hdr_Field_Value_Date_Insert == true) &&
5489 (test_passed_Mime_Hdr_Field_Value_Date_Get == true) && (test_passed_Mime_Hdr_Field_Value_Date_Set == true) &&
5490 (test_passed_Mime_Hdr_Field_Value_Int_Insert == true) && (test_passed_Mime_Hdr_Field_Value_Int_Get == true) &&
5491 (test_passed_Mime_Hdr_Field_Value_Int_Set == true) && (test_passed_Mime_Hdr_Field_Value_Uint_Insert == true) &&
5492 (test_passed_Mime_Hdr_Field_Value_Uint_Get == true) && (test_passed_Mime_Hdr_Field_Value_Uint_Set == true) &&
5493 (test_passed_Mime_Hdr_Field_Value_Append == true) && (test_passed_Mime_Hdr_Field_Value_Delete == true) &&
5494 (test_passed_Mime_Hdr_Field_Values_Clear == true) && (test_passed_Mime_Hdr_Field_Values_Count == true) &&
5495 (test_passed_Mime_Hdr_Field_Destroy == true) && (test_passed_Mime_Hdr_Fields_Clear == true) &&
5496 (test_passed_Mime_Hdr_Destroy == true) && (test_passed_MBuffer_Destroy == true) &&
5497 (test_passed_Mime_Hdr_Field_Length_Get == true)) {
5498 *pstatus = REGRESSION_TEST_PASSED;
5499 } else {
5500 *pstatus = REGRESSION_TEST_FAILED;
5501 }
5502 return;
5503 }
5504
5505 //////////////////////////////////////////////
5506 // SDK_API_TSHttpHdrParse
5507 //
5508 // Unit Test for API: TSHttpParserCreate
5509 // TSHttpParserDestroy
5510 // TSHttpParserClear
5511 // TSHttpHdrParseReq
5512 // TSHttpHdrParseResp
5513 //////////////////////////////////////////////
5514
5515 char *
convert_http_hdr_to_string(TSMBuffer bufp,TSMLoc hdr_loc)5516 convert_http_hdr_to_string(TSMBuffer bufp, TSMLoc hdr_loc)
5517 {
5518 TSIOBuffer output_buffer;
5519 TSIOBufferReader reader;
5520 int64_t total_avail;
5521
5522 TSIOBufferBlock block;
5523 const char *block_start;
5524 int64_t block_avail;
5525
5526 char *output_string;
5527 int output_len;
5528
5529 output_buffer = TSIOBufferCreate();
5530
5531 if (!output_buffer) {
5532 TSError("[InkAPITest] couldn't allocate IOBuffer");
5533 }
5534
5535 reader = TSIOBufferReaderAlloc(output_buffer);
5536
5537 /* This will print just MIMEFields and not
5538 the http request line */
5539 TSHttpHdrPrint(bufp, hdr_loc, output_buffer);
5540
5541 /* Find out how the big the complete header is by
5542 seeing the total bytes in the buffer. We need to
5543 look at the buffer rather than the first block to
5544 see the size of the entire header */
5545 total_avail = TSIOBufferReaderAvail(reader);
5546
5547 /* Allocate the string with an extra byte for the string
5548 terminator */
5549 output_string = static_cast<char *>(TSmalloc(total_avail + 1));
5550 output_len = 0;
5551
5552 /* We need to loop over all the buffer blocks to make
5553 sure we get the complete header since the header can
5554 be in multiple blocks */
5555 block = TSIOBufferReaderStart(reader);
5556 while (block) {
5557 block_start = TSIOBufferBlockReadStart(block, reader, &block_avail);
5558
5559 /* We'll get a block pointer back even if there is no data
5560 left to read so check for this condition and break out of
5561 the loop. A block with no data to read means we've exhausted
5562 buffer of data since if there was more data on a later
5563 block in the chain, this block would have been skipped over */
5564 if (block_avail == 0) {
5565 break;
5566 }
5567
5568 memcpy(output_string + output_len, block_start, block_avail);
5569 output_len += block_avail;
5570
5571 /* Consume the data so that we get to the next block */
5572 TSIOBufferReaderConsume(reader, block_avail);
5573
5574 /* Get the next block now that we've consumed the
5575 data off the last block */
5576 block = TSIOBufferReaderStart(reader);
5577 }
5578
5579 /* Terminate the string */
5580 output_string[output_len] = '\0';
5581 output_len++;
5582
5583 /* Free up the TSIOBuffer that we used to print out the header */
5584 TSIOBufferReaderFree(reader);
5585 TSIOBufferDestroy(output_buffer);
5586
5587 return output_string;
5588 }
5589
REGRESSION_TEST(SDK_API_TSHttpHdrParse)5590 REGRESSION_TEST(SDK_API_TSHttpHdrParse)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
5591 {
5592 const char *req =
5593 "GET http://www.example.com/ HTTP/1.1\r\nmimefield1:field1value1,field1value2\r\nmimefield2:field2value1,field2value2\r\n\r\n";
5594 const char *resp = "HTTP/1.1 200 OK\r\n1mimefield:1field1value,1field2value\r\n2mimefield:2field1value,2field2value\r\n\r\n";
5595 const char *start;
5596 const char *end;
5597 char *temp;
5598
5599 int retval;
5600
5601 TSMBuffer reqbufp;
5602 TSMBuffer respbufp = (TSMBuffer) nullptr;
5603
5604 TSMLoc req_hdr_loc = (TSMLoc) nullptr;
5605 TSMLoc resp_hdr_loc = (TSMLoc) nullptr;
5606
5607 TSHttpParser parser;
5608
5609 bool test_passed_parse_req = false;
5610 bool test_passed_parse_resp = false;
5611 bool test_passed_parser_clear = false;
5612 bool test_passed_parser_destroy = false;
5613
5614 // Create Parser
5615 parser = TSHttpParserCreate();
5616 SDK_RPRINT(test, "TSHttpParserCreate", "TestCase1", TC_PASS, "ok");
5617
5618 // Request
5619 reqbufp = TSMBufferCreate();
5620 req_hdr_loc = TSHttpHdrCreate(reqbufp);
5621 start = req;
5622 end = req + strlen(req) + 1;
5623 if ((retval = TSHttpHdrParseReq(parser, reqbufp, req_hdr_loc, &start, end)) == TS_PARSE_ERROR) {
5624 SDK_RPRINT(test, "TSHttpHdrParseReq", "TestCase1", TC_FAIL, "TSHttpHdrParseReq returns TS_PARSE_ERROR");
5625 } else {
5626 if (retval == TS_PARSE_DONE) {
5627 test_passed_parse_req = true;
5628 } else {
5629 SDK_RPRINT(test, "TSHttpHdrParseReq", "TestCase1", TC_FAIL, "Parsing Error");
5630 }
5631 }
5632
5633 TSHttpParserClear(parser);
5634 SDK_RPRINT(test, "TSHttpParserClear", "TestCase1", TC_PASS, "ok");
5635 test_passed_parser_clear = true;
5636
5637 // Response
5638 if (test_passed_parser_clear == true) {
5639 respbufp = TSMBufferCreate();
5640 resp_hdr_loc = TSHttpHdrCreate(respbufp);
5641 start = resp;
5642 end = resp + strlen(resp) + 1;
5643 if ((retval = TSHttpHdrParseResp(parser, respbufp, resp_hdr_loc, &start, end)) == TS_PARSE_ERROR) {
5644 SDK_RPRINT(test, "TSHttpHdrParseResp", "TestCase1", TC_FAIL, "TSHttpHdrParseResp returns TS_PARSE_ERROR.");
5645 } else {
5646 if (retval == TS_PARSE_DONE) {
5647 test_passed_parse_resp = true;
5648 } else {
5649 SDK_RPRINT(test, "TSHttpHdrParseResp", "TestCase1", TC_FAIL, "Parsing Error");
5650 }
5651 }
5652 }
5653
5654 if (test_passed_parse_req == true) {
5655 temp = convert_http_hdr_to_string(reqbufp, req_hdr_loc);
5656 if (strcmp(req, temp) == 0) {
5657 SDK_RPRINT(test, "TSHttpHdrParseReq", "TestCase1", TC_PASS, "ok");
5658 } else {
5659 SDK_RPRINT(test, "TSHttpHdrParseReq", "TestCase1", TC_FAIL, "Incorrect parsing");
5660 test_passed_parse_req = false;
5661 }
5662 TSfree(temp);
5663 }
5664
5665 if (test_passed_parse_resp == true) {
5666 temp = convert_http_hdr_to_string(respbufp, resp_hdr_loc);
5667 if (strcmp(resp, temp) == 0) {
5668 SDK_RPRINT(test, "TSHttpHdrParseResp", "TestCase1", TC_PASS, "ok");
5669 } else {
5670 SDK_RPRINT(test, "TSHttpHdrParseResp", "TestCase1", TC_FAIL, "Incorrect parsing");
5671 test_passed_parse_resp = false;
5672 }
5673 TSfree(temp);
5674 }
5675
5676 TSHttpParserDestroy(parser);
5677 SDK_RPRINT(test, "TSHttpParserDestroy", "TestCase1", TC_PASS, "ok");
5678 test_passed_parser_destroy = true;
5679
5680 if ((test_passed_parse_req != true) || (test_passed_parse_resp != true) || (test_passed_parser_clear != true) ||
5681 (test_passed_parser_destroy != true)) {
5682 *pstatus = REGRESSION_TEST_FAILED;
5683 } else {
5684 *pstatus = REGRESSION_TEST_PASSED;
5685 }
5686
5687 TSMimeHdrDestroy(reqbufp, req_hdr_loc);
5688 TSHandleMLocRelease(reqbufp, TS_NULL_MLOC, req_hdr_loc);
5689 TSMBufferDestroy(reqbufp);
5690
5691 if (resp_hdr_loc) {
5692 TSMimeHdrDestroy(respbufp, resp_hdr_loc);
5693 TSHandleMLocRelease(respbufp, TS_NULL_MLOC, resp_hdr_loc);
5694 }
5695
5696 if (respbufp) {
5697 TSMBufferDestroy(respbufp);
5698 }
5699
5700 return;
5701 }
5702
5703 //////////////////////////////////////////////
5704 // SDK_API_TSMimeHdrParse
5705 //
5706 // Unit Test for API: TSMimeHdrCopy
5707 // TSMimeHdrClone
5708 // TSMimeHdrFieldCopy
5709 // TSMimeHdrFieldClone
5710 // TSMimeHdrFieldCopyValues
5711 // TSMimeHdrFieldNextDup
5712 // TSMimeHdrFieldRemove
5713 // TSMimeHdrLengthGet
5714 // TSMimeHdrParse
5715 // TSMimeHdrPrint
5716 // TSMimeParserClear
5717 // TSMimeParserCreate
5718 // TSMimeParserDestroy
5719 // TSHandleMLocRelease
5720 //////////////////////////////////////////////
5721
5722 static char *
convert_mime_hdr_to_string(TSMBuffer bufp,TSMLoc hdr_loc)5723 convert_mime_hdr_to_string(TSMBuffer bufp, TSMLoc hdr_loc)
5724 {
5725 TSIOBuffer output_buffer;
5726 TSIOBufferReader reader;
5727 int64_t total_avail;
5728
5729 TSIOBufferBlock block;
5730 const char *block_start;
5731 int64_t block_avail;
5732
5733 char *output_string;
5734 int output_len;
5735
5736 output_buffer = TSIOBufferCreate();
5737
5738 if (!output_buffer) {
5739 TSError("[InkAPITest] couldn't allocate IOBuffer");
5740 }
5741
5742 reader = TSIOBufferReaderAlloc(output_buffer);
5743
5744 /* This will print just MIMEFields and not
5745 the http request line */
5746 TSMimeHdrPrint(bufp, hdr_loc, output_buffer);
5747
5748 /* Find out how the big the complete header is by
5749 seeing the total bytes in the buffer. We need to
5750 look at the buffer rather than the first block to
5751 see the size of the entire header */
5752 total_avail = TSIOBufferReaderAvail(reader);
5753
5754 /* Allocate the string with an extra byte for the string
5755 terminator */
5756 output_string = static_cast<char *>(TSmalloc(total_avail + 1));
5757 output_len = 0;
5758
5759 /* We need to loop over all the buffer blocks to make
5760 sure we get the complete header since the header can
5761 be in multiple blocks */
5762 block = TSIOBufferReaderStart(reader);
5763 while (block) {
5764 block_start = TSIOBufferBlockReadStart(block, reader, &block_avail);
5765
5766 /* We'll get a block pointer back even if there is no data
5767 left to read so check for this condition and break out of
5768 the loop. A block with no data to read means we've exhausted
5769 buffer of data since if there was more data on a later
5770 block in the chain, this block would have been skipped over */
5771 if (block_avail == 0) {
5772 break;
5773 }
5774
5775 memcpy(output_string + output_len, block_start, block_avail);
5776 output_len += block_avail;
5777
5778 /* Consume the data so that we get to the next block */
5779 TSIOBufferReaderConsume(reader, block_avail);
5780
5781 /* Get the next block now that we've consumed the
5782 data off the last block */
5783 block = TSIOBufferReaderStart(reader);
5784 }
5785
5786 /* Terminate the string */
5787 output_string[output_len] = '\0';
5788 output_len++;
5789
5790 /* Free up the TSIOBuffer that we used to print out the header */
5791 TSIOBufferReaderFree(reader);
5792 TSIOBufferDestroy(output_buffer);
5793
5794 return output_string;
5795 }
5796
5797 TSReturnCode
compare_field_values(RegressionTest * test,TSMBuffer bufp1,TSMLoc hdr_loc1,TSMLoc field_loc1,TSMBuffer bufp2,TSMLoc hdr_loc2,TSMLoc field_loc2)5798 compare_field_values(RegressionTest *test, TSMBuffer bufp1, TSMLoc hdr_loc1, TSMLoc field_loc1, TSMBuffer bufp2, TSMLoc hdr_loc2,
5799 TSMLoc field_loc2)
5800 {
5801 int no_of_values1;
5802 int no_of_values2;
5803 int i;
5804
5805 const char *str1 = nullptr;
5806 const char *str2 = nullptr;
5807
5808 int length1 = 0;
5809 int length2 = 0;
5810
5811 no_of_values1 = TSMimeHdrFieldValuesCount(bufp1, hdr_loc1, field_loc1);
5812 no_of_values2 = TSMimeHdrFieldValuesCount(bufp2, hdr_loc2, field_loc2);
5813 if (no_of_values1 != no_of_values2) {
5814 SDK_RPRINT(test, "compare_field_values", "TestCase", TC_FAIL, "Field Values not equal");
5815 return TS_ERROR;
5816 }
5817
5818 for (i = 0; i < no_of_values1; i++) {
5819 str1 = TSMimeHdrFieldValueStringGet(bufp1, hdr_loc1, field_loc1, i, &length1);
5820 str2 = TSMimeHdrFieldValueStringGet(bufp2, hdr_loc2, field_loc2, i, &length2);
5821 if (!((length1 == length2) && (strncmp(str1, str2, length1) == 0))) {
5822 SDK_RPRINT(test, "compare_field_values", "TestCase", TC_FAIL, "Field Value %d differ from each other", i);
5823 return TS_ERROR;
5824 }
5825 }
5826
5827 return TS_SUCCESS;
5828 }
5829
REGRESSION_TEST(SDK_API_TSMimeHdrParse)5830 REGRESSION_TEST(SDK_API_TSMimeHdrParse)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
5831 {
5832 const char *parse_string =
5833 "field1:field1Value1,field1Value2\r\nfield2:10,-34,45\r\nfield3:field3Value1,23\r\nfield2: 2345, field2Value2\r\n\r\n";
5834 const char *DUPLICATE_FIELD_NAME = "field2";
5835 const char *REMOVE_FIELD_NAME = "field3";
5836
5837 TSMimeParser parser;
5838
5839 TSMBuffer bufp1 = (TSMBuffer) nullptr;
5840 TSMBuffer bufp2 = (TSMBuffer) nullptr;
5841 TSMBuffer bufp3 = (TSMBuffer) nullptr;
5842
5843 TSMLoc mime_hdr_loc1 = (TSMLoc) nullptr;
5844 TSMLoc mime_hdr_loc2 = (TSMLoc) nullptr;
5845 TSMLoc mime_hdr_loc3 = (TSMLoc) nullptr;
5846
5847 TSMLoc field_loc1 = (TSMLoc) nullptr;
5848 TSMLoc field_loc2 = (TSMLoc) nullptr;
5849
5850 const char *start;
5851 const char *end;
5852 char *temp;
5853
5854 TSParseResult retval;
5855 int hdrLength;
5856
5857 bool test_passed_parse = false;
5858 bool test_passed_parser_clear = false;
5859 bool test_passed_parser_destroy = false;
5860 bool test_passed_mime_hdr_print = false;
5861 bool test_passed_mime_hdr_length_get = false;
5862 bool test_passed_mime_hdr_field_next_dup = false;
5863 bool test_passed_mime_hdr_copy = false;
5864 bool test_passed_mime_hdr_field_remove = false;
5865 bool test_passed_mime_hdr_field_copy = false;
5866 bool test_passed_mime_hdr_field_copy_values = false;
5867 bool test_passed_handle_mloc_release = false;
5868 bool test_passed_mime_hdr_field_find = false;
5869
5870 // Create Parser
5871 parser = TSMimeParserCreate();
5872 SDK_RPRINT(test, "TSMimeParserCreate", "TestCase1", TC_PASS, "ok");
5873
5874 // Parsing
5875 bufp1 = TSMBufferCreate();
5876 if (TSMimeHdrCreate(bufp1, &mime_hdr_loc1) != TS_SUCCESS) {
5877 SDK_RPRINT(test, "TSMimeHdrParse", "TestCase1", TC_FAIL, "Cannot create Mime hdr for parsing");
5878 SDK_RPRINT(test, "TSMimeHdrPrint", "TestCase1", TC_FAIL, "Cannot run test as unable to create Mime Header for parsing");
5879 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_FAIL, "Cannot run test as unable to create Mime Header for parsing");
5880
5881 if (TSMBufferDestroy(bufp1) == TS_ERROR) {
5882 SDK_RPRINT(test, "TSMimeHdrParse", "TestCase1", TC_FAIL, "Error in Destroying MBuffer");
5883 }
5884 } else {
5885 start = parse_string;
5886 end = parse_string + strlen(parse_string) + 1;
5887 if ((retval = TSMimeHdrParse(parser, bufp1, mime_hdr_loc1, &start, end)) == TS_PARSE_ERROR) {
5888 SDK_RPRINT(test, "TSMimeHdrParse", "TestCase1", TC_FAIL, "TSMimeHdrParse returns TS_PARSE_ERROR");
5889 SDK_RPRINT(test, "TSMimeHdrPrint", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrParse returned Error.");
5890 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrParse returned Error.");
5891 } else {
5892 if (retval == TS_PARSE_DONE) {
5893 temp = convert_mime_hdr_to_string(bufp1, mime_hdr_loc1); // Implements TSMimeHdrPrint.
5894 if (strcmp(parse_string, temp) == 0) {
5895 SDK_RPRINT(test, "TSMimeHdrParse", "TestCase1", TC_PASS, "ok");
5896 SDK_RPRINT(test, "TSMimeHdrPrint", "TestCase1", TC_PASS, "ok");
5897
5898 // TSMimeHdrLengthGet
5899 hdrLength = TSMimeHdrLengthGet(bufp1, mime_hdr_loc1);
5900 if (hdrLength == static_cast<int>(strlen(temp))) {
5901 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_PASS, "ok");
5902 test_passed_mime_hdr_length_get = true;
5903 } else {
5904 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_FAIL, "Value's Mismatch");
5905 }
5906
5907 test_passed_parse = true;
5908 test_passed_mime_hdr_print = true;
5909 } else {
5910 SDK_RPRINT(test, "TSMimeHdrParse|TSMimeHdrPrint", "TestCase1", TC_FAIL, "Incorrect parsing or incorrect Printing");
5911 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrParse|TSMimeHdrPrint failed.");
5912 }
5913
5914 TSfree(temp);
5915 } else {
5916 SDK_RPRINT(test, "TSMimeHdrParse", "TestCase1", TC_FAIL, "Parsing Error");
5917 SDK_RPRINT(test, "TSMimeHdrPrint", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrParse returned error.");
5918 SDK_RPRINT(test, "TSMimeHdrLengthGet", "TestCase1", TC_FAIL, "Cannot run test as TSMimeHdrParse returned error.");
5919 }
5920 }
5921 }
5922
5923 TSMimeParserClear(parser);
5924 SDK_RPRINT(test, "TSMimeParserClear", "TestCase1", TC_PASS, "ok");
5925 test_passed_parser_clear = true;
5926
5927 TSMimeParserDestroy(parser);
5928 SDK_RPRINT(test, "TSMimeParserDestroy", "TestCase1", TC_PASS, "ok");
5929 test_passed_parser_destroy = true;
5930
5931 // TSMimeHdrFieldNextDup
5932 if (test_passed_parse == true) {
5933 if ((field_loc1 = TSMimeHdrFieldFind(bufp1, mime_hdr_loc1, DUPLICATE_FIELD_NAME, -1)) == TS_NULL_MLOC) {
5934 SDK_RPRINT(test, "TSMimeHdrFieldNextDup", "TestCase1", TC_FAIL, "TSMimeHdrFieldFind returns TS_NULL_MLOC");
5935 SDK_RPRINT(test, "TSMimeHdrFieldFind", "TestCase1", TC_PASS, "TSMimeHdrFieldFind returns TS_NULL_MLOC");
5936 } else {
5937 const char *fieldName;
5938 int length;
5939
5940 fieldName = TSMimeHdrFieldNameGet(bufp1, mime_hdr_loc1, field_loc1, &length);
5941 if (strncmp(fieldName, DUPLICATE_FIELD_NAME, length) == 0) {
5942 SDK_RPRINT(test, "TSMimeHdrFieldFind", "TestCase1", TC_PASS, "ok");
5943 test_passed_mime_hdr_field_find = true;
5944 } else {
5945 SDK_RPRINT(test, "TSMimeHdrFieldFind", "TestCase1", TC_PASS, "TSMimeHdrFieldFind returns incorrect field pointer");
5946 }
5947
5948 field_loc2 = TSMimeHdrFieldNextDup(bufp1, mime_hdr_loc1, field_loc1);
5949 if (compare_field_names(test, bufp1, mime_hdr_loc1, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
5950 SDK_RPRINT(test, "TSMimeHdrFieldNextDup", "TestCase1", TC_FAIL, "Incorrect Pointer");
5951 } else {
5952 SDK_RPRINT(test, "TSMimeHdrFieldNextDup", "TestCase1", TC_PASS, "ok");
5953 test_passed_mime_hdr_field_next_dup = true;
5954 }
5955
5956 // TSHandleMLocRelease
5957 if (TSHandleMLocRelease(bufp1, mime_hdr_loc1, field_loc1) == TS_ERROR) {
5958 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase1", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
5959 } else {
5960 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase1", TC_PASS, "ok");
5961 test_passed_handle_mloc_release = true;
5962 }
5963
5964 if (field_loc2 != nullptr) {
5965 if (TSHandleMLocRelease(bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
5966 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase2", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
5967 test_passed_handle_mloc_release = false;
5968 } else {
5969 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase2", TC_PASS, "ok");
5970 }
5971 }
5972 }
5973 } else {
5974 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase1", TC_FAIL, "Unable to run test as parsing failed.");
5975 }
5976
5977 // TSMimeHdrCopy
5978 if (test_passed_parse == true) {
5979 // Parsing
5980 bufp2 = TSMBufferCreate();
5981 if (TSMimeHdrCreate(bufp2, &mime_hdr_loc2) != TS_SUCCESS) {
5982 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_FAIL, "Cannot create Mime hdr for copying");
5983 if (TSMBufferDestroy(bufp2) == TS_ERROR) {
5984 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_FAIL, "Error in Destroying MBuffer");
5985 }
5986 } else {
5987 if (TSMimeHdrCopy(bufp2, mime_hdr_loc2, bufp1, mime_hdr_loc1) == TS_ERROR) {
5988 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_FAIL, "TSMimeHdrCopy returns TS_ERROR");
5989 } else {
5990 temp = convert_mime_hdr_to_string(bufp2, mime_hdr_loc2); // Implements TSMimeHdrPrint.
5991 if (strcmp(parse_string, temp) == 0) {
5992 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_PASS, "ok");
5993 test_passed_mime_hdr_copy = true;
5994 } else {
5995 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_FAIL, "Value's Mismatch");
5996 }
5997 TSfree(temp);
5998 }
5999 }
6000 } else {
6001 SDK_RPRINT(test, "TSMimeHdrCopy", "TestCase1", TC_FAIL, "Unable to run test as parsing failed.");
6002 }
6003
6004 bufp3 = TSMBufferCreate();
6005 TSMimeHdrCreate(bufp3, &mime_hdr_loc3);
6006
6007 // TSMimeHdrFieldRemove
6008 if (test_passed_mime_hdr_copy == true) {
6009 if ((field_loc1 = TSMimeHdrFieldFind(bufp2, mime_hdr_loc2, REMOVE_FIELD_NAME, -1)) == TS_NULL_MLOC) {
6010 SDK_RPRINT(test, "TSMimeHdrFieldRemove", "TestCase1", TC_FAIL, "TSMimeHdrFieldFind returns TS_NULL_MLOC");
6011 } else {
6012 if (TSMimeHdrFieldRemove(bufp2, mime_hdr_loc2, field_loc1) != TS_SUCCESS) {
6013 SDK_RPRINT(test, "TSMimeHdrFieldRemove", "TestCase1", TC_FAIL, "TSMimeHdrFieldRemove returns TS_ERROR");
6014 } else {
6015 // Make sure the remove actually took effect
6016 field_loc2 = TSMimeHdrFieldFind(bufp2, mime_hdr_loc2, REMOVE_FIELD_NAME, -1);
6017 if ((field_loc2 == TS_NULL_MLOC) || (field_loc1 != field_loc2)) {
6018 test_passed_mime_hdr_field_remove = true;
6019 } else {
6020 SDK_RPRINT(test, "TSMimeHdrFieldRemove", "TestCase1", TC_FAIL, "Field Not Removed");
6021 }
6022
6023 if (test_passed_mime_hdr_field_remove == true) {
6024 if (TSMimeHdrFieldAppend(bufp2, mime_hdr_loc2, field_loc1) != TS_SUCCESS) {
6025 SDK_RPRINT(test, "TSMimeHdrFieldRemove", "TestCase1", TC_FAIL,
6026 "Unable to readd the field to mime header. Probably destroyed");
6027 test_passed_mime_hdr_field_remove = false;
6028 } else {
6029 SDK_RPRINT(test, "TSMimeHdrFieldRemove", "TestCase1", TC_PASS, "ok");
6030 }
6031 }
6032 }
6033
6034 // TSHandleMLocRelease
6035 if (TSHandleMLocRelease(bufp2, mime_hdr_loc2, field_loc1) == TS_ERROR) {
6036 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase3", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6037 test_passed_handle_mloc_release = false;
6038 } else {
6039 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase3", TC_PASS, "ok");
6040 }
6041
6042 if (field_loc2 != nullptr) {
6043 if (TSHandleMLocRelease(bufp2, mime_hdr_loc2, field_loc2) == TS_ERROR) {
6044 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase4", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6045 test_passed_handle_mloc_release = false;
6046 } else {
6047 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase4", TC_PASS, "ok");
6048 }
6049 }
6050 }
6051 } else {
6052 SDK_RPRINT(test, "TSMimeHdrFieldNext", "TestCase1", TC_FAIL, "Unable to run test as parsing failed.");
6053 }
6054
6055 // TSMimeHdrFieldCopy
6056 if (test_passed_mime_hdr_copy == true) {
6057 if (TSMimeHdrFieldCreate(bufp2, mime_hdr_loc2, &field_loc1) != TS_SUCCESS) {
6058 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "Unable to create field for Copying");
6059 } else {
6060 if ((field_loc2 = TSMimeHdrFieldGet(bufp1, mime_hdr_loc1, 0)) == TS_NULL_MLOC) {
6061 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "Unable to get source field for copying");
6062 } else {
6063 if (TSMimeHdrFieldCopy(bufp2, mime_hdr_loc2, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6064 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "TSMimeHdrFieldCopy returns TS_ERROR");
6065 } else {
6066 if ((compare_field_names(test, bufp2, mime_hdr_loc2, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) ||
6067 (compare_field_values(test, bufp2, mime_hdr_loc2, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR)) {
6068 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "Value's Mismatch");
6069 } else {
6070 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_PASS, "ok");
6071 test_passed_mime_hdr_field_copy = true;
6072 }
6073 }
6074 }
6075 if (TSHandleMLocRelease(bufp2, mime_hdr_loc2, field_loc1) == TS_ERROR) {
6076 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase5", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6077 test_passed_handle_mloc_release = false;
6078 } else {
6079 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase5", TC_PASS, "ok");
6080 }
6081
6082 if (field_loc2 != nullptr) {
6083 if (TSHandleMLocRelease(bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6084 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase6", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6085 test_passed_handle_mloc_release = false;
6086 } else {
6087 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase6", TC_PASS, "ok");
6088 }
6089 }
6090 }
6091 } else {
6092 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "Unable to run test as bufp2 might not have been created");
6093 }
6094
6095 // TSMimeHdrFieldClone
6096 field_loc1 = nullptr;
6097 field_loc2 = nullptr;
6098 if ((field_loc2 = TSMimeHdrFieldGet(bufp1, mime_hdr_loc1, 0)) == TS_NULL_MLOC) {
6099 SDK_RPRINT(test, "TSMimeHdrFieldClone", "TestCase1", TC_FAIL, "Unable to get source field for copying");
6100 } else {
6101 if (TSMimeHdrFieldClone(bufp3, mime_hdr_loc3, bufp1, mime_hdr_loc1, field_loc2, &field_loc1) != TS_SUCCESS) {
6102 SDK_RPRINT(test, "TSMimeHdrFieldClone", "TestCase1", TC_FAIL, "TSMimeHdrFieldClone returns TS_ERROR");
6103 } else {
6104 if ((compare_field_names(test, bufp3, mime_hdr_loc3, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) ||
6105 (compare_field_values(test, bufp3, mime_hdr_loc3, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR)) {
6106 SDK_RPRINT(test, "TSMimeHdrFieldClone", "TestCase1", TC_FAIL, "Value's Mismatch");
6107 } else {
6108 SDK_RPRINT(test, "TSMimeHdrFieldClone", "TestCase1", TC_PASS, "ok");
6109 }
6110 }
6111 }
6112 if (field_loc1 != nullptr) {
6113 if (TSHandleMLocRelease(bufp3, mime_hdr_loc3, field_loc1) == TS_ERROR) {
6114 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase7", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6115 test_passed_handle_mloc_release = false;
6116 } else {
6117 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase7", TC_PASS, "ok");
6118 }
6119 }
6120
6121 if (field_loc2 != nullptr) {
6122 if (TSHandleMLocRelease(bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6123 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase8", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6124 test_passed_handle_mloc_release = false;
6125 } else {
6126 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase8", TC_PASS, "ok");
6127 }
6128 }
6129
6130 // TSMimeHdrFieldCopyValues
6131 if (test_passed_mime_hdr_copy == true) {
6132 if (TSMimeHdrFieldCreate(bufp2, mime_hdr_loc2, &field_loc1) != TS_SUCCESS) {
6133 SDK_RPRINT(test, "TSMimeHdrFieldCopyValues", "TestCase1", TC_FAIL, "Unable to create field for Copying");
6134 } else {
6135 if ((field_loc2 = TSMimeHdrFieldGet(bufp1, mime_hdr_loc1, 0)) == TS_NULL_MLOC) {
6136 SDK_RPRINT(test, "TSMimeHdrFieldCopyValues", "TestCase1", TC_FAIL, "Unable to get source field for copying");
6137 } else {
6138 if (TSMimeHdrFieldCopyValues(bufp2, mime_hdr_loc2, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6139 SDK_RPRINT(test, "TSMimeHdrFieldCopyValues", "TestCase1", TC_FAIL, "TSMimeHdrFieldCopy returns TS_ERROR");
6140 } else {
6141 if (compare_field_values(test, bufp2, mime_hdr_loc2, field_loc1, bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6142 SDK_RPRINT(test, "TSMimeHdrFieldCopyValues", "TestCase1", TC_FAIL, "Value's Mismatch");
6143 } else {
6144 SDK_RPRINT(test, "TSMimeHdrFieldCopyValues", "TestCase1", TC_PASS, "ok");
6145 test_passed_mime_hdr_field_copy_values = true;
6146 }
6147 }
6148 }
6149 if (TSHandleMLocRelease(bufp2, mime_hdr_loc2, field_loc1) == TS_ERROR) {
6150 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase9", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6151 test_passed_handle_mloc_release = false;
6152 } else {
6153 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase9", TC_PASS, "ok");
6154 }
6155
6156 if (field_loc2 != nullptr) {
6157 if (TSHandleMLocRelease(bufp1, mime_hdr_loc1, field_loc2) == TS_ERROR) {
6158 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase10", TC_FAIL, "TSHandleMLocRelease returns TS_ERROR");
6159 test_passed_handle_mloc_release = false;
6160 } else {
6161 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase10", TC_PASS, "ok");
6162 }
6163 }
6164 }
6165 } else {
6166 SDK_RPRINT(test, "TSMimeHdrFieldCopy", "TestCase1", TC_FAIL, "Unable to run test as bufp2 might not have been created");
6167 }
6168
6169 if ((TSMimeHdrDestroy(bufp1, mime_hdr_loc1) == TS_ERROR) || (TSMimeHdrDestroy(bufp2, mime_hdr_loc2) == TS_ERROR) ||
6170 (TSMimeHdrDestroy(bufp3, mime_hdr_loc3) == TS_ERROR)) {
6171 SDK_RPRINT(test, "", "TestCase", TC_FAIL, "TSMimeHdrDestroy returns TS_ERROR");
6172 }
6173
6174 if (TSHandleMLocRelease(bufp1, TS_NULL_MLOC, mime_hdr_loc1) == TS_ERROR) {
6175 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase11|12|13", TC_FAIL, "Unable to release mime_hdr_loc1 to Mime Hdrs");
6176 test_passed_handle_mloc_release = false;
6177 }
6178
6179 if (TSHandleMLocRelease(bufp2, TS_NULL_MLOC, mime_hdr_loc2) == TS_ERROR) {
6180 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase11|12|13", TC_FAIL, "Unable to release mime_hdr_loc2 to Mime Hdrs");
6181 test_passed_handle_mloc_release = false;
6182 }
6183
6184 if (TSHandleMLocRelease(bufp3, TS_NULL_MLOC, mime_hdr_loc3) == TS_ERROR) {
6185 SDK_RPRINT(test, "TSHandleMLocRelease", "TestCase11|12|13", TC_FAIL, "Unable to release mime_hdr_loc3 to Mime Hdrs");
6186 test_passed_handle_mloc_release = false;
6187 }
6188
6189 if (TSMBufferDestroy(bufp1) == TS_ERROR) {
6190 SDK_RPRINT(test, "", "TestCase", TC_FAIL, "TSMBufferDestroy(bufp1) returns TS_ERROR");
6191 }
6192
6193 if (TSMBufferDestroy(bufp2) == TS_ERROR) {
6194 SDK_RPRINT(test, "", "TestCase", TC_FAIL, "TSMBufferDestroy(bufp2) returns TS_ERROR");
6195 }
6196
6197 if (TSMBufferDestroy(bufp3) == TS_ERROR) {
6198 SDK_RPRINT(test, "", "TestCase", TC_FAIL, "TSMBufferDestroy(bufp3) returns TS_ERROR");
6199 }
6200
6201 if ((test_passed_parse != true) || (test_passed_parser_clear != true) || (test_passed_parser_destroy != true) ||
6202 (test_passed_mime_hdr_print != true) || (test_passed_mime_hdr_length_get != true) ||
6203 (test_passed_mime_hdr_field_next_dup != true) || (test_passed_mime_hdr_copy != true) ||
6204 (test_passed_mime_hdr_field_remove != true) || (test_passed_mime_hdr_field_copy != true) ||
6205 (test_passed_mime_hdr_field_copy_values != true) || (test_passed_handle_mloc_release != true) ||
6206 (test_passed_mime_hdr_field_find != true)) {
6207 *pstatus = REGRESSION_TEST_FAILED;
6208 } else {
6209 *pstatus = REGRESSION_TEST_PASSED;
6210 }
6211 }
6212
6213 //////////////////////////////////////////////
6214 // SDK_API_TSUrlParse
6215 //
6216 // Unit Test for API: TSUrlParse
6217 //////////////////////////////////////////////
6218
REGRESSION_TEST(SDK_API_TSUrlParse)6219 REGRESSION_TEST(SDK_API_TSUrlParse)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
6220 {
6221 static const char *const urls[] = {
6222 "file:///test.dat;ab?abc=def#abc",
6223 "http://www.example.com/",
6224 "http://abc:def@www.example.com/",
6225 "http://www.example.com:3426/",
6226 "http://abc:def@www.example.com:3426/",
6227 "http://www.example.com/homepage.cgi",
6228 "http://www.example.com/homepage.cgi;ab?abc=def#abc",
6229 "http://abc:def@www.example.com:3426/homepage.cgi;ab?abc=def#abc",
6230 "https://abc:def@www.example.com:3426/homepage.cgi;ab?abc=def#abc",
6231 "ftp://abc:def@www.example.com:3426/homepage.cgi;ab?abc=def#abc",
6232 "file:///c:/test.dat;ab?abc=def#abc", // Note: file://c: is malformed URL because no host is present.
6233 "file:///test.dat;ab?abc=def#abc",
6234 "foo://bar.com/baz/",
6235 "http://a.b.com/xx.jpg?newpath=http://b.c.com" // https://issues.apache.org/jira/browse/TS-1635
6236 };
6237
6238 static int const num_urls = sizeof(urls) / sizeof(urls[0]);
6239 bool test_passed[num_urls] = {false};
6240
6241 const char *start;
6242 const char *end;
6243 char *temp;
6244
6245 int retval;
6246
6247 TSMBuffer bufp;
6248 TSMLoc url_loc = (TSMLoc) nullptr;
6249 int length;
6250
6251 *pstatus = REGRESSION_TEST_INPROGRESS;
6252
6253 int idx;
6254 for (idx = 0; idx < num_urls; idx++) {
6255 const char *url = urls[idx];
6256
6257 bufp = TSMBufferCreate();
6258 if (TSUrlCreate(bufp, &url_loc) != TS_SUCCESS) {
6259 SDK_RPRINT(test, "TSUrlParse", url, TC_FAIL, "Cannot create Url for parsing the url");
6260 if (TSMBufferDestroy(bufp) == TS_ERROR) {
6261 SDK_RPRINT(test, "TSUrlParse", url, TC_FAIL, "Error in Destroying MBuffer");
6262 }
6263 } else {
6264 start = url;
6265 end = url + strlen(url);
6266 if ((retval = TSUrlParse(bufp, url_loc, &start, end)) == TS_PARSE_ERROR) {
6267 SDK_RPRINT(test, "TSUrlParse", url, TC_FAIL, "TSUrlParse returns TS_PARSE_ERROR");
6268 } else {
6269 if (retval == TS_PARSE_DONE) {
6270 temp = TSUrlStringGet(bufp, url_loc, &length);
6271 if (strncmp(url, temp, length) == 0) {
6272 SDK_RPRINT(test, "TSUrlParse", url, TC_PASS, "ok");
6273 test_passed[idx] = true;
6274 } else {
6275 SDK_RPRINT(test, "TSUrlParse", url, TC_FAIL, "Value's Mismatch");
6276 }
6277 TSfree(temp);
6278 } else {
6279 SDK_RPRINT(test, "TSUrlParse", url, TC_FAIL, "Parsing Error");
6280 }
6281 }
6282 }
6283
6284 TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc);
6285 TSMBufferDestroy(bufp);
6286 }
6287
6288 for (idx = 0; idx < num_urls; idx++) {
6289 if (test_passed[idx] != true) {
6290 *pstatus = REGRESSION_TEST_FAILED;
6291 break;
6292 }
6293 }
6294
6295 if (idx >= num_urls) {
6296 *pstatus = REGRESSION_TEST_PASSED;
6297 }
6298
6299 return;
6300 }
6301
6302 //////////////////////////////////////////////
6303 // SDK_API_TSTextLog
6304 //
6305 // Unit Test for APIs: TSTextLogObjectCreate
6306 // TSTextLogObjectWrite
6307 // TSTextLogObjectDestroy
6308 // TSTextLogObjectFlush
6309 //////////////////////////////////////////////
6310 #define LOG_TEST_PATTERN "SDK team rocks"
6311
6312 struct LogTestData {
6313 RegressionTest *test;
6314 int *pstatus;
6315 char *fullpath_logname;
6316 unsigned long magic;
6317 TSTextLogObject log;
6318 };
6319
6320 static int
log_test_handler(TSCont contp,TSEvent event,void *)6321 log_test_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
6322 {
6323 TSFile filep;
6324 char buf[1024];
6325 bool str_found;
6326 int retVal = 0;
6327
6328 TSAssert(event == TS_EVENT_TIMEOUT);
6329
6330 LogTestData *data = static_cast<LogTestData *>(TSContDataGet(contp));
6331 TSAssert(data->magic == MAGIC_ALIVE);
6332
6333 // Verify content was correctly written into log file
6334
6335 if ((filep = TSfopen(data->fullpath_logname, "r")) == nullptr) {
6336 SDK_RPRINT(data->test, "TSTextLogObject", "TestCase1", TC_FAIL, "can not open log file %s", data->fullpath_logname);
6337 *(data->pstatus) = REGRESSION_TEST_FAILED;
6338 return -1;
6339 } else {
6340 // The logfile is created
6341 str_found = false;
6342 while (TSfgets(filep, buf, 1024) != nullptr) {
6343 if (strstr(buf, LOG_TEST_PATTERN) != nullptr) {
6344 str_found = true;
6345 break;
6346 }
6347 }
6348 TSfclose(filep);
6349 if (str_found == false) {
6350 SDK_RPRINT(data->test, "TSTextLogObject", "TestCase1", TC_FAIL, "can not find pattern %s in log file", LOG_TEST_PATTERN);
6351 *(data->pstatus) = REGRESSION_TEST_FAILED;
6352 return -1;
6353 }
6354 }
6355
6356 retVal = TSTextLogObjectDestroy(data->log);
6357 if (retVal != TS_SUCCESS) {
6358 SDK_RPRINT(data->test, "TSTextLogObjectDestroy", "TestCase1", TC_FAIL, "can not destroy log object");
6359 *(data->pstatus) = REGRESSION_TEST_FAILED;
6360 return -1;
6361 } else {
6362 SDK_RPRINT(data->test, "TSTextLogObjectDestroy", "TestCase1", TC_PASS, "ok");
6363 }
6364
6365 *(data->pstatus) = REGRESSION_TEST_PASSED;
6366 SDK_RPRINT(data->test, "TSTextLogObject", "TestCase1", TC_PASS, "ok");
6367
6368 // figure out the metainfo file for cleanup.
6369 // code from MetaInfo::_build_name(const char *filename)
6370 int i = -1, l = 0;
6371 char c;
6372 while (c = data->fullpath_logname[l], c != 0) {
6373 if (c == '/') {
6374 i = l;
6375 }
6376 ++l;
6377 }
6378
6379 // 7 = 1 (dot at beginning) + 5 (".meta") + 1 (null terminating)
6380 //
6381 char *meta_filename = static_cast<char *>(ats_malloc(l + 7));
6382
6383 if (i < 0) {
6384 ink_string_concatenate_strings(meta_filename, ".", data->fullpath_logname, ".meta", NULL);
6385 } else {
6386 memcpy(meta_filename, data->fullpath_logname, i + 1);
6387 ink_string_concatenate_strings(&meta_filename[i + 1], ".", &data->fullpath_logname[i + 1], ".meta", NULL);
6388 }
6389
6390 unlink(data->fullpath_logname);
6391 unlink(meta_filename);
6392 TSfree(data->fullpath_logname);
6393 TSfree(meta_filename);
6394 meta_filename = nullptr;
6395
6396 data->magic = MAGIC_DEAD;
6397 TSfree(data);
6398 data = nullptr;
6399
6400 return -1;
6401 }
6402
REGRESSION_TEST(SDK_API_TSTextLog)6403 REGRESSION_TEST(SDK_API_TSTextLog)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
6404 {
6405 *pstatus = REGRESSION_TEST_INPROGRESS;
6406
6407 TSTextLogObject log;
6408 TSReturnCode retVal;
6409
6410 char logname[PATH_NAME_MAX];
6411 char fullpath_logname[PATH_NAME_MAX];
6412
6413 /* Generate a random log file name, so if we run the test several times, we won't use the
6414 same log file name. */
6415 ats_scoped_str tmp(RecConfigReadLogDir());
6416 snprintf(logname, sizeof(logname), "RegressionTestLog%d.log", static_cast<int>(getpid()));
6417 snprintf(fullpath_logname, sizeof(fullpath_logname), "%s/%s", (const char *)tmp, logname);
6418
6419 unlink(fullpath_logname);
6420 retVal = TSTextLogObjectCreate(logname, TS_LOG_MODE_ADD_TIMESTAMP, &log);
6421 if (retVal != TS_SUCCESS) {
6422 SDK_RPRINT(test, "TSTextLogObjectCreate", "TestCase1", TC_FAIL, "can not create log object");
6423 *pstatus = REGRESSION_TEST_FAILED;
6424 return;
6425 } else {
6426 SDK_RPRINT(test, "TSTextLogObjectCreate", "TestCase1", TC_PASS, "ok");
6427 }
6428
6429 retVal = TSTextLogObjectWrite(log, (char *)LOG_TEST_PATTERN);
6430 if (retVal != TS_SUCCESS) {
6431 SDK_RPRINT(test, "TSTextLogObjectWrite", "TestCase1", TC_FAIL, "can not write to log object");
6432 *pstatus = REGRESSION_TEST_FAILED;
6433 return;
6434 } else {
6435 SDK_RPRINT(test, "TSTextLogObjectWrite", "TestCase1", TC_PASS, "ok");
6436 }
6437
6438 TSTextLogObjectFlush(log);
6439 SDK_RPRINT(test, "TSTextLogObjectFlush", "TestCase1", TC_PASS, "ok");
6440
6441 TSCont log_test_cont = TSContCreate(log_test_handler, TSMutexCreate());
6442 LogTestData *data = static_cast<LogTestData *>(TSmalloc(sizeof(LogTestData)));
6443 data->test = test;
6444 data->pstatus = pstatus;
6445 data->fullpath_logname = TSstrdup(fullpath_logname);
6446 data->magic = MAGIC_ALIVE;
6447 data->log = log;
6448 TSContDataSet(log_test_cont, data);
6449
6450 TSContScheduleOnPool(log_test_cont, 6000, TS_THREAD_POOL_NET);
6451 return;
6452 }
6453
6454 //////////////////////////////////////////////
6455 // SDK_API_TSMgmtGet
6456 //
6457 // Unit Test for APIs: TSMgmtCounterGet
6458 // TSMgmtFloatGet
6459 // TSMgmtIntGet
6460 // TSMgmtStringGet
6461 // TSMgmtDataTypeGet
6462 //////////////////////////////////////////////
6463
REGRESSION_TEST(SDK_API_TSMgmtGet)6464 REGRESSION_TEST(SDK_API_TSMgmtGet)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
6465 {
6466 const char *CONFIG_PARAM_COUNTER_NAME = "proxy.process.ssl.total_tickets_renewed";
6467 int CONFIG_PARAM_COUNTER_VALUE = 0;
6468
6469 const char *CONFIG_PARAM_FLOAT_NAME = "proxy.config.http.background_fill_completed_threshold";
6470 float CONFIG_PARAM_FLOAT_VALUE = 0.0;
6471
6472 const char *CONFIG_PARAM_INT_NAME = "proxy.config.http.cache.http";
6473 int CONFIG_PARAM_INT_VALUE = 1;
6474
6475 const char *CONFIG_PARAM_STRING_NAME = "proxy.config.product_name";
6476 const char *CONFIG_PARAM_STRING_VALUE = "Traffic Server";
6477
6478 *pstatus = REGRESSION_TEST_INPROGRESS;
6479
6480 int err = 0;
6481 TSMgmtCounter cvalue = 0;
6482 TSMgmtFloat fvalue = 0.0;
6483 TSMgmtInt ivalue = -1;
6484 TSMgmtString svalue = nullptr;
6485
6486 if (TS_SUCCESS != TSMgmtCounterGet(CONFIG_PARAM_COUNTER_NAME, &cvalue)) {
6487 SDK_RPRINT(test, "TSMgmtCounterGet", "TestCase1.1", TC_FAIL, "can not get value of param %s", CONFIG_PARAM_COUNTER_NAME);
6488 err = 1;
6489 } else if (cvalue != CONFIG_PARAM_COUNTER_VALUE) {
6490 SDK_RPRINT(test, "TSMgmtCounterGet", "TestCase1.1", TC_FAIL, "got incorrect value of param %s, should have been %d, found %d",
6491 CONFIG_PARAM_COUNTER_NAME, CONFIG_PARAM_COUNTER_VALUE, cvalue);
6492 err = 1;
6493 } else {
6494 SDK_RPRINT(test, "TSMgmtCounterGet", "TestCase1.1", TC_PASS, "ok");
6495 }
6496
6497 if ((TS_SUCCESS != TSMgmtFloatGet(CONFIG_PARAM_FLOAT_NAME, &fvalue)) || (fvalue != CONFIG_PARAM_FLOAT_VALUE)) {
6498 SDK_RPRINT(test, "TSMgmtFloatGet", "TestCase2", TC_FAIL, "can not get value of param %s", CONFIG_PARAM_FLOAT_NAME);
6499 err = 1;
6500 } else {
6501 SDK_RPRINT(test, "TSMgmtFloatGet", "TestCase1.2", TC_PASS, "ok");
6502 }
6503
6504 if ((TSMgmtIntGet(CONFIG_PARAM_INT_NAME, &ivalue) != TS_SUCCESS) || (ivalue != CONFIG_PARAM_INT_VALUE)) {
6505 SDK_RPRINT(test, "TSMgmtIntGet", "TestCase1.3", TC_FAIL, "can not get value of param %s", CONFIG_PARAM_INT_NAME);
6506 err = 1;
6507 } else {
6508 SDK_RPRINT(test, "TSMgmtIntGet", "TestCase1.3", TC_PASS, "ok");
6509 }
6510
6511 if (TS_SUCCESS != TSMgmtStringGet(CONFIG_PARAM_STRING_NAME, &svalue)) {
6512 SDK_RPRINT(test, "TSMgmtStringGet", "TestCase1.4", TC_FAIL, "can not get value of param %s", CONFIG_PARAM_STRING_NAME);
6513 err = 1;
6514 } else if (strcmp(svalue, CONFIG_PARAM_STRING_VALUE) != 0) {
6515 SDK_RPRINT(test, "TSMgmtStringGet", "TestCase1.4", TC_FAIL,
6516 R"(got incorrect value of param %s, should have been "%s", found "%s")", CONFIG_PARAM_STRING_NAME,
6517 CONFIG_PARAM_STRING_VALUE, svalue);
6518 err = 1;
6519 } else {
6520 SDK_RPRINT(test, "TSMgmtStringGet", "TestCase1.4", TC_PASS, "ok");
6521 }
6522
6523 {
6524 TSRecordDataType result;
6525 auto ret = TSMgmtDataTypeGet(CONFIG_PARAM_STRING_NAME, &result);
6526 if (ret != TS_SUCCESS) {
6527 SDK_RPRINT(test, "TSMgmtDataTypeGet", "TestCase1.5", TC_FAIL, "can not get value of param %s", CONFIG_PARAM_STRING_NAME);
6528 err = 1;
6529 } else if (result != TSRecordDataType::TS_RECORDDATATYPE_STRING) {
6530 SDK_RPRINT(test, "TSMgmtDataTypeGet", "TestCase1.5", TC_FAIL, "can not get right type for %s - %d", CONFIG_PARAM_STRING_NAME,
6531 result);
6532 err = 1;
6533 } else {
6534 SDK_RPRINT(test, "TSMgmtDataTypeGet", "TestCase1.5", TC_PASS, "ok");
6535 }
6536 }
6537
6538 if (err) {
6539 *pstatus = REGRESSION_TEST_FAILED;
6540 return;
6541 }
6542
6543 *pstatus = REGRESSION_TEST_PASSED;
6544 SDK_RPRINT(test, "TSMgmtGet", "TestCase1", TC_PASS, "ok");
6545 return;
6546 }
6547
6548 //////////////////////////////////////////////
6549 // SDK_API_TSConstant
6550 //
6551 // Unit Test for APIs: All TS_XXX constants
6552 //
6553 //////////////////////////////////////////////
6554
6555 #define PRINT_DIFF(_x) \
6556 { \
6557 if (_x - ORIG_##_x != 0) { \
6558 test_passed = false; \
6559 SDK_RPRINT(test, "##_x", "TestCase1", TC_FAIL, "%s:Original Value = %d; New Value = %d \n", #_x, _x, ORIG_##_x); \
6560 } \
6561 }
6562
6563 enum ORIG_TSParseResult {
6564 ORIG_TS_PARSE_ERROR = -1,
6565 ORIG_TS_PARSE_DONE = 0,
6566 ORIG_TS_PARSE_CONT = 1,
6567 };
6568
6569 enum ORIG_TSHttpType {
6570 ORIG_TS_HTTP_TYPE_UNKNOWN,
6571 ORIG_TS_HTTP_TYPE_REQUEST,
6572 ORIG_TS_HTTP_TYPE_RESPONSE,
6573 };
6574
6575 enum ORIG_TSHttpStatus {
6576 ORIG_TS_HTTP_STATUS_NONE = 0,
6577
6578 ORIG_TS_HTTP_STATUS_CONTINUE = 100,
6579 ORIG_TS_HTTP_STATUS_SWITCHING_PROTOCOL = 101,
6580 ORIG_TS_HTTP_STATUS_EARLY_HINTS = 103,
6581
6582 ORIG_TS_HTTP_STATUS_OK = 200,
6583 ORIG_TS_HTTP_STATUS_CREATED = 201,
6584 ORIG_TS_HTTP_STATUS_ACCEPTED = 202,
6585 ORIG_TS_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
6586 ORIG_TS_HTTP_STATUS_NO_CONTENT = 204,
6587 ORIG_TS_HTTP_STATUS_RESET_CONTENT = 205,
6588 ORIG_TS_HTTP_STATUS_PARTIAL_CONTENT = 206,
6589
6590 ORIG_TS_HTTP_STATUS_MULTIPLE_CHOICES = 300,
6591 ORIG_TS_HTTP_STATUS_MOVED_PERMANENTLY = 301,
6592 ORIG_TS_HTTP_STATUS_MOVED_TEMPORARILY = 302,
6593 ORIG_TS_HTTP_STATUS_SEE_OTHER = 303,
6594 ORIG_TS_HTTP_STATUS_NOT_MODIFIED = 304,
6595 ORIG_TS_HTTP_STATUS_USE_PROXY = 305,
6596
6597 ORIG_TS_HTTP_STATUS_BAD_REQUEST = 400,
6598 ORIG_TS_HTTP_STATUS_UNAUTHORIZED = 401,
6599 ORIG_TS_HTTP_STATUS_PAYMENT_REQUIRED = 402,
6600 ORIG_TS_HTTP_STATUS_FORBIDDEN = 403,
6601 ORIG_TS_HTTP_STATUS_NOT_FOUND = 404,
6602 ORIG_TS_HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
6603 ORIG_TS_HTTP_STATUS_NOT_ACCEPTABLE = 406,
6604 ORIG_TS_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
6605 ORIG_TS_HTTP_STATUS_REQUEST_TIMEOUT = 408,
6606 ORIG_TS_HTTP_STATUS_CONFLICT = 409,
6607 ORIG_TS_HTTP_STATUS_GONE = 410,
6608 ORIG_TS_HTTP_STATUS_LENGTH_REQUIRED = 411,
6609 ORIG_TS_HTTP_STATUS_PRECONDITION_FAILED = 412,
6610 ORIG_TS_HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
6611 ORIG_TS_HTTP_STATUS_REQUEST_URI_TOO_LONG = 414,
6612 ORIG_TS_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
6613
6614 ORIG_TS_HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
6615 ORIG_TS_HTTP_STATUS_NOT_IMPLEMENTED = 501,
6616 ORIG_TS_HTTP_STATUS_BAD_GATEWAY = 502,
6617 ORIG_TS_HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
6618 ORIG_TS_HTTP_STATUS_GATEWAY_TIMEOUT = 504,
6619 ORIG_TS_HTTP_STATUS_HTTPVER_NOT_SUPPORTED = 505
6620 };
6621
6622 enum ORIG_TSHttpHookID {
6623 ORIG_TS_HTTP_READ_REQUEST_HDR_HOOK,
6624 ORIG_TS_HTTP_OS_DNS_HOOK,
6625 ORIG_TS_HTTP_SEND_REQUEST_HDR_HOOK,
6626 ORIG_TS_HTTP_READ_CACHE_HDR_HOOK,
6627 ORIG_TS_HTTP_READ_RESPONSE_HDR_HOOK,
6628 ORIG_TS_HTTP_SEND_RESPONSE_HDR_HOOK,
6629 ORIG_TS_HTTP_REQUEST_TRANSFORM_HOOK,
6630 ORIG_TS_HTTP_RESPONSE_TRANSFORM_HOOK,
6631 ORIG_TS_HTTP_SELECT_ALT_HOOK,
6632 ORIG_TS_HTTP_TXN_START_HOOK,
6633 ORIG_TS_HTTP_TXN_CLOSE_HOOK,
6634 ORIG_TS_HTTP_SSN_START_HOOK,
6635 ORIG_TS_HTTP_SSN_CLOSE_HOOK,
6636 ORIG_TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK,
6637 ORIG_TS_HTTP_PRE_REMAP_HOOK,
6638 ORIG_TS_HTTP_POST_REMAP_HOOK,
6639 ORIG_TS_HTTP_RESPONSE_CLIENT_HOOK,
6640 ORIG_TS_SSL_FIRST_HOOK,
6641 ORIG_TS_VCONN_START_HOOK = ORIG_TS_SSL_FIRST_HOOK,
6642 ORIG_TS_VCONN_CLOSE_HOOK,
6643 ORIG_TS_SSL_CLIENT_HELLO_HOOK,
6644 ORIG_TS_SSL_SNI_HOOK,
6645 ORIG_TS_SSL_SERVERNAME_HOOK,
6646 ORIG_TS_SSL_VERIFY_SERVER_HOOK,
6647 ORIG_TS_SSL_VERIFY_CLIENT_HOOK,
6648 ORIG_TS_SSL_SESSION_HOOK,
6649 ORIG_TS_VCONN_OUTBOUND_START_HOOK,
6650 ORIG_TS_VCONN_OUTBOUND_CLOSE_HOOK,
6651 ORIG_TS_SSL_LAST_HOOK = ORIG_TS_VCONN_OUTBOUND_CLOSE_HOOK,
6652 ORIG_TS_HTTP_REQUEST_BUFFER_READ_COMPLETE_HOOK,
6653 ORIG_TS_HTTP_LAST_HOOK
6654 };
6655
6656 enum ORIG_TSEvent {
6657 ORIG_TS_EVENT_NONE = 0,
6658 ORIG_TS_EVENT_IMMEDIATE = 1,
6659 ORIG_TS_EVENT_TIMEOUT = 2,
6660 ORIG_TS_EVENT_ERROR = 3,
6661 ORIG_TS_EVENT_CONTINUE = 4,
6662
6663 ORIG_TS_EVENT_VCONN_READ_READY = 100,
6664 ORIG_TS_EVENT_VCONN_WRITE_READY = 101,
6665 ORIG_TS_EVENT_VCONN_READ_COMPLETE = 102,
6666 ORIG_TS_EVENT_VCONN_WRITE_COMPLETE = 103,
6667 ORIG_TS_EVENT_VCONN_EOS = 104,
6668
6669 ORIG_TS_EVENT_NET_CONNECT = 200,
6670 ORIG_TS_EVENT_NET_CONNECT_FAILED = 201,
6671 ORIG_TS_EVENT_NET_ACCEPT = 202,
6672 ORIG_TS_EVENT_NET_ACCEPT_FAILED = 204,
6673
6674 ORIG_TS_EVENT_HOST_LOOKUP = 500,
6675
6676 ORIG_TS_EVENT_CACHE_OPEN_READ = 1102,
6677 ORIG_TS_EVENT_CACHE_OPEN_READ_FAILED = 1103,
6678 ORIG_TS_EVENT_CACHE_OPEN_WRITE = 1108,
6679 ORIG_TS_EVENT_CACHE_OPEN_WRITE_FAILED = 1109,
6680 ORIG_TS_EVENT_CACHE_REMOVE = 1112,
6681 ORIG_TS_EVENT_CACHE_REMOVE_FAILED = 1113,
6682 ORIG_TS_EVENT_CACHE_SCAN = 1120,
6683 ORIG_TS_EVENT_CACHE_SCAN_FAILED = 1121,
6684 ORIG_TS_EVENT_CACHE_SCAN_OBJECT = 1122,
6685 ORIG_TS_EVENT_CACHE_SCAN_OPERATION_BLOCKED = 1123,
6686 ORIG_TS_EVENT_CACHE_SCAN_OPERATION_FAILED = 1124,
6687 ORIG_TS_EVENT_CACHE_SCAN_DONE = 1125,
6688
6689 ORIG_TS_EVENT_HTTP_CONTINUE = 60000,
6690 ORIG_TS_EVENT_HTTP_ERROR = 60001,
6691 ORIG_TS_EVENT_HTTP_READ_REQUEST_HDR = 60002,
6692 ORIG_TS_EVENT_HTTP_OS_DNS = 60003,
6693 ORIG_TS_EVENT_HTTP_SEND_REQUEST_HDR = 60004,
6694 ORIG_TS_EVENT_HTTP_READ_CACHE_HDR = 60005,
6695 ORIG_TS_EVENT_HTTP_READ_RESPONSE_HDR = 60006,
6696 ORIG_TS_EVENT_HTTP_SEND_RESPONSE_HDR = 60007,
6697 ORIG_TS_EVENT_HTTP_REQUEST_TRANSFORM = 60008,
6698 ORIG_TS_EVENT_HTTP_RESPONSE_TRANSFORM = 60009,
6699 ORIG_TS_EVENT_HTTP_SELECT_ALT = 60010,
6700 ORIG_TS_EVENT_HTTP_TXN_START = 60011,
6701 ORIG_TS_EVENT_HTTP_TXN_CLOSE = 60012,
6702 ORIG_TS_EVENT_HTTP_SSN_START = 60013,
6703 ORIG_TS_EVENT_HTTP_SSN_CLOSE = 60014,
6704 ORIG_TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE = 60015,
6705
6706 ORIG_TS_EVENT_MGMT_UPDATE = 60300
6707 };
6708
6709 enum ORIG_TSCacheLookupResult {
6710 ORIG_TS_CACHE_LOOKUP_MISS,
6711 ORIG_TS_CACHE_LOOKUP_HIT_STALE,
6712 ORIG_TS_CACHE_LOOKUP_HIT_FRESH,
6713 };
6714
6715 enum ORIG_TSCacheDataType {
6716 ORIG_TS_CACHE_DATA_TYPE_NONE,
6717 ORIG_TS_CACHE_DATA_TYPE_HTTP,
6718 ORIG_TS_CACHE_DATA_TYPE_OTHER,
6719 };
6720
6721 enum ORIG_TSCacheError {
6722 ORIG_TS_CACHE_ERROR_NO_DOC = -20400,
6723 ORIG_TS_CACHE_ERROR_DOC_BUSY = -20401,
6724 ORIG_TS_CACHE_ERROR_NOT_READY = -20407
6725 };
6726
6727 enum ORIG_TSCacheScanResult {
6728 ORIG_TS_CACHE_SCAN_RESULT_DONE = 0,
6729 ORIG_TS_CACHE_SCAN_RESULT_CONTINUE = 1,
6730 ORIG_TS_CACHE_SCAN_RESULT_DELETE = 10,
6731 ORIG_TS_CACHE_SCAN_RESULT_DELETE_ALL_ALTERNATES,
6732 ORIG_TS_CACHE_SCAN_RESULT_UPDATE,
6733 ORIG_TS_CACHE_SCAN_RESULT_RETRY
6734 };
6735
6736 enum ORIG_TSVConnCloseFlags {
6737 ORIG_TS_VC_CLOSE_ABORT = -1,
6738 ORIG_TS_VC_CLOSE_NORMAL = 1,
6739 };
6740
6741 enum ORIG_TSReturnCode {
6742 ORIG_TS_ERROR = -1,
6743 ORIG_TS_SUCCESS = 0,
6744 };
6745
REGRESSION_TEST(SDK_API_TSConstant)6746 REGRESSION_TEST(SDK_API_TSConstant)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
6747 {
6748 *pstatus = REGRESSION_TEST_INPROGRESS;
6749 bool test_passed = true;
6750
6751 PRINT_DIFF(TS_PARSE_ERROR);
6752 PRINT_DIFF(TS_PARSE_DONE);
6753 PRINT_DIFF(TS_PARSE_CONT);
6754
6755 PRINT_DIFF(TS_HTTP_STATUS_NONE);
6756 PRINT_DIFF(TS_HTTP_STATUS_CONTINUE);
6757 PRINT_DIFF(TS_HTTP_STATUS_SWITCHING_PROTOCOL);
6758 PRINT_DIFF(TS_HTTP_STATUS_EARLY_HINTS);
6759
6760 PRINT_DIFF(TS_HTTP_STATUS_OK);
6761 PRINT_DIFF(TS_HTTP_STATUS_CREATED);
6762
6763 PRINT_DIFF(TS_HTTP_STATUS_ACCEPTED);
6764 PRINT_DIFF(TS_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION);
6765 PRINT_DIFF(TS_HTTP_STATUS_NO_CONTENT);
6766 PRINT_DIFF(TS_HTTP_STATUS_RESET_CONTENT);
6767 PRINT_DIFF(TS_HTTP_STATUS_PARTIAL_CONTENT);
6768
6769 PRINT_DIFF(TS_HTTP_STATUS_MULTIPLE_CHOICES);
6770 PRINT_DIFF(TS_HTTP_STATUS_MOVED_PERMANENTLY);
6771 PRINT_DIFF(TS_HTTP_STATUS_MOVED_TEMPORARILY);
6772 PRINT_DIFF(TS_HTTP_STATUS_SEE_OTHER);
6773 PRINT_DIFF(TS_HTTP_STATUS_NOT_MODIFIED);
6774 PRINT_DIFF(TS_HTTP_STATUS_USE_PROXY);
6775 PRINT_DIFF(TS_HTTP_STATUS_BAD_REQUEST);
6776 PRINT_DIFF(TS_HTTP_STATUS_UNAUTHORIZED);
6777 PRINT_DIFF(TS_HTTP_STATUS_FORBIDDEN);
6778 PRINT_DIFF(TS_HTTP_STATUS_NOT_FOUND);
6779 PRINT_DIFF(TS_HTTP_STATUS_METHOD_NOT_ALLOWED);
6780 PRINT_DIFF(TS_HTTP_STATUS_NOT_ACCEPTABLE);
6781 PRINT_DIFF(TS_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED);
6782 PRINT_DIFF(TS_HTTP_STATUS_REQUEST_TIMEOUT);
6783 PRINT_DIFF(TS_HTTP_STATUS_CONFLICT);
6784 PRINT_DIFF(TS_HTTP_STATUS_GONE);
6785 PRINT_DIFF(TS_HTTP_STATUS_PRECONDITION_FAILED);
6786 PRINT_DIFF(TS_HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
6787 PRINT_DIFF(TS_HTTP_STATUS_REQUEST_URI_TOO_LONG);
6788 PRINT_DIFF(TS_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE);
6789 PRINT_DIFF(TS_HTTP_STATUS_INTERNAL_SERVER_ERROR);
6790 PRINT_DIFF(TS_HTTP_STATUS_NOT_IMPLEMENTED);
6791 PRINT_DIFF(TS_HTTP_STATUS_BAD_GATEWAY);
6792 PRINT_DIFF(TS_HTTP_STATUS_GATEWAY_TIMEOUT);
6793 PRINT_DIFF(TS_HTTP_STATUS_HTTPVER_NOT_SUPPORTED);
6794
6795 PRINT_DIFF(TS_HTTP_READ_REQUEST_HDR_HOOK);
6796 PRINT_DIFF(TS_HTTP_OS_DNS_HOOK);
6797 PRINT_DIFF(TS_HTTP_SEND_REQUEST_HDR_HOOK);
6798 PRINT_DIFF(TS_HTTP_READ_RESPONSE_HDR_HOOK);
6799 PRINT_DIFF(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
6800 PRINT_DIFF(TS_HTTP_REQUEST_TRANSFORM_HOOK);
6801 PRINT_DIFF(TS_HTTP_RESPONSE_TRANSFORM_HOOK);
6802 PRINT_DIFF(TS_HTTP_SELECT_ALT_HOOK);
6803 PRINT_DIFF(TS_HTTP_TXN_START_HOOK);
6804 PRINT_DIFF(TS_HTTP_TXN_CLOSE_HOOK);
6805 PRINT_DIFF(TS_HTTP_SSN_START_HOOK);
6806 PRINT_DIFF(TS_HTTP_SSN_CLOSE_HOOK);
6807 PRINT_DIFF(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK);
6808 PRINT_DIFF(TS_HTTP_LAST_HOOK);
6809
6810 PRINT_DIFF(TS_EVENT_NONE);
6811 PRINT_DIFF(TS_EVENT_IMMEDIATE);
6812 PRINT_DIFF(TS_EVENT_TIMEOUT);
6813 PRINT_DIFF(TS_EVENT_ERROR);
6814
6815 PRINT_DIFF(TS_EVENT_CONTINUE);
6816 PRINT_DIFF(TS_EVENT_VCONN_READ_READY);
6817 PRINT_DIFF(TS_EVENT_VCONN_WRITE_READY);
6818 PRINT_DIFF(TS_EVENT_VCONN_READ_COMPLETE);
6819 PRINT_DIFF(TS_EVENT_VCONN_WRITE_COMPLETE);
6820 PRINT_DIFF(TS_EVENT_VCONN_EOS);
6821
6822 PRINT_DIFF(TS_EVENT_NET_CONNECT);
6823 PRINT_DIFF(TS_EVENT_NET_CONNECT_FAILED);
6824 PRINT_DIFF(TS_EVENT_NET_ACCEPT);
6825 PRINT_DIFF(TS_EVENT_NET_ACCEPT_FAILED);
6826
6827 PRINT_DIFF(TS_EVENT_HOST_LOOKUP);
6828
6829 PRINT_DIFF(TS_EVENT_CACHE_OPEN_READ);
6830 PRINT_DIFF(TS_EVENT_CACHE_OPEN_READ_FAILED);
6831 PRINT_DIFF(TS_EVENT_CACHE_OPEN_WRITE);
6832 PRINT_DIFF(TS_EVENT_CACHE_OPEN_WRITE_FAILED);
6833 PRINT_DIFF(TS_EVENT_CACHE_REMOVE);
6834 PRINT_DIFF(TS_EVENT_CACHE_REMOVE_FAILED);
6835 PRINT_DIFF(TS_EVENT_CACHE_SCAN);
6836 PRINT_DIFF(TS_EVENT_CACHE_SCAN_FAILED);
6837 PRINT_DIFF(TS_EVENT_CACHE_SCAN_OBJECT);
6838 PRINT_DIFF(TS_EVENT_CACHE_SCAN_OPERATION_BLOCKED);
6839 PRINT_DIFF(TS_EVENT_CACHE_SCAN_OPERATION_FAILED);
6840 PRINT_DIFF(TS_EVENT_CACHE_SCAN_DONE);
6841
6842 PRINT_DIFF(TS_EVENT_HTTP_CONTINUE);
6843 PRINT_DIFF(TS_EVENT_HTTP_ERROR);
6844 PRINT_DIFF(TS_EVENT_HTTP_READ_REQUEST_HDR);
6845 PRINT_DIFF(TS_EVENT_HTTP_OS_DNS);
6846 PRINT_DIFF(TS_EVENT_HTTP_SEND_REQUEST_HDR);
6847 PRINT_DIFF(TS_EVENT_HTTP_READ_CACHE_HDR);
6848 PRINT_DIFF(TS_EVENT_HTTP_READ_RESPONSE_HDR);
6849 PRINT_DIFF(TS_EVENT_HTTP_SEND_RESPONSE_HDR);
6850 PRINT_DIFF(TS_EVENT_HTTP_REQUEST_TRANSFORM);
6851 PRINT_DIFF(TS_EVENT_HTTP_RESPONSE_TRANSFORM);
6852 PRINT_DIFF(TS_EVENT_HTTP_SELECT_ALT);
6853 PRINT_DIFF(TS_EVENT_HTTP_TXN_START);
6854 PRINT_DIFF(TS_EVENT_HTTP_TXN_CLOSE);
6855 PRINT_DIFF(TS_EVENT_HTTP_SSN_START);
6856 PRINT_DIFF(TS_EVENT_HTTP_SSN_CLOSE);
6857 PRINT_DIFF(TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE);
6858
6859 PRINT_DIFF(TS_EVENT_MGMT_UPDATE);
6860
6861 PRINT_DIFF(TS_CACHE_LOOKUP_MISS);
6862 PRINT_DIFF(TS_CACHE_LOOKUP_HIT_STALE);
6863 PRINT_DIFF(TS_CACHE_LOOKUP_HIT_FRESH);
6864
6865 PRINT_DIFF(TS_CACHE_DATA_TYPE_NONE);
6866 PRINT_DIFF(TS_CACHE_DATA_TYPE_HTTP);
6867 PRINT_DIFF(TS_CACHE_DATA_TYPE_OTHER);
6868
6869 PRINT_DIFF(TS_CACHE_ERROR_NO_DOC);
6870 PRINT_DIFF(TS_CACHE_ERROR_DOC_BUSY);
6871 PRINT_DIFF(TS_CACHE_ERROR_NOT_READY);
6872
6873 PRINT_DIFF(TS_CACHE_SCAN_RESULT_DONE);
6874 PRINT_DIFF(TS_CACHE_SCAN_RESULT_CONTINUE);
6875 PRINT_DIFF(TS_CACHE_SCAN_RESULT_DELETE);
6876 PRINT_DIFF(TS_CACHE_SCAN_RESULT_DELETE_ALL_ALTERNATES);
6877 PRINT_DIFF(TS_CACHE_SCAN_RESULT_UPDATE);
6878 PRINT_DIFF(TS_CACHE_SCAN_RESULT_RETRY);
6879
6880 PRINT_DIFF(TS_VC_CLOSE_ABORT);
6881 PRINT_DIFF(TS_VC_CLOSE_NORMAL);
6882
6883 PRINT_DIFF(TS_ERROR);
6884 PRINT_DIFF(TS_SUCCESS);
6885
6886 if (test_passed) {
6887 *pstatus = REGRESSION_TEST_PASSED;
6888 } else {
6889 *pstatus = REGRESSION_TEST_FAILED;
6890 }
6891 }
6892
6893 //////////////////////////////////////////////
6894 // SDK_API_TSHttpSsn
6895 //
6896 // Unit Test for API: TSHttpSsnHookAdd
6897 // TSHttpSsnReenable
6898 // TSHttpTxnHookAdd
6899 // TSHttpTxnErrorBodySet
6900 // TSHttpTxnParentProxyGet
6901 // TSHttpTxnParentProxySet
6902 //////////////////////////////////////////////
6903
6904 struct ContData {
6905 RegressionTest *test;
6906 int *pstatus;
6907 SocketServer *os;
6908 ClientTxn *browser;
6909 TSHttpSsn ssnp;
6910 int test_passed_ssn_hook_add;
6911 int test_passed_ssn_reenable;
6912 int test_passed_txn_ssn_get;
6913 int test_passed_txn_hook_add;
6914 int test_passed_txn_error_body_set;
6915 bool test_passed_Parent_Proxy;
6916 int magic;
6917 };
6918
6919 static int
checkHttpTxnParentProxy(ContData * data,TSHttpTxn txnp)6920 checkHttpTxnParentProxy(ContData *data, TSHttpTxn txnp)
6921 {
6922 const char *hostname = "txnpp.example.com";
6923 int port = 10180;
6924 const char *hostnameget = nullptr;
6925 int portget = 0;
6926
6927 TSHttpTxnParentProxySet(txnp, const_cast<char *>(hostname), port);
6928 if (TSHttpTxnParentProxyGet(txnp, &hostnameget, &portget) != TS_SUCCESS) {
6929 SDK_RPRINT(data->test, "TSHttpTxnParentProxySet", "TestCase1", TC_FAIL, "TSHttpTxnParentProxyGet doesn't return TS_SUCCESS");
6930 SDK_RPRINT(data->test, "TSHttpTxnParentProxyGet", "TestCase1", TC_FAIL, "TSHttpTxnParentProxyGet doesn't return TS_SUCCESS");
6931 return TS_EVENT_CONTINUE;
6932 }
6933
6934 if ((strcmp(hostname, hostnameget) == 0) && (port == portget)) {
6935 SDK_RPRINT(data->test, "TSHttpTxnParentProxySet", "TestCase1", TC_PASS, "ok");
6936 SDK_RPRINT(data->test, "TSHttpTxnParentProxyGet", "TestCase1", TC_PASS, "ok");
6937 data->test_passed_Parent_Proxy = true;
6938 } else {
6939 SDK_RPRINT(data->test, "TSHttpTxnParentProxySet", "TestCase1", TC_FAIL, "Value's Mismatch");
6940 SDK_RPRINT(data->test, "TSHttpTxnParentProxyGet", "TestCase1", TC_FAIL, "Value's Mismatch");
6941 }
6942
6943 return TS_EVENT_CONTINUE;
6944 }
6945
6946 static int
ssn_handler(TSCont contp,TSEvent event,void * edata)6947 ssn_handler(TSCont contp, TSEvent event, void *edata)
6948 {
6949 TSHttpTxn txnp = nullptr;
6950 ContData *data = nullptr;
6951 data = static_cast<ContData *>(TSContDataGet(contp));
6952 if (data == nullptr) {
6953 switch (event) {
6954 case TS_EVENT_HTTP_SSN_START:
6955 TSHttpSsnReenable(static_cast<TSHttpSsn>(edata), TS_EVENT_HTTP_CONTINUE);
6956 break;
6957 case TS_EVENT_IMMEDIATE:
6958 case TS_EVENT_TIMEOUT:
6959 break;
6960 case TS_EVENT_HTTP_TXN_START:
6961 default:
6962 TSHttpTxnReenable(static_cast<TSHttpTxn>(edata), TS_EVENT_HTTP_CONTINUE);
6963 break;
6964 }
6965 return 0;
6966 }
6967
6968 switch (event) {
6969 case TS_EVENT_HTTP_SSN_START:
6970 data->ssnp = static_cast<TSHttpSsn>(edata);
6971 TSHttpSsnHookAdd(data->ssnp, TS_HTTP_TXN_START_HOOK, contp);
6972 TSHttpSsnReenable(data->ssnp, TS_EVENT_HTTP_CONTINUE);
6973 break;
6974
6975 case TS_EVENT_HTTP_TXN_START:
6976 TSSkipRemappingSet(static_cast<TSHttpTxn>(edata), 1);
6977 SDK_RPRINT(data->test, "TSHttpSsnReenable", "TestCase", TC_PASS, "ok");
6978 data->test_passed_ssn_reenable++;
6979 {
6980 txnp = static_cast<TSHttpTxn>(edata);
6981 TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
6982 if (ssnp != data->ssnp) {
6983 SDK_RPRINT(data->test, "TSHttpSsnHookAdd", "TestCase", TC_FAIL, "Value's mismatch");
6984 data->test_passed_ssn_hook_add--;
6985 SDK_RPRINT(data->test, "TSHttpTxnSsnGet", "TestCase", TC_FAIL, "Session doesn't match");
6986 data->test_passed_txn_ssn_get--;
6987 } else {
6988 SDK_RPRINT(data->test, "TSHttpSsnHookAdd", "TestCase1", TC_PASS, "ok");
6989 data->test_passed_ssn_hook_add++;
6990 SDK_RPRINT(data->test, "TSHttpTxnSsnGet", "TestCase1", TC_PASS, "ok");
6991 data->test_passed_txn_ssn_get++;
6992 }
6993 TSHttpTxnHookAdd(txnp, TS_HTTP_OS_DNS_HOOK, contp);
6994 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
6995 }
6996 break;
6997
6998 case TS_EVENT_HTTP_OS_DNS:
6999 SDK_RPRINT(data->test, "TSHttpTxnHookAdd", "TestCase1", TC_PASS, "ok");
7000 data->test_passed_txn_hook_add++;
7001 txnp = static_cast<TSHttpTxn>(edata);
7002
7003 TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);
7004 checkHttpTxnParentProxy(data, txnp);
7005
7006 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
7007 break;
7008
7009 case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
7010 SDK_RPRINT(data->test, "TSHttpTxnHookAdd", "TestCase2", TC_PASS, "ok");
7011 data->test_passed_txn_hook_add++;
7012 txnp = static_cast<TSHttpTxn>(edata);
7013 if (true) {
7014 char *temp = TSstrdup(ERROR_BODY);
7015 TSHttpTxnErrorBodySet(txnp, temp, strlen(temp), nullptr);
7016 }
7017 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7018 break;
7019
7020 case TS_EVENT_IMMEDIATE:
7021 case TS_EVENT_TIMEOUT:
7022 /* Browser still waiting the response ? */
7023 if (data->browser->status == REQUEST_INPROGRESS) {
7024 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7025 }
7026 /* Browser got the response. test is over. clean up */
7027 else {
7028 /* Check if browser response body is the one we expected */
7029 char *temp = data->browser->response;
7030 temp = strstr(temp, "\r\n\r\n");
7031 if (temp != nullptr) {
7032 temp += strlen("\r\n\r\n");
7033 if ((temp[0] == '\0') || (strncmp(temp, "\r\n\r\n", 4) == 0)) {
7034 SDK_RPRINT(data->test, "TSHttpTxnErrorBodySet", "TestCase1", TC_FAIL, "No Error Body found");
7035 data->test_passed_txn_error_body_set--;
7036 }
7037 if (strncmp(temp, ERROR_BODY, strlen(ERROR_BODY)) == 0) {
7038 SDK_RPRINT(data->test, "TSHttpTxnErrorBodySet", "TestCase1", TC_PASS, "ok");
7039 data->test_passed_txn_error_body_set++;
7040 }
7041 } else {
7042 SDK_RPRINT(data->test, "TSHttpTxnErrorBodySet", "TestCase1", TC_FAIL, "strstr returns NULL. Didn't find end of headers.");
7043 data->test_passed_txn_error_body_set--;
7044 }
7045
7046 /* Note: response is available using test->browser->response pointer */
7047 if ((data->browser->status == REQUEST_SUCCESS) && (data->test_passed_ssn_hook_add == 1) &&
7048 (data->test_passed_ssn_reenable == 1) && (data->test_passed_txn_ssn_get == 1) && (data->test_passed_txn_hook_add == 2) &&
7049 (data->test_passed_txn_error_body_set == 1) && (data->test_passed_Parent_Proxy == true)) {
7050 *(data->pstatus) = REGRESSION_TEST_PASSED;
7051 } else {
7052 *(data->pstatus) = REGRESSION_TEST_FAILED;
7053 }
7054
7055 // transaction is over. clean up.
7056 synclient_txn_delete(data->browser);
7057 /* Don't need it as didn't initialize the server
7058 synserver_delete(data->os);
7059 */
7060 data->os = nullptr;
7061 data->magic = MAGIC_DEAD;
7062 TSfree(data);
7063 TSContDataSet(contp, nullptr);
7064 }
7065 break;
7066
7067 default:
7068 *(data->pstatus) = REGRESSION_TEST_FAILED;
7069 SDK_RPRINT(data->test, "TSHttpSsn", "TestCase1", TC_FAIL, "Unexpected event %d", event);
7070 break;
7071 }
7072 return 0;
7073 }
7074
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpSsn)7075 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpSsn)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
7076 {
7077 *pstatus = REGRESSION_TEST_INPROGRESS;
7078
7079 TSCont cont = TSContCreate(ssn_handler, TSMutexCreate());
7080 if (cont == nullptr) {
7081 SDK_RPRINT(test, "TSHttpSsn", "TestCase1", TC_FAIL, "Unable to create Continuation.");
7082 *pstatus = REGRESSION_TEST_FAILED;
7083 return;
7084 }
7085
7086 ContData *socktest = static_cast<ContData *>(TSmalloc(sizeof(ContData)));
7087 socktest->test = test;
7088 socktest->pstatus = pstatus;
7089 socktest->test_passed_ssn_hook_add = 0;
7090 socktest->test_passed_ssn_reenable = 0;
7091 socktest->test_passed_txn_ssn_get = 0;
7092 socktest->test_passed_txn_hook_add = 0;
7093 socktest->test_passed_txn_error_body_set = 0;
7094 socktest->test_passed_Parent_Proxy = false;
7095 socktest->magic = MAGIC_ALIVE;
7096 TSContDataSet(cont, socktest);
7097
7098 /* Register to HTTP hooks that are called in case of a cache MISS */
7099 TSHttpHookAdd(TS_HTTP_SSN_START_HOOK, cont);
7100
7101 /* Create a client transaction */
7102 socktest->browser = synclient_txn_create();
7103 char *request = generate_request(3); // response is expected to be error case
7104 synclient_txn_send_request(socktest->browser, request);
7105 TSfree(request);
7106
7107 /* Wait until transaction is done */
7108 if (socktest->browser->status == REQUEST_INPROGRESS) {
7109 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
7110 }
7111
7112 return;
7113 }
7114
7115 struct ParentTest {
ParentTestParentTest7116 ParentTest(RegressionTest *test, int *pstatus)
7117 {
7118 ink_zero(*this);
7119 this->regtest = test;
7120 this->pstatus = pstatus;
7121 this->magic = MAGIC_ALIVE;
7122 this->configured = false;
7123 this->browser = synclient_txn_create();
7124 }
7125
~ParentTestParentTest7126 ~ParentTest()
7127 {
7128 synclient_txn_close(this->browser);
7129 synclient_txn_delete(this->browser);
7130 synserver_delete(this->os);
7131 this->os = nullptr;
7132 this->magic = MAGIC_DEAD;
7133 }
7134
7135 bool
parent_routing_enabledParentTest7136 parent_routing_enabled() const
7137 {
7138 RecBool enabled = false;
7139
7140 ParentConfigParams *params = ParentConfig::acquire();
7141 enabled = params->policy.ParentEnable;
7142 ParentConfig::release(params);
7143
7144 return enabled;
7145 }
7146
7147 RegressionTest *regtest;
7148 int *pstatus;
7149 bool configured;
7150
7151 const char *testcase;
7152 SocketServer *os;
7153 ClientTxn *browser;
7154 TSEventFunc handler;
7155
7156 unsigned int magic;
7157 };
7158
7159 static int
parent_proxy_success(TSCont contp,TSEvent event,void * edata)7160 parent_proxy_success(TSCont contp, TSEvent event, void *edata)
7161 {
7162 ParentTest *ptest = static_cast<ParentTest *>(TSContDataGet(contp));
7163 TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
7164
7165 int expected;
7166 int received;
7167 int status;
7168
7169 switch (event) {
7170 case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
7171 expected = get_request_id(txnp);
7172 received = get_response_id(txnp);
7173
7174 if (expected != received) {
7175 status = REGRESSION_TEST_FAILED;
7176 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Expected response ID %d, received %d", expected,
7177 received);
7178 } else {
7179 status = REGRESSION_TEST_PASSED;
7180 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_PASS, "Received expected response ID %d", expected);
7181 }
7182 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7183 return status;
7184
7185 default:
7186 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", ptest->testcase, TC_FAIL, "Unexpected event %d", event);
7187 return REGRESSION_TEST_FAILED;
7188 }
7189 }
7190
7191 static int
parent_proxy_fail(TSCont contp,TSEvent event,void * edata)7192 parent_proxy_fail(TSCont contp, TSEvent event, void *edata)
7193 {
7194 ParentTest *ptest = static_cast<ParentTest *>(TSContDataGet(contp));
7195 TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
7196
7197 TSMBuffer mbuf;
7198 TSMLoc hdr;
7199 TSHttpStatus expected = TS_HTTP_STATUS_BAD_GATEWAY;
7200 TSHttpStatus received;
7201 int status;
7202
7203 switch (event) {
7204 case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
7205 ink_release_assert(TSHttpTxnClientRespGet(txnp, &mbuf, &hdr) == TS_SUCCESS);
7206 received = TSHttpHdrStatusGet(mbuf, hdr);
7207
7208 if (expected != received) {
7209 status = REGRESSION_TEST_FAILED;
7210 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Expected response status %d, received %d",
7211 expected, received);
7212 } else {
7213 status = REGRESSION_TEST_PASSED;
7214 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_PASS, "Received expected response status %d", expected);
7215 }
7216
7217 TSHandleMLocRelease(mbuf, TS_NULL_MLOC, hdr);
7218 return status;
7219
7220 default:
7221 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", ptest->testcase, TC_FAIL, "Unexpected event %d", event);
7222 return REGRESSION_TEST_FAILED;
7223 }
7224 }
7225
7226 static int
parent_proxy_handler(TSCont contp,TSEvent event,void * edata)7227 parent_proxy_handler(TSCont contp, TSEvent event, void *edata)
7228 {
7229 ParentTest *ptest = nullptr;
7230
7231 CHECK_SPURIOUS_EVENT(contp, event, edata);
7232 ptest = static_cast<ParentTest *>(TSContDataGet(contp));
7233 ink_release_assert(ptest);
7234
7235 TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
7236
7237 switch (event) {
7238 case TS_EVENT_HTTP_READ_REQUEST_HDR:
7239 rprintf(ptest->regtest, "setting synserver parent proxy to %s:%d\n", "127.0.0.1", SYNSERVER_LISTEN_PORT);
7240
7241 // Since we chose a request format with a hostname of trafficserver.apache.org, it won't get
7242 // sent to the synserver unless we set a parent proxy.
7243 TSHttpTxnParentProxySet(txnp, "127.0.0.1", SYNSERVER_LISTEN_PORT);
7244
7245 TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);
7246 TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, contp);
7247
7248 TSSkipRemappingSet(txnp, 1);
7249 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7250 break;
7251
7252 case TS_EVENT_TIMEOUT:
7253 if (*(ptest->pstatus) == REGRESSION_TEST_INPROGRESS) {
7254 if (ptest->configured) {
7255 // If we are still in progress, reschedule.
7256 rprintf(ptest->regtest, "waiting for response\n");
7257 TSContScheduleOnPool(contp, 100, TS_THREAD_POOL_NET);
7258 break;
7259 }
7260
7261 if (!ptest->parent_routing_enabled()) {
7262 rprintf(ptest->regtest, "waiting for configuration\n");
7263 TSContScheduleOnPool(contp, 100, TS_THREAD_POOL_NET);
7264 break;
7265 }
7266
7267 // Now that the configuration is applied, it is safe to create a request.
7268 // HTTP_REQUEST_FORMAT11 is a hostname with a no-cache response, so
7269 // we will need to set the parent to the synserver to get a
7270 // response.
7271 char *request = generate_request(11);
7272 synclient_txn_send_request(ptest->browser, request);
7273 TSfree(request);
7274
7275 ptest->configured = true;
7276
7277 } else {
7278 // Otherwise the test completed so clean up.
7279 TSContDataSet(contp, nullptr);
7280 delete ptest;
7281 }
7282 break;
7283
7284 case TS_EVENT_HTTP_TXN_CLOSE:
7285 // We expected to pass or fail reading the response header. At this point we must have failed.
7286 if (*(ptest->pstatus) == REGRESSION_TEST_INPROGRESS) {
7287 *(ptest->pstatus) = REGRESSION_TEST_FAILED;
7288 SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", ptest->testcase, TC_FAIL, "Failed on txn close");
7289 }
7290 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7291 break;
7292
7293 default:
7294
7295 {
7296 int status = ptest->handler(contp, event, edata);
7297 if (status != REGRESSION_TEST_INPROGRESS) {
7298 int *pstatus = ptest->pstatus;
7299
7300 TSContDataSet(contp, nullptr);
7301 delete ptest;
7302
7303 *pstatus = status;
7304 }
7305 }
7306 }
7307
7308 return TS_EVENT_NONE;
7309 }
7310
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpParentProxySet_Fail)7311 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpParentProxySet_Fail)(RegressionTest *test, int level, int *pstatus)
7312 {
7313 *pstatus = REGRESSION_TEST_INPROGRESS;
7314
7315 if (level < REGRESSION_TEST_EXTENDED) {
7316 *pstatus = REGRESSION_TEST_NOT_RUN;
7317 return;
7318 }
7319
7320 TSCont cont = TSContCreate(parent_proxy_handler, TSMutexCreate());
7321 if (cont == nullptr) {
7322 SDK_RPRINT(test, "TSHttpTxnParentProxySet", "FailCase", TC_FAIL, "Unable to create continuation");
7323 *pstatus = REGRESSION_TEST_FAILED;
7324 return;
7325 }
7326
7327 ParentTest *ptest = new ParentTest(test, pstatus);
7328
7329 ptest->testcase = "FailCase";
7330 ptest->handler = parent_proxy_fail;
7331 TSContDataSet(cont, ptest);
7332
7333 /* Hook read request headers, since that is the earliest reasonable place to set the parent proxy. */
7334 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
7335
7336 /* Create a new synthetic server */
7337 ptest->os = synserver_create(SYNSERVER_LISTEN_PORT, TSContCreate(synserver_vc_refuse, TSMutexCreate()));
7338 synserver_start(ptest->os);
7339
7340 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
7341 }
7342
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpParentProxySet_Success)7343 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpParentProxySet_Success)(RegressionTest *test, int level, int *pstatus)
7344 {
7345 *pstatus = REGRESSION_TEST_INPROGRESS;
7346
7347 if (level < REGRESSION_TEST_EXTENDED) {
7348 *pstatus = REGRESSION_TEST_NOT_RUN;
7349 return;
7350 }
7351
7352 TSCont cont = TSContCreate(parent_proxy_handler, TSMutexCreate());
7353 if (cont == nullptr) {
7354 SDK_RPRINT(test, "TSHttpTxnParentProxySet", "SuccessCase", TC_FAIL, "Unable to create continuation");
7355 *pstatus = REGRESSION_TEST_FAILED;
7356 return;
7357 }
7358
7359 ParentTest *ptest = new ParentTest(test, pstatus);
7360
7361 ptest->testcase = "SuccessCase";
7362 ptest->handler = parent_proxy_success;
7363 TSContDataSet(cont, ptest);
7364
7365 /* Hook read request headers, since that is the earliest reasonable place to set the parent proxy. */
7366 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
7367
7368 /* Create a new synthetic server */
7369 ptest->os = synserver_create(SYNSERVER_LISTEN_PORT, TSContCreate(synserver_vc_accept, TSMutexCreate()));
7370 synserver_start(ptest->os);
7371
7372 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
7373 }
7374
7375 /////////////////////////////////////////////////////
7376 // SDK_API_TSHttpTxnCache
7377 //
7378 // Unit Test for API: TSHttpTxnCachedReqGet
7379 // TSHttpTxnCachedRespGet
7380 // TSHttpTxnCacheLookupStatusGet
7381 /////////////////////////////////////////////////////
7382
7383 struct CacheTestData {
7384 RegressionTest *test;
7385 int *pstatus;
7386 SocketServer *os;
7387 ClientTxn *browser1;
7388 ClientTxn *browser2;
7389 char *request;
7390 bool test_passed_txn_cached_req_get;
7391 bool test_passed_txn_cached_resp_get;
7392 bool test_passed_txn_cache_lookup_status;
7393 bool first_time;
7394 int magic;
7395 };
7396
7397 static int
cache_hook_handler(TSCont contp,TSEvent event,void * edata)7398 cache_hook_handler(TSCont contp, TSEvent event, void *edata)
7399 {
7400 TSHttpTxn txnp = nullptr;
7401 CacheTestData *data = nullptr;
7402
7403 CHECK_SPURIOUS_EVENT(contp, event, edata);
7404 data = static_cast<CacheTestData *>(TSContDataGet(contp));
7405
7406 switch (event) {
7407 case TS_EVENT_HTTP_READ_REQUEST_HDR:
7408 txnp = static_cast<TSHttpTxn>(edata);
7409 TSSkipRemappingSet(txnp, 1);
7410 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7411 break;
7412
7413 case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: {
7414 int lookup_status;
7415 if (data->first_time == true) {
7416 txnp = static_cast<TSHttpTxn>(edata);
7417 if (TSHttpTxnCacheLookupStatusGet(txnp, &lookup_status) != TS_SUCCESS) {
7418 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase1", TC_FAIL,
7419 "TSHttpTxnCacheLookupStatus doesn't return TS_SUCCESS");
7420 } else {
7421 if (lookup_status == TS_CACHE_LOOKUP_MISS) {
7422 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase1", TC_PASS, "ok");
7423 data->test_passed_txn_cache_lookup_status = true;
7424 } else {
7425 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase1", TC_FAIL,
7426 "Incorrect Value returned by TSHttpTxnCacheLookupStatusGet");
7427 }
7428 }
7429 } else {
7430 txnp = static_cast<TSHttpTxn>(edata);
7431 if (TSHttpTxnCacheLookupStatusGet(txnp, &lookup_status) != TS_SUCCESS) {
7432 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase2", TC_FAIL,
7433 "TSHttpTxnCacheLookupStatus doesn't return TS_SUCCESS");
7434 data->test_passed_txn_cache_lookup_status = false;
7435 } else {
7436 if (lookup_status == TS_CACHE_LOOKUP_HIT_FRESH) {
7437 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase2", TC_PASS, "ok");
7438 } else {
7439 SDK_RPRINT(data->test, "TSHttpTxnCacheLookupStatusGet", "TestCase2", TC_FAIL,
7440 "Incorrect Value returned by TSHttpTxnCacheLookupStatusGet");
7441 data->test_passed_txn_cache_lookup_status = false;
7442 }
7443 }
7444 }
7445 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7446 } break;
7447 case TS_EVENT_HTTP_READ_CACHE_HDR: {
7448 TSMBuffer reqbuf;
7449 TSMBuffer respbuf;
7450
7451 TSMLoc reqhdr;
7452 TSMLoc resphdr;
7453
7454 txnp = static_cast<TSHttpTxn>(edata);
7455
7456 if (TSHttpTxnCachedReqGet(txnp, &reqbuf, &reqhdr) != TS_SUCCESS) {
7457 SDK_RPRINT(data->test, "TSHttpTxnCachedReqGet", "TestCase1", TC_FAIL, "TSHttpTxnCachedReqGet returns 0");
7458 } else {
7459 if ((reqbuf == reinterpret_cast<TSMBuffer>(((HttpSM *)txnp)->t_state.cache_req_hdr_heap_handle)) &&
7460 (reqhdr == reinterpret_cast<TSMLoc>((((HttpSM *)txnp)->t_state.cache_info.object_read->request_get())->m_http))) {
7461 SDK_RPRINT(data->test, "TSHttpTxnCachedReqGet", "TestCase1", TC_PASS, "ok");
7462 data->test_passed_txn_cached_req_get = true;
7463 } else {
7464 SDK_RPRINT(data->test, "TSHttpTxnCachedReqGet", "TestCase1", TC_FAIL, "Value's Mismatch");
7465 }
7466 }
7467
7468 if (TSHttpTxnCachedRespGet(txnp, &respbuf, &resphdr) != TS_SUCCESS) {
7469 SDK_RPRINT(data->test, "TSHttpTxnCachedRespGet", "TestCase1", TC_FAIL, "TSHttpTxnCachedRespGet returns 0");
7470 } else {
7471 if ((respbuf == reinterpret_cast<TSMBuffer>(((HttpSM *)txnp)->t_state.cache_resp_hdr_heap_handle)) &&
7472 (resphdr == reinterpret_cast<TSMLoc>((((HttpSM *)txnp)->t_state.cache_info.object_read->response_get())->m_http))) {
7473 SDK_RPRINT(data->test, "TSHttpTxnCachedRespGet", "TestCase1", TC_PASS, "ok");
7474 data->test_passed_txn_cached_resp_get = true;
7475 } else {
7476 SDK_RPRINT(data->test, "TSHttpTxnCachedRespGet", "TestCase1", TC_FAIL, "Value's Mismatch");
7477 }
7478 }
7479
7480 if ((TSHandleMLocRelease(reqbuf, TS_NULL_MLOC, reqhdr) != TS_SUCCESS) ||
7481 (TSHandleMLocRelease(respbuf, TS_NULL_MLOC, resphdr) != TS_SUCCESS)) {
7482 SDK_RPRINT(data->test, "TSHttpTxnCache", "", TC_FAIL, "Unable to release handle to headers.");
7483 }
7484
7485 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7486 }
7487
7488 break;
7489
7490 case TS_EVENT_IMMEDIATE:
7491 case TS_EVENT_TIMEOUT:
7492 /* Browser still waiting the response ? */
7493 if (data->first_time == true) {
7494 if (data->browser1->status == REQUEST_INPROGRESS) {
7495 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7496 return 0;
7497 }
7498 } else {
7499 if (data->browser2->status == REQUEST_INPROGRESS) {
7500 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7501 return 0;
7502 }
7503 }
7504
7505 /* Browser got the response. test is over. clean up */
7506 {
7507 /* If this is the first time, then the response is in cache and we should make */
7508 /* another request to get cache hit */
7509 if (data->first_time == true) {
7510 data->first_time = false;
7511 /* Kill the origin server */
7512 synserver_delete(data->os);
7513 data->os = nullptr;
7514
7515 /* Send another similar client request */
7516 synclient_txn_send_request(data->browser2, data->request);
7517 ink_assert(REQUEST_INPROGRESS == data->browser2->status);
7518 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7519 return 0;
7520 }
7521
7522 /* Note: response is available using test->browser->response pointer */
7523 if ((data->browser1->status == REQUEST_SUCCESS) && (data->browser2->status == REQUEST_SUCCESS) &&
7524 (data->test_passed_txn_cached_req_get == true) && (data->test_passed_txn_cached_resp_get == true) &&
7525 (data->test_passed_txn_cache_lookup_status == true)) {
7526 *(data->pstatus) = REGRESSION_TEST_PASSED;
7527 } else {
7528 *(data->pstatus) = REGRESSION_TEST_FAILED;
7529 }
7530
7531 // transaction is over. clean up.
7532 synclient_txn_delete(data->browser1);
7533 synclient_txn_delete(data->browser2);
7534
7535 data->magic = MAGIC_DEAD;
7536 TSfree(data->request);
7537 TSfree(data);
7538 TSContDataSet(contp, nullptr);
7539 }
7540 break;
7541
7542 default:
7543 *(data->pstatus) = REGRESSION_TEST_FAILED;
7544 SDK_RPRINT(data->test, "TSHttpTxnCache", "TestCase1", TC_FAIL, "Unexpected event %d", event);
7545 break;
7546 }
7547 return 0;
7548 }
7549
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnCache)7550 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnCache)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
7551 {
7552 *pstatus = REGRESSION_TEST_INPROGRESS;
7553
7554 TSCont cont = TSContCreate(cache_hook_handler, TSMutexCreate());
7555
7556 if (cont == nullptr) {
7557 SDK_RPRINT(test, "TSHttpSsn", "TestCase1", TC_FAIL, "Unable to create Continuation.");
7558 *pstatus = REGRESSION_TEST_FAILED;
7559 return;
7560 }
7561
7562 CacheTestData *socktest = static_cast<CacheTestData *>(TSmalloc(sizeof(CacheTestData)));
7563 socktest->test = test;
7564 socktest->pstatus = pstatus;
7565 socktest->test_passed_txn_cached_req_get = false;
7566 socktest->test_passed_txn_cached_resp_get = false;
7567 socktest->first_time = true;
7568 socktest->magic = MAGIC_ALIVE;
7569 TSContDataSet(cont, socktest);
7570
7571 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
7572 /* Register to HTTP hooks that are called in case of a cache MISS */
7573 TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, cont);
7574 TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont);
7575
7576 /* Create a new synthetic server */
7577 socktest->os = synserver_create(SYNSERVER_LISTEN_PORT);
7578 synserver_start(socktest->os);
7579
7580 /* Create a client transaction */
7581 socktest->browser1 = synclient_txn_create();
7582 socktest->browser2 = synclient_txn_create();
7583 socktest->request = generate_request(2);
7584 synclient_txn_send_request(socktest->browser1, socktest->request);
7585
7586 /* Wait until transaction is done */
7587 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
7588
7589 return;
7590 }
7591
7592 ///////////////////////////////////////////////////////
7593 // SDK_API_TSHttpTxnTransform
7594 //
7595 // Unit Test for API: TSHttpTxnTransformRespGet
7596 // TSHttpTxnTransformedRespCache
7597 // TSHttpTxnUntransformedRespCache
7598 ///////////////////////////////////////////////////////
7599
7600 /** Append Transform Data Structure Ends **/
7601
7602 struct TransformTestData {
7603 RegressionTest *test;
7604 int *pstatus;
7605 SocketServer *os;
7606 ClientTxn *browser1;
7607 ClientTxn *browser2;
7608 ClientTxn *browser3;
7609 ClientTxn *browser4;
7610 char *request1;
7611 char *request2;
7612 bool test_passed_txn_transform_resp_get;
7613 bool test_passed_txn_transformed_resp_cache;
7614 bool test_passed_txn_untransformed_resp_cache;
7615 bool test_passed_transform_create;
7616 int req_no;
7617 uint32_t magic;
7618 };
7619
7620 /** Append Transform Data Structure **/
7621 struct AppendTransformTestData {
7622 TSVIO output_vio = nullptr;
7623 TSIOBuffer output_buffer = nullptr;
7624 TSIOBufferReader output_reader = nullptr;
7625 TransformTestData *test_data = nullptr;
7626 int append_needed = 1;
7627
~AppendTransformTestDataAppendTransformTestData7628 ~AppendTransformTestData()
7629 {
7630 if (output_buffer) {
7631 TSIOBufferDestroy(output_buffer);
7632 }
7633 }
7634 };
7635
7636 /**** Append Transform Code (Tailored to needs)****/
7637
7638 static TSIOBuffer append_buffer;
7639 static TSIOBufferReader append_buffer_reader;
7640 static int64_t append_buffer_length;
7641
7642 static void
handle_transform(TSCont contp)7643 handle_transform(TSCont contp)
7644 {
7645 TSVConn output_conn;
7646 TSVIO write_vio;
7647 int64_t towrite;
7648 int64_t avail;
7649
7650 /* Get the output connection where we'll write data to. */
7651 output_conn = TSTransformOutputVConnGet(contp);
7652
7653 /* Get the write VIO for the write operation that was performed on
7654 ourself. This VIO contains the buffer that we are to read from
7655 as well as the continuation we are to call when the buffer is
7656 empty. */
7657 write_vio = TSVConnWriteVIOGet(contp);
7658
7659 /* Get our data structure for this operation. The private data
7660 structure contains the output VIO and output buffer.
7661 */
7662 auto *data = static_cast<AppendTransformTestData *>(TSContDataGet(contp));
7663 if (!data->output_buffer) {
7664 towrite = TSVIONBytesGet(write_vio);
7665 if (towrite != INT64_MAX) {
7666 towrite += append_buffer_length;
7667 }
7668 data->output_buffer = TSIOBufferCreate();
7669 data->output_reader = TSIOBufferReaderAlloc(data->output_buffer);
7670 data->output_vio = TSVConnWrite(output_conn, contp, data->output_reader, towrite);
7671 }
7672 ink_assert(data->output_vio);
7673
7674 /* We also check to see if the write VIO's buffer is non-NULL. A
7675 NULL buffer indicates that the write operation has been
7676 shutdown and that the continuation does not want us to send any
7677 more WRITE_READY or WRITE_COMPLETE events. For this simplistic
7678 transformation that means we're done. In a more complex
7679 transformation we might have to finish writing the transformed
7680 data to our output connection. */
7681 if (!TSVIOBufferGet(write_vio)) {
7682 if (data->append_needed) {
7683 data->append_needed = 0;
7684 TSIOBufferCopy(TSVIOBufferGet(data->output_vio), append_buffer_reader, append_buffer_length, 0);
7685 }
7686
7687 TSVIONBytesSet(data->output_vio, TSVIONDoneGet(write_vio) + append_buffer_length);
7688 TSVIOReenable(data->output_vio);
7689 return;
7690 }
7691
7692 /* Determine how much data we have left to read. For this append
7693 transform plugin this is also the amount of data we have left
7694 to write to the output connection. */
7695 towrite = TSVIONTodoGet(write_vio);
7696 if (towrite > 0) {
7697 /* The amount of data left to read needs to be truncated by
7698 the amount of data actually in the read buffer. */
7699 avail = TSIOBufferReaderAvail(TSVIOReaderGet(write_vio));
7700 if (towrite > avail) {
7701 towrite = avail;
7702 }
7703
7704 if (towrite > 0) {
7705 /* Copy the data from the read buffer to the output buffer. */
7706 TSIOBufferCopy(TSVIOBufferGet(data->output_vio), TSVIOReaderGet(write_vio), towrite, 0);
7707
7708 /* Tell the read buffer that we have read the data and are no
7709 longer interested in it. */
7710 TSIOBufferReaderConsume(TSVIOReaderGet(write_vio), towrite);
7711
7712 /* Modify the write VIO to reflect how much data we've
7713 completed. */
7714 TSVIONDoneSet(write_vio, TSVIONDoneGet(write_vio) + towrite);
7715 }
7716 }
7717
7718 /* Now we check the write VIO to see if there is data left to
7719 read. */
7720 if (TSVIONTodoGet(write_vio) > 0) {
7721 if (towrite > 0) {
7722 /* If there is data left to read, then we reenable the output
7723 connection by reenabling the output VIO. This will wakeup
7724 the output connection and allow it to consume data from the
7725 output buffer. */
7726 TSVIOReenable(data->output_vio);
7727
7728 /* Call back the write VIO continuation to let it know that we
7729 are ready for more data. */
7730 TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_READY, write_vio);
7731 }
7732 } else {
7733 if (data->append_needed) {
7734 data->append_needed = 0;
7735 TSIOBufferCopy(TSVIOBufferGet(data->output_vio), append_buffer_reader, append_buffer_length, 0);
7736 }
7737
7738 /* If there is no data left to read, then we modify the output
7739 VIO to reflect how much data the output connection should
7740 expect. This allows the output connection to know when it
7741 is done reading. We then reenable the output connection so
7742 that it can consume the data we just gave it. */
7743 TSVIONBytesSet(data->output_vio, TSVIONDoneGet(write_vio) + append_buffer_length);
7744 TSVIOReenable(data->output_vio);
7745
7746 /* Call back the write VIO continuation to let it know that we
7747 have completed the write operation. */
7748 TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_COMPLETE, write_vio);
7749 }
7750 }
7751
7752 static int
transformtest_transform(TSCont contp,TSEvent event,void *)7753 transformtest_transform(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
7754 {
7755 auto *data = static_cast<AppendTransformTestData *>(TSContDataGet(contp));
7756 if (data->test_data->test_passed_transform_create == false) {
7757 data->test_data->test_passed_transform_create = true;
7758 SDK_RPRINT(data->test_data->test, "TSTransformCreate", "TestCase1", TC_PASS, "ok");
7759 }
7760 /* Check to see if the transformation has been closed by a call to
7761 TSVConnClose. */
7762 if (TSVConnClosedGet(contp)) {
7763 delete data;
7764 TSContDestroy(contp);
7765 return 0;
7766 } else {
7767 switch (event) {
7768 case TS_EVENT_ERROR: {
7769 TSVIO write_vio;
7770
7771 /* Get the write VIO for the write operation that was
7772 performed on ourself. This VIO contains the continuation of
7773 our parent transformation. */
7774 write_vio = TSVConnWriteVIOGet(contp);
7775
7776 /* Call back the write VIO continuation to let it know that we
7777 have completed the write operation. */
7778 TSContCall(TSVIOContGet(write_vio), TS_EVENT_ERROR, write_vio);
7779 } break;
7780 case TS_EVENT_VCONN_WRITE_COMPLETE:
7781 /* When our output connection says that it has finished
7782 reading all the data we've written to it then we should
7783 shutdown the write portion of its connection to
7784 indicate that we don't want to hear about it anymore. */
7785 TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
7786 break;
7787 case TS_EVENT_VCONN_WRITE_READY:
7788 default:
7789 /* If we get a WRITE_READY event or any other type of
7790 event (sent, perhaps, because we were reenabled) then
7791 we'll attempt to transform more data. */
7792 handle_transform(contp);
7793 break;
7794 }
7795 }
7796
7797 return 0;
7798 }
7799
7800 static int
transformable(TSHttpTxn txnp,TransformTestData * data)7801 transformable(TSHttpTxn txnp, TransformTestData *data)
7802 {
7803 TSMBuffer bufp;
7804 TSMLoc hdr_loc;
7805 int ret = 0;
7806
7807 if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
7808 SDK_RPRINT(data->test, "TSHttpTxnTransform", "", TC_FAIL, "[transformable]: TSHttpTxnServerRespGet return 0");
7809 return ret;
7810 }
7811
7812 /*
7813 * We are only interested in "200 OK" responses.
7814 */
7815
7816 if (TS_HTTP_STATUS_OK == TSHttpHdrStatusGet(bufp, hdr_loc)) {
7817 ret = 1;
7818 }
7819
7820 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
7821 return ret; /* not a 200 */
7822 }
7823
7824 static void
transform_add(TSHttpTxn txnp,TransformTestData * test_data)7825 transform_add(TSHttpTxn txnp, TransformTestData *test_data)
7826 {
7827 TSVConn connp = TSTransformCreate(transformtest_transform, txnp);
7828 if (connp == nullptr) {
7829 SDK_RPRINT(test_data->test, "TSHttpTxnTransform", "", TC_FAIL, "Unable to create Transformation.");
7830 return;
7831 }
7832
7833 // Add data to the continuation
7834 auto *data = new AppendTransformTestData;
7835 data->test_data = test_data;
7836 TSContDataSet(connp, data);
7837
7838 TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
7839 return;
7840 }
7841
7842 static int
load(const char * append_string)7843 load(const char *append_string)
7844 {
7845 TSIOBufferBlock blk;
7846 char *p;
7847 int64_t avail;
7848
7849 append_buffer = TSIOBufferCreate();
7850 append_buffer_reader = TSIOBufferReaderAlloc(append_buffer);
7851
7852 blk = TSIOBufferStart(append_buffer);
7853 p = TSIOBufferBlockWriteStart(blk, &avail);
7854
7855 ink_strlcpy(p, append_string, avail);
7856 if (append_string != nullptr) {
7857 TSIOBufferProduce(append_buffer, strlen(append_string));
7858 }
7859
7860 append_buffer_length = TSIOBufferReaderAvail(append_buffer_reader);
7861
7862 return 1;
7863 }
7864
7865 /**** Append Transform Code Ends ****/
7866
7867 static int
transform_hook_handler(TSCont contp,TSEvent event,void * edata)7868 transform_hook_handler(TSCont contp, TSEvent event, void *edata)
7869 {
7870 TSHttpTxn txnp = nullptr;
7871 TransformTestData *data = nullptr;
7872
7873 CHECK_SPURIOUS_EVENT(contp, event, edata);
7874 data = static_cast<TransformTestData *>(TSContDataGet(contp));
7875
7876 switch (event) {
7877 case TS_EVENT_HTTP_READ_REQUEST_HDR:
7878 txnp = static_cast<TSHttpTxn>(edata);
7879 TSSkipRemappingSet(txnp, 1);
7880 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7881 break;
7882 case TS_EVENT_HTTP_READ_RESPONSE_HDR:
7883 txnp = static_cast<TSHttpTxn>(edata);
7884 /* Setup hooks for Transformation */
7885 if (transformable(txnp, data)) {
7886 transform_add(txnp, data);
7887 }
7888 /* Call TransformedRespCache or UntransformedRespCache depending on request */
7889 {
7890 TSMBuffer bufp;
7891 TSMLoc hdr;
7892 TSMLoc field;
7893
7894 if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr) != TS_SUCCESS) {
7895 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase", TC_FAIL, "TSHttpTxnClientReqGet returns 0");
7896 } else {
7897 if (TS_NULL_MLOC == (field = TSMimeHdrFieldFind(bufp, hdr, "Request", -1))) {
7898 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase", TC_FAIL, "Didn't find field request");
7899 } else {
7900 int reqid = TSMimeHdrFieldValueIntGet(bufp, hdr, field, 0);
7901 if (reqid == 1) {
7902 TSHttpTxnTransformedRespCache(txnp, 0);
7903 TSHttpTxnUntransformedRespCache(txnp, 1);
7904 }
7905 if (reqid == 2) {
7906 TSHttpTxnTransformedRespCache(txnp, 1);
7907 TSHttpTxnUntransformedRespCache(txnp, 0);
7908 }
7909 if (TSHandleMLocRelease(bufp, hdr, field) != TS_SUCCESS) {
7910 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase", TC_FAIL,
7911 "Unable to release handle to field in Client request");
7912 }
7913 }
7914 if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr) != TS_SUCCESS) {
7915 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase", TC_FAIL, "Unable to release handle to Client request");
7916 }
7917 }
7918 }
7919
7920 /* Add the transaction hook to SEND_RESPONSE_HDR_HOOK */
7921 TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);
7922 /* Reenable the transaction */
7923 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7924 break;
7925
7926 case TS_EVENT_HTTP_SEND_RESPONSE_HDR: {
7927 TSMBuffer bufp;
7928 TSMLoc hdr;
7929 txnp = static_cast<TSHttpTxn>(edata);
7930 if (TSHttpTxnTransformRespGet(txnp, &bufp, &hdr) != TS_SUCCESS) {
7931 SDK_RPRINT(data->test, "TSHttpTxnTransformRespGet", "TestCase", TC_FAIL, "TSHttpTxnTransformRespGet returns 0");
7932 data->test_passed_txn_transform_resp_get = false;
7933 } else {
7934 if ((bufp == reinterpret_cast<TSMBuffer>(&(((HttpSM *)txnp)->t_state.hdr_info.transform_response))) &&
7935 (hdr == reinterpret_cast<TSMLoc>((&(((HttpSM *)txnp)->t_state.hdr_info.transform_response))->m_http))) {
7936 SDK_RPRINT(data->test, "TSHttpTxnTransformRespGet", "TestCase", TC_PASS, "ok");
7937 } else {
7938 SDK_RPRINT(data->test, "TSHttpTxnTransformRespGet", "TestCase", TC_FAIL, "Value's Mismatch");
7939 data->test_passed_txn_transform_resp_get = false;
7940 }
7941 if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr) != TS_SUCCESS) {
7942 SDK_RPRINT(data->test, "TSHttpTxnTransformRespGet", "TestCase", TC_FAIL,
7943 "Unable to release handle to Transform header handle");
7944 }
7945 }
7946 }
7947 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
7948 break;
7949
7950 case TS_EVENT_IMMEDIATE:
7951 case TS_EVENT_TIMEOUT:
7952
7953 switch (data->req_no) {
7954 case 1:
7955 if (data->browser1->status == REQUEST_INPROGRESS) {
7956 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7957 return 0;
7958 }
7959 data->req_no++;
7960 Debug(UTDBG_TAG "_transform", "Running Browser 2");
7961 synclient_txn_send_request(data->browser2, data->request2);
7962 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7963 return 0;
7964 case 2:
7965 if (data->browser2->status == REQUEST_INPROGRESS) {
7966 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7967 return 0;
7968 }
7969 data->req_no++;
7970 Debug(UTDBG_TAG "_transform", "Running Browser 3");
7971 synclient_txn_send_request(data->browser3, data->request1);
7972 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7973 return 0;
7974 case 3:
7975 if (data->browser3->status == REQUEST_INPROGRESS) {
7976 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7977 return 0;
7978 }
7979 data->req_no++;
7980 Debug(UTDBG_TAG "_transform", "Running Browser 4");
7981 synclient_txn_send_request(data->browser4, data->request2);
7982 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7983 return 0;
7984 case 4:
7985 if (data->browser4->status == REQUEST_INPROGRESS) {
7986 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
7987 return 0;
7988 }
7989 synserver_delete(data->os);
7990 data->os = nullptr;
7991 data->req_no++;
7992 TSfree(data->request1);
7993 TSfree(data->request2);
7994 // for squid log: if this is the last (or only) test in your
7995 // regression run you will not see any log entries in squid
7996 // (because logging is buffered and not flushed before
7997 // termination when running regressions)
7998 // sleep(10);
7999 break;
8000 default:
8001 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase", TC_FAIL, "Something terribly wrong with the test");
8002 exit(0);
8003 }
8004 /* Browser got the response. test is over */
8005 {
8006 /* Check if we got the response we were expecting or not */
8007 if ((strstr(data->browser1->response, TRANSFORM_APPEND_STRING) != nullptr) &&
8008 (strstr(data->browser3->response, TRANSFORM_APPEND_STRING) == nullptr)) {
8009 SDK_RPRINT(data->test, "TSHttpTxnUntransformedResponseCache", "TestCase1", TC_PASS, "ok");
8010 data->test_passed_txn_untransformed_resp_cache = true;
8011 } else {
8012 SDK_RPRINT(data->test, "TSHttpTxnUntransformedResponseCache", "TestCase1", TC_FAIL, "Value's Mismatch");
8013 }
8014
8015 if ((strstr(data->browser2->response, TRANSFORM_APPEND_STRING) != nullptr) &&
8016 (strstr(data->browser4->response, TRANSFORM_APPEND_STRING) != nullptr)) {
8017 SDK_RPRINT(data->test, "TSHttpTxnTransformedResponseCache", "TestCase1", TC_PASS, "ok");
8018 data->test_passed_txn_transformed_resp_cache = true;
8019 } else {
8020 SDK_RPRINT(data->test, "TSHttpTxnTransformedResponseCache", "TestCase1", TC_FAIL, "Value's Mismatch");
8021 }
8022
8023 /* Note: response is available using test->browser->response pointer */
8024 *(data->pstatus) = REGRESSION_TEST_PASSED;
8025 if (data->browser1->status != REQUEST_SUCCESS) {
8026 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "Browser 1 status was not REQUEST_SUCCESS");
8027 *(data->pstatus) = REGRESSION_TEST_FAILED;
8028 }
8029 if (data->browser2->status != REQUEST_SUCCESS) {
8030 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "Browser 2 status was not REQUEST_SUCCESS");
8031 *(data->pstatus) = REGRESSION_TEST_FAILED;
8032 }
8033 if (data->browser3->status != REQUEST_SUCCESS) {
8034 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "Browser 3 status was not REQUEST_SUCCESS");
8035 *(data->pstatus) = REGRESSION_TEST_FAILED;
8036 }
8037 if (data->browser4->status != REQUEST_SUCCESS) {
8038 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "Browser 4 status was not REQUEST_SUCCESS");
8039 *(data->pstatus) = REGRESSION_TEST_FAILED;
8040 }
8041 if (data->test_passed_txn_transform_resp_get != true) {
8042 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "did not pass transform_resp_get");
8043 *(data->pstatus) = REGRESSION_TEST_FAILED;
8044 }
8045 if (data->test_passed_txn_transformed_resp_cache != true) {
8046 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "did not pass transformed_resp_cache");
8047 *(data->pstatus) = REGRESSION_TEST_FAILED;
8048 }
8049 if (data->test_passed_txn_untransformed_resp_cache != true) {
8050 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "did not pass untransformed_resp_cache");
8051 *(data->pstatus) = REGRESSION_TEST_FAILED;
8052 }
8053 if (data->test_passed_transform_create != true) {
8054 SDK_RPRINT(data->test, "TSTransformCreate", "TestCase1", TC_FAIL, "did not pass transform_create");
8055 *(data->pstatus) = REGRESSION_TEST_FAILED;
8056 }
8057 // transaction is over. clean up.
8058 synclient_txn_delete(data->browser1);
8059 synclient_txn_delete(data->browser2);
8060 synclient_txn_delete(data->browser3);
8061 synclient_txn_delete(data->browser4);
8062
8063 TSContDataSet(contp, nullptr);
8064 data->magic = MAGIC_DEAD;
8065 TSfree(data);
8066 }
8067 break;
8068
8069 default:
8070 *(data->pstatus) = REGRESSION_TEST_FAILED;
8071 SDK_RPRINT(data->test, "TSHttpTxnTransform", "TestCase1", TC_FAIL, "Unexpected event %d", event);
8072 break;
8073 }
8074 return 0;
8075 }
8076
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnTransform)8077 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpTxnTransform)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8078 {
8079 *pstatus = REGRESSION_TEST_INPROGRESS;
8080
8081 Debug(UTDBG_TAG "_transform", "Starting test");
8082
8083 TSCont cont = TSContCreate(transform_hook_handler, TSMutexCreate());
8084 if (cont == nullptr) {
8085 SDK_RPRINT(test, "TSHttpSsn", "TestCase1", TC_FAIL, "Unable to create Continuation.");
8086 *pstatus = REGRESSION_TEST_FAILED;
8087 return;
8088 }
8089
8090 TransformTestData *socktest = static_cast<TransformTestData *>(TSmalloc(sizeof(TransformTestData)));
8091 socktest->test = test;
8092 socktest->pstatus = pstatus;
8093 socktest->test_passed_txn_transform_resp_get = true;
8094 socktest->test_passed_txn_transformed_resp_cache = false;
8095 socktest->test_passed_txn_transformed_resp_cache = false;
8096 socktest->test_passed_transform_create = false;
8097 socktest->req_no = 1;
8098 socktest->magic = MAGIC_ALIVE;
8099 TSContDataSet(cont, socktest);
8100
8101 /* Prepare the buffer to be appended to responses */
8102 load(TRANSFORM_APPEND_STRING);
8103
8104 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont); // so we can skip remapping
8105
8106 /* Register to HTTP hooks that are called in case of a cache MISS */
8107 TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, cont);
8108
8109 /* Create a new synthetic server */
8110 socktest->os = synserver_create(SYNSERVER_LISTEN_PORT);
8111 synserver_start(socktest->os);
8112
8113 /* Create a client transaction */
8114 socktest->browser1 = synclient_txn_create();
8115 socktest->browser2 = synclient_txn_create();
8116 socktest->browser3 = synclient_txn_create();
8117 socktest->browser4 = synclient_txn_create();
8118 socktest->request1 = generate_request(4);
8119 socktest->request2 = generate_request(5);
8120 Debug(UTDBG_TAG "_transform", "Running Browser 1");
8121 synclient_txn_send_request(socktest->browser1, socktest->request1);
8122 // synclient_txn_send_request(socktest->browser2, socktest->request2);
8123
8124 /* Wait until transaction is done */
8125 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
8126
8127 return;
8128 }
8129
8130 //////////////////////////////////////////////
8131 // SDK_API_TSHttpTxnAltInfo
8132 //
8133 // Unit Test for API: TSHttpTxnCachedReqGet
8134 // TSHttpTxnCachedRespGet
8135 //////////////////////////////////////////////
8136
8137 struct AltInfoTestData {
8138 RegressionTest *test;
8139 int *pstatus;
8140 SocketServer *os;
8141 ClientTxn *browser1;
8142 ClientTxn *browser2;
8143 ClientTxn *browser3;
8144 char *request1;
8145 char *request2;
8146 char *request3;
8147 bool test_passed_txn_alt_info_client_req_get;
8148 bool test_passed_txn_alt_info_cached_req_get;
8149 bool test_passed_txn_alt_info_cached_resp_get;
8150 bool test_passed_txn_alt_info_quality_set;
8151 bool run_at_least_once;
8152 bool first_time;
8153 int magic;
8154 };
8155
8156 static int
altinfo_hook_handler(TSCont contp,TSEvent event,void * edata)8157 altinfo_hook_handler(TSCont contp, TSEvent event, void *edata)
8158 {
8159 AltInfoTestData *data = nullptr;
8160 TSHttpTxn txnp = nullptr;
8161
8162 CHECK_SPURIOUS_EVENT(contp, event, edata);
8163 data = static_cast<AltInfoTestData *>(TSContDataGet(contp));
8164
8165 switch (event) {
8166 case TS_EVENT_HTTP_READ_REQUEST_HDR:
8167 txnp = static_cast<TSHttpTxn>(edata);
8168 TSSkipRemappingSet(txnp, 1);
8169 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
8170 break;
8171
8172 case TS_EVENT_HTTP_SELECT_ALT: {
8173 TSMBuffer clientreqbuf;
8174 TSMBuffer cachereqbuf;
8175 TSMBuffer cacherespbuf;
8176
8177 TSMLoc clientreqhdr;
8178 TSMLoc cachereqhdr;
8179 TSMLoc cacheresphdr;
8180
8181 TSHttpAltInfo infop = static_cast<TSHttpAltInfo>(edata);
8182
8183 data->run_at_least_once = true;
8184 if (TSHttpAltInfoClientReqGet(infop, &clientreqbuf, &clientreqhdr) != TS_SUCCESS) {
8185 SDK_RPRINT(data->test, "TSHttpAltInfoClientReqGet", "TestCase", TC_FAIL,
8186 "TSHttpAltInfoClientReqGet doesn't return TS_SUCCESS");
8187 data->test_passed_txn_alt_info_client_req_get = false;
8188 } else {
8189 if ((clientreqbuf == reinterpret_cast<TSMBuffer>(&(((HttpAltInfo *)infop)->m_client_req))) &&
8190 (clientreqhdr == reinterpret_cast<TSMLoc>(((HttpAltInfo *)infop)->m_client_req.m_http))) {
8191 SDK_RPRINT(data->test, "TSHttpAltInfoClientReqGet", "TestCase", TC_PASS, "ok");
8192 } else {
8193 SDK_RPRINT(data->test, "TSHttpAltInfoClientReqGet", "TestCase", TC_FAIL, "Value's Mismatch");
8194 data->test_passed_txn_alt_info_client_req_get = false;
8195 }
8196 }
8197
8198 if (TSHttpAltInfoCachedReqGet(infop, &cachereqbuf, &cachereqhdr) != TS_SUCCESS) {
8199 SDK_RPRINT(data->test, "TSHttpAltInfoCachedReqGet", "TestCase", TC_FAIL,
8200 "TSHttpAltInfoCachedReqGet doesn't return TS_SUCCESS");
8201 data->test_passed_txn_alt_info_cached_req_get = false;
8202 } else {
8203 if ((cachereqbuf == reinterpret_cast<TSMBuffer>(&(((HttpAltInfo *)infop)->m_cached_req))) &&
8204 (cachereqhdr == reinterpret_cast<TSMLoc>(((HttpAltInfo *)infop)->m_cached_req.m_http))) {
8205 SDK_RPRINT(data->test, "TSHttpAltInfoCachedReqGet", "TestCase", TC_PASS, "ok");
8206 } else {
8207 SDK_RPRINT(data->test, "TSHttpAltInfoCachedReqGet", "TestCase", TC_FAIL, "Value's Mismatch");
8208 data->test_passed_txn_alt_info_cached_req_get = false;
8209 }
8210 }
8211
8212 if (TSHttpAltInfoCachedRespGet(infop, &cacherespbuf, &cacheresphdr) != TS_SUCCESS) {
8213 SDK_RPRINT(data->test, "TSHttpAltInfoCachedRespGet", "TestCase", TC_FAIL,
8214 "TSHttpAltInfoCachedRespGet doesn't return TS_SUCCESS");
8215 data->test_passed_txn_alt_info_cached_resp_get = false;
8216 } else {
8217 if ((cacherespbuf == reinterpret_cast<TSMBuffer>(&(((HttpAltInfo *)infop)->m_cached_resp))) &&
8218 (cacheresphdr == reinterpret_cast<TSMLoc>(((HttpAltInfo *)infop)->m_cached_resp.m_http))) {
8219 SDK_RPRINT(data->test, "TSHttpAltInfoCachedRespGet", "TestCase", TC_PASS, "ok");
8220 } else {
8221 SDK_RPRINT(data->test, "TSHttpAltInfoCachedRespGet", "TestCase", TC_FAIL, "Value's Mismatch");
8222 data->test_passed_txn_alt_info_cached_resp_get = false;
8223 }
8224 }
8225
8226 TSHttpAltInfoQualitySet(infop, 0.5);
8227 SDK_RPRINT(data->test, "TSHttpAltInfoQualitySet", "TestCase", TC_PASS, "ok");
8228 }
8229
8230 break;
8231
8232 case TS_EVENT_IMMEDIATE:
8233 case TS_EVENT_TIMEOUT:
8234 /* Browser still waiting the response ? */
8235 if (data->first_time == true) {
8236 if ((data->browser1->status == REQUEST_INPROGRESS) || (data->browser2->status == REQUEST_INPROGRESS)) {
8237 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
8238 return 0;
8239 }
8240 } else {
8241 if (data->browser3->status == REQUEST_INPROGRESS) {
8242 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
8243 return 0;
8244 }
8245 }
8246
8247 /* Browser got the response. test is over. clean up */
8248 {
8249 /* If this is the first time, then both the responses are in cache and we should make */
8250 /* another request to get cache hit */
8251 if (data->first_time == true) {
8252 data->first_time = false;
8253 /* Kill the origin server */
8254 synserver_delete(data->os);
8255 data->os = nullptr;
8256 // ink_release_assert(0);
8257 /* Send another similar client request */
8258 synclient_txn_send_request(data->browser3, data->request3);
8259
8260 /* Register to HTTP hooks that are called in case of alternate selection */
8261 TSHttpHookAdd(TS_HTTP_SELECT_ALT_HOOK, contp);
8262 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
8263 return 0;
8264 }
8265
8266 /* Note: response is available using test->browser->response pointer */
8267 if ((data->browser3->status == REQUEST_SUCCESS) && (data->test_passed_txn_alt_info_client_req_get == true) &&
8268 (data->test_passed_txn_alt_info_cached_req_get == true) && (data->test_passed_txn_alt_info_cached_resp_get == true) &&
8269 (data->test_passed_txn_alt_info_quality_set == true) && (data->run_at_least_once == true)) {
8270 *(data->pstatus) = REGRESSION_TEST_PASSED;
8271 } else {
8272 if (data->run_at_least_once == false) {
8273 SDK_RPRINT(data->test, "TSHttpAltInfo", "All", TC_FAIL, "Test not executed even once");
8274 }
8275 *(data->pstatus) = REGRESSION_TEST_FAILED;
8276 }
8277
8278 // transaction is over. clean up.
8279 synclient_txn_delete(data->browser1);
8280 synclient_txn_delete(data->browser2);
8281 synclient_txn_delete(data->browser3);
8282
8283 TSfree(data->request1);
8284 TSfree(data->request2);
8285 TSfree(data->request3);
8286
8287 data->magic = MAGIC_DEAD;
8288 TSfree(data);
8289 TSContDataSet(contp, nullptr);
8290 }
8291 break;
8292
8293 default:
8294 *(data->pstatus) = REGRESSION_TEST_FAILED;
8295 SDK_RPRINT(data->test, "TSHttpTxnCache", "TestCase1", TC_FAIL, "Unexpected event %d", event);
8296 break;
8297 }
8298 return 0;
8299 }
8300
EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpAltInfo)8301 EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpAltInfo)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8302 {
8303 *pstatus = REGRESSION_TEST_INPROGRESS;
8304
8305 TSCont cont = TSContCreate(altinfo_hook_handler, TSMutexCreate());
8306 if (cont == nullptr) {
8307 SDK_RPRINT(test, "TSHttpSsn", "TestCase1", TC_FAIL, "Unable to create Continuation.");
8308 *pstatus = REGRESSION_TEST_FAILED;
8309 return;
8310 }
8311
8312 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont); // so we can skip remapping
8313
8314 AltInfoTestData *socktest = static_cast<AltInfoTestData *>(TSmalloc(sizeof(AltInfoTestData)));
8315 socktest->test = test;
8316 socktest->pstatus = pstatus;
8317 socktest->test_passed_txn_alt_info_client_req_get = true;
8318 socktest->test_passed_txn_alt_info_cached_req_get = true;
8319 socktest->test_passed_txn_alt_info_cached_resp_get = true;
8320 socktest->test_passed_txn_alt_info_quality_set = true;
8321 socktest->run_at_least_once = false;
8322 socktest->first_time = true;
8323 socktest->magic = MAGIC_ALIVE;
8324 TSContDataSet(cont, socktest);
8325
8326 /* Create a new synthetic server */
8327 socktest->os = synserver_create(SYNSERVER_LISTEN_PORT);
8328 synserver_start(socktest->os);
8329
8330 /* Create a client transaction */
8331 socktest->browser1 = synclient_txn_create();
8332 socktest->browser2 = synclient_txn_create();
8333 socktest->browser3 = synclient_txn_create();
8334 socktest->request1 = generate_request(6);
8335 socktest->request2 = generate_request(7);
8336 socktest->request3 = generate_request(8);
8337 synclient_txn_send_request(socktest->browser1, socktest->request1);
8338 synclient_txn_send_request(socktest->browser2, socktest->request2);
8339
8340 /* Wait until transaction is done */
8341 TSContScheduleOnPool(cont, 25, TS_THREAD_POOL_NET);
8342
8343 return;
8344 }
8345
8346 //////////////////////////////////////////////
8347 // SDK_API_TSHttpConnect
8348 //
8349 // Unit Test for APIs:
8350 // - TSHttpConnect
8351 // - TSHttpTxnIntercept
8352 // - TSHttpTxnInterceptServer
8353 //
8354 //
8355 // 2 Test cases.
8356 //
8357 // Same test strategy:
8358 // - create a synthetic server listening on port A
8359 // - use HttpConnect to send a request to TS for an url on a remote host H, port B
8360 // - use TxnIntercept or TxnServerIntercept to forward the request
8361 // to the synthetic server on local host, port A
8362 // - make sure response is correct
8363 //
8364 //////////////////////////////////////////////
8365
8366 // Important: we create servers listening on different port than the default one
8367 // to make sure our synthetic servers are called
8368
8369 #define TEST_CASE_CONNECT_ID1 9 // TSHttpTxnIntercept
8370 #define TEST_CASE_CONNECT_ID2 10 // TSHttpTxnServerIntercept
8371
8372 struct ConnectTestData {
8373 RegressionTest *test;
8374 int *pstatus;
8375 int test_case;
8376 TSVConn vc;
8377 SocketServer *os;
8378 ClientTxn *browser;
8379 char *request;
8380 unsigned long magic;
8381 };
8382
8383 static int
cont_test_handler(TSCont contp,TSEvent event,void * edata)8384 cont_test_handler(TSCont contp, TSEvent event, void *edata)
8385 {
8386 TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
8387 ConnectTestData *data = nullptr;
8388 int request_id = -1;
8389
8390 CHECK_SPURIOUS_EVENT(contp, event, edata);
8391 data = static_cast<ConnectTestData *>(TSContDataGet(contp));
8392
8393 TSReleaseAssert(data->magic == MAGIC_ALIVE);
8394 TSReleaseAssert((data->test_case == TEST_CASE_CONNECT_ID1) || (data->test_case == TEST_CASE_CONNECT_ID2));
8395
8396 TSDebug(UTDBG_TAG, "Calling cont_test_handler with event %s (%d)", TSHttpEventNameLookup(event), event);
8397
8398 switch (event) {
8399 case TS_EVENT_HTTP_READ_REQUEST_HDR:
8400 TSDebug(UTDBG_TAG, "cont_test_handler: event READ_REQUEST");
8401
8402 // First make sure we're getting called for either request 9 or txn 10
8403 // Otherwise, this is a request sent by another test. do nothing.
8404 request_id = get_request_id(txnp);
8405 TSReleaseAssert(request_id != -1);
8406
8407 TSDebug(UTDBG_TAG, "cont_test_handler: Request id = %d", request_id);
8408
8409 if ((request_id != TEST_CASE_CONNECT_ID1) && (request_id != TEST_CASE_CONNECT_ID2)) {
8410 TSDebug(UTDBG_TAG, "This is not an event for this test !");
8411 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
8412 goto done;
8413 }
8414
8415 if ((request_id == TEST_CASE_CONNECT_ID1) && (data->test_case == TEST_CASE_CONNECT_ID1)) {
8416 TSDebug(UTDBG_TAG, "Calling TSHttpTxnIntercept");
8417 TSHttpTxnIntercept(data->os->accept_cont, txnp);
8418 } else if ((request_id == TEST_CASE_CONNECT_ID2) && (data->test_case == TEST_CASE_CONNECT_ID2)) {
8419 TSDebug(UTDBG_TAG, "Calling TSHttpTxnServerIntercept");
8420 TSHttpTxnServerIntercept(data->os->accept_cont, txnp);
8421 }
8422
8423 TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
8424 break;
8425
8426 case TS_EVENT_TIMEOUT:
8427 /* Browser still waiting the response ? */
8428 if (data->browser->status == REQUEST_INPROGRESS) {
8429 TSDebug(UTDBG_TAG, "Browser still waiting response...");
8430 TSContScheduleOnPool(contp, 25, TS_THREAD_POOL_NET);
8431 }
8432 /* Browser got the response */
8433 else {
8434 /* Check if browser response body is the one we expected */
8435 char *body_response = get_body_ptr(data->browser->response);
8436 const char *body_expected;
8437 if (data->test_case == TEST_CASE_CONNECT_ID1) {
8438 body_expected = "Body for response 9";
8439 } else {
8440 body_expected = "Body for response 10";
8441 }
8442 TSDebug(UTDBG_TAG, "Body Response = \n|%s|\nBody Expected = \n|%s|", body_response ? body_response : "*NULL*", body_expected);
8443
8444 if (!body_response || strncmp(body_response, body_expected, strlen(body_expected)) != 0) {
8445 if (data->test_case == TEST_CASE_CONNECT_ID1) {
8446 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase1", TC_FAIL, "Unexpected response");
8447 SDK_RPRINT(data->test, "TSHttpTxnIntercept", "TestCase1", TC_FAIL, "Unexpected response");
8448 } else {
8449 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase2", TC_FAIL, "Unexpected response");
8450 SDK_RPRINT(data->test, "TSHttpTxnServerIntercept", "TestCase2", TC_FAIL, "Unexpected response");
8451 }
8452 *(data->pstatus) = REGRESSION_TEST_FAILED;
8453
8454 } else {
8455 if (data->test_case == TEST_CASE_CONNECT_ID1) {
8456 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase1", TC_PASS, "ok");
8457 SDK_RPRINT(data->test, "TSHttpTxnIntercept", "TestCase1", TC_PASS, "ok");
8458 } else {
8459 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase2", TC_PASS, "ok");
8460 SDK_RPRINT(data->test, "TSHttpTxnServerIntercept", "TestCase2", TC_PASS, "ok");
8461 }
8462 *(data->pstatus) = REGRESSION_TEST_PASSED;
8463 }
8464
8465 // transaction is over. clean it up.
8466 synclient_txn_delete(data->browser);
8467 synserver_delete(data->os);
8468 data->os = nullptr;
8469 data->magic = MAGIC_DEAD;
8470 TSfree(data);
8471 TSContDataSet(contp, nullptr);
8472 }
8473 break;
8474
8475 default:
8476 *(data->pstatus) = REGRESSION_TEST_FAILED;
8477 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase1 or 2", TC_FAIL, "Unexpected event %d", event);
8478 break;
8479 }
8480
8481 done:
8482 return TS_EVENT_IMMEDIATE;
8483 }
8484
EXCLUSIVE_REGRESSION_TEST(SDK_API_TSHttpConnectIntercept)8485 EXCLUSIVE_REGRESSION_TEST(SDK_API_TSHttpConnectIntercept)(RegressionTest *test, int /* atype */, int *pstatus)
8486 {
8487 *pstatus = REGRESSION_TEST_INPROGRESS;
8488
8489 TSDebug(UTDBG_TAG, "Starting test TSHttpConnectIntercept");
8490
8491 TSCont cont_test = TSContCreate(cont_test_handler, TSMutexCreate());
8492 ConnectTestData *data = static_cast<ConnectTestData *>(TSmalloc(sizeof(ConnectTestData)));
8493 TSContDataSet(cont_test, data);
8494
8495 data->test = test;
8496 data->pstatus = pstatus;
8497 data->magic = MAGIC_ALIVE;
8498 data->test_case = TEST_CASE_CONNECT_ID1;
8499
8500 /* Register to hook READ_REQUEST */
8501 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont_test);
8502
8503 // Create a synthetic server which won't really listen on a socket port
8504 // It will be called by the Http SM with a VC
8505 data->os = synserver_create(SYNSERVER_DUMMY_PORT);
8506
8507 data->browser = synclient_txn_create();
8508 data->request = generate_request(9);
8509
8510 /* Now send a request to the OS via TS using TSHttpConnect */
8511
8512 /* ip and log do not matter as it is used for logging only */
8513 sockaddr_in addr;
8514 ats_ip4_set(&addr, 1, 1);
8515 data->vc = TSHttpConnect(ats_ip_sa_cast(&addr));
8516 if (TSVConnClosedGet(data->vc)) {
8517 SDK_RPRINT(data->test, "TSHttpConnect", "TestCase 1", TC_FAIL, "Connect reported as closed immediately after open");
8518 }
8519 synclient_txn_send_request_to_vc(data->browser, data->request, data->vc);
8520
8521 /* Wait until transaction is done */
8522 TSContScheduleOnPool(cont_test, 25, TS_THREAD_POOL_NET);
8523
8524 return;
8525 }
8526
EXCLUSIVE_REGRESSION_TEST(SDK_API_TSHttpConnectServerIntercept)8527 EXCLUSIVE_REGRESSION_TEST(SDK_API_TSHttpConnectServerIntercept)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8528 {
8529 *pstatus = REGRESSION_TEST_INPROGRESS;
8530
8531 TSDebug(UTDBG_TAG, "Starting test TSHttpConnectServerIntercept");
8532
8533 TSCont cont_test = TSContCreate(cont_test_handler, TSMutexCreate());
8534 ConnectTestData *data = static_cast<ConnectTestData *>(TSmalloc(sizeof(ConnectTestData)));
8535 TSContDataSet(cont_test, data);
8536
8537 data->test = test;
8538 data->pstatus = pstatus;
8539 data->magic = MAGIC_ALIVE;
8540 data->test_case = TEST_CASE_CONNECT_ID2;
8541
8542 /* Register to hook READ_REQUEST */
8543 TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont_test);
8544
8545 /* This is cool ! we can use the code written for the synthetic server and client in InkAPITest.cc */
8546 data->os = synserver_create(SYNSERVER_DUMMY_PORT);
8547
8548 data->browser = synclient_txn_create();
8549 data->request = generate_request(10);
8550
8551 /* Now send a request to the OS via TS using TSHttpConnect */
8552
8553 /* ip and log do not matter as it is used for logging only */
8554 sockaddr_in addr;
8555 ats_ip4_set(&addr, 2, 2);
8556 data->vc = TSHttpConnect(ats_ip_sa_cast(&addr));
8557
8558 synclient_txn_send_request_to_vc(data->browser, data->request, data->vc);
8559
8560 /* Wait until transaction is done */
8561 TSContScheduleOnPool(cont_test, 25, TS_THREAD_POOL_NET);
8562
8563 return;
8564 }
8565
8566 ////////////////////////////////////////////////
8567 // SDK_API_OVERRIDABLE_CONFIGS
8568 //
8569 // Unit Test for API: TSHttpTxnConfigFind
8570 // TSHttpTxnConfigIntSet
8571 // TSHttpTxnConfigIntGet
8572 // TSHttpTxnConfigFloatSet
8573 // TSHttpTxnConfigFloatGet
8574 // TSHttpTxnConfigStringSet
8575 // TSHttpTxnConfigStringGet
8576 ////////////////////////////////////////////////
8577
8578 // The order of these should be the same as TSOverridableConfigKey
8579 std::array<std::string_view, TS_CONFIG_LAST_ENTRY> SDK_Overridable_Configs = {
8580 {"proxy.config.url_remap.pristine_host_hdr",
8581 "proxy.config.http.chunking_enabled",
8582 "proxy.config.http.negative_caching_enabled",
8583 "proxy.config.http.negative_caching_lifetime",
8584 "proxy.config.http.cache.when_to_revalidate",
8585 "proxy.config.http.keep_alive_enabled_in",
8586 "proxy.config.http.keep_alive_enabled_out",
8587 "proxy.config.http.keep_alive_post_out",
8588 "proxy.config.http.server_session_sharing.match",
8589 "proxy.config.net.sock_recv_buffer_size_out",
8590 "proxy.config.net.sock_send_buffer_size_out",
8591 "proxy.config.net.sock_option_flag_out",
8592 "proxy.config.http.forward.proxy_auth_to_parent",
8593 "proxy.config.http.anonymize_remove_from",
8594 "proxy.config.http.anonymize_remove_referer",
8595 "proxy.config.http.anonymize_remove_user_agent",
8596 "proxy.config.http.anonymize_remove_cookie",
8597 "proxy.config.http.anonymize_remove_client_ip",
8598 "proxy.config.http.insert_client_ip",
8599 "proxy.config.http.response_server_enabled",
8600 "proxy.config.http.insert_squid_x_forwarded_for",
8601 "proxy.config.http.send_http11_requests",
8602 "proxy.config.http.cache.http",
8603 "proxy.config.http.cache.ignore_client_no_cache",
8604 "proxy.config.http.cache.ignore_client_cc_max_age",
8605 "proxy.config.http.cache.ims_on_client_no_cache",
8606 "proxy.config.http.cache.ignore_server_no_cache",
8607 "proxy.config.http.cache.cache_responses_to_cookies",
8608 "proxy.config.http.cache.ignore_authentication",
8609 "proxy.config.http.cache.cache_urls_that_look_dynamic",
8610 "proxy.config.http.cache.required_headers",
8611 "proxy.config.http.insert_request_via_str",
8612 "proxy.config.http.insert_response_via_str",
8613 "proxy.config.http.cache.heuristic_min_lifetime",
8614 "proxy.config.http.cache.heuristic_max_lifetime",
8615 "proxy.config.http.cache.guaranteed_min_lifetime",
8616 "proxy.config.http.cache.guaranteed_max_lifetime",
8617 "proxy.config.http.cache.max_stale_age",
8618 "proxy.config.http.keep_alive_no_activity_timeout_in",
8619 "proxy.config.http.keep_alive_no_activity_timeout_out",
8620 "proxy.config.http.transaction_no_activity_timeout_in",
8621 "proxy.config.http.transaction_no_activity_timeout_out",
8622 "proxy.config.http.transaction_active_timeout_out",
8623 "proxy.config.http.connect_attempts_max_retries",
8624 "proxy.config.http.connect_attempts_max_retries_dead_server",
8625 "proxy.config.http.connect_attempts_rr_retries",
8626 "proxy.config.http.connect_attempts_timeout",
8627 "proxy.config.http.post_connect_attempts_timeout",
8628 "proxy.config.http.down_server.cache_time",
8629 "proxy.config.http.down_server.abort_threshold",
8630 "proxy.config.http.doc_in_cache_skip_dns",
8631 "proxy.config.http.background_fill_active_timeout",
8632 "proxy.config.http.response_server_str",
8633 "proxy.config.http.cache.heuristic_lm_factor",
8634 "proxy.config.http.background_fill_completed_threshold",
8635 "proxy.config.net.sock_packet_mark_out",
8636 "proxy.config.net.sock_packet_tos_out",
8637 "proxy.config.http.insert_age_in_response",
8638 "proxy.config.http.chunking.size",
8639 "proxy.config.http.flow_control.enabled",
8640 "proxy.config.http.flow_control.low_water",
8641 "proxy.config.http.flow_control.high_water",
8642 "proxy.config.http.cache.range.lookup",
8643 "proxy.config.http.default_buffer_size",
8644 "proxy.config.http.default_buffer_water_mark",
8645 "proxy.config.http.request_header_max_size",
8646 "proxy.config.http.response_header_max_size",
8647 "proxy.config.http.negative_revalidating_enabled",
8648 "proxy.config.http.negative_revalidating_lifetime",
8649 "proxy.config.ssl.hsts_max_age",
8650 "proxy.config.ssl.hsts_include_subdomains",
8651 "proxy.config.http.cache.open_read_retry_time",
8652 "proxy.config.http.cache.max_open_read_retries",
8653 "proxy.config.http.cache.range.write",
8654 "proxy.config.http.post.check.content_length.enabled",
8655 "proxy.config.http.global_user_agent_header",
8656 "proxy.config.http.auth_server_session_private",
8657 "proxy.config.http.slow.log.threshold",
8658 "proxy.config.http.cache.generation",
8659 "proxy.config.body_factory.template_base",
8660 "proxy.config.http.cache.open_write_fail_action",
8661 "proxy.config.http.number_of_redirections",
8662 "proxy.config.http.cache.max_open_write_retries",
8663 "proxy.config.http.redirect_use_orig_cache_key",
8664 "proxy.config.http.attach_server_session_to_client",
8665 "proxy.config.websocket.no_activity_timeout",
8666 "proxy.config.websocket.active_timeout",
8667 "proxy.config.http.uncacheable_requests_bypass_parent",
8668 "proxy.config.http.parent_proxy.total_connect_attempts",
8669 "proxy.config.http.transaction_active_timeout_in",
8670 "proxy.config.srv_enabled",
8671 "proxy.config.http.forward_connect_method",
8672 "proxy.config.ssl.client.cert.filename",
8673 "proxy.config.ssl.client.cert.path",
8674 "proxy.config.http.parent_proxy.mark_down_hostdb",
8675 "proxy.config.http.cache.ignore_accept_mismatch",
8676 "proxy.config.http.cache.ignore_accept_language_mismatch",
8677 "proxy.config.http.cache.ignore_accept_encoding_mismatch",
8678 "proxy.config.http.cache.ignore_accept_charset_mismatch",
8679 "proxy.config.http.parent_proxy.fail_threshold",
8680 "proxy.config.http.parent_proxy.retry_time",
8681 "proxy.config.http.parent_proxy.per_parent_connect_attempts",
8682 "proxy.config.http.parent_proxy.connect_attempts_timeout",
8683 "proxy.config.http.normalize_ae",
8684 "proxy.config.http.insert_forwarded",
8685 "proxy.config.http.proxy_protocol_out",
8686 "proxy.config.http.allow_multi_range",
8687 "proxy.config.http.request_buffer_enabled",
8688 "proxy.config.http.allow_half_open",
8689 OutboundConnTrack::CONFIG_VAR_MIN,
8690 OutboundConnTrack::CONFIG_VAR_MAX,
8691 OutboundConnTrack::CONFIG_VAR_MATCH,
8692 "proxy.config.ssl.client.verify.server",
8693 "proxy.config.ssl.client.verify.server.policy",
8694 "proxy.config.ssl.client.verify.server.properties",
8695 "proxy.config.ssl.client.sni_policy",
8696 "proxy.config.ssl.client.private_key.filename",
8697 "proxy.config.ssl.client.CA.cert.filename",
8698 "proxy.config.hostdb.ip_resolve",
8699 "proxy.config.http.connect.dead.policy"}};
8700
8701 extern ClassAllocator<HttpSM> httpSMAllocator;
8702
REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS)8703 REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8704 {
8705 TSOverridableConfigKey key;
8706 TSRecordDataType type;
8707 HttpSM *s = THREAD_ALLOC(httpSMAllocator, this_thread());
8708 bool success = true;
8709 TSHttpTxn txnp = reinterpret_cast<TSHttpTxn>(s);
8710 InkRand generator(17);
8711 TSMgmtInt ival_read, ival_rand;
8712 TSMgmtFloat fval_read, fval_rand;
8713 const char *sval_read;
8714 const char *test_string = "The Apache Traffic Server";
8715 int len;
8716
8717 s->init();
8718
8719 *pstatus = REGRESSION_TEST_INPROGRESS;
8720 for (int i = 0; i < static_cast<int>(SDK_Overridable_Configs.size()); ++i) {
8721 std::string_view conf{SDK_Overridable_Configs[i]};
8722
8723 if (TS_SUCCESS == TSHttpTxnConfigFind(conf.data(), -1, &key, &type)) {
8724 if (key != i) {
8725 SDK_RPRINT(test, "TSHttpTxnConfigFind", "TestCase1", TC_FAIL, "Failed on %s, expected %d, got %d", conf.data(), i, key);
8726 success = false;
8727 continue;
8728 }
8729 } else {
8730 SDK_RPRINT(test, "TSHttpTxnConfigFind", "TestCase1", TC_FAIL, "Call returned unexpected TS_ERROR for %s", conf.data());
8731 success = false;
8732 continue;
8733 }
8734
8735 if (TS_SUCCESS == TSHttpTxnConfigFind(conf.data(), conf.size(), &key, &type)) {
8736 if (key != i) {
8737 SDK_RPRINT(test, "TSHttpTxnConfigFind", "TestCase1", TC_FAIL, "Failed on %s, expected %d, got %d", conf.data(), i, key);
8738 success = false;
8739 continue;
8740 }
8741 } else {
8742 SDK_RPRINT(test, "TSHttpTxnConfigFind", "TestCase1", TC_FAIL, "Call returned unexpected TS_ERROR for %s", conf.data());
8743 success = false;
8744 continue;
8745 }
8746
8747 // Now check the getters / setters
8748 switch (type) {
8749 case TS_RECORDDATATYPE_INT:
8750 ival_rand = generator.random() % 126; // to fit in a signed byte
8751 TSHttpTxnConfigIntSet(txnp, key, ival_rand);
8752 TSHttpTxnConfigIntGet(txnp, key, &ival_read);
8753 if (ival_rand != ival_read) {
8754 SDK_RPRINT(test, "TSHttpTxnConfigIntSet", "TestCase1", TC_FAIL, "Failed on %s, %d != %d", conf.data(), ival_read,
8755 ival_rand);
8756 success = false;
8757 continue;
8758 }
8759 break;
8760
8761 case TS_RECORDDATATYPE_FLOAT:
8762 fval_rand = generator.random();
8763 TSHttpTxnConfigFloatSet(txnp, key, fval_rand);
8764 TSHttpTxnConfigFloatGet(txnp, key, &fval_read);
8765 if (fval_rand != fval_read) {
8766 SDK_RPRINT(test, "TSHttpTxnConfigFloatSet", "TestCase1", TC_FAIL, "Failed on %s, %f != %f", conf.data(), fval_read,
8767 fval_rand);
8768 success = false;
8769 continue;
8770 }
8771 break;
8772
8773 case TS_RECORDDATATYPE_STRING:
8774 TSHttpTxnConfigStringSet(txnp, key, test_string, -1);
8775 TSHttpTxnConfigStringGet(txnp, key, &sval_read, &len);
8776 if (test_string != sval_read) {
8777 SDK_RPRINT(test, "TSHttpTxnConfigStringSet", "TestCase1", TC_FAIL, "Failed on %s, %s != %s", conf.data(), sval_read,
8778 test_string);
8779 success = false;
8780 continue;
8781 }
8782 break;
8783
8784 default:
8785 break;
8786 }
8787 }
8788
8789 s->destroy();
8790 if (success) {
8791 *pstatus = REGRESSION_TEST_PASSED;
8792 SDK_RPRINT(test, "TSHttpTxnConfigFind", "TestCase1", TC_PASS, "ok");
8793 SDK_RPRINT(test, "TSHttpTxnConfigIntSet", "TestCase1", TC_PASS, "ok");
8794 SDK_RPRINT(test, "TSHttpTxnConfigFloatSet", "TestCase1", TC_PASS, "ok");
8795 SDK_RPRINT(test, "TSHttpTxnConfigStringSet", "TestCase1", TC_PASS, "ok");
8796 } else {
8797 *pstatus = REGRESSION_TEST_FAILED;
8798 }
8799
8800 return;
8801 }
8802
8803 ////////////////////////////////////////////////
8804 // SDK_API_TXN_HTTP_INFO_INFO_GET
8805 //
8806 // Unit Test for API: TSHttpTxnInfoIntGet
8807 ////////////////////////////////////////////////
8808
REGRESSION_TEST(SDK_API_TXN_HTTP_INFO_GET)8809 REGRESSION_TEST(SDK_API_TXN_HTTP_INFO_GET)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8810 {
8811 HttpSM *s = THREAD_ALLOC(httpSMAllocator, this_thread());
8812 bool success = true;
8813 TSHttpTxn txnp = reinterpret_cast<TSHttpTxn>(s);
8814 TSMgmtInt ival_read;
8815
8816 s->init();
8817
8818 *pstatus = REGRESSION_TEST_INPROGRESS;
8819 HttpCacheSM *c_sm = &(s->get_cache_sm());
8820 c_sm->set_readwhilewrite_inprogress(true);
8821 c_sm->set_open_read_tries(5);
8822 c_sm->set_open_write_tries(8);
8823
8824 TSHttpTxnInfoIntGet(txnp, TS_TXN_INFO_CACHE_HIT_RWW, &ival_read);
8825 if (ival_read == 0) {
8826 SDK_RPRINT(test, "TSHttpTxnInfoIntGet", "TestCase1", TC_FAIL, "Failed on %d, %d != %d", TS_TXN_INFO_CACHE_HIT_RWW, ival_read,
8827 1);
8828 success = false;
8829 }
8830
8831 TSHttpTxnInfoIntGet(txnp, TS_TXN_INFO_CACHE_OPEN_READ_TRIES, &ival_read);
8832 if (ival_read != 5) {
8833 SDK_RPRINT(test, "TSHttpTxnInfoIntGet", "TestCase1", TC_FAIL, "Failed on %d, %d != %d", TS_TXN_INFO_CACHE_HIT_RWW, ival_read,
8834 5);
8835 success = false;
8836 }
8837
8838 TSHttpTxnInfoIntGet(txnp, TS_TXN_INFO_CACHE_OPEN_WRITE_TRIES, &ival_read);
8839 if (ival_read != 8) {
8840 SDK_RPRINT(test, "TSHttpTxnInfoIntGet", "TestCase1", TC_FAIL, "Failed on %d, %d != %d", TS_TXN_INFO_CACHE_HIT_RWW, ival_read,
8841 8);
8842 success = false;
8843 }
8844
8845 s->destroy();
8846 if (success) {
8847 *pstatus = REGRESSION_TEST_PASSED;
8848 SDK_RPRINT(test, "TSHttpTxnInfoIntGet", "TestCase1", TC_PASS, "ok");
8849 } else {
8850 *pstatus = REGRESSION_TEST_FAILED;
8851 }
8852
8853 return;
8854 }
8855
8856 ////////////////////////////////////////////////
8857 // SDK_API_ENCODING
8858 //
8859 // Unit Test for API: TSStringPercentEncode
8860 // TSUrlPercentEncode
8861 // TSStringPercentDecode
8862 ////////////////////////////////////////////////
8863
REGRESSION_TEST(SDK_API_ENCODING)8864 REGRESSION_TEST(SDK_API_ENCODING)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8865 {
8866 const char *url = "http://www.example.com/foo?fie= \"#%<>[]\\^`{}~&bar={test}&fum=Apache Traffic Server";
8867 const char *url_encoded =
8868 "http://www.example.com/foo?fie=%20%22%23%25%3C%3E%5B%5D%5C%5E%60%7B%7D%7E&bar=%7Btest%7D&fum=Apache%20Traffic%20Server";
8869 const char *url_base64 =
8870 "aHR0cDovL3d3dy5leGFtcGxlLmNvbS9mb28/ZmllPSAiIyU8PltdXF5ge31+JmJhcj17dGVzdH0mZnVtPUFwYWNoZSBUcmFmZmljIFNlcnZlcg==";
8871 const char *url2 = "http://www.example.com/"; // No Percent encoding necessary
8872 const char *url3 = "https://www.thisisoneexampleofastringoflengtheightyasciilowercasecharacters.com/";
8873 char buf[1024];
8874 size_t length;
8875 bool success = true;
8876
8877 if (TS_SUCCESS != TSStringPercentEncode(url, strlen(url), buf, sizeof(buf), &length, nullptr)) {
8878 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase1", TC_FAIL, "Failed on %s", url);
8879 success = false;
8880 } else {
8881 if (strcmp(buf, url_encoded)) {
8882 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase1", TC_FAIL, "Failed on %s != %s", buf, url_encoded);
8883 success = false;
8884 } else {
8885 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase1", TC_PASS, "ok");
8886 }
8887 }
8888
8889 if (TS_SUCCESS != TSStringPercentEncode(url2, strlen(url2), buf, sizeof(buf), &length, nullptr)) {
8890 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase2", TC_FAIL, "Failed on %s", url2);
8891 success = false;
8892 } else {
8893 if (strcmp(buf, url2)) {
8894 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase2", TC_FAIL, "Failed on %s != %s", buf, url2);
8895 success = false;
8896 } else {
8897 SDK_RPRINT(test, "TSStringPercentEncode", "TestCase2", TC_PASS, "ok");
8898 }
8899 }
8900
8901 if (TS_SUCCESS != TSStringPercentDecode(url_encoded, strlen(url_encoded), buf, sizeof(buf), &length)) {
8902 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase1", TC_FAIL, "Failed on %s", url_encoded);
8903 success = false;
8904 } else {
8905 if (length != strlen(url) || strcmp(buf, url)) {
8906 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase1", TC_FAIL, "Failed on %s != %s", buf, url);
8907 success = false;
8908 } else {
8909 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase1", TC_PASS, "ok");
8910 }
8911 }
8912
8913 if (TS_SUCCESS != TSStringPercentDecode(url2, strlen(url2), buf, sizeof(buf), &length)) {
8914 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase2", TC_FAIL, "Failed on %s", url2);
8915 success = false;
8916 } else {
8917 if (length != strlen(url2) || strcmp(buf, url2)) {
8918 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase2", TC_FAIL, "Failed on %s != %s", buf, url2);
8919 success = false;
8920 } else {
8921 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase2", TC_PASS, "ok");
8922 }
8923 }
8924
8925 // test to verify TSStringPercentDecode does not write past the end of the
8926 // buffer
8927 const size_t buf_len = strlen(url3) + 1; // 81
8928 memcpy(buf, url3, buf_len - 1);
8929 const char canary = 0xFF;
8930 buf[buf_len - 1] = canary;
8931
8932 const char *url3_clipped = "https://www.thisisoneexampleofastringoflengtheightyasciilowercasecharacters.com";
8933 if (TS_SUCCESS != TSStringPercentDecode(buf, buf_len - 1, buf, buf_len - 1, &length)) {
8934 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase3", TC_FAIL, "Failed on %s", url3);
8935 success = false;
8936 } else {
8937 if (memcmp(buf + buf_len - 1, &canary, 1)) { // Overwrite
8938 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase3", TC_FAIL, "Failed on %s overwrites buffer", url3);
8939 success = false;
8940 } else if (length != strlen(url3_clipped) || strcmp(buf, url3_clipped)) {
8941 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase3", TC_FAIL, "Failed on %s != %s", buf, url3_clipped);
8942 success = false;
8943 } else {
8944 SDK_RPRINT(test, "TSStringPercentDecode", "TestCase3", TC_PASS, "ok");
8945 }
8946 }
8947
8948 if (TS_SUCCESS != TSBase64Encode(url, strlen(url), buf, sizeof(buf), &length)) {
8949 SDK_RPRINT(test, "TSBase64Encode", "TestCase1", TC_FAIL, "Failed on %s", url);
8950 success = false;
8951 } else {
8952 if (length != strlen(url_base64) || strcmp(buf, url_base64)) {
8953 SDK_RPRINT(test, "TSBase64Encode", "TestCase1", TC_FAIL, "Failed on %s != %s", buf, url_base64);
8954 success = false;
8955 } else {
8956 SDK_RPRINT(test, "TSBase64Encode", "TestCase1", TC_PASS, "ok");
8957 }
8958 }
8959
8960 if (TS_SUCCESS != TSBase64Decode(url_base64, strlen(url_base64), reinterpret_cast<unsigned char *>(buf), sizeof(buf), &length)) {
8961 SDK_RPRINT(test, "TSBase64Decode", "TestCase1", TC_FAIL, "Failed on %s", url_base64);
8962 success = false;
8963 } else {
8964 if (length != strlen(url) || strcmp(buf, url)) {
8965 SDK_RPRINT(test, "TSBase64Decode", "TestCase1", TC_FAIL, "Failed on %s != %s", buf, url);
8966 success = false;
8967 } else {
8968 SDK_RPRINT(test, "TSBase64Decode", "TestCase1", TC_PASS, "ok");
8969 }
8970 }
8971
8972 *pstatus = success ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED;
8973
8974 return;
8975 }
8976
8977 ////////////////////////////////////////////////
8978 // SDK_API_DEBUG_NAME_LOOKUPS
8979 //
8980 // Unit Test for API: TSHttpServerStateNameLookup
8981 // TSHttpHookNameLookup
8982 // TSHttpEventNameLookup
8983 ////////////////////////////////////////////////
8984
REGRESSION_TEST(SDK_API_DEBUG_NAME_LOOKUPS)8985 REGRESSION_TEST(SDK_API_DEBUG_NAME_LOOKUPS)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
8986 {
8987 bool success = true;
8988 const char state_name[] = "INACTIVE_TIMEOUT";
8989 const char hook_name[] = "TS_HTTP_READ_RESPONSE_HDR_HOOK";
8990 const char event_name[] = "TS_EVENT_IMMEDIATE";
8991 const char *str;
8992
8993 *pstatus = REGRESSION_TEST_INPROGRESS;
8994
8995 str = TSHttpServerStateNameLookup(TS_SRVSTATE_INACTIVE_TIMEOUT);
8996 if ((strlen(str) != strlen(state_name) || strcmp(str, state_name))) {
8997 SDK_RPRINT(test, "TSHttpServerStateNameLookup", "TestCase1", TC_FAIL, "Failed on %d, expected %s, got %s",
8998 TS_SRVSTATE_INACTIVE_TIMEOUT, state_name, str);
8999 success = false;
9000 } else {
9001 SDK_RPRINT(test, "TSHttpServerStateNameLookup", "TestCase1", TC_PASS, "ok");
9002 }
9003
9004 str = TSHttpHookNameLookup(TS_HTTP_READ_RESPONSE_HDR_HOOK);
9005 if ((strlen(str) != strlen(hook_name) || strcmp(str, hook_name))) {
9006 SDK_RPRINT(test, "TSHttpHookNameLookup", "TestCase1", TC_FAIL, "Failed on %d, expected %s, got %s",
9007 TS_HTTP_READ_RESPONSE_HDR_HOOK, hook_name, str);
9008 success = false;
9009 } else {
9010 SDK_RPRINT(test, "TSHttpHookNameLookup", "TestCase1", TC_PASS, "ok");
9011 }
9012
9013 str = TSHttpEventNameLookup(TS_EVENT_IMMEDIATE);
9014 if (strstr(str, event_name) == nullptr) {
9015 SDK_RPRINT(test, "TSHttpEventNameLookup", "TestCase1", TC_FAIL, "Failed on %d, expected %s to be within %s", TS_EVENT_IMMEDIATE,
9016 event_name, str);
9017 success = false;
9018 } else {
9019 SDK_RPRINT(test, "TSHttpEventNameLookup", "TestCase1", TC_PASS, "ok");
9020 }
9021
9022 *pstatus = success ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED;
9023
9024 return;
9025 }
9026
9027 ////////////////////////////////////////////////
9028 // SDK_API_UUID
9029 //
9030 // Unit Test for API: TSUuidCreate
9031 // TSUuidDestroy
9032 // TSUuidCopy
9033 // TSUuidInitialize
9034 // TSProcessUuidGet
9035 // TSUuidStringGet
9036 // TSUuidVersionGet
9037 // TSUuidStringParse
9038 ////////////////////////////////////////////////
9039 #include "tscore/ink_uuid.h"
9040
REGRESSION_TEST(SDK_API_UUID)9041 REGRESSION_TEST(SDK_API_UUID)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
9042 {
9043 TSUuid machine, uuid;
9044 const char *str1;
9045 const char *str2;
9046 static const char uuid_v1[] = "5de5f9ec-30f4-11e6-a073-002590a33e4e";
9047 static const char uuid_v4[] = "0e95fe5f-295a-401d-9ae4-eb32756d73cb";
9048
9049 *pstatus = REGRESSION_TEST_INPROGRESS;
9050
9051 // Test TSProcessUuidGet(), should just return a non-NULL pointer now.
9052 machine = TSProcessUuidGet();
9053 if (!machine) {
9054 SDK_RPRINT(test, "TSProcessUuidGet", "TestCase1", TC_FAIL, "Returned a NULL pointer");
9055 *pstatus = REGRESSION_TEST_FAILED;
9056 return;
9057 } else if (!(reinterpret_cast<ATSUuid *>(machine))->valid()) {
9058 SDK_RPRINT(test, "TSProcessUuidGet", "TestCase2", TC_FAIL, "Returned an invalid UUID object");
9059 *pstatus = REGRESSION_TEST_FAILED;
9060 return;
9061 } else {
9062 SDK_RPRINT(test, "TSProcessUuidGet", "TestCase1", TC_PASS, "ok");
9063 SDK_RPRINT(test, "TSProcessUuidGet", "TestCase2", TC_PASS, "ok");
9064 }
9065
9066 // Test TSUuidStringGet, should return a random string (so can't check the string value itself)
9067 str1 = TSUuidStringGet(machine);
9068 if (!str1 || (TS_UUID_STRING_LEN != strlen(str1))) {
9069 SDK_RPRINT(test, "TSUuidStringGet", "TestCase1", TC_FAIL, "Did not return a valid UUID string representation");
9070 *pstatus = REGRESSION_TEST_FAILED;
9071 return;
9072 } else {
9073 SDK_RPRINT(test, "TSUuidStringGet", "TestCase1", TC_PASS, "ok");
9074 }
9075
9076 // Test TSUuidCreate
9077 if (!(uuid = TSUuidCreate())) {
9078 SDK_RPRINT(test, "TSUuidCreate", "TestCase1", TC_FAIL, "Failed to create a UUID object");
9079 *pstatus = REGRESSION_TEST_FAILED;
9080 return;
9081 } else {
9082 SDK_RPRINT(test, "TSUuidCreate", "TestCase1", TC_PASS, "ok");
9083 if (TS_SUCCESS != TSUuidInitialize(uuid, TS_UUID_V4)) {
9084 SDK_RPRINT(test, "TSUuidInitialize", "TestCase1", TC_FAIL, "Failed to Initialize a V4 UUID");
9085 *pstatus = REGRESSION_TEST_FAILED;
9086 goto cleanup;
9087 } else {
9088 SDK_RPRINT(test, "TSUuidInitialize", "TestCase1", TC_PASS, "ok");
9089 }
9090 }
9091
9092 // Test TSUuidVersion
9093 if (TS_UUID_V4 != TSUuidVersionGet(uuid)) {
9094 SDK_RPRINT(test, "TSUuidVersionGet", "TestCase1", TC_FAIL, "Failed to get the UUID version");
9095 *pstatus = REGRESSION_TEST_FAILED;
9096 goto cleanup;
9097 } else {
9098 SDK_RPRINT(test, "TSUuidVersionGet", "TestCase1", TC_PASS, "ok");
9099 }
9100
9101 // Test TSUuidCopy
9102 if (TS_SUCCESS != TSUuidCopy(uuid, machine)) {
9103 SDK_RPRINT(test, "TSUuidCopy", "TestCase1", TC_FAIL, "Failed to copy the Machine UUID object");
9104 *pstatus = REGRESSION_TEST_FAILED;
9105 goto cleanup;
9106 } else {
9107 SDK_RPRINT(test, "TSUuidCopy", "TestCase1", TC_PASS, "ok");
9108 str2 = TSUuidStringGet(uuid);
9109 if (!str2 || (TS_UUID_STRING_LEN != strlen(str2)) || strcmp(str1, str2)) {
9110 SDK_RPRINT(test, "TSUuidCopy", "TestCase2", TC_FAIL, "The copied UUID strings are not identical");
9111 *pstatus = REGRESSION_TEST_FAILED;
9112 goto cleanup;
9113 } else {
9114 SDK_RPRINT(test, "TSUuidCopy", "TestCase2", TC_PASS, "ok");
9115 }
9116 }
9117
9118 // Test TSUuidInitialize again, make sure they take effect when called multiple times
9119 if (TS_SUCCESS != TSUuidInitialize(uuid, TS_UUID_V4)) {
9120 SDK_RPRINT(test, "TSUuidInitialize", "TestCase2", TC_FAIL, "Failed to re-initialize the UUID object");
9121 *pstatus = REGRESSION_TEST_FAILED;
9122 goto cleanup;
9123 } else {
9124 SDK_RPRINT(test, "TSUuidInitialize", "TestCase2", TC_PASS, "ok");
9125 str2 = TSUuidStringGet(uuid);
9126 if (!str2 || (TS_UUID_STRING_LEN != strlen(str2)) || !strcmp(str1, str2)) {
9127 SDK_RPRINT(test, "TSUuidInitialize", "TestCase3", TC_FAIL, "The re-initialized string is the same as before");
9128 *pstatus = REGRESSION_TEST_FAILED;
9129 goto cleanup;
9130 } else {
9131 SDK_RPRINT(test, "TSUuidInitialize", "TestCase3", TC_PASS, "ok");
9132 }
9133 }
9134
9135 // Test TSUuidStringParse
9136 if ((TS_SUCCESS != TSUuidStringParse(uuid, uuid_v1)) || (TS_UUID_V1 != TSUuidVersionGet(uuid))) {
9137 SDK_RPRINT(test, "TSUuidStringParse", "TestCase1", TC_FAIL, "Failed to parse the UUID v1 string");
9138 *pstatus = REGRESSION_TEST_FAILED;
9139 goto cleanup;
9140 } else {
9141 SDK_RPRINT(test, "TSUuidStringParse", "TestCase1", TC_PASS, "ok");
9142 str1 = TSUuidStringGet(uuid);
9143 if (!str1 || (TS_UUID_STRING_LEN != strlen(str1)) || strcmp(str1, uuid_v1)) {
9144 SDK_RPRINT(test, "TSUuidStringString", "TestCase2", TC_FAIL, "The parse UUID v1 string does not match the original");
9145 *pstatus = REGRESSION_TEST_FAILED;
9146 goto cleanup;
9147 } else {
9148 SDK_RPRINT(test, "TSUuidStringParse", "TestCase2", TC_PASS, "ok");
9149 }
9150 }
9151 if ((TS_SUCCESS != TSUuidStringParse(uuid, uuid_v4)) || (TS_UUID_V4 != TSUuidVersionGet(uuid))) {
9152 SDK_RPRINT(test, "TSUuidStringParse", "TestCase3", TC_FAIL, "Failed to parse the UUID v4 string");
9153 *pstatus = REGRESSION_TEST_FAILED;
9154 goto cleanup;
9155 } else {
9156 SDK_RPRINT(test, "TSUuidStringParse", "TestCase3", TC_PASS, "ok");
9157 str1 = TSUuidStringGet(uuid);
9158 if (!str1 || (TS_UUID_STRING_LEN != strlen(str1)) || strcmp(str1, uuid_v4)) {
9159 SDK_RPRINT(test, "TSUuidStringParse", "TestCase4", TC_FAIL, "The parse UUID v4 string does not match the original");
9160 *pstatus = REGRESSION_TEST_FAILED;
9161 goto cleanup;
9162 } else {
9163 SDK_RPRINT(test, "TSUuidStringParse", "TestCase4", TC_PASS, "ok");
9164 }
9165 }
9166
9167 *pstatus = REGRESSION_TEST_PASSED;
9168
9169 cleanup:
9170 TSUuidDestroy(uuid);
9171
9172 return;
9173 }
9174
REGRESSION_TEST(SDK_API_TSSslServerContextCreate)9175 REGRESSION_TEST(SDK_API_TSSslServerContextCreate)(RegressionTest *test, int level, int *pstatus)
9176 {
9177 TSSslContext ctx;
9178
9179 // See TS-4769: TSSslServerContextCreate always returns null.
9180 ctx = TSSslServerContextCreate(nullptr, nullptr, nullptr);
9181
9182 *pstatus = ctx ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED;
9183 TSSslContextDestroy(ctx);
9184 }
9185
REGRESSION_TEST(SDK_API_TSStatCreate)9186 REGRESSION_TEST(SDK_API_TSStatCreate)(RegressionTest *test, int level, int *pstatus)
9187 {
9188 const char name[] = "regression.test.metric";
9189 int id;
9190
9191 TestBox box(test, pstatus);
9192
9193 box = REGRESSION_TEST_PASSED;
9194
9195 if (TSStatFindName(name, &id) == TS_SUCCESS) {
9196 box.check(id >= 0, "TSStatFind(%s) failed with bogus ID %d", name, id);
9197 } else {
9198 id = TSStatCreate(name, TS_RECORDDATATYPE_COUNTER, TS_STAT_NON_PERSISTENT, TS_STAT_SYNC_SUM);
9199 box.check(id != TS_ERROR, "TSStatCreate(%s) failed with %d", name, id);
9200 }
9201
9202 TSStatIntSet(id, getpid());
9203 TSStatIntIncrement(id, 1);
9204 TSStatIntIncrement(id, 1);
9205
9206 TSMgmtInt value = TSStatIntGet(id);
9207 TSMgmtInt expected = getpid() + 2;
9208
9209 box.check(expected >= value, "TSStatIntGet(%s) gave %" PRId64 ", expected at least %" PRId64, name, value, expected);
9210 }
9211