55/* Test data */
66#include "data/td/json_td.h" /* JSON_TD */
77
8+ /* CloudWatch API constants */
9+ #include "../../plugins/out_cloudwatch_logs/cloudwatch_api.h"
10+
811#define ERROR_ALREADY_EXISTS "{\"__type\":\"ResourceAlreadyExistsException\"}"
912/* not a real error code, but tests that the code can respond to any error */
1013#define ERROR_UNKNOWN "{\"__type\":\"UNKNOWN\"}"
1114
15+ /* JSON structure constants for test message generation */
16+ static const char * TEST_JSON_PREFIX = "{\"message\":\"" ;
17+ static const char * TEST_JSON_SUFFIX = "\"}" ;
18+
1219/* It writes a big JSON message (copied from TD test) */
1320void flb_test_cloudwatch_success (void )
1421{
@@ -393,6 +400,134 @@ void flb_test_cloudwatch_error_put_retention_policy(void)
393400 flb_destroy (ctx );
394401}
395402
403+ /* Helper function to create a large JSON message of specified size */
404+ static char * create_large_json_message (size_t target_size )
405+ {
406+ size_t prefix_len = strlen (TEST_JSON_PREFIX );
407+ size_t suffix_len = strlen (TEST_JSON_SUFFIX );
408+ size_t overhead = prefix_len + suffix_len ;
409+ size_t data_size ;
410+ char * json ;
411+ size_t i ;
412+
413+ /* Ensure target size can accommodate JSON structure */
414+ if (target_size < overhead + 1 ) {
415+ target_size = overhead + 1 ;
416+ }
417+
418+ json = flb_malloc (target_size + 1 );
419+ if (!json ) {
420+ return NULL ;
421+ }
422+
423+ /* Build JSON: prefix + data + suffix */
424+ strcpy (json , TEST_JSON_PREFIX );
425+ data_size = target_size - overhead ;
426+
427+ /* Fill with 'A' characters */
428+ for (i = 0 ; i < data_size ; i ++ ) {
429+ json [prefix_len + i ] = 'A' ;
430+ }
431+
432+ /* Close JSON object */
433+ strcpy (json + prefix_len + data_size , TEST_JSON_SUFFIX );
434+ json [target_size ] = '\0' ;
435+
436+ return json ;
437+ }
438+
439+ /* Helper to setup and run a CloudWatch test with custom JSON data */
440+ static void run_cloudwatch_test_with_data (char * data , size_t data_len )
441+ {
442+ int ret ;
443+ flb_ctx_t * ctx ;
444+ int in_ffd ;
445+ int out_ffd ;
446+
447+ setenv ("FLB_CLOUDWATCH_PLUGIN_UNDER_TEST" , "true" , 1 );
448+
449+ ctx = flb_create ();
450+ TEST_CHECK (ctx != NULL );
451+
452+ in_ffd = flb_input (ctx , (char * ) "lib" , NULL );
453+ TEST_CHECK (in_ffd >= 0 );
454+ flb_input_set (ctx , in_ffd , "tag" , "test" , NULL );
455+
456+ out_ffd = flb_output (ctx , (char * ) "cloudwatch_logs" , NULL );
457+ TEST_CHECK (out_ffd >= 0 );
458+ flb_output_set (ctx , out_ffd , "match" , "test" , NULL );
459+ flb_output_set (ctx , out_ffd , "region" , "us-west-2" , NULL );
460+ flb_output_set (ctx , out_ffd , "log_group_name" , "fluent" , NULL );
461+ flb_output_set (ctx , out_ffd , "log_stream_prefix" , "from-fluent-" , NULL );
462+ flb_output_set (ctx , out_ffd , "auto_create_group" , "On" , NULL );
463+ flb_output_set (ctx , out_ffd , "net.keepalive" , "Off" , NULL );
464+ flb_output_set (ctx , out_ffd , "Retry_Limit" , "1" , NULL );
465+
466+ ret = flb_start (ctx );
467+ TEST_CHECK (ret == 0 );
468+
469+ if (data ) {
470+ flb_lib_push (ctx , in_ffd , data , data_len );
471+ }
472+
473+ sleep (2 );
474+ flb_stop (ctx );
475+ flb_destroy (ctx );
476+ }
477+
478+ /* Test event size at maximum allowed limit (should succeed without truncation) */
479+ void flb_test_cloudwatch_event_size_at_limit (void )
480+ {
481+ char * large_json ;
482+
483+ /* Create message at MAX_EVENT_LEN */
484+ large_json = create_large_json_message (MAX_EVENT_LEN );
485+ TEST_CHECK (large_json != NULL );
486+
487+ if (large_json ) {
488+ run_cloudwatch_test_with_data (large_json , strlen (large_json ));
489+ flb_free (large_json );
490+ }
491+ }
492+
493+ /* Test event size exceeding limit (should be truncated to MAX_EVENT_LEN) */
494+ void flb_test_cloudwatch_event_size_over_limit (void )
495+ {
496+ char * large_json ;
497+
498+ /* Create message exceeding MAX_EVENT_LEN by 1 byte to test truncation */
499+ large_json = create_large_json_message (MAX_EVENT_LEN + 1 );
500+ TEST_CHECK (large_json != NULL );
501+
502+ if (large_json ) {
503+ run_cloudwatch_test_with_data (large_json , strlen (large_json ));
504+ flb_free (large_json );
505+ }
506+ }
507+
508+ /* Test event with trailing backslash at truncation boundary */
509+ void flb_test_cloudwatch_event_truncation_with_backslash (void )
510+ {
511+ char * large_json ;
512+ size_t prefix_len = strlen (TEST_JSON_PREFIX );
513+ size_t i ;
514+
515+ /* Create base message near MAX_EVENT_LEN */
516+ large_json = create_large_json_message (MAX_EVENT_LEN + 100 );
517+ TEST_CHECK (large_json != NULL );
518+
519+ if (large_json ) {
520+ /* Post-process: replace every 100th character with backslash */
521+ for (i = 99 ; large_json [prefix_len + i ] != '\0' &&
522+ large_json [prefix_len + i ] != '"' ; i += 100 ) {
523+ large_json [prefix_len + i ] = '\\' ;
524+ }
525+
526+ run_cloudwatch_test_with_data (large_json , strlen (large_json ));
527+ flb_free (large_json );
528+ }
529+ }
530+
396531/* Test list */
397532TEST_LIST = {
398533 {"success" , flb_test_cloudwatch_success },
@@ -405,5 +540,8 @@ TEST_LIST = {
405540 {"put_retention_policy_success" , flb_test_cloudwatch_put_retention_policy_success },
406541 {"already_exists_create_group_put_retention_policy" , flb_test_cloudwatch_already_exists_create_group_put_retention_policy },
407542 {"error_put_retention_policy" , flb_test_cloudwatch_error_put_retention_policy },
543+ {"event_size_at_limit" , flb_test_cloudwatch_event_size_at_limit },
544+ {"event_size_over_limit" , flb_test_cloudwatch_event_size_over_limit },
545+ {"event_truncation_with_backslash" , flb_test_cloudwatch_event_truncation_with_backslash },
408546 {NULL , NULL }
409547};
0 commit comments