1 /**************************************************************************//**
3 * Utility to post test control commands to the test_collector testControl API.
5 * This software is a test capability, allowing test cases to trigger
6 * expected throttling behaviours at the test collector, for automated test
12 * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
17 * 1. Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement: This product includes software
24 * developed by the AT&T.
25 * 4. Neither the name of AT&T nor the names of its contributors may be used to
26 * endorse or promote products derived from this software without specific
27 * prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
30 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *****************************************************************************/
43 #include <curl/curl.h>
46 #include "evel_test_control.h"
47 #include "evel_internal.h" /* For MEMORY_CHUNK */
49 /*****************************************************************************/
50 /* Local prototypes. */
51 /*****************************************************************************/
52 static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
54 /**************************************************************************//**
55 * POST provide JSON to the test_collector testControl API.
57 * This function does not take ownership of the json_buffer passed in.
59 * @param json_buffer Pointer to the JSON to POST
60 * @param json_size The number of bytes to POST
61 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
62 * @param fqdn The test control API FQDN or IP address.
63 * @param port The test control API port.
64 *****************************************************************************/
65 void evel_test_control(char * const json_buffer,
71 CURLcode curl_rc = CURLE_OK;
72 char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
74 /***************************************************************************/
75 /* Get a curl handle. */
76 /***************************************************************************/
77 CURL * curl_handle = curl_easy_init();
78 assert(curl_handle != NULL);
80 /***************************************************************************/
81 /* Prime the library to give friendly error codes. */
82 /***************************************************************************/
83 curl_rc = curl_easy_setopt(curl_handle,
86 assert(curl_rc == CURLE_OK);
88 /***************************************************************************/
89 /* Build and set the testControl API URL. */
90 /***************************************************************************/
91 char version_string[10] = {0};
92 int offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
93 if (EVEL_API_MINOR_VERSION != 0)
95 sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
97 char test_control_url[EVEL_MAX_URL_LEN + 1] = {0};
98 snprintf(test_control_url,
100 "%s://%s:%d/testControl/v%s/commandList",
101 secure ? "https" : "http",
105 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, test_control_url);
106 assert(curl_rc == CURLE_OK);
108 /***************************************************************************/
109 /* Some servers don't like requests that are made without a user-agent */
110 /* field, so we provide one. */
111 /***************************************************************************/
112 curl_rc = curl_easy_setopt(curl_handle,
114 "libcurl-agent/1.0");
115 assert(curl_rc == CURLE_OK);
117 /***************************************************************************/
118 /* Specify that we are going to POST data. */
119 /***************************************************************************/
120 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
121 assert(curl_rc == CURLE_OK);
123 /***************************************************************************/
124 /* We want to use our own read function. */
125 /***************************************************************************/
126 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
127 assert(curl_rc == CURLE_OK);
129 /***************************************************************************/
130 /* All of our events are JSON encoded. We also suppress the */
131 /* Expect: 100-continue header that we would otherwise get since it */
132 /* confuses some servers. */
133 /***************************************************************************/
134 static struct curl_slist * hdr_chunk = NULL;
135 hdr_chunk = curl_slist_append(hdr_chunk, "Content-type: application/json");
136 hdr_chunk = curl_slist_append(hdr_chunk, "Expect:");
138 /***************************************************************************/
139 /* Set our custom set of headers. */
140 /***************************************************************************/
141 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, hdr_chunk);
142 assert(curl_rc == CURLE_OK);
144 /***************************************************************************/
145 /* Set the timeout for the operation. */
146 /***************************************************************************/
147 const int TEST_CTRL_TIMEOUT = 2;
148 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, TEST_CTRL_TIMEOUT);
149 assert(curl_rc == CURLE_OK);
151 /***************************************************************************/
152 /* Create a common pointer to pass to our read function, on stack. */
153 /***************************************************************************/
154 MEMORY_CHUNK tx_chunk = {json_buffer, json_size};
155 curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk);
156 assert(curl_rc == CURLE_OK);
158 /***************************************************************************/
159 /* Set transmit size. */
160 /***************************************************************************/
161 curl_rc = curl_easy_setopt(curl_handle,
162 CURLOPT_POSTFIELDSIZE,
164 assert(curl_rc == CURLE_OK);
166 /***************************************************************************/
167 /* Perform the POST. */
168 /***************************************************************************/
169 curl_rc = curl_easy_perform(curl_handle);
170 assert(curl_rc == CURLE_OK);
172 /***************************************************************************/
173 /* Shut down the cURL library in a tidy manner. */
174 /***************************************************************************/
175 curl_easy_cleanup(curl_handle);
180 /**************************************************************************//**
181 * Callback function to provide POST data.
183 * Copy data into the supplied buffer, read_callback::ptr, checking size
186 * @returns Number of bytes placed into read_callback::ptr. 0 for EOF.
187 *****************************************************************************/
188 static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
191 size_t bytes_to_write = 0;
192 MEMORY_CHUNK * tx_chunk = (MEMORY_CHUNK *)userp;
196 bytes_to_write = min(size * nmemb, tx_chunk->size);
198 if (bytes_to_write > 0)
200 strncpy((char *)ptr, tx_chunk->memory, bytes_to_write);
201 tx_chunk->memory += bytes_to_write;
202 tx_chunk->size -= bytes_to_write;
203 rtn = bytes_to_write;
211 /**************************************************************************//**
212 * POST a pre-set test scenario to the test_collector testControl API.
214 * This function provides various pre-configured scenarios, purely to avoid
215 * duplicating them elsewhere.
217 * @param scenario The scenario to POST.
218 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
219 * @param fqdn The test control API FQDN or IP address.
220 * @param port The test control API port.
221 *****************************************************************************/
222 void evel_test_control_scenario(const EVEL_TEST_CONTROL_SCENARIO scenario,
227 const int MAX_JSON = 10000;
228 char json_buffer[MAX_JSON];
235 case TC_RESET_ALL_DOMAINS:
236 json_size += snprintf(
237 json_buffer + json_size,
238 MAX_JSON - json_size,
240 " \"commandList\": ["
243 " \"commandType\": \"throttlingSpecification\","
244 " \"eventDomainThrottleSpecification\": {"
245 " \"eventDomain\": \"fault\""
251 " \"commandType\": \"throttlingSpecification\","
252 " \"eventDomainThrottleSpecification\": {"
253 " \"eventDomain\": \"measurementsForVfScaling\""
259 " \"commandType\": \"throttlingSpecification\","
260 " \"eventDomainThrottleSpecification\": {"
261 " \"eventDomain\": \"mobileFlow\""
267 " \"commandType\": \"throttlingSpecification\","
268 " \"eventDomainThrottleSpecification\": {"
269 " \"eventDomain\": \"serviceEvents\""
275 " \"commandType\": \"throttlingSpecification\","
276 " \"eventDomainThrottleSpecification\": {"
277 " \"eventDomain\": \"signaling\""
283 " \"commandType\": \"throttlingSpecification\","
284 " \"eventDomainThrottleSpecification\": {"
285 " \"eventDomain\": \"stateChange\""
291 " \"commandType\": \"throttlingSpecification\","
292 " \"eventDomainThrottleSpecification\": {"
293 " \"eventDomain\": \"syslog\""
301 case TC_FAULT_SUPPRESS_FIELDS:
302 json_size += snprintf(
303 json_buffer + json_size,
304 MAX_JSON - json_size,
306 " \"commandList\": ["
309 " \"commandType\": \"throttlingSpecification\","
310 " \"eventDomainThrottleSpecification\": {"
311 " \"suppressedFieldNames\": ["
312 " \"alarmInterfaceA\","
313 " \"alarmAdditionalInformation\""
315 " \"eventDomain\": \"fault\""
323 case TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS:
324 json_size += snprintf(
325 json_buffer + json_size,
326 MAX_JSON - json_size,
328 " \"commandList\": ["
331 " \"commandType\": \"throttlingSpecification\","
332 " \"eventDomainThrottleSpecification\": {"
333 " \"suppressedNvPairsList\": ["
335 " \"nvPairFieldName\": \"alarmAdditionalInformation\","
336 " \"suppressedNvPairNames\": ["
342 " \"suppressedFieldNames\": ["
343 " \"alarmInterfaceA\""
345 " \"eventDomain\": \"fault\""
353 case TC_FAULT_SUPPRESS_NOTHING:
354 json_size += snprintf(
355 json_buffer + json_size,
356 MAX_JSON - json_size,
358 " \"commandList\": ["
361 " \"commandType\": \"throttlingSpecification\","
362 " \"eventDomainThrottleSpecification\": {"
363 " \"eventDomain\": \"fault\""
371 case TC_FAULT_SUPPRESS_PAIRS:
372 json_size += snprintf(
373 json_buffer + json_size,
374 MAX_JSON - json_size,
376 " \"commandList\": ["
379 " \"commandType\": \"throttlingSpecification\","
380 " \"eventDomainThrottleSpecification\": {"
381 " \"suppressedNvPairsList\": ["
383 " \"nvPairFieldName\": \"alarmAdditionalInformation\","
384 " \"suppressedNvPairNames\": ["
390 " \"eventDomain\": \"fault\""
398 case TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS:
399 json_size += snprintf(
400 json_buffer + json_size,
401 MAX_JSON - json_size,
403 " \"commandList\": ["
406 " \"commandType\": \"throttlingSpecification\","
407 " \"eventDomainThrottleSpecification\": {"
408 " \"suppressedNvPairsList\": ["
410 " \"nvPairFieldName\": \"cpuUsageArray\","
411 " \"suppressedNvPairNames\": ["
417 " \"suppressedFieldNames\": ["
418 " \"numberOfMediaPortsInUse\""
420 " \"eventDomain\": \"measurementsForVfScaling\""
428 case TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS:
429 json_size += snprintf(
430 json_buffer + json_size,
431 MAX_JSON - json_size,
433 " \"commandList\": ["
436 " \"commandType\": \"throttlingSpecification\","
437 " \"eventDomainThrottleSpecification\": {"
438 " \"suppressedFieldNames\": ["
439 " \"radioAccessTechnology\","
440 " \"samplingAlgorithm\""
442 " \"eventDomain\": \"mobileFlow\""
450 case TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS:
451 json_size += snprintf(
452 json_buffer + json_size,
453 MAX_JSON - json_size,
455 " \"commandList\": ["
458 " \"commandType\": \"throttlingSpecification\","
459 " \"eventDomainThrottleSpecification\": {"
460 " \"suppressedNvPairsList\": ["
462 " \"nvPairFieldName\": \"additionalFields\","
463 " \"suppressedNvPairNames\": ["
469 " \"suppressedFieldNames\": ["
470 " \"reportingEntityId\","
474 " \"endOfCallVqmSummaries\","
477 " \"eventDomain\": \"serviceEvents\""
485 case TC_SIGNALING_SUPPRESS_FIELDS:
486 json_size += snprintf(
487 json_buffer + json_size,
488 MAX_JSON - json_size,
490 " \"commandList\": ["
493 " \"commandType\": \"throttlingSpecification\","
494 " \"eventDomainThrottleSpecification\": {"
495 " \"suppressedFieldNames\": ["
496 " \"reportingEntityId\","
499 " \"localIpAddress\","
501 " \"remoteIpAddress\","
505 " \"eventDomain\": \"signaling\""
513 case TC_STATE_SUPPRESS_FIELDS_AND_PAIRS:
514 json_size += snprintf(
515 json_buffer + json_size,
516 MAX_JSON - json_size,
518 " \"commandList\": ["
521 " \"commandType\": \"throttlingSpecification\","
522 " \"eventDomainThrottleSpecification\": {"
523 " \"suppressedNvPairsList\": ["
525 " \"nvPairFieldName\": \"additionalFields\","
526 " \"suppressedNvPairNames\": ["
531 " \"suppressedFieldNames\": ["
532 " \"reportingEntityId\","
536 " \"eventDomain\": \"stateChange\""
544 case TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS:
545 json_size += snprintf(
546 json_buffer + json_size,
547 MAX_JSON - json_size,
549 " \"commandList\": ["
552 " \"commandType\": \"throttlingSpecification\","
553 " \"eventDomainThrottleSpecification\": {"
554 " \"suppressedNvPairsList\": ["
556 " \"nvPairFieldName\": \"additionalFields\","
557 " \"suppressedNvPairNames\": ["
563 " \"suppressedFieldNames\": ["
564 " \"syslogFacility\","
568 " \"eventDomain\": \"syslog\""
576 case TC_PROVIDE_THROTTLING_SPEC:
577 json_size += snprintf(
578 json_buffer + json_size,
579 MAX_JSON - json_size,
581 " \"commandList\": ["
584 " \"commandType\": \"provideThrottlingState\""
597 evel_test_control(json_buffer, json_size, secure, fqdn, port);
603 /**************************************************************************//**
604 * POST a measurement interval change to the test_collector testControl API.
606 * @param interval The measurement interval.
607 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
608 * @param fqdn The test control API FQDN or IP address.
609 * @param port The test control API port.
610 *****************************************************************************/
611 void evel_test_control_meas_interval(const int interval,
616 const int MAX_JSON = 10000;
617 char json_buffer[MAX_JSON];
622 json_size += snprintf(
623 json_buffer + json_size,
624 MAX_JSON - json_size,
625 "{\"commandList\": [{\"command\": "
626 "{\"commandType\": \"measurementIntervalChange\", "
627 "\"measurementInterval\": %d}}]}",
629 evel_test_control(json_buffer, json_size, secure, fqdn, port);