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\": ["
242 " \"commandType\": \"throttlingSpecification\","
243 " \"eventDomainThrottleSpecification\": {"
244 " \"eventDomain\": \"fault\""
248 " \"commandType\": \"throttlingSpecification\","
249 " \"eventDomainThrottleSpecification\": {"
250 " \"eventDomain\": \"measurementsForVfScaling\""
254 " \"commandType\": \"throttlingSpecification\","
255 " \"eventDomainThrottleSpecification\": {"
256 " \"eventDomain\": \"mobileFlow\""
260 " \"commandType\": \"throttlingSpecification\","
261 " \"eventDomainThrottleSpecification\": {"
262 " \"eventDomain\": \"serviceEvents\""
266 " \"commandType\": \"throttlingSpecification\","
267 " \"eventDomainThrottleSpecification\": {"
268 " \"eventDomain\": \"signaling\""
272 " \"commandType\": \"throttlingSpecification\","
273 " \"eventDomainThrottleSpecification\": {"
274 " \"eventDomain\": \"stateChange\""
278 " \"commandType\": \"throttlingSpecification\","
279 " \"eventDomainThrottleSpecification\": {"
280 " \"eventDomain\": \"syslog\""
287 case TC_FAULT_SUPPRESS_FIELDS:
288 json_size += snprintf(
289 json_buffer + json_size,
290 MAX_JSON - json_size,
292 " \"commandList\": ["
294 " \"commandType\": \"throttlingSpecification\","
295 " \"eventDomainThrottleSpecification\": {"
296 " \"suppressedFieldNames\": ["
297 " \"alarmInterfaceA\","
298 " \"alarmAdditionalInformation\""
300 " \"eventDomain\": \"fault\""
307 case TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS:
308 json_size += snprintf(
309 json_buffer + json_size,
310 MAX_JSON - json_size,
312 " \"commandList\": ["
314 " \"commandType\": \"throttlingSpecification\","
315 " \"eventDomainThrottleSpecification\": {"
316 " \"suppressedNvPairsList\": ["
318 " \"nvPairFieldName\": \"alarmAdditionalInformation\","
319 " \"suppressedNvPairNames\": ["
325 " \"suppressedFieldNames\": ["
326 " \"alarmInterfaceA\""
328 " \"eventDomain\": \"fault\""
335 case TC_FAULT_SUPPRESS_NOTHING:
336 json_size += snprintf(
337 json_buffer + json_size,
338 MAX_JSON - json_size,
340 " \"commandList\": ["
342 " \"commandType\": \"throttlingSpecification\","
343 " \"eventDomainThrottleSpecification\": {"
344 " \"eventDomain\": \"fault\""
351 case TC_FAULT_SUPPRESS_PAIRS:
352 json_size += snprintf(
353 json_buffer + json_size,
354 MAX_JSON - json_size,
356 " \"commandList\": ["
358 " \"commandType\": \"throttlingSpecification\","
359 " \"eventDomainThrottleSpecification\": {"
360 " \"suppressedNvPairsList\": ["
362 " \"nvPairFieldName\": \"alarmAdditionalInformation\","
363 " \"suppressedNvPairNames\": ["
369 " \"eventDomain\": \"fault\""
376 case TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS:
377 json_size += snprintf(
378 json_buffer + json_size,
379 MAX_JSON - json_size,
381 " \"commandList\": ["
383 " \"commandType\": \"throttlingSpecification\","
384 " \"eventDomainThrottleSpecification\": {"
385 " \"suppressedNvPairsList\": ["
387 " \"nvPairFieldName\": \"cpuUsageArray\","
388 " \"suppressedNvPairNames\": ["
394 " \"suppressedFieldNames\": ["
395 " \"numberOfMediaPortsInUse\","
396 " \"aggregateCpuUsage\""
398 " \"eventDomain\": \"measurementsForVfScaling\""
405 case TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS:
406 json_size += snprintf(
407 json_buffer + json_size,
408 MAX_JSON - json_size,
410 " \"commandList\": ["
412 " \"commandType\": \"throttlingSpecification\","
413 " \"eventDomainThrottleSpecification\": {"
414 " \"suppressedFieldNames\": ["
415 " \"radioAccessTechnology\","
416 " \"samplingAlgorithm\""
418 " \"eventDomain\": \"mobileFlow\""
425 case TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS:
426 json_size += snprintf(
427 json_buffer + json_size,
428 MAX_JSON - json_size,
430 " \"commandList\": ["
432 " \"commandType\": \"throttlingSpecification\","
433 " \"eventDomainThrottleSpecification\": {"
434 " \"suppressedNvPairsList\": ["
436 " \"nvPairFieldName\": \"additionalFields\","
437 " \"suppressedNvPairNames\": ["
443 " \"suppressedFieldNames\": ["
444 " \"reportingEntityId\","
447 " \"codecSelected\","
448 " \"codecSelectedTranscoding\","
450 " \"endOfCallVqmSummaries\","
453 " \"eventDomain\": \"serviceEvents\""
460 case TC_SIGNALING_SUPPRESS_FIELDS:
461 json_size += snprintf(
462 json_buffer + json_size,
463 MAX_JSON - json_size,
465 " \"commandList\": ["
467 " \"commandType\": \"throttlingSpecification\","
468 " \"eventDomainThrottleSpecification\": {"
469 " \"suppressedFieldNames\": ["
470 " \"reportingEntityId\","
473 " \"localIpAddress\","
475 " \"remoteIpAddress\","
479 " \"eventDomain\": \"signaling\""
486 case TC_STATE_SUPPRESS_FIELDS_AND_PAIRS:
487 json_size += snprintf(
488 json_buffer + json_size,
489 MAX_JSON - json_size,
491 " \"commandList\": ["
493 " \"commandType\": \"throttlingSpecification\","
494 " \"eventDomainThrottleSpecification\": {"
495 " \"suppressedNvPairsList\": ["
497 " \"nvPairFieldName\": \"additionalFields\","
498 " \"suppressedNvPairNames\": ["
503 " \"suppressedFieldNames\": ["
504 " \"reportingEntityId\","
508 " \"eventDomain\": \"stateChange\""
515 case TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS:
516 json_size += snprintf(
517 json_buffer + json_size,
518 MAX_JSON - json_size,
520 " \"commandList\": ["
522 " \"commandType\": \"throttlingSpecification\","
523 " \"eventDomainThrottleSpecification\": {"
524 " \"suppressedNvPairsList\": ["
526 " \"nvPairFieldName\": \"additionalFields\","
527 " \"suppressedNvPairNames\": ["
533 " \"suppressedFieldNames\": ["
534 " \"syslogFacility\","
538 " \"eventDomain\": \"syslog\""
545 case TC_PROVIDE_THROTTLING_SPEC:
546 json_size += snprintf(
547 json_buffer + json_size,
548 MAX_JSON - json_size,
550 " \"commandList\": ["
552 " \"commandType\": \"provideThrottlingState\""
564 evel_test_control(json_buffer, json_size, secure, fqdn, port);
570 /**************************************************************************//**
571 * POST a measurement interval change to the test_collector testControl API.
573 * @param interval The measurement interval.
574 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
575 * @param fqdn The test control API FQDN or IP address.
576 * @param port The test control API port.
577 *****************************************************************************/
578 void evel_test_control_meas_interval(const int interval,
583 const int MAX_JSON = 10000;
584 char json_buffer[MAX_JSON];
589 json_size += snprintf(
590 json_buffer + json_size,
591 MAX_JSON - json_size,
592 "{\"commandList\": [\"command\": "
593 "{\"commandType\": \"measurementIntervalChange\", "
594 "\"measurementInterval\": %d}]}",
596 evel_test_control(json_buffer, json_size, secure, fqdn, port);