summaryrefslogtreecommitdiffstats
path: root/fluent-bit/tests/internal/utils.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
commitbe1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch)
tree9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/tests/internal/utils.c
parentInitial commit. (diff)
downloadnetdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz
netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--fluent-bit/tests/internal/utils.c622
1 files changed, 622 insertions, 0 deletions
diff --git a/fluent-bit/tests/internal/utils.c b/fluent-bit/tests/internal/utils.c
new file mode 100644
index 00000000..119094bd
--- /dev/null
+++ b/fluent-bit/tests/internal/utils.c
@@ -0,0 +1,622 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_utils.h>
+#include <stdarg.h>
+#include "flb_tests_internal.h"
+#include "fluent-bit/flb_macros.h"
+
+
+struct url_check {
+ int ret;
+ char *url; /* full URL */
+ char *prot; /* expected protocol */
+ char *host; /* expected host */
+ char *port; /* expected port */
+ char *uri; /* expected uri */
+};
+
+struct write_str_case {
+ char *input;
+ int input_len;
+ char *output;
+ int ret;
+};
+
+struct url_check url_checks[] = {
+ {0, "https://fluentbit.io/something",
+ "https", "fluentbit.io", "443", "/something"},
+ {0, "http://fluentbit.io/something",
+ "http", "fluentbit.io", "80", "/something"},
+ {0, "https://fluentbit.io", "https", "fluentbit.io", "443", "/"},
+ {0, "https://fluentbit.io:1234/something",
+ "https", "fluentbit.io", "1234", "/something"},
+ {0, "https://fluentbit.io:1234", "https", "fluentbit.io", "1234", "/"},
+ {0, "https://fluentbit.io:1234/", "https", "fluentbit.io", "1234", "/"},
+ {0, "https://fluentbit.io:1234/v", "https", "fluentbit.io", "1234", "/v"},
+ {-1, "://", NULL, NULL, NULL, NULL},
+};
+
+void test_url_split()
+{
+ int i;
+ int ret;
+ int size;
+ char *protocol;
+ char *host;
+ char *port;
+ char *uri;
+ struct url_check *u;
+
+ size = sizeof(url_checks) / sizeof(struct url_check);
+ for (i = 0; i < size; i ++) {
+ u = &url_checks[i];
+
+ protocol = NULL;
+ host = NULL;
+ port = NULL;
+ uri = NULL;
+
+ ret = flb_utils_url_split(u->url, &protocol, &host, &port, &uri);
+ TEST_CHECK(ret == u->ret);
+ if (ret == -1) {
+ continue;
+ }
+
+ /* protocol */
+ if (u->prot) {
+ TEST_CHECK(protocol != NULL);
+
+ ret = strcmp(u->prot, protocol);
+ TEST_CHECK(ret == 0);
+ }
+ else {
+ TEST_CHECK(protocol == NULL);
+ }
+
+ /* host */
+ if (u->host) {
+ TEST_CHECK(host != NULL);
+ ret = strcmp(u->host, host);
+ TEST_CHECK(ret == 0);
+ }
+ else {
+ TEST_CHECK(host == NULL);
+ }
+
+ /* port */
+ if (u->port) {
+ TEST_CHECK(port != NULL);
+ ret = strcmp(u->port, port);
+ TEST_CHECK(ret == 0);
+ }
+ else {
+ TEST_CHECK(port == NULL);
+ }
+
+ /* uri */
+ if (u->uri) {
+ TEST_CHECK(uri != NULL);
+ ret = strcmp(u->uri, uri);
+ TEST_CHECK(ret == 0);
+ }
+ else {
+ TEST_CHECK(uri == NULL);
+ }
+
+ if (protocol) {
+ flb_free(protocol);
+ }
+ if (host) {
+ flb_free(host);
+ }
+ if (port) {
+ flb_free(port);
+ }
+ if (uri) {
+ flb_free(uri);
+ }
+ }
+}
+
+/* test case loop for flb_utils_write_str */
+static void write_str_test_cases_w_buf_size(struct write_str_case *cases, int buf_size);
+static void write_str_test_cases(struct write_str_case *cases) {
+ write_str_test_cases_w_buf_size(cases, 100);
+}
+
+/* test case loop for flb_utils_write_str */
+static void write_str_test_cases_w_buf_size(struct write_str_case *cases, int buf_size) {
+ char *buf = flb_calloc(buf_size + 1, sizeof(char));
+ int size = buf_size + 1;
+ int off;
+ int ret;
+
+ struct write_str_case *tcase = cases;
+ while (!(tcase->input == 0 && tcase->output == 0)) {
+ memset(buf, 0, size);
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, buf_size, tcase->input, tcase->input_len);
+
+ if(!TEST_CHECK(ret == tcase->ret)) {
+ TEST_MSG("Input string: %s", tcase->input);
+ TEST_MSG("| Expected return value: %s", (tcase->ret == FLB_TRUE) ? "FLB_TRUE"
+ : "FLB_FALSE");
+ TEST_MSG("| Produced return value: %s", (ret == FLB_TRUE) ? "FLB_TRUE"
+ : "FLB_FALSE");
+ }
+ if(!TEST_CHECK(memcmp(buf, tcase->output, off) == 0)) {
+ TEST_MSG("Input string: %s", tcase->input);
+ TEST_MSG("| Expected output: %s", tcase->output);
+ TEST_MSG("| Produced output: %s", buf);
+ }
+ if (!TEST_CHECK(strlen(buf) == strlen(tcase->output))) {
+ TEST_MSG("Input string: %s", tcase->input);
+ TEST_MSG("| Expected length: %zu", strlen(tcase->output));
+ TEST_MSG("| Produced length: %zu", strlen(buf));
+ TEST_MSG("| Expected output: %s", tcase->output);
+ TEST_MSG("| Produced output: %s", buf);
+ }
+ if (!TEST_CHECK(buf[size-1] == 0)) {
+ TEST_MSG("Out buffer overwrite detected '%c'", buf[size-1]);
+ }
+
+ ++tcase;
+ }
+
+ flb_free(buf);
+}
+
+void test_write_str()
+{
+ char buf[10];
+ char japanese_a[4] = {0xe3, 0x81, 0x82};
+ int size = sizeof(buf);
+ int off;
+ int ret;
+
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, size, "a", 1);
+ TEST_CHECK(ret == FLB_TRUE);
+ TEST_CHECK(memcmp(buf, "a", off) == 0);
+
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, size, "\n", 1);
+ TEST_CHECK(ret == FLB_TRUE);
+ TEST_CHECK(memcmp(buf, "\\n", off) == 0);
+
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, size, "\xe3\x81\x82", 3);
+ TEST_CHECK(ret == FLB_TRUE);
+ TEST_CHECK(memcmp(buf, japanese_a, off) == 0);
+
+ // Truncated bytes
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, size, "\xe3\x81\x82\xe3", 1);
+ TEST_CHECK(ret == FLB_TRUE);
+ TEST_CHECK(memcmp(buf, japanese_a, off) == 0);
+
+ // Error: buffer too small
+ off = 0;
+ ret = flb_utils_write_str(buf, &off, size, "aaaaaaaaaaa", 11);
+ TEST_CHECK(ret == FLB_FALSE);
+}
+
+void test_write_str_invalid_trailing_bytes()
+{
+ struct write_str_case cases[] = {
+ /* Invalid unicode (one bad trailing bytes) */
+ {
+ "\xe3\x81\x01""abc", 6, /* note that 0x01 is an invalid byte */
+ "\xee\x83\xa3" /* e3 fragment */ /* replace invalid unicode */
+ "\xee\x82\x81" /* 81 fragment */
+ "\\u0001abc",
+ FLB_TRUE
+ },
+ /*
+ * Invalid unicode (two bad trailing bytes)
+ */
+ {
+ "\xe3\x01\x01""abc", 6,
+ "\xee\x83\xa3" /* e3 fragment */
+ "\\u0001\\u0001abc",
+ FLB_TRUE
+ },
+ { 0 }
+ };
+
+ write_str_test_cases(cases);
+}
+
+void test_write_str_invalid_leading_byte()
+{
+
+ struct write_str_case cases[] = {
+ /*
+ * Escaped leading hex (two hex, one valid unicode)
+ */
+ {
+ "\x00\x01\xe3\x81\x82""abc", 8, /* note that 0x01 is an invalid byte */
+ "\\u0000\\u0001""\xe3\x81\x82""abc", /* escape hex */
+ FLB_TRUE
+ },
+ /*
+ * Invalid unicode fragment (two byte fragment)
+ * note that 0xf3 is a leading byte with 3 trailing bytes. note that 0xe3 is also a
+ * leading byte with 2 trailing bytes. This should not be consumed by 0xf3 invalid
+ * unicode character
+ */
+ {
+ "\xf3\x81\x81\xe3\x81\x82""abc", 9, /* note that 0xf3 0x81 0x81 is an invalid fragment */
+ "\xee\x83\xb3" /* f3 fragment */ /* replace invalid unicode */
+ "\xee\x82\x81" /* 81 fragment */
+ "\xee\x82\x81" /* 81 fragment */
+ "\xe3\x81\x82""abc", /* valid unicode */
+ FLB_TRUE
+ },
+ /*
+ * Invalid unicode (one bad leading byte + one bad trailing byte)
+ * note that 0xf3 is a leading byte with 3 trailing bytes. 0x01 is an invalid byte
+ */
+ {
+ "\xf3\x81\x01\xe3\x81\x82""abc", 9, /* note that 0x01 is an invalid byte */
+ "\xee\x83\xb3" /* f3 fragment */ /* replace invalid unicode */
+ "\xee\x82\x81" /* 81 fragment */
+ "\\u0001""\xe3\x81\x82""abc",
+ FLB_TRUE
+ },
+ { 0 }
+ };
+
+ write_str_test_cases(cases);
+}
+
+void test_write_str_invalid_leading_byte_case_2()
+{
+
+ struct write_str_case cases[] = {
+ /* Invalid leading bytes */
+ {
+ "\x81\x82""abc", 5, /* note that 0x81 & 0x82 are invalid leading bytes */
+ "\xee\x82\x81" /* 81 fragment */ /* replace invalid unicode */
+ "\xee\x82\x82" /* 82 fragment */
+ "abc",
+ FLB_TRUE
+ },
+ /*
+ * Invalid unicode (one bad leading byte + one bad trailing byte + one bad leading byte)
+ * note that 0xf3 is a leading byte with 3 trailing bytes. 0x01 is an invalid byte
+ * 0x81 & 0x82 are invalid leading bytes
+ */
+ {
+ "\xf3\x81\x01\x81\x82""abc", 8, /* note that 0x81 & 0x82 are invalid leading bytes */
+ "\xee\x83\xb3" /* f3 fragment */ /* replace invalid unicode */
+ "\xee\x82\x81" /* 81 fragment */
+ "\\u0001" /* 0x01 hex escape */
+ "\xee\x82\x81" /* 81 fragment */
+ "\xee\x82\x82" /* 82 fragment */
+ "abc",
+ FLB_TRUE
+ },
+ { 0 }
+ };
+
+ write_str_test_cases(cases);
+}
+
+void test_write_str_edge_cases()
+{
+ struct write_str_case cases[] = {
+ /* Invalid unicode (one bad leading byte) */
+ {
+ "\xf3", 1, /* will this buffer overrun? */
+ "", /* discard invalid unicode */
+ FLB_TRUE
+ },
+ { 0 }
+ };
+
+ write_str_test_cases(cases);
+}
+
+void test_write_str_buffer_overrun()
+{
+ struct write_str_case cases[] = {
+ {
+ "aa""\x81", 3,
+ "aa"
+ "\xee\x82\x81", /* just enough space for 81 fragment */
+ FLB_TRUE
+ },
+ {
+ "aaa""\x81", 4, /* out buffer size: 5, needed bytes: 2 + 3 + 3 = 8 */
+ "aaa",
+ /* "\xee\x82\x81", */ /* 81 fragment -- would overrun */
+ FLB_FALSE
+ },
+ {
+ "aaa"
+ "\xe3\x81\x82", 6, /* required is already grater than buffer */
+ "",
+ FLB_FALSE
+ },
+ {
+ "\""
+ "\xe3\x81\x82", 4, /* valid unicode */
+ "\\\"""\xe3\x81\x82", /* just enough space for valid unicode */
+ FLB_TRUE
+ },
+ {
+ "\x81"
+ "\xe3\x81\x82", 4, /* valid unicode */
+ "\xee\x82\x81", /* 81 fragment */
+ /* not enough space for valid unicode fragment "\xe3\x81\x82" */
+ FLB_FALSE
+ },
+ { 0 }
+ };
+ write_str_test_cases_w_buf_size(cases, 5);
+}
+
+struct proxy_url_check {
+ int ret;
+ char *url; /* full URL */
+ char *prot; /* expected protocol */
+ char *host; /* expected host */
+ char *port; /* expected port */
+ char *username; /* expected username */
+ char *password; /* expected password */
+};
+
+struct proxy_url_check proxy_url_checks[] = {
+ {0, "http://foo:bar@proxy.com:8080",
+ "http", "proxy.com", "8080", "foo", "bar"},
+ {0, "http://proxy.com",
+ "http", "proxy.com", "80", NULL, NULL},
+ {0, "http://proxy.com:8080",
+ "http", "proxy.com", "8080", NULL, NULL},
+ /* issue #5530. Password contains @ */
+ {0, "http://example_user:example_pass_w_@_char@proxy.com:8080",
+ "http", "proxy.com", "8080", "example_user", "example_pass_w_@_char"},
+ {-1, "https://proxy.com:8080",
+ NULL, NULL, NULL, NULL, NULL}
+
+};
+
+void test_proxy_url_split() {
+ int i;
+ int ret;
+ int size;
+ char *protocol;
+ char *host;
+ char *port;
+ char *username;
+ char *password;
+ struct proxy_url_check *u;
+
+ size = sizeof(proxy_url_checks) / sizeof(struct proxy_url_check);
+ for (i = 0; i < size; i++) {
+ u = &proxy_url_checks[i];
+
+ protocol = NULL;
+ host = NULL;
+ port = NULL;
+ username = NULL;
+ password = NULL;
+
+ ret = flb_utils_proxy_url_split(u->url, &protocol, &username, &password, &host, &port);
+ TEST_CHECK(ret == u->ret);
+ if (ret == -1) {
+ continue;
+ }
+
+ /* Protocol */
+ TEST_CHECK(protocol != NULL);
+ ret = strcmp(u->prot, protocol);
+ TEST_CHECK(ret == 0);
+ TEST_MSG("Expected protocol: %s", u->prot);
+ TEST_MSG("Produced protocol: %s", protocol);
+
+ /* Host */
+ TEST_CHECK(host != NULL);
+ ret = strcmp(u->host, host);
+ TEST_CHECK(ret == 0);
+ TEST_MSG("Expected host: %s", u->host);
+ TEST_MSG("Produced host: %s", host);
+
+ /* Port */
+ TEST_CHECK(port != NULL);
+ ret = strcmp(u->port, port);
+ TEST_CHECK(ret == 0);
+ TEST_MSG("Expected port: %s", u->port);
+ TEST_MSG("Produced port: %s", port);
+
+ /* Username */
+ if (u->username) {
+ TEST_CHECK(port != NULL);
+ ret = strcmp(u->port, port);
+ TEST_CHECK(ret == 0);
+ TEST_MSG("Expected username: %s", u->username);
+ TEST_MSG("Produced username: %s", username);
+
+ }
+ else {
+ TEST_CHECK(username == NULL);
+ }
+
+ /* Password */
+ if (u->password) {
+ TEST_CHECK(port != NULL);
+ ret = strcmp(u->port, port);
+ TEST_CHECK(ret == 0);
+ TEST_MSG("Expected password: %s", u->password);
+ TEST_MSG("Produced password: %s", password);
+ }
+ else {
+ TEST_CHECK(password == NULL);
+ }
+
+ if (protocol) {
+ flb_free(protocol);
+ }
+ if (host) {
+ flb_free(host);
+ }
+ if (port) {
+ flb_free(port);
+ }
+ if (username) {
+ flb_free(username);
+ }
+ if (password) {
+ flb_free(password);
+ }
+ }
+}
+
+static int compare_split_entry(const char* input, int separator, int max_split, int quoted, ...)
+{
+ va_list ap;
+ int count = 1;
+ char *expect;
+ struct mk_list *split = NULL;
+ struct mk_list *tmp_list = NULL;
+ struct mk_list *head = NULL;
+ struct flb_split_entry *entry = NULL;
+
+ if (quoted) {
+ split = flb_utils_split_quoted(input, separator, max_split);
+ }
+ else {
+ split = flb_utils_split(input, separator, max_split);
+ }
+
+ if (!TEST_CHECK(split != NULL)) {
+ TEST_MSG("flb_utils_split failed. input=%s", input);
+ return -1;
+ }
+ if (!TEST_CHECK(mk_list_is_empty(split) != 0)) {
+ TEST_MSG("list is empty. input=%s", input);
+ return -1;
+ }
+
+ va_start(ap, quoted);
+ mk_list_foreach_safe(head, tmp_list, split) {
+ if (max_split > 0 && !TEST_CHECK(count <= max_split) ) {
+ TEST_MSG("count error. got=%d expect=%d input=%s", count, max_split, input);
+ }
+
+ expect = va_arg(ap, char*);
+ entry = mk_list_entry(head, struct flb_split_entry, _head);
+ if (!TEST_CHECK(entry != NULL)) {
+ TEST_MSG("entry is NULL. input=%s", input);
+ goto comp_end;
+ }
+ /*
+ printf("%d:%s\n", count, entry->value);
+ */
+ if (!TEST_CHECK(strcmp(expect, entry->value) == 0)) {
+ TEST_MSG("mismatch. got=%s expect=%s. input=%s", entry->value, expect, input);
+ goto comp_end;
+ }
+ count++;
+ }
+ comp_end:
+ if (split != NULL) {
+ flb_utils_split_free(split);
+ }
+ va_end(ap);
+ return 0;
+}
+
+void test_flb_utils_split()
+{
+ compare_split_entry("aa,bb", ',', 2, FLB_FALSE, "aa","bb" );
+ compare_split_entry("localhost:12345", ':', 2, FLB_FALSE, "localhost","12345" );
+ compare_split_entry("https://fluentbit.io/announcements/", '/', -1, FLB_FALSE, "https:", "fluentbit.io","announcements" );
+
+ /* /proc/net/dev example */
+ compare_split_entry("enp0s3: 1955136 1768 0 0 0 0 0 0 89362 931 0 0 0 0 0 0",
+ ' ', 256, FLB_FALSE,
+ "enp0s3:", "1955136", "1768", "0", "0", "0", "0", "0", "0", "89362", "931", "0", "0", "0", "0", "0", "0", "0");
+
+ /* filter_grep configuration */
+ compare_split_entry("Regex test *a*", ' ', 3, FLB_FALSE, "Regex", "test", "*a*");
+
+ /* filter_modify configuration */
+ compare_split_entry("Condition Key_Value_Does_Not_Equal cpustats KNOWN", ' ', 4,
+ FLB_FALSE, "Condition", "Key_Value_Does_Not_Equal", "cpustats", "KNOWN");
+
+ /* nginx_exporter_metrics example */
+ compare_split_entry("Active connections: 1\nserver accepts handled requests\n 10 10 10\nReading: 0 Writing: 1 Waiting: 0", '\n', 4,
+ FLB_FALSE, "Active connections: 1", "server accepts handled requests", " 10 10 10","Reading: 0 Writing: 1 Waiting: 0");
+
+ /* out_cloudwatch_logs example */
+ compare_split_entry("dimension_1,dimension_2;dimension_3", ';', 256,
+ FLB_FALSE, "dimension_1,dimension_2", "dimension_3");
+ /* separator is not contained */
+ compare_split_entry("aa,bb", '/', 2, FLB_FALSE, "aa,bb");
+
+ /* do not parse quotes when tokenizing */
+ compare_split_entry("aa \"bb cc\" dd", ' ', 256, FLB_FALSE, "aa", "\"bb", "cc\"", "dd");
+}
+
+void test_flb_utils_split_quoted()
+{
+ /* Tokens quoted with "..." */
+ compare_split_entry("aa \"double quote\" bb", ' ', 256, FLB_TRUE, "aa", "double quote", "bb");
+ compare_split_entry("\"begin with double quote\" aa", ' ', 256, FLB_TRUE, "begin with double quote", "aa");
+ compare_split_entry("aa \"end with double quote\"", ' ', 256, FLB_TRUE, "aa", "end with double quote");
+
+ /* Tokens quoted with '...' */
+ compare_split_entry("aa bb 'single quote' cc", ' ', 256, FLB_TRUE, "aa", "bb", "single quote", "cc");
+ compare_split_entry("'begin with single quote' aa", ' ', 256, FLB_TRUE, "begin with single quote", "aa");
+ compare_split_entry("aa 'end with single quote'", ' ', 256, FLB_TRUE, "aa", "end with single quote");
+
+ /* Tokens surrounded by more than one separator character */
+ compare_split_entry(" aa \" spaces bb \" cc ' spaces dd ' ff", ' ', 256, FLB_TRUE,
+ "aa", " spaces bb ", "cc", " spaces dd ", "ff");
+
+ /* Escapes within quoted token */
+ compare_split_entry("aa \"escaped \\\" quote\" bb", ' ', 256, FLB_TRUE, "aa", "escaped \" quote", "bb");
+ compare_split_entry("aa 'escaped \\' quote\' bb", ' ', 256, FLB_TRUE, "aa", "escaped \' quote", "bb");
+ compare_split_entry("aa \"\\\"escaped balanced quotes\\\"\" bb", ' ', 256, FLB_TRUE,
+ "aa", "\"escaped balanced quotes\"", "bb");
+ compare_split_entry("aa '\\'escaped balanced quotes\\'\' bb", ' ', 256, FLB_TRUE,
+ "aa", "'escaped balanced quotes'", "bb");
+ compare_split_entry("aa 'escaped \\\\ escape\' bb", ' ', 256, FLB_TRUE, "aa", "escaped \\ escape", "bb");
+
+ /* Escapes that are not processed */
+ compare_split_entry("\\\"aa bb", ' ', 256, FLB_TRUE, "\\\"aa", "bb");
+ compare_split_entry("\\'aa bb", ' ', 256, FLB_TRUE, "\\'aa", "bb");
+ compare_split_entry("\\\\aa bb", ' ', 256, FLB_TRUE, "\\\\aa", "bb");
+ compare_split_entry("aa\\ bb", ' ', 256, FLB_TRUE, "aa\\", "bb");
+
+}
+
+void test_flb_utils_split_quoted_errors()
+{
+ struct mk_list *split = NULL;
+
+ split = flb_utils_split_quoted("aa \"unbalanced quotes should fail", ' ', 256);
+ TEST_CHECK(split == NULL);
+ split = flb_utils_split_quoted("aa 'unbalanced quotes should fail", ' ', 256);
+ TEST_CHECK(split == NULL);
+}
+
+TEST_LIST = {
+ /* JSON maps iteration */
+ { "url_split", test_url_split },
+ { "write_str", test_write_str },
+ { "test_write_str_invalid_trailing_bytes", test_write_str_invalid_trailing_bytes },
+ { "test_write_str_invalid_leading_byte", test_write_str_invalid_leading_byte },
+ { "test_write_str_edge_cases", test_write_str_edge_cases },
+ { "test_write_str_invalid_leading_byte_case_2", test_write_str_invalid_leading_byte_case_2 },
+ { "test_write_str_buffer_overrun", test_write_str_buffer_overrun },
+ { "proxy_url_split", test_proxy_url_split },
+ { "test_flb_utils_split", test_flb_utils_split },
+ { "test_flb_utils_split_quoted", test_flb_utils_split_quoted},
+ { "test_flb_utils_split_quoted_errors", test_flb_utils_split_quoted_errors},
+ { 0 }
+};