123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "dyncfg-internals.h"
- #include "dyncfg.h"
- // ----------------------------------------------------------------------------
- // unit test
- #define LINE_FILE_STR TOSTRING(__LINE__) "@" __FILE__
- struct dyncfg_unittest {
- bool enabled;
- size_t errors;
- DICTIONARY *nodes;
- SPINLOCK spinlock;
- struct dyncfg_unittest_action *queue;
- } dyncfg_unittest_data = { 0 };
- typedef struct {
- bool enabled;
- bool removed;
- struct {
- double dbl;
- bool bln;
- } value;
- } TEST_CFG;
- typedef struct {
- const char *id;
- const char *source;
- bool sync;
- DYNCFG_TYPE type;
- DYNCFG_CMDS cmds;
- DYNCFG_SOURCE_TYPE source_type;
- TEST_CFG current;
- TEST_CFG expected;
- bool received;
- bool finished;
- size_t last_saves;
- bool needs_save;
- } TEST;
- struct dyncfg_unittest_action {
- TEST *t;
- BUFFER *result;
- BUFFER *payload;
- DYNCFG_CMDS cmd;
- const char *add_name;
- const char *source;
- rrd_function_result_callback_t result_cb;
- void *result_cb_data;
- struct dyncfg_unittest_action *prev, *next;
- };
- static void dyncfg_unittest_register_error(const char *id, const char *msg) {
- if(msg)
- nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG UNITTEST: error on id '%s': %s", id ? id : "", msg);
- __atomic_add_fetch(&dyncfg_unittest_data.errors, 1, __ATOMIC_RELAXED);
- }
- static int dyncfg_unittest_execute_cb(struct rrd_function_execute *rfe, void *data);
- bool dyncfg_unittest_parse_payload(BUFFER *payload, TEST *t, DYNCFG_CMDS cmd, const char *add_name, const char *source) {
- CLEAN_JSON_OBJECT *jobj = json_tokener_parse(buffer_tostring(payload));
- if(!jobj) {
- dyncfg_unittest_register_error(t->id, "cannot parse json payload");
- return false;
- }
- struct json_object *json_double;
- struct json_object *json_boolean;
- json_object_object_get_ex(jobj, "double", &json_double);
- double value_double = json_object_get_double(json_double);
- json_object_object_get_ex(jobj, "boolean", &json_boolean);
- int value_boolean = json_object_get_boolean(json_boolean);
- if(cmd == DYNCFG_CMD_UPDATE) {
- t->current.value.dbl = value_double;
- t->current.value.bln = value_boolean;
- }
- else if(cmd == DYNCFG_CMD_ADD) {
- char buf[strlen(t->id) + strlen(add_name) + 20];
- snprintfz(buf, sizeof(buf), "%s:%s", t->id, add_name);
- TEST tmp = {
- .id = strdupz(buf),
- .source = strdupz(source),
- .cmds = (t->cmds & ~DYNCFG_CMD_ADD) | DYNCFG_CMD_GET | DYNCFG_CMD_REMOVE | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE | DYNCFG_CMD_TEST,
- .sync = t->sync,
- .type = DYNCFG_TYPE_JOB,
- .source_type = DYNCFG_SOURCE_TYPE_DYNCFG,
- .received = true,
- .finished = true,
- .current =
- {.enabled = true,
- .removed = false,
- .value =
- {
- .dbl = value_double,
- .bln = value_boolean,
- }},
- .expected = {
- .enabled = true,
- .removed = false,
- .value = {
- .dbl = 3.14,
- .bln = true,
- }
- },
- .needs_save = true,
- };
- const DICTIONARY_ITEM *item = dictionary_set_and_acquire_item(dyncfg_unittest_data.nodes, buf, &tmp, sizeof(tmp));
- TEST *t2 = dictionary_acquired_item_value(item);
- dictionary_acquired_item_release(dyncfg_unittest_data.nodes, item);
- dyncfg_add_low_level(localhost, t2->id, "/unittests",
- DYNCFG_STATUS_RUNNING, t2->type, t2->source_type, t2->source,
- t2->cmds, 0, 0, t2->sync,
- dyncfg_unittest_execute_cb, t2);
- }
- else {
- dyncfg_unittest_register_error(t->id, "invalid command received to parse payload");
- return false;
- }
- return true;
- }
- static int dyncfg_unittest_action(struct dyncfg_unittest_action *a) {
- TEST *t = a->t;
- int rc = HTTP_RESP_OK;
- if(a->cmd == DYNCFG_CMD_ENABLE)
- t->current.enabled = true;
- else if(a->cmd == DYNCFG_CMD_DISABLE)
- t->current.enabled = false;
- else if(a->cmd == DYNCFG_CMD_ADD || a->cmd == DYNCFG_CMD_UPDATE)
- rc = dyncfg_unittest_parse_payload(a->payload, a->t, a->cmd, a->add_name, a->source) ? HTTP_RESP_OK : HTTP_RESP_BAD_REQUEST;
- else if(a->cmd == DYNCFG_CMD_REMOVE)
- t->current.removed = true;
- else
- rc = HTTP_RESP_BAD_REQUEST;
- dyncfg_default_response(a->result, rc, NULL);
- a->result_cb(a->result, rc, a->result_cb_data);
- buffer_free(a->payload);
- freez((void *)a->add_name);
- freez(a);
- __atomic_store_n(&t->finished, true, __ATOMIC_RELAXED);
- return rc;
- }
- static void *dyncfg_unittest_thread_action(void *ptr __maybe_unused) {
- while(1) {
- struct dyncfg_unittest_action *a = NULL;
- spinlock_lock(&dyncfg_unittest_data.spinlock);
- a = dyncfg_unittest_data.queue;
- if(a)
- DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(dyncfg_unittest_data.queue, a, prev, next);
- spinlock_unlock(&dyncfg_unittest_data.spinlock);
- if(a)
- dyncfg_unittest_action(a);
- else
- sleep_usec(10 * USEC_PER_MS);
- }
- }
- static int dyncfg_unittest_execute_cb(struct rrd_function_execute *rfe, void *data) {
- int rc;
- bool run_the_callback = true;
- TEST *t = data;
- t->received = true;
- char buf[strlen(rfe->function) + 1];
- memcpy(buf, rfe->function, sizeof(buf));
- char *words[MAX_FUNCTION_PARAMETERS]; // an array of pointers for the words in this line
- size_t num_words = quoted_strings_splitter_pluginsd(buf, words, MAX_FUNCTION_PARAMETERS);
- const char *config = get_word(words, num_words, 0);
- const char *id = get_word(words, num_words, 1);
- const char *action = get_word(words, num_words, 2);
- const char *add_name = get_word(words, num_words, 3);
- if(!config || !*config || strcmp(config, PLUGINSD_FUNCTION_CONFIG) != 0) {
- char *msg = "did not receive a config call";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- if(!id || !*id) {
- char *msg = "did not receive an id";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- if(t->type != DYNCFG_TYPE_TEMPLATE && strcmp(t->id, id) != 0) {
- char *msg = "id received is not the expected";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- if(!action || !*action) {
- char *msg = "did not receive an action";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- DYNCFG_CMDS cmd = dyncfg_cmds2id(action);
- if(cmd == DYNCFG_CMD_NONE) {
- char *msg = "action received is not known";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- if(!(t->cmds & cmd)) {
- char *msg = "received a command that is not supported";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- if(t->current.removed && cmd != DYNCFG_CMD_ADD) {
- char *msg = "received a command for a removed entry";
- dyncfg_unittest_register_error(id, msg);
- rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST, msg);
- goto cleanup;
- }
- struct dyncfg_unittest_action *a = callocz(1, sizeof(*a));
- a->t = t;
- a->add_name = add_name ? strdupz(add_name) : NULL;
- a->source = rfe->source,
- a->result = rfe->result.wb;
- a->payload = buffer_dup(rfe->payload);
- a->cmd = cmd;
- a->result_cb = rfe->result.cb;
- a->result_cb_data = rfe->result.data;
- run_the_callback = false;
- if(t->sync)
- rc = dyncfg_unittest_action(a);
- else {
- spinlock_lock(&dyncfg_unittest_data.spinlock);
- DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(dyncfg_unittest_data.queue, a, prev, next);
- spinlock_unlock(&dyncfg_unittest_data.spinlock);
- rc = HTTP_RESP_OK;
- }
- cleanup:
- if(run_the_callback) {
- __atomic_store_n(&t->finished, true, __ATOMIC_RELAXED);
- if (rfe->result.cb)
- rfe->result.cb(rfe->result.wb, rc, rfe->result.data);
- }
- return rc;
- }
- static bool dyncfg_unittest_check(TEST *t, const char *cmd, bool received) {
- size_t errors = 0;
- fprintf(stderr, "CHECK '%s' after cmd '%s'...", t->id, cmd);
- if(t->received != received) {
- fprintf(stderr, "\n - received flag found '%s', expected '%s'",
- t->received?"true":"false",
- received?"true":"false");
- errors++;
- goto cleanup;
- }
- if(!received)
- goto cleanup;
- usec_t give_up_ut = now_monotonic_usec() + 2 * USEC_PER_SEC;
- while(!__atomic_load_n(&t->finished, __ATOMIC_RELAXED)) {
- static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 };
- nanosleep(&ns, NULL);
- if(now_monotonic_usec() > give_up_ut) {
- fprintf(stderr, "\n - gave up waiting for the plugin to process this!");
- errors++;
- goto cleanup;
- }
- }
- if(t->type != DYNCFG_TYPE_TEMPLATE && t->current.enabled != t->expected.enabled) {
- fprintf(stderr, "\n - enabled flag found '%s', expected '%s'",
- t->current.enabled?"true":"false",
- t->expected.enabled?"true":"false");
- errors++;
- }
- if(t->current.removed != t->expected.removed) {
- fprintf(stderr, "\n - removed flag found '%s', expected '%s'",
- t->current.removed?"true":"false",
- t->expected.removed?"true":"false");
- errors++;
- }
- if(t->current.value.bln != t->expected.value.bln) {
- fprintf(stderr, "\n - boolean value found '%s', expected '%s'",
- t->current.value.bln?"true":"false",
- t->expected.value.bln?"true":"false");
- errors++;
- }
- if(t->current.value.dbl != t->expected.value.dbl) {
- fprintf(stderr, "\n - double value found '%f', expected '%f'",
- t->current.value.dbl, t->expected.value.dbl);
- errors++;
- }
- DYNCFG *df = dictionary_get(dyncfg_globals.nodes, t->id);
- if(!df) {
- fprintf(stderr, "\n - not found in DYNCFG nodes dictionary!");
- errors++;
- }
- else if(df->cmds != t->cmds) {
- fprintf(stderr, "\n - has different cmds in DYNCFG nodes dictionary; found: ");
- dyncfg_cmds2fp(df->cmds, stderr);
- fprintf(stderr, ", expected: ");
- dyncfg_cmds2fp(t->cmds, stderr);
- fprintf(stderr, "\n");
- errors++;
- }
- else if(df->type == DYNCFG_TYPE_JOB && df->source_type == DYNCFG_SOURCE_TYPE_DYNCFG && !df->saves) {
- fprintf(stderr, "\n - DYNCFG job has no saves!");
- errors++;
- }
- else if(df->type == DYNCFG_TYPE_JOB && df->source_type == DYNCFG_SOURCE_TYPE_DYNCFG && (!df->payload || !buffer_strlen(df->payload))) {
- fprintf(stderr, "\n - DYNCFG job has no payload!");
- errors++;
- }
- else if(df->user_disabled && !df->saves) {
- fprintf(stderr, "\n - DYNCFG disabled config has no saves!");
- errors++;
- }
- else if(t->source && string_strcmp(df->source, t->source) != 0) {
- fprintf(stderr, "\n - source does not match!");
- errors++;
- }
- else if(df->source && !t->source) {
- fprintf(stderr, "\n - there is a source but it shouldn't be any!");
- errors++;
- }
- else if(t->needs_save && df->saves <= t->last_saves) {
- fprintf(stderr, "\n - should be saved, but it is not saved!");
- errors++;
- }
- else if(!t->needs_save && df->saves > t->last_saves) {
- fprintf(stderr, "\n - should be not be saved, but it saved!");
- errors++;
- }
- cleanup:
- if(errors) {
- fprintf(stderr, "\n >>> FAILED\n\n");
- dyncfg_unittest_register_error(NULL, NULL);
- return false;
- }
- fprintf(stderr, " OK\n");
- return true;
- }
- static void dyncfg_unittest_reset(void) {
- TEST *t;
- dfe_start_read(dyncfg_unittest_data.nodes, t) {
- t->received = t->finished = false;
- t->needs_save = false;
- DYNCFG *df = dictionary_get(dyncfg_globals.nodes, t->id);
- if(!df) {
- nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG UNITTEST: cannot find id '%s'", t->id);
- dyncfg_unittest_register_error(NULL, NULL);
- }
- else
- t->last_saves = df->saves;
- }
- dfe_done(t);
- }
- void should_be_saved(TEST *t, DYNCFG_CMDS c) {
- DYNCFG *df;
- if(t->type == DYNCFG_TYPE_TEMPLATE) {
- df = dictionary_get(dyncfg_globals.nodes, t->id);
- t->current.enabled = !df->user_disabled;
- }
- t->needs_save =
- c == DYNCFG_CMD_UPDATE ||
- (t->current.enabled && c == DYNCFG_CMD_DISABLE) ||
- (!t->current.enabled && c == DYNCFG_CMD_ENABLE);
- }
- static int dyncfg_unittest_run(const char *cmd, BUFFER *wb, const char *payload, const char *source) {
- dyncfg_unittest_reset();
- char buf[strlen(cmd) + 1];
- memcpy(buf, cmd, sizeof(buf));
- char *words[MAX_FUNCTION_PARAMETERS]; // an array of pointers for the words in this line
- size_t num_words = quoted_strings_splitter_pluginsd(buf, words, MAX_FUNCTION_PARAMETERS);
- // const char *config = get_word(words, num_words, 0);
- const char *id = get_word(words, num_words, 1);
- char *action = get_word(words, num_words, 2);
- const char *add_name = get_word(words, num_words, 3);
- DYNCFG_CMDS c = dyncfg_cmds2id(action);
- TEST *t = dictionary_get(dyncfg_unittest_data.nodes, id);
- if(!t) {
- nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG UNITTEST: cannot find id '%s' from cmd: %s", id, cmd);
- dyncfg_unittest_register_error(NULL, NULL);
- return HTTP_RESP_NOT_FOUND;
- }
- if(t->type == DYNCFG_TYPE_TEMPLATE)
- t->received = t->finished = true;
- if(c == DYNCFG_CMD_DISABLE)
- t->expected.enabled = false;
- if(c == DYNCFG_CMD_ENABLE)
- t->expected.enabled = true;
- if(c == DYNCFG_CMD_UPDATE)
- memset(&t->current.value, 0, sizeof(t->current.value));
- buffer_flush(wb);
- CLEAN_BUFFER *pld = NULL;
- if(payload) {
- pld = buffer_create(1024, NULL);
- buffer_strcat(pld, payload);
- }
- should_be_saved(t, c);
- int rc = rrd_function_run(localhost, wb, 10, HTTP_ACCESS_ADMIN, cmd,
- true, NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL,
- pld, source);
- if(!DYNCFG_RESP_SUCCESS(rc)) {
- nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG UNITTEST: failed to run: %s; returned code %d", cmd, rc);
- dyncfg_unittest_register_error(NULL, NULL);
- }
- dyncfg_unittest_check(t, cmd, true);
- if(rc == HTTP_RESP_OK && t->type == DYNCFG_TYPE_TEMPLATE) {
- if(c == DYNCFG_CMD_ADD) {
- char buf2[strlen(id) + strlen(add_name) + 2];
- snprintfz(buf2, sizeof(buf2), "%s:%s", id, add_name);
- TEST *tt = dictionary_get(dyncfg_unittest_data.nodes, buf2);
- if (!tt) {
- nd_log(NDLS_DAEMON, NDLP_ERR,
- "DYNCFG UNITTEST: failed to find newly added id '%s' of command: %s",
- id, cmd);
- dyncfg_unittest_register_error(NULL, NULL);
- }
- dyncfg_unittest_check(tt, cmd, true);
- }
- else {
- STRING *template = string_strdupz(t->id);
- DYNCFG *df;
- dfe_start_read(dyncfg_globals.nodes, df) {
- if(df->type == DYNCFG_TYPE_JOB && df->template == template) {
- TEST *tt = dictionary_get(dyncfg_unittest_data.nodes, df_dfe.name);
- if (!tt) {
- nd_log(NDLS_DAEMON, NDLP_ERR,
- "DYNCFG UNITTEST: failed to find id '%s' while running command: %s", df_dfe.name, cmd);
- dyncfg_unittest_register_error(NULL, NULL);
- }
- else {
- if(c == DYNCFG_CMD_DISABLE)
- tt->expected.enabled = false;
- if(c == DYNCFG_CMD_ENABLE)
- tt->expected.enabled = true;
- dyncfg_unittest_check(tt, cmd, true);
- }
- }
- }
- dfe_done(df);
- string_freez(template);
- }
- }
- return rc;
- }
- static void dyncfg_unittest_cleanup_files(void) {
- char path[FILENAME_MAX];
- snprintfz(path, sizeof(path) - 1, "%s/%s", netdata_configured_varlib_dir, "config");
- DIR *dir = opendir(path);
- if (!dir) {
- nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG UNITTEST: cannot open directory '%s'", path);
- return;
- }
- struct dirent *entry;
- char filename[FILENAME_MAX + sizeof(entry->d_name)];
- while ((entry = readdir(dir)) != NULL) {
- if ((entry->d_type == DT_REG || entry->d_type == DT_LNK) && strstartswith(entry->d_name, "unittest:") && strendswith(entry->d_name, ".dyncfg")) {
- snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
- nd_log(NDLS_DAEMON, NDLP_INFO, "DYNCFG UNITTEST: deleting file '%s'", filename);
- unlink(filename);
- }
- }
- closedir(dir);
- }
- static TEST *dyncfg_unittest_add(TEST t) {
- dyncfg_unittest_reset();
- TEST *ret = dictionary_set(dyncfg_unittest_data.nodes, t.id, &t, sizeof(t));
- if(!dyncfg_add_low_level(localhost, t.id, "/unittests", DYNCFG_STATUS_RUNNING, t.type,
- t.source_type, t.source,
- t.cmds, 0, 0, t.sync, dyncfg_unittest_execute_cb, ret)) {
- dyncfg_unittest_register_error(t.id, "addition of job failed");
- }
- dyncfg_unittest_check(ret, "plugin create", t.type != DYNCFG_TYPE_TEMPLATE);
- return ret;
- }
- void dyncfg_unittest_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
- TEST *v = value;
- freez((void *)v->id);
- freez((void *)v->source);
- }
- int dyncfg_unittest(void) {
- dyncfg_unittest_data.nodes = dictionary_create(DICT_OPTION_NONE);
- dictionary_register_delete_callback(dyncfg_unittest_data.nodes, dyncfg_unittest_delete_cb, NULL);
- dyncfg_unittest_cleanup_files();
- rrd_functions_inflight_init();
- dyncfg_init(false);
- // ------------------------------------------------------------------------
- // create the thread for testing async communication
- netdata_thread_t thread;
- netdata_thread_create(&thread, "unittest", NETDATA_THREAD_OPTION_JOINABLE,
- dyncfg_unittest_thread_action, NULL);
- // ------------------------------------------------------------------------
- // single
- TEST *single1 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:sync:single1"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_SINGLE,
- .cmds = DYNCFG_CMD_GET | DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_INTERNAL,
- .sync = true,
- .current = {
- .enabled = true,
- },
- .expected = {
- .enabled = true,
- }
- }); (void)single1;
- TEST *single2 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:async:single2"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_SINGLE,
- .cmds = DYNCFG_CMD_GET | DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_INTERNAL,
- .sync = false,
- .current = {
- .enabled = true,
- },
- .expected = {
- .enabled = true,
- }
- }); (void)single2;
- // ------------------------------------------------------------------------
- // template
- TEST *template1 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:sync:template1"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_TEMPLATE,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_ADD | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_INTERNAL,
- .sync = true,
- }); (void)template1;
- TEST *template2 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:async:template2"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_TEMPLATE,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_ADD | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_INTERNAL,
- .sync = false,
- }); (void)template2;
- // ------------------------------------------------------------------------
- // job
- TEST *user1 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:sync:template1:user1"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = true,
- .current = {
- .enabled = true,
- },
- .expected = {
- .enabled = true,
- }
- }); (void)user1;
- TEST *user2 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:async:template2:user2"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = false,
- .expected = {
- .enabled = true,
- }
- }); (void)user2;
- // ------------------------------------------------------------------------
- int rc; (void)rc;
- BUFFER *wb = buffer_create(0, NULL);
- // ------------------------------------------------------------------------
- // dynamic job
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 add dyn1", wb, "{\"double\":3.14,\"boolean\":true}", LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 add dyn2", wb, "{\"double\":3.14,\"boolean\":true}", LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 add dyn3", wb, "{\"double\":3.14,\"boolean\":true}", LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 add dyn4", wb, "{\"double\":3.14,\"boolean\":true}", LINE_FILE_STR);
- // ------------------------------------------------------------------------
- // saving of user_disabled
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:single1 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:single2 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:user1 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:user2 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:dyn1 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:dyn2 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:dyn3 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:dyn4 disable", wb, NULL, LINE_FILE_STR);
- // ------------------------------------------------------------------------
- // enabling
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:single1 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:single2 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:user1 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:user2 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:dyn1 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:dyn2 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:dyn3 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:dyn4 enable", wb, NULL, LINE_FILE_STR);
- // ------------------------------------------------------------------------
- // disabling template
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 disable", wb, NULL, LINE_FILE_STR);
- // ------------------------------------------------------------------------
- // enabling template
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 enable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 enable", wb, NULL, LINE_FILE_STR);
- // ------------------------------------------------------------------------
- // adding job on disabled template
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 disable", wb, NULL, LINE_FILE_STR);
- dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 disable", wb, NULL, LINE_FILE_STR);
- TEST *user3 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:sync:template1:user3"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = true,
- .expected = {
- .enabled = false,
- }
- }); (void)user3;
- TEST *user4 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:async:template2:user4"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = false,
- .expected = {
- .enabled = false,
- }
- }); (void)user4;
- TEST *user5 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:sync:template1:user5"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = true,
- .expected = {
- .enabled = false,
- }
- }); (void)user5;
- TEST *user6 = dyncfg_unittest_add((TEST){
- .id = strdupz("unittest:async:template2:user6"),
- .source = strdupz(LINE_FILE_STR),
- .type = DYNCFG_TYPE_JOB,
- .cmds = DYNCFG_CMD_SCHEMA | DYNCFG_CMD_UPDATE | DYNCFG_CMD_ENABLE | DYNCFG_CMD_DISABLE,
- .source_type = DYNCFG_SOURCE_TYPE_USER,
- .sync = false,
- .expected = {
- .enabled = false,
- }
- }); (void)user6;
- // dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1:user5 disable", wb, NULL, LINE_FILE_STR);
- // dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2:user6 disable", wb, NULL, LINE_FILE_STR);
- // // ------------------------------------------------------------------------
- // // enable template with disabled jobs
- //
- // user3->expected.enabled = true;
- // user5->expected.enabled = false;
- // dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:sync:template1 enable", wb, NULL, LINE_FILE_STR);
- //
- // user4->expected.enabled = true;
- // user6->expected.enabled = false;
- // dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " unittest:async:template2 enable", wb, NULL, LINE_FILE_STR);
- // // ------------------------------------------------------------------------
- //
- // rc = dyncfg_unittest_run(PLUGINSD_FUNCTION_CONFIG " tree", wb, NULL);
- // if(rc == HTTP_RESP_OK)
- // fprintf(stderr, "%s\n", buffer_tostring(wb));
- void *ptr;
- netdata_thread_cancel(thread);
- netdata_thread_join(thread, &ptr);
- dyncfg_unittest_cleanup_files();
- dictionary_destroy(dyncfg_unittest_data.nodes);
- buffer_free(wb);
- return __atomic_load_n(&dyncfg_unittest_data.errors, __ATOMIC_RELAXED) > 0 ? 1 : 0;
- }
|