test_end();
}
+static const char *settings_blob_2 =
+"metric=test\n"
+"metric/test/name=test\n"
+"metric/test/event_name=test\n"
+"metric/test/group_by=test_name\n"
+"\n";
+
+static int
+test_reader_server_input_args_group_by(struct connection *conn,
+ const char *const *args)
+{
+ struct test_connection *tconn =
+ container_of(conn, struct test_connection, conn);
+
+ if (args[0] == NULL)
+ return -1;
+
+ tconn->row_count++;
+
+ if (tconn->row_count == 1) {
+ test_assert_strcmp(args[0], "test");
+ test_assert_strcmp(args[1], "1");
+ } else if (tconn->row_count == 2) {
+ test_assert_strcmp(args[0], "test_alpha");
+ test_assert_strcmp(args[1], "1");
+ }
+ return 1;
+}
+
+static void test_dump_metrics_group_by(void)
+{
+ int fds[2];
+
+ test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
+
+ struct test_connection *conn = i_new(struct test_connection, 1);
+
+ struct ioloop *loop = io_loop_create();
+
+ client_reader_create(fds[1], metrics);
+ connection_init_client_fd(conn_list, &conn->conn, "stats", fds[0], fds[0]);
+ o_stream_nsend_str(conn->conn.output, "DUMP\tcount\n");
+
+ io_loop_run(loop);
+ connection_deinit(&conn->conn);
+ i_free(conn);
+
+ io_loop_set_running(loop);
+ io_loop_handler_run(loop);
+
+ io_loop_destroy(&loop);
+}
+
+static void test_client_reader_group_by(void)
+{
+ const struct connection_vfuncs client_vfuncs = {
+ .input_args = test_reader_server_input_args_group_by,
+ .destroy = test_reader_server_destroy,
+ };
+
+ test_begin("client reader (group by)");
+
+ /* register some stats */
+ test_init(settings_blob_2);
+
+ client_readers_init();
+ conn_list = connection_list_init(&client_set, &client_vfuncs);
+
+ /* push event in */
+ struct event *event = event_create(NULL);
+ event_add_category(event, &test_category);
+ event_set_name(event, "test");
+ event_add_str(event, "event_name", "alpha");
+ test_event_send(event);
+ event_unref(&event);
+
+ test_assert(get_stats_dist_field("test", STATS_DIST_COUNT) == 1);
+ test_assert(get_stats_dist_field("test", STATS_DIST_SUM) > 0);
+
+ /* check output from reader */
+ test_dump_metrics_group_by();
+
+ test_deinit();
+
+ client_readers_deinit();
+ connection_list_deinit(&conn_list);
+
+ test_end();
+}
+
int main(void) {
/* fake master service to pretend destroying
connections. */
};
void (*const test_functions[])(void) = {
test_client_reader,
+ test_client_reader_group_by,
NULL
};
/* Copyright (c) 2019 Dovecot authors, see the included COPYING file */
#include "test-stats-common.h"
+#include "array.h"
bool test_stats_callback(struct event *event,
enum event_callback_type type ATTR_UNUSED,
test_end();
}
+static const char *settings_blob_3 =
+"metric=test\n"
+"metric/test/name=test\n"
+"metric/test/event_name=test\n"
+"metric/test/group_by=test_name sub_name\n"
+"\n";
+
+static void test_stats_metrics_group_by(void)
+{
+ test_begin("stats metrics (group by)");
+
+ test_init(settings_blob_3);
+
+ struct event *event;
+
+ event = event_create(NULL);
+ event_add_category(event, &test_category);
+ event_set_name(event, "test");
+ event_add_str(event, "test_name", "alpha");
+ event_add_str(event, "sub_name", "eta");
+ test_event_send(event);
+ event_unref(&event);
+
+ event = event_create(NULL);
+ event_add_category(event, &test_category);
+ event_set_name(event, "test");
+ event_add_str(event, "test_name", "phi");
+ event_add_str(event, "sub_name", "beta");
+ test_event_send(event);
+ event_unref(&event);
+
+ event = event_create(NULL);
+ event_add_category(event, &test_category);
+ event_set_name(event, "test");
+ event_add_str(event, "test_name", "omega");
+ event_add_str(event, "sub_name", "pi");
+ test_event_send(event);
+ event_unref(&event);
+
+ /* we should have now three events */
+ test_assert(get_stats_dist_field("test", STATS_DIST_COUNT) == 3);
+
+ /* analyze the structure */
+ const struct metric *root_metric, *leaf ATTR_UNUSED;
+ struct metric *const *children;
+ struct stats_metrics_iter *iter = stats_metrics_iterate_init(metrics);
+ root_metric = stats_metrics_iterate(iter);
+ stats_metrics_iterate_deinit(&iter);
+
+ test_assert(array_is_created(&root_metric->sub_metrics));
+ test_assert(array_count(&root_metric->sub_metrics) == 3);
+
+ /* then look at each level */
+ children = array_idx(&root_metric->sub_metrics, 0);
+ test_assert_strcmp(children[0]->sub_name, "alpha");
+ test_assert(stats_dist_get_count(children[0]->duration_stats) == 1);
+
+ test_assert(array_is_created(&children[0]->sub_metrics));
+ test_assert(array_count(&children[0]->sub_metrics) == 1);
+
+ leaf = *array_idx(&children[0]->sub_metrics, 0);
+ test_assert_strcmp(leaf->sub_name, "eta");
+ test_assert(stats_dist_get_count(leaf->duration_stats) == 1);
+
+ test_assert_strcmp(children[1]->sub_name, "phi");
+
+ test_assert(array_is_created(&children[1]->sub_metrics));
+ test_assert(array_count(&children[1]->sub_metrics) == 1);
+
+ leaf = *array_idx(&children[1]->sub_metrics, 0);
+ test_assert_strcmp(leaf->sub_name, "beta");
+ test_assert(stats_dist_get_count(leaf->duration_stats) == 1);
+
+ test_assert_strcmp(children[2]->sub_name, "omega");
+
+ test_assert(array_is_created(&children[2]->sub_metrics));
+ test_assert(array_count(&children[2]->sub_metrics) == 1);
+
+ leaf = *array_idx(&children[2]->sub_metrics, 0);
+ test_assert_strcmp(leaf->sub_name, "pi");
+ test_assert(stats_dist_get_count(leaf->duration_stats) == 1);
+
+ test_deinit();
+ test_end();
+}
+
int main(void) {
void (*const test_functions[])(void) = {
test_stats_metrics,
test_stats_metrics_filter,
+ test_stats_metrics_group_by,
NULL
};