From 476eed1ecf8f3103362011c05a81d7599ff385e6 Mon Sep 17 00:00:00 2001 From: navarrop Date: Tue, 13 Apr 2010 10:18:21 +0000 Subject: [PATCH] Add sources for target testall for pipol deployment. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@7547 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/config_unit.c | 146 ++++++++++ src/cunit_unit.c | 28 ++ src/dict_unit.c | 594 +++++++++++++++++++++++++++++++++++++++++ src/dynar_unit.c | 482 +++++++++++++++++++++++++++++++++ src/ex_unit.c | 224 ++++++++++++++++ src/set_unit.c | 247 +++++++++++++++++ src/swag_unit.c | 74 +++++ src/xbt_sha_unit.c | 58 ++++ src/xbt_str_unit.c | 70 +++++ src/xbt_strbuff_unit.c | 150 +++++++++++ src/xbt_synchro_unit.c | 49 ++++ 11 files changed, 2122 insertions(+) create mode 100644 src/config_unit.c create mode 100644 src/cunit_unit.c create mode 100644 src/dict_unit.c create mode 100644 src/dynar_unit.c create mode 100644 src/ex_unit.c create mode 100644 src/set_unit.c create mode 100644 src/swag_unit.c create mode 100644 src/xbt_sha_unit.c create mode 100644 src/xbt_str_unit.c create mode 100644 src/xbt_strbuff_unit.c create mode 100644 src/xbt_synchro_unit.c diff --git a/src/config_unit.c b/src/config_unit.c new file mode 100644 index 0000000000..de350fd677 --- /dev/null +++ b/src/config_unit.c @@ -0,0 +1,146 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 1296 "/home/navarrop/Developments/simgrid/src/xbt/config.c" +#include "xbt.h" +#include "xbt/ex.h" + +XBT_LOG_EXTERNAL_CATEGORY(xbt_cfg); + + +static xbt_cfg_t make_set() +{ + xbt_cfg_t set = NULL; + + xbt_log_threshold_set(&_XBT_LOGV(xbt_cfg), xbt_log_priority_critical); + xbt_cfg_register_str(&set, "speed:1_to_2_int"); + xbt_cfg_register_str(&set, "peername:1_to_1_string"); + xbt_cfg_register_str(&set, "user:1_to_10_string"); + + return set; +} /* end_of_make_set */ + +XBT_TEST_UNIT("memuse", test_config_memuse, "Alloc and free a config set") +{ + xbt_cfg_t set = make_set(); + xbt_test_add0("Alloc and free a config set"); + xbt_cfg_set_parse(set, + "peername:veloce user:mquinson\nuser:oaumage\tuser:alegrand"); + xbt_cfg_free(&set); + xbt_cfg_free(&set); +} + +XBT_TEST_UNIT("validation", test_config_validation, "Validation tests") +{ + xbt_cfg_t set = set = make_set(); + xbt_ex_t e; + + xbt_test_add0("Having too few elements for speed"); + xbt_cfg_set_parse(set, + "peername:veloce user:mquinson\nuser:oaumage\tuser:alegrand"); + TRY { + xbt_cfg_check(set); + } + CATCH(e) { + if (e.category != mismatch_error || + strncmp(e.msg, "Config elem speed needs", + strlen("Config elem speed needs"))) + xbt_test_fail1("Got an exception. msg=%s", e.msg); + xbt_ex_free(e); + } + xbt_cfg_free(&set); + xbt_cfg_free(&set); + + + + xbt_test_add0("Having too much values of 'speed'"); + set = make_set(); + xbt_cfg_set_parse(set, "peername:toto:42 user:alegrand"); + TRY { + xbt_cfg_set_parse(set, "speed:42 speed:24 speed:34"); + } + CATCH(e) { + if (e.category != mismatch_error || + strncmp(e.msg, "Cannot add value 34 to the config elem speed", + strlen("Config elem speed needs"))) + xbt_test_fail1("Got an exception. msg=%s", e.msg); + xbt_ex_free(e); + } + xbt_cfg_check(set); + xbt_cfg_free(&set); + xbt_cfg_free(&set); + +} + +XBT_TEST_UNIT("use", test_config_use, "Data retrieving tests") +{ + + xbt_test_add0("Get a single value"); + { + /* get_single_value */ + int ival; + xbt_cfg_t myset = make_set(); + + xbt_cfg_set_parse(myset, "peername:toto:42 speed:42"); + ival = xbt_cfg_get_int(myset, "speed"); + if (ival != 42) + xbt_test_fail1("Speed value = %d, I expected 42", ival); + xbt_cfg_free(&myset); + } + + xbt_test_add0("Get multiple values"); + { + /* get_multiple_value */ + xbt_dynar_t dyn; + xbt_cfg_t myset = make_set(); + + xbt_cfg_set_parse(myset, "peername:veloce user:foo\nuser:bar\tuser:toto"); + xbt_cfg_set_parse(myset, "speed:42"); + xbt_cfg_check(myset); + dyn = xbt_cfg_get_dynar(myset, "user"); + + if (xbt_dynar_length(dyn) != 3) + xbt_test_fail1("Dynar length = %lu, I expected 3", + xbt_dynar_length(dyn)); + + if (strcmp(xbt_dynar_get_as(dyn, 0, char *), "foo")) + xbt_test_fail1("Dynar[0] = %s, I expected foo", + xbt_dynar_get_as(dyn, 0, char *)); + + if (strcmp(xbt_dynar_get_as(dyn, 1, char *), "bar")) + xbt_test_fail1("Dynar[1] = %s, I expected bar", + xbt_dynar_get_as(dyn, 1, char *)); + + if (strcmp(xbt_dynar_get_as(dyn, 2, char *), "toto")) + xbt_test_fail1("Dynar[2] = %s, I expected toto", + xbt_dynar_get_as(dyn, 2, char *)); + xbt_cfg_free(&myset); + } + + xbt_test_add0("Access to a non-existant entry"); + { + /* non-existant_entry */ + xbt_cfg_t myset = make_set(); + xbt_ex_t e; + + TRY { + xbt_cfg_set_parse(myset, "color:blue"); + } CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + } + xbt_cfg_free(&myset); + } +} +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/cunit_unit.c b/src/cunit_unit.c new file mode 100644 index 0000000000..6b1fcf51d6 --- /dev/null +++ b/src/cunit_unit.c @@ -0,0 +1,28 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 824 "/home/navarrop/Developments/simgrid/src/xbt/cunit.c" + + +XBT_TEST_UNIT("expect", test_expected_failure, "expected failures") +{ + xbt_test_add0("Skipped test"); + xbt_test_skip(); + + xbt_test_add2("%s %s", "EXPECTED", "FAILURE"); + xbt_test_expect_failure(); + xbt_test_log2("%s %s", "Test", "log"); + xbt_test_fail0("EXPECTED FAILURE"); +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/dict_unit.c b/src/dict_unit.c new file mode 100644 index 0000000000..d851ee6a9e --- /dev/null +++ b/src/dict_unit.c @@ -0,0 +1,594 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 799 "/home/navarrop/Developments/simgrid/src/xbt/dict.c" +#include "xbt.h" +#include "xbt/ex.h" +#include "portable.h" + +XBT_LOG_EXTERNAL_CATEGORY(xbt_dict); +XBT_LOG_DEFAULT_CATEGORY(xbt_dict); + + +static void print_str(void *str) +{ + printf("%s", (char *) PRINTF_STR(str)); +} + +static void debuged_add_ext(xbt_dict_t head, const char *key, + const char *data_to_fill) +{ + char *data = xbt_strdup(data_to_fill); + + xbt_test_log2("Add %s under %s", PRINTF_STR(data_to_fill), PRINTF_STR(key)); + + xbt_dict_set(head, key, data, &free); + if (XBT_LOG_ISENABLED(xbt_dict, xbt_log_priority_debug)) { + xbt_dict_dump(head, (void (*)(void *)) &printf); + fflush(stdout); + } +} + +static void debuged_add(xbt_dict_t head, const char *key) +{ + debuged_add_ext(head, key, key); +} + +static void fill(xbt_dict_t * head) +{ + xbt_test_add0("Fill in the dictionnary"); + + *head = xbt_dict_new(); + debuged_add(*head, "12"); + debuged_add(*head, "12a"); + debuged_add(*head, "12b"); + debuged_add(*head, "123"); + debuged_add(*head, "123456"); + /* Child becomes child of what to add */ + debuged_add(*head, "1234"); + /* Need of common ancestor */ + debuged_add(*head, "123457"); +} + + +static void search_ext(xbt_dict_t head, const char *key, const char *data) +{ + void *found; + + xbt_test_add1("Search %s", key); + found = xbt_dict_get(head, key); + xbt_test_log1("Found %s", (char *) found); + if (data) + xbt_test_assert1(found, + "data do not match expectations: found NULL while searching for %s", + data); + if (found) + xbt_test_assert2(!strcmp((char *) data, found), + "data do not match expectations: found %s while searching for %s", + (char *) found, data); +} + +static void search(xbt_dict_t head, const char *key) +{ + search_ext(head, key, key); +} + +static void debuged_remove(xbt_dict_t head, const char *key) +{ + + xbt_test_add1("Remove '%s'", PRINTF_STR(key)); + xbt_dict_remove(head, key); + /* xbt_dict_dump(head,(void (*)(void*))&printf); */ +} + + +static void traverse(xbt_dict_t head) +{ + xbt_dict_cursor_t cursor = NULL; + char *key; + char *data; + int i = 0; + + xbt_dict_foreach(head, cursor, key, data) { + if (!key || !data || strcmp(key, data)) { + xbt_test_log3("Seen #%d: %s->%s", ++i, PRINTF_STR(key), + PRINTF_STR(data)); + } else { + xbt_test_log2("Seen #%d: %s", ++i, PRINTF_STR(key)); + } + xbt_test_assert2(!data || !strcmp(key, data), + "Key(%s) != value(%s). Aborting", key, data); + } +} + +static void search_not_found(xbt_dict_t head, const char *data) +{ + int ok = 0; + xbt_ex_t e; + + xbt_test_add1("Search %s (expected not to be found)", data); + + TRY { + data = xbt_dict_get(head, data); + THROW1(unknown_error, 0, "Found something which shouldn't be there (%s)", + data); + } CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + ok = 1; + } + xbt_test_assert0(ok, "Exception not raised"); +} + +static void count(xbt_dict_t dict, int length) +{ + xbt_dict_cursor_t cursor; + char *key; + void *data; + int effective = 0; + + + xbt_test_add1("Count elements (expecting %d)", length); + xbt_test_assert2(xbt_dict_length(dict) == length, + "Announced length(%d) != %d.", xbt_dict_length(dict), + length); + + xbt_dict_foreach(dict, cursor, key, data) + effective++; + + xbt_test_assert2(effective == length, "Effective length(%d) != %d.", + effective, length); + +} + +static void count_check_get_key(xbt_dict_t dict, int length) +{ + xbt_dict_cursor_t cursor; + char *key,*key2; + void *data; + int effective = 0; + + + xbt_test_add1("Count elements (expecting %d), and test the getkey function", length); + xbt_test_assert2(xbt_dict_length(dict) == length, + "Announced length(%d) != %d.", xbt_dict_length(dict), + length); + + xbt_dict_foreach(dict, cursor, key, data) { + effective++; + key2 = xbt_dict_get_key(dict,data); + xbt_assert2(!strcmp(key,key2), + "The data was registered under %s instead of %s as expected",key2,key); + } + + xbt_test_assert2(effective == length, "Effective length(%d) != %d.", + effective, length); + +} + +xbt_ex_t e; +xbt_dict_t head = NULL; +char *data; + + +XBT_TEST_UNIT("basic", test_dict_basic,"Basic usage: change, retrieve, traverse") +{ + xbt_test_add0("Traversal the null dictionary"); + traverse(head); + + xbt_test_add0("Traversal and search the empty dictionary"); + head = xbt_dict_new(); + traverse(head); + TRY { + debuged_remove(head, "12346"); + } CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + } + xbt_dict_free(&head); + + xbt_test_add0("Traverse the full dictionary"); + fill(&head); + count_check_get_key(head, 7); + + debuged_add_ext(head, "toto", "tutu"); + search_ext(head, "toto", "tutu"); + debuged_remove(head, "toto"); + + search(head, "12a"); + traverse(head); + + xbt_test_add0("Free the dictionary (twice)"); + xbt_dict_free(&head); + xbt_dict_free(&head); + + /* CHANGING */ + fill(&head); + count_check_get_key(head, 7); + xbt_test_add0("Change 123 to 'Changed 123'"); + xbt_dict_set(head, "123", strdup("Changed 123"), &free); + count_check_get_key(head, 7); + + xbt_test_add0("Change 123 back to '123'"); + xbt_dict_set(head, "123", strdup("123"), &free); + count_check_get_key(head, 7); + + xbt_test_add0("Change 12a to 'Dummy 12a'"); + xbt_dict_set(head, "12a", strdup("Dummy 12a"), &free); + count_check_get_key(head, 7); + + xbt_test_add0("Change 12a to '12a'"); + xbt_dict_set(head, "12a", strdup("12a"), &free); + count_check_get_key(head, 7); + + xbt_test_add0("Traverse the resulting dictionary"); + traverse(head); + + /* RETRIEVE */ + xbt_test_add0("Search 123"); + data = xbt_dict_get(head, "123"); + xbt_test_assert(data); + xbt_test_assert(!strcmp("123", data)); + + search_not_found(head, "Can't be found"); + search_not_found(head, "123 Can't be found"); + search_not_found(head, "12345678 NOT"); + + search(head, "12a"); + search(head, "12b"); + search(head, "12"); + search(head, "123456"); + search(head, "1234"); + search(head, "123457"); + + xbt_test_add0("Traverse the resulting dictionary"); + traverse(head); + + /* xbt_dict_dump(head,(void (*)(void*))&printf); */ + + xbt_test_add0("Free the dictionary twice"); + xbt_dict_free(&head); + xbt_dict_free(&head); + + xbt_test_add0("Traverse the resulting dictionary"); + traverse(head); +} + +XBT_TEST_UNIT("remove", test_dict_remove, "Removing some values") +{ + fill(&head); + count(head, 7); + xbt_test_add0("Remove non existing data"); + TRY { + debuged_remove(head, "Does not exist"); + } + CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + } + traverse(head); + + xbt_dict_free(&head); + + xbt_test_add0 + ("Remove each data manually (traversing the resulting dictionary each time)"); + fill(&head); + debuged_remove(head, "12a"); + traverse(head); + count(head, 6); + debuged_remove(head, "12b"); + traverse(head); + count(head, 5); + debuged_remove(head, "12"); + traverse(head); + count(head, 4); + debuged_remove(head, "123456"); + traverse(head); + count(head, 3); + TRY { + debuged_remove(head, "12346"); + } + CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + traverse(head); + } + debuged_remove(head, "1234"); + traverse(head); + debuged_remove(head, "123457"); + traverse(head); + debuged_remove(head, "123"); + traverse(head); + TRY { + debuged_remove(head, "12346"); + } + CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + } + traverse(head); + + xbt_test_add0("Free dict, create new fresh one, and then reset the dict"); + xbt_dict_free(&head); + fill(&head); + xbt_dict_reset(head); + count(head, 0); + traverse(head); + + xbt_test_add0("Free the dictionary twice"); + xbt_dict_free(&head); + xbt_dict_free(&head); +} + +XBT_TEST_UNIT("nulldata", test_dict_nulldata, "NULL data management") +{ + fill(&head); + + xbt_test_add0("Store NULL under 'null'"); + xbt_dict_set(head, "null", NULL, NULL); + search_ext(head, "null", NULL); + + xbt_test_add0("Check whether I see it while traversing..."); + { + xbt_dict_cursor_t cursor = NULL; + char *key; + int found = 0; + + xbt_dict_foreach(head, cursor, key, data) { + if (!key || !data || strcmp(key, data)) { + xbt_test_log2("Seen: %s->%s", PRINTF_STR(key), PRINTF_STR(data)); + } else { + xbt_test_log1("Seen: %s", PRINTF_STR(key)); + } + + if (!strcmp(key, "null")) + found = 1; + } + xbt_test_assert0(found, + "the key 'null', associated to NULL is not found"); + } + xbt_dict_free(&head); +} + +static void debuged_addi(xbt_dict_t head, uintptr_t key, uintptr_t data) { + xbt_test_log2("Add %zu under %zu", data, key); + + xbt_dicti_set(head, key, data); + if (XBT_LOG_ISENABLED(xbt_dict, xbt_log_priority_debug)) { + xbt_dict_dump(head, (void (*)(void *)) &printf); + fflush(stdout); + } + uintptr_t stored_data = xbt_dicti_get(head, key); + xbt_test_assert3(stored_data==data, + "Retrieved data (%zu) is not what I just stored (%zu) under key %zu",stored_data,data,key); +} + +XBT_TEST_UNIT("dicti", test_dict_scalar, "Scalar data and key management") +{ + xbt_test_add0("Fill in the dictionnary"); + + head = xbt_dict_new(); + debuged_addi(head, 12, 12); + debuged_addi(head, 13, 13); + debuged_addi(head, 14, 14); + debuged_addi(head, 15, 15); + /* Change values */ + debuged_addi(head, 12, 15); + debuged_addi(head, 15, 2000); + debuged_addi(head, 15, 3000); + /* 0 as key */ + debuged_addi(head, 0, 1000); + debuged_addi(head, 0, 2000); + debuged_addi(head, 0, 3000); + /* 0 as value */ + debuged_addi(head, 12, 0); + debuged_addi(head, 13, 0); + debuged_addi(head, 12, 0); + debuged_addi(head, 0, 0); + + xbt_dict_free(&head); +} + +#define NB_ELM 20000 +#define SIZEOFKEY 1024 +static int countelems(xbt_dict_t head) +{ + xbt_dict_cursor_t cursor; + char *key; + void *data; + int res = 0; + + xbt_dict_foreach(head, cursor, key, data) { + res++; + } + return res; +} + +XBT_TEST_UNIT("crash", test_dict_crash, "Crash test") +{ + xbt_dict_t head = NULL; + int i, j, k, nb; + char *key; + void *data; + + srand((unsigned int) time(NULL)); + + for (i = 0; i < 10; i++) { + xbt_test_add2("CRASH test number %d (%d to go)", i + 1, 10 - i - 1); + xbt_test_log0("Fill the struct, count its elems and frees the structure"); + xbt_test_log1("using 1000 elements with %d chars long randomized keys.", + SIZEOFKEY); + head = xbt_dict_new(); + /* if (i%10) printf("."); else printf("%d",i/10); fflush(stdout); */ + nb = 0; + for (j = 0; j < 1000; j++) { + char *data = NULL; + key = xbt_malloc(SIZEOFKEY); + + do { + for (k = 0; k < SIZEOFKEY - 1; k++) + key[k] = rand() % ('z' - 'a') + 'a'; + key[k] = '\0'; + /* printf("[%d %s]\n",j,key); */ + data = xbt_dict_get_or_null(head, key); + } while (data != NULL); + + xbt_dict_set(head, key, key, &free); + data = xbt_dict_get(head, key); + xbt_test_assert2(!strcmp(key, data), + "Retrieved value (%s) != Injected value (%s)", key, + data); + + count(head, j + 1); + } + /* xbt_dict_dump(head,(void (*)(void*))&printf); */ + traverse(head); + xbt_dict_free(&head); + xbt_dict_free(&head); + } + + + head = xbt_dict_new(); + xbt_test_add1("Fill %d elements, with keys being the number of element", + NB_ELM); + for (j = 0; j < NB_ELM; j++) { + /* if (!(j%1000)) { printf("."); fflush(stdout); } */ + + key = xbt_malloc(10); + + sprintf(key, "%d", j); + xbt_dict_set(head, key, key, &free); + } + /*xbt_dict_dump(head,(void (*)(void*))&printf); */ + + xbt_test_add0("Count the elements (retrieving the key and data for each)"); + i = countelems(head); + xbt_test_log1("There is %d elements", i); + + xbt_test_add1("Search my %d elements 20 times", NB_ELM); + key = xbt_malloc(10); + for (i = 0; i < 20; i++) { + /* if (i%10) printf("."); else printf("%d",i/10); fflush(stdout); */ + for (j = 0; j < NB_ELM; j++) { + + sprintf(key, "%d", j); + data = xbt_dict_get(head, key); + xbt_test_assert2(!strcmp(key, (char *) data), + "with get, key=%s != data=%s", key, (char *) data); + data = xbt_dict_get_ext(head, key, strlen(key)); + xbt_test_assert2(!strcmp(key, (char *) data), + "with get_ext, key=%s != data=%s", key, (char *) data); + } + } + free(key); + + xbt_test_add1("Remove my %d elements", NB_ELM); + key = xbt_malloc(10); + for (j = 0; j < NB_ELM; j++) { + /* if (!(j%10000)) printf("."); fflush(stdout); */ + + sprintf(key, "%d", j); + xbt_dict_remove(head, key); + } + free(key); + + + xbt_test_add0("Free the structure (twice)"); + xbt_dict_free(&head); + xbt_dict_free(&head); +} + +static void str_free(void *s) +{ + char *c = *(char **) s; + free(c); +} + +XBT_TEST_UNIT("multicrash", test_dict_multicrash, "Multi-dict crash test") +{ + +#undef NB_ELM +#define NB_ELM 100 /*00 */ +#define DEPTH 5 +#define KEY_SIZE 512 +#define NB_TEST 20 /*20 */ + int verbose = 0; + + xbt_dict_t mdict = NULL; + int i, j, k, l; + xbt_dynar_t keys = xbt_dynar_new(sizeof(char *), str_free); + void *data; + char *key; + + + xbt_test_add0("Generic multicache CRASH test"); + xbt_test_log4(" Fill the struct and frees it %d times, using %d elements, " + "depth of multicache=%d, key size=%d", + NB_TEST, NB_ELM, DEPTH, KEY_SIZE); + + for (l = 0; l < DEPTH; l++) { + key = xbt_malloc(KEY_SIZE); + xbt_dynar_push(keys, &key); + } + + for (i = 0; i < NB_TEST; i++) { + mdict = xbt_dict_new(); + VERB1("mdict=%p", mdict); + if (verbose > 0) + printf("Test %d\n", i); + /* else if (i%10) printf("."); else printf("%d",i/10); */ + + for (j = 0; j < NB_ELM; j++) { + if (verbose > 0) + printf(" Add {"); + + for (l = 0; l < DEPTH; l++) { + key = *(char **) xbt_dynar_get_ptr(keys, l); + + for (k = 0; k < KEY_SIZE - 1; k++) + key[k] = rand() % ('z' - 'a') + 'a'; + + key[k] = '\0'; + + if (verbose > 0) + printf("%p=%s %s ", key, key, (l < DEPTH - 1 ? ";" : "}")); + } + if (verbose > 0) + printf("in multitree %p.\n", mdict); + + xbt_multidict_set(mdict, keys, xbt_strdup(key), free); + + data = xbt_multidict_get(mdict, keys); + + xbt_test_assert2(data && !strcmp((char *) data, key), + "Retrieved value (%s) does not match the given one (%s)\n", + (char *) data, key); + } + xbt_dict_free(&mdict); + } + + xbt_dynar_free(&keys); + + /* if (verbose>0) + xbt_dict_dump(mdict,&xbt_dict_print); */ + + xbt_dict_free(&mdict); + xbt_dynar_free(&keys); + +} +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/dynar_unit.c b/src/dynar_unit.c new file mode 100644 index 0000000000..c3c2336d1a --- /dev/null +++ b/src/dynar_unit.c @@ -0,0 +1,482 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 691 "/home/navarrop/Developments/simgrid/src/xbt/dynar.c" + +#define NB_ELEM 5000 + +XBT_LOG_EXTERNAL_CATEGORY(xbt_dyn); +XBT_LOG_DEFAULT_CATEGORY(xbt_dyn); + +XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers") +{ + /* Vars_decl [doxygen cruft] */ + xbt_dynar_t d; + int i, cpt; + unsigned int cursor; + int *iptr; + + xbt_test_add0("==== Traverse the empty dynar"); + d = xbt_dynar_new(sizeof(int), NULL); + xbt_dynar_foreach(d, cursor, i) { + xbt_assert0(0, "Damnit, there is something in the empty dynar"); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + xbt_test_add1 + ("==== Push %d int, set them again 3 times, traverse them, shift them", + NB_ELEM); + /* Populate_ints [doxygen cruft] */ + /* 1. Populate the dynar */ + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_push_as(d, int, cpt); /* This is faster (and possible only with scalars) */ + /* xbt_dynar_push(d,&cpt); This would also work */ + xbt_test_log2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + + /* 2. Traverse manually the dynar */ + for (cursor = 0; cursor < NB_ELEM; cursor++) { + iptr = xbt_dynar_get_ptr(d, cursor); + xbt_test_assert2(cursor == *iptr, + "The retrieved value is not the same than the injected one (%d!=%d)", + cursor, cpt); + } + + /* 3. Traverse the dynar using the neat macro to that extend */ + xbt_dynar_foreach(d, cursor, cpt) { + xbt_test_assert2(cursor == cpt, + "The retrieved value is not the same than the injected one (%d!=%d)", + cursor, cpt); + } + /* end_of_traversal */ + + for (cpt = 0; cpt < NB_ELEM; cpt++) + *(int *) xbt_dynar_get_ptr(d, cpt) = cpt; + + for (cpt = 0; cpt < NB_ELEM; cpt++) + *(int *) xbt_dynar_get_ptr(d, cpt) = cpt; + /* xbt_dynar_set(d,cpt,&cpt); */ + + for (cpt = 0; cpt < NB_ELEM; cpt++) + *(int *) xbt_dynar_get_ptr(d, cpt) = cpt; + + cpt = 0; + xbt_dynar_foreach(d, cursor, i) { + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one (%d!=%d)", + i, cpt); + cpt++; + } + xbt_test_assert2(cpt == NB_ELEM, + "Cannot retrieve my %d values. Last got one is %d", + NB_ELEM, cpt); + + /* shifting [doxygen cruft] */ + /* 4. Shift all the values */ + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_shift(d, &i); + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one (%d!=%d)", + i, cpt); + xbt_test_log2("Pop %d, length=%lu", cpt, xbt_dynar_length(d)); + } + + /* 5. Free the resources */ + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add1("==== Unshift/pop %d int", NB_ELEM); + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_unshift(d, &cpt); + DEBUG2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + for (cpt = 0; cpt < NB_ELEM; cpt++) { + i = xbt_dynar_pop_as(d, int); + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one (%d!=%d)", + i, cpt); + xbt_test_log2("Pop %d, length=%lu", cpt, xbt_dynar_length(d)); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add1 + ("==== Push %d int, insert 1000 int in the middle, shift everything", + NB_ELEM); + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_push_as(d, int, cpt); + DEBUG2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + for (cpt = 0; cpt < 1000; cpt++) { + xbt_dynar_insert_at_as(d, 2500, int, cpt); + DEBUG2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + + for (cpt = 0; cpt < 2500; cpt++) { + xbt_dynar_shift(d, &i); + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one at the begining (%d!=%d)", + i, cpt); + DEBUG2("Pop %d, length=%lu", cpt, xbt_dynar_length(d)); + } + for (cpt = 999; cpt >= 0; cpt--) { + xbt_dynar_shift(d, &i); + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one in the middle (%d!=%d)", + i, cpt); + } + for (cpt = 2500; cpt < NB_ELEM; cpt++) { + xbt_dynar_shift(d, &i); + xbt_test_assert2(i == cpt, + "The retrieved value is not the same than the injected one at the end (%d!=%d)", + i, cpt); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add1("==== Push %d int, remove 2000-4000. free the rest", NB_ELEM); + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) + xbt_dynar_push_as(d, int, cpt); + + for (cpt = 2000; cpt < 4000; cpt++) { + xbt_dynar_remove_at(d, 2000, &i); + xbt_test_assert2(i == cpt, + "Remove a bad value. Got %d, expected %d", i, cpt); + DEBUG2("remove %d, length=%lu", cpt, xbt_dynar_length(d)); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); +} + +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles") +{ + xbt_dynar_t d; + int cpt; + unsigned int cursor; + double d1, d2; + + xbt_test_add0("==== Traverse the empty dynar"); + d = xbt_dynar_new(sizeof(int), NULL); + xbt_dynar_foreach(d, cursor, cpt) { + xbt_test_assert0(FALSE, "Damnit, there is something in the empty dynar"); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + xbt_test_add0("==== Push/shift 5000 doubles"); + d = xbt_dynar_new(sizeof(double), NULL); + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_push(d, &d1); + } + xbt_dynar_foreach(d, cursor, d2) { + d1 = (double) cursor; + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one (%f!=%f)", + d1, d2); + } + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_shift(d, &d2); + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one (%f!=%f)", + d1, d2); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add0("==== Unshift/pop 5000 doubles"); + d = xbt_dynar_new(sizeof(double), NULL); + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_unshift(d, &d1); + } + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_pop(d, &d2); + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one (%f!=%f)", + d1, d2); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + + xbt_test_add0 + ("==== Push 5000 doubles, insert 1000 doubles in the middle, shift everything"); + d = xbt_dynar_new(sizeof(double), NULL); + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_push(d, &d1); + } + for (cpt = 0; cpt < 1000; cpt++) { + d1 = (double) cpt; + xbt_dynar_insert_at(d, 2500, &d1); + } + + for (cpt = 0; cpt < 2500; cpt++) { + d1 = (double) cpt; + xbt_dynar_shift(d, &d2); + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one at the begining (%f!=%f)", + d1, d2); + DEBUG2("Pop %d, length=%lu", cpt, xbt_dynar_length(d)); + } + for (cpt = 999; cpt >= 0; cpt--) { + d1 = (double) cpt; + xbt_dynar_shift(d, &d2); + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one in the middle (%f!=%f)", + d1, d2); + } + for (cpt = 2500; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_shift(d, &d2); + xbt_test_assert2(d1 == d2, + "The retrieved value is not the same than the injected one at the end (%f!=%f)", + d1, d2); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add0("==== Push 5000 double, remove 2000-4000. free the rest"); + d = xbt_dynar_new(sizeof(double), NULL); + for (cpt = 0; cpt < 5000; cpt++) { + d1 = (double) cpt; + xbt_dynar_push(d, &d1); + } + for (cpt = 2000; cpt < 4000; cpt++) { + d1 = (double) cpt; + xbt_dynar_remove_at(d, 2000, &d2); + xbt_test_assert2(d1 == d2, + "Remove a bad value. Got %f, expected %f", d2, d1); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); +} + + +/* doxygen_string_cruft */ + +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings") +{ + xbt_dynar_t d; + int cpt; + unsigned int iter; + char buf[1024]; + char *s1, *s2; + + xbt_test_add0("==== Traverse the empty dynar"); + d = xbt_dynar_new(sizeof(char *), &xbt_free_ref); + xbt_dynar_foreach(d, iter, s1) { + xbt_test_assert0(FALSE, "Damnit, there is something in the empty dynar"); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + xbt_test_add1("==== Push %d strings, set them again 3 times, shift them", + NB_ELEM); + /* Populate_str [doxygen cruft] */ + d = xbt_dynar_new(sizeof(char *), &xbt_free_ref); + /* 1. Populate the dynar */ + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_push(d, &s1); + } + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_replace(d, cpt, &s1); + } + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_replace(d, cpt, &s1); + } + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_replace(d, cpt, &s1); + } + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + xbt_dynar_shift(d, &s2); + xbt_test_assert2(!strcmp(buf, s2), + "The retrieved value is not the same than the injected one (%s!=%s)", + buf, s2); + free(s2); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add1("==== Unshift, traverse and pop %d strings", NB_ELEM); + d = xbt_dynar_new(sizeof(char **), &xbt_free_ref); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_unshift(d, &s1); + } + /* 2. Traverse the dynar with the macro */ + xbt_dynar_foreach(d, iter, s1) { + sprintf(buf, "%d", NB_ELEM - iter - 1); + xbt_test_assert2(!strcmp(buf, s1), + "The retrieved value is not the same than the injected one (%s!=%s)", + buf, s1); + } + /* 3. Traverse the dynar with the macro */ + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + xbt_dynar_pop(d, &s2); + xbt_test_assert2(!strcmp(buf, s2), + "The retrieved value is not the same than the injected one (%s!=%s)", + buf, s2); + free(s2); + } + /* 4. Free the resources */ + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add2 + ("==== Push %d strings, insert %d strings in the middle, shift everything", + NB_ELEM, NB_ELEM / 5); + d = xbt_dynar_new(sizeof(char *), &xbt_free_ref); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_push(d, &s1); + } + for (cpt = 0; cpt < NB_ELEM / 5; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_insert_at(d, NB_ELEM / 2, &s1); + } + + for (cpt = 0; cpt < NB_ELEM / 2; cpt++) { + sprintf(buf, "%d", cpt); + xbt_dynar_shift(d, &s2); + xbt_test_assert2(!strcmp(buf, s2), + "The retrieved value is not the same than the injected one at the begining (%s!=%s)", + buf, s2); + free(s2); + } + for (cpt = (NB_ELEM / 5) - 1; cpt >= 0; cpt--) { + sprintf(buf, "%d", cpt); + xbt_dynar_shift(d, &s2); + xbt_test_assert2(!strcmp(buf, s2), + "The retrieved value is not the same than the injected one in the middle (%s!=%s)", + buf, s2); + free(s2); + } + for (cpt = NB_ELEM / 2; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + xbt_dynar_shift(d, &s2); + xbt_test_assert2(!strcmp(buf, s2), + "The retrieved value is not the same than the injected one at the end (%s!=%s)", + buf, s2); + free(s2); + } + xbt_dynar_free(&d); + xbt_dynar_free(&d); + + + xbt_test_add3("==== Push %d strings, remove %d-%d. free the rest", NB_ELEM, + 2 * (NB_ELEM / 5), 4 * (NB_ELEM / 5)); + d = xbt_dynar_new(sizeof(char *), &xbt_free_ref); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + sprintf(buf, "%d", cpt); + s1 = strdup(buf); + xbt_dynar_push(d, &s1); + } + for (cpt = 2 * (NB_ELEM / 5); cpt < 4 * (NB_ELEM / 5); cpt++) { + sprintf(buf, "%d", cpt); + xbt_dynar_remove_at(d, 2 * (NB_ELEM / 5), &s2); + xbt_test_assert2(!strcmp(buf, s2), + "Remove a bad value. Got %s, expected %s", s2, buf); + free(s2); + } + xbt_dynar_free(&d); /* end_of_doxygen */ +} + + +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +#include "xbt/synchro.h" +static void pusher_f(void *a) +{ + xbt_dynar_t d = (xbt_dynar_t) a; + int i; + for (i = 0; i < 500; i++) { + xbt_dynar_push(d, &i); + } +} + +static void poper_f(void *a) +{ + xbt_dynar_t d = (xbt_dynar_t) a; + int i; + int data; + xbt_ex_t e; + + for (i = 0; i < 500; i++) { + TRY { + xbt_dynar_pop(d, &data); + } + CATCH(e) { + if (e.category == bound_error) { + xbt_ex_free(e); + i--; + } else { + RETHROW; + } + } + } +} + + +XBT_TEST_UNIT("synchronized int", test_dynar_sync_int,"Synchronized dynars of integers") +{ + /* Vars_decl [doxygen cruft] */ + xbt_dynar_t d; + xbt_thread_t pusher, poper; + + xbt_test_add0("==== Have a pusher and a popper on the dynar"); + d = xbt_dynar_new_sync(sizeof(int), NULL); + pusher = xbt_thread_create("pusher", pusher_f, d,0/*not joinable*/); + poper = xbt_thread_create("poper", poper_f, d,0/*not joinable*/); + xbt_thread_join(pusher); + xbt_thread_join(poper); + xbt_dynar_free(&d); +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/ex_unit.c b/src/ex_unit.c new file mode 100644 index 0000000000..86b3d2bd69 --- /dev/null +++ b/src/ex_unit.c @@ -0,0 +1,224 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 202 "/home/navarrop/Developments/simgrid/src/xbt/ex.c" +#include +#include "xbt/ex.h" + + +XBT_TEST_UNIT("controlflow", test_controlflow, "basic nested control flow") +{ + xbt_ex_t ex; + volatile int n = 1; + + xbt_test_add0("basic nested control flow"); + + TRY { + if (n != 1) + xbt_test_fail1("M1: n=%d (!= 1)", n); + n++; + TRY { + if (n != 2) + xbt_test_fail1("M2: n=%d (!= 2)", n); + n++; + THROW0(unknown_error, 0, "something"); + } + CATCH(ex) { + if (n != 3) + xbt_test_fail1("M3: n=%d (!= 3)", n); + n++; + xbt_ex_free(ex); + } + n++; + TRY { + if (n != 5) + xbt_test_fail1("M2: n=%d (!= 5)", n); + n++; + THROW0(unknown_error, 0, "something"); + } + CATCH(ex) { + if (n != 6) + xbt_test_fail1("M3: n=%d (!= 6)", n); + n++; + RETHROW; + n++; + } + xbt_test_fail1("MX: n=%d (shouldn't reach this point)", n); + } + CATCH(ex) { + if (n != 7) + xbt_test_fail1("M4: n=%d (!= 7)", n); + n++; + xbt_ex_free(ex); + } + if (n != 8) + xbt_test_fail1("M5: n=%d (!= 8)", n); +} + +XBT_TEST_UNIT("value", test_value, "exception value passing") +{ + xbt_ex_t ex; + + TRY { + THROW0(unknown_error, 2, "toto"); + } + CATCH(ex) { + xbt_test_add0("exception value passing"); + if (ex.category != unknown_error) + xbt_test_fail1("category=%d (!= 1)", ex.category); + if (ex.value != 2) + xbt_test_fail1("value=%d (!= 2)", ex.value); + if (strcmp(ex.msg, "toto")) + xbt_test_fail1("message=%s (!= toto)", ex.msg); + xbt_ex_free(ex); + } +} + +XBT_TEST_UNIT("variables", test_variables, "variable value preservation") +{ + xbt_ex_t ex; + int r1, r2; + volatile int v1, v2; + + r1 = r2 = v1 = v2 = 1234; + TRY { + r2 = 5678; + v2 = 5678; + THROW0(unknown_error, 0, "toto"); + } CATCH(ex) { + xbt_test_add0("variable preservation"); + if (r1 != 1234) + xbt_test_fail1("r1=%d (!= 1234)", r1); + if (v1 != 1234) + xbt_test_fail1("v1=%d (!= 1234)", v1); + /* r2 is allowed to be destroyed because not volatile */ + if (v2 != 5678) + xbt_test_fail1("v2=%d (!= 5678)", v2); + xbt_ex_free(ex); + } +} + +XBT_TEST_UNIT("cleanup", test_cleanup, "cleanup handling") +{ + xbt_ex_t ex; + volatile int v1; + int c; + + xbt_test_add0("cleanup handling"); + + v1 = 1234; + c = 0; + TRY { + v1 = 5678; + THROW0(1, 2, "blah"); + } CLEANUP { + if (v1 != 5678) + xbt_test_fail1("v1 = %d (!= 5678)", v1); + c = 1; + } + CATCH(ex) { + if (v1 != 5678) + xbt_test_fail1("v1 = %d (!= 5678)", v1); + if (!(ex.category == 1 && ex.value == 2 && !strcmp(ex.msg, "blah"))) + xbt_test_fail0("unexpected exception contents"); + xbt_ex_free(ex); + } + if (!c) + xbt_test_fail0("xbt_ex_free not executed"); +} + + +/* + * The following is the example included in the documentation. It's a good + * idea to check its syntax even if we don't try to run it. + * And actually, it allows to put comments in the code despite doxygen. + */ +static char *mallocex(int size) +{ + return NULL; +} + +#define SMALLAMOUNT 10 +#define TOOBIG 100000000 + +#if 0 /* this contains syntax errors, actually */ +static void bad_example(void) +{ + struct { + char *first; + } *globalcontext; + ex_t ex; + + /* BAD_EXAMPLE */ + TRY { + char *cp1, *cp2, *cp3; + + cp1 = mallocex(SMALLAMOUNT); + globalcontext->first = cp1; + cp2 = mallocex(TOOBIG); + cp3 = mallocex(SMALLAMOUNT); + strcpy(cp1, "foo"); + strcpy(cp2, "bar"); + } CLEANUP { + if (cp3 != NULL) + free(cp3); + if (cp2 != NULL) + free(cp2); + if (cp1 != NULL) + free(cp1); + } + CATCH(ex) { + printf("cp3=%s", cp3); + RETHROW; + } + /* end_of_bad_example */ +} +#endif +typedef struct { + char *first; +} global_context_t; + +static void good_example(void) +{ + global_context_t *global_context = malloc(sizeof(global_context_t)); + xbt_ex_t ex; + + /* GOOD_EXAMPLE */ + { /*01 */ + char *volatile /*03 */ cp1 = NULL /*02 */ ; + char *volatile /*03 */ cp2 = NULL /*02 */ ; + char *volatile /*03 */ cp3 = NULL /*02 */ ; + TRY { + cp1 = mallocex(SMALLAMOUNT); + global_context->first = cp1; + cp1 = NULL /*05 give away */ ; + cp2 = mallocex(TOOBIG); + cp3 = mallocex(SMALLAMOUNT); + strcpy(cp1, "foo"); + strcpy(cp2, "bar"); + } CLEANUP { /*04 */ + printf("cp3=%s", cp3 == NULL /*02 */ ? "" : cp3); + if (cp3 != NULL) + free(cp3); + if (cp2 != NULL) + free(cp2); + /*05 cp1 was given away */ + } + CATCH(ex) { + /*05 global context untouched */ + RETHROW; + } + } + /* end_of_good_example */ +} +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/set_unit.c b/src/set_unit.c new file mode 100644 index 0000000000..7152476cfe --- /dev/null +++ b/src/set_unit.c @@ -0,0 +1,247 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 317 "/home/navarrop/Developments/simgrid/src/xbt/set.c" +#include "xbt.h" +#include "xbt/ex.h" + + +typedef struct { + /* headers */ + unsigned int ID; + char *name; + unsigned int name_len; + + /* payload */ + char *data; +} s_my_elem_t, *my_elem_t; + + +static void my_elem_free(void *e) +{ + my_elem_t elm = (my_elem_t) e; + + if (elm) { + free(elm->name); + free(elm->data); + free(elm); + } +} + +static void debuged_add(xbt_set_t set, const char *name, const char *data) +{ + my_elem_t elm; + + elm = xbt_new(s_my_elem_t, 1); + elm->name = xbt_strdup(name); + elm->name_len = 0; + + elm->data = xbt_strdup(data); + + xbt_test_log2("Add %s (->%s)", name, data); + xbt_set_add(set, (xbt_set_elm_t) elm, &my_elem_free); +} + +static void fill(xbt_set_t * set) +{ + xbt_test_add0("Fill in the data set"); + + *set = xbt_set_new(); + debuged_add(*set, "12", "12"); + debuged_add(*set, "12a", "12a"); + debuged_add(*set, "12b", "12b"); + debuged_add(*set, "123", "123"); + debuged_add(*set, "123456", "123456"); + xbt_test_log0("Child becomes child of what to add"); + debuged_add(*set, "1234", "1234"); + xbt_test_log0("Need of common ancestor"); + debuged_add(*set, "123457", "123457"); +} + +static void search_name(xbt_set_t head, const char *key) +{ + my_elem_t elm; + + xbt_test_add1("Search by name %s", key); + elm = (my_elem_t) xbt_set_get_by_name(head, key); + xbt_test_log2(" Found %s (under ID %d)\n", + elm ? elm->data : "(null)", elm ? elm->ID : -1); + if (strcmp(key, elm->name)) + THROW2(mismatch_error, 0, "The key (%s) is not the one expected (%s)", + key, elm->name); + if (strcmp(elm->name, elm->data)) + THROW2(mismatch_error, 0, "The name (%s) != data (%s)", key, elm->name); + fflush(stdout); +} + +static void search_id(xbt_set_t head, int id, const char *key) +{ + my_elem_t elm; + + xbt_test_add1("Search by id %d", id); + elm = (my_elem_t) xbt_set_get_by_id(head, id); + xbt_test_log2("Found %s (data %s)", + elm ? elm->name : "(null)", elm ? elm->data : "(null)"); + if (id != elm->ID) + THROW2(mismatch_error, 0, + "The found ID (%d) is not the one expected (%d)", elm->ID, id); + if (strcmp(key, elm->name)) + THROW2(mismatch_error, 0, "The key (%s) is not the one expected (%s)", + elm->name, key); + if (strcmp(elm->name, elm->data)) + THROW2(mismatch_error, 0, "The name (%s) != data (%s)", + elm->name, elm->data); +} + + +static void traverse(xbt_set_t set) +{ + xbt_set_cursor_t cursor = NULL; + my_elem_t elm = NULL; + + xbt_set_foreach(set, cursor, elm) { + xbt_test_assert0(elm, "Dude ! Got a null elm during traversal!"); + xbt_test_log3("Id(%d): %s->%s\n", elm->ID, elm->name, elm->data); + xbt_test_assert2(!strcmp(elm->name, elm->data), + "Key(%s) != value(%s). Abording", elm->name, elm->data); + } +} + +static void search_not_found(xbt_set_t set, const char *data) +{ + xbt_ex_t e; + + xbt_test_add1("Search %s (expected not to be found)", data); + TRY { + xbt_set_get_by_name(set, data); + THROW1(unknown_error, 0, "Found something which shouldn't be there (%s)", + data); + } CATCH(e) { + if (e.category != not_found_error) + xbt_test_exception(e); + xbt_ex_free(e); + } +} + +xbt_set_t set = NULL; + + +XBT_TEST_UNIT("basic", test_set_basic, "Basic usage") +{ + set = NULL; + + xbt_test_add0("Traverse the empty set"); + traverse(set); + + xbt_test_add0("Free a data set"); + fill(&set); + xbt_set_free(&set); + + xbt_test_add0("Free the NULL data set"); + xbt_set_free(&set); + +} + +XBT_TEST_UNIT("change", test_set_change, "Changing some values") +{ + fill(&set); + + xbt_test_add0("Change 123 to 'Changed 123'"); + debuged_add(set, "123", "Changed 123"); + + xbt_test_add0("Change 123 back to '123'"); + debuged_add(set, "123", "123"); + + xbt_test_add0("Change 12a to 'Dummy 12a'"); + debuged_add(set, "12a", "Dummy 12a"); + + xbt_test_add0("Change 12a to '12a'"); + debuged_add(set, "12a", "12a"); + + /* xbt_dict_dump(head,(void (*)(void*))&printf); */ + xbt_test_add0("Traverse the resulting data set"); + traverse(set); +} + +XBT_TEST_UNIT("retrieve", test_set_retrieve, "Retrieving some values") +{ + my_elem_t elm; + + xbt_test_add0("Search 123"); + elm = (my_elem_t) xbt_set_get_by_name(set, "123"); + xbt_test_assert0(elm, "elm must be there"); + xbt_assert(!strcmp("123", elm->data)); + + search_not_found(set, "Can't be found"); + search_not_found(set, "123 Can't be found"); + search_not_found(set, "12345678 NOT"); + + search_name(set, "12"); + search_name(set, "12a"); + search_name(set, "12b"); + search_name(set, "123"); + search_name(set, "123456"); + search_name(set, "1234"); + search_name(set, "123457"); + + search_id(set, 0, "12"); + search_id(set, 1, "12a"); + search_id(set, 2, "12b"); + search_id(set, 3, "123"); + search_id(set, 4, "123456"); + search_id(set, 5, "1234"); + search_id(set, 6, "123457"); + + xbt_test_add0("Traverse the resulting data set"); + traverse(set); + + /* xbt_dict_dump(head,(void (*)(void*))&printf); */ + + xbt_test_add0("Free the data set (twice)"); + xbt_set_free(&set); + xbt_set_free(&set); + + xbt_test_add0("Traverse the resulting data set"); + traverse(set); +} + +XBT_TEST_UNIT("remove", test_set_remove, "Removing some values") +{ + my_elem_t elm; + + xbt_set_free(&set); + fill(&set); + + xbt_set_remove_by_name(set, "12a"); + search_not_found(set, "12a"); + + search_name(set, "12"); + search_name(set, "12b"); + search_name(set, "123"); + search_name(set, "123456"); + search_name(set, "1234"); + search_name(set, "123457"); + + search_id(set, 0, "12"); + search_id(set, 2, "12b"); + search_id(set, 3, "123"); + search_id(set, 4, "123456"); + search_id(set, 5, "1234"); + search_id(set, 6, "123457"); + + debuged_add(set, "12anew", "12anew"); + elm = (my_elem_t) xbt_set_get_by_id(set, 1); + xbt_test_assert1(elm->ID == 1, "elm->ID is %d but should be 1", elm->ID); +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/swag_unit.c b/src/swag_unit.c new file mode 100644 index 0000000000..c6b6ce3109 --- /dev/null +++ b/src/swag_unit.c @@ -0,0 +1,74 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 220 "/home/navarrop/Developments/simgrid/src/xbt/swag.c" + + +typedef struct { + s_xbt_swag_hookup_t setA; + s_xbt_swag_hookup_t setB; + const char *name; +} shmurtz, s_shmurtz_t, *shmurtz_t; + + +XBT_TEST_UNIT("basic", test_swag_basic, "Basic usage") +{ + shmurtz_t obj1, obj2, obj; + xbt_swag_t setA, setB; + + obj1 = xbt_new0(s_shmurtz_t, 1); + obj2 = xbt_new0(s_shmurtz_t, 1); + + obj1->name = "Obj 1"; + obj2->name = "Obj 2"; + + xbt_test_add0("Basic usage"); + xbt_test_log3("%p %p %ld\n", obj1, &(obj1->setB), + (long) ((char *) &(obj1->setB) - (char *) obj1)); + + setA = xbt_swag_new(xbt_swag_offset(*obj1, setA)); + setB = xbt_swag_new(xbt_swag_offset(*obj1, setB)); + + xbt_swag_insert(obj1, setA); + xbt_swag_insert(obj1, setB); + xbt_swag_insert(obj2, setA); + xbt_swag_insert(obj2, setB); + + xbt_swag_remove(obj1, setB); + /* xbt_swag_remove(obj2, setB); */ + + xbt_test_add0("Traverse set A"); + xbt_swag_foreach(obj, setA) { + xbt_test_log1("Saw: %s", obj->name); + } + + xbt_test_add0("Traverse set B"); + xbt_swag_foreach(obj, setB) { + xbt_test_log1("Saw: %s", obj->name); + } + + xbt_test_add0("Ensure set content and length"); + xbt_test_assert(xbt_swag_belongs(obj1, setA)); + xbt_test_assert(xbt_swag_belongs(obj2, setA)); + + xbt_test_assert(!xbt_swag_belongs(obj1, setB)); + xbt_test_assert(xbt_swag_belongs(obj2, setB)); + + xbt_test_assert(xbt_swag_size(setA) == 2); + xbt_test_assert(xbt_swag_size(setB) == 1); + + xbt_swag_free(setA); + xbt_swag_free(setB); +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/xbt_sha_unit.c b/src/xbt_sha_unit.c new file mode 100644 index 0000000000..8229c8c00f --- /dev/null +++ b/src/xbt_sha_unit.c @@ -0,0 +1,58 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 177 "/home/navarrop/Developments/simgrid/src/xbt/xbt_sha.c" +#include "xbt/hash.h" +#include "portable.h" /* hexa_str */ + +static char *mycmp(const char *p1, const char *p2, size_t n) +{ + int i; + + for (i = 0; i < n; i++) { + if (p1[i] != p2[i]) { + return bprintf("Differs on %d -- Ox%x", i, p1[i]); + } + } + return xbt_strdup(""); +} + +static void test_sha(const char *clear, const char *hashed) +{ + char hash[41]; + xbt_sha(clear, hash); + + xbt_test_add1("==== Test with '%s'", clear); + xbt_test_assert3(!memcmp(hash, hashed, 40), "Wrong sha: %40s!=%40s (%s)", + hash, hashed, mycmp(hash, hashed, 40)); +} + + +XBT_LOG_NEW_DEFAULT_CATEGORY(hash, "Tests of various hash functions "); + + +XBT_TEST_UNIT("sha", test_crypto_sha, "Test of the sha algorithm") +{ + /* Empty string as test vector */ + test_sha("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + + /* Some pangram as test vector */ + test_sha("The quick brown fox jumps over the lazy dog", + "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); + test_sha("Woven silk pyjamas exchanged for blue quartz", + "da3aff337c810c6470db4dbf0f205c8afc31c442"); + test_sha("Pack my box with five dozen liquor jugs", + "373ba8be29d4d95708bf7cd43038f4e409dcb439"); + +} +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/xbt_str_unit.c b/src/xbt_str_unit.c new file mode 100644 index 0000000000..68cc6f8030 --- /dev/null +++ b/src/xbt_str_unit.c @@ -0,0 +1,70 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 426 "/home/navarrop/Developments/simgrid/src/xbt/xbt_str.c" +#include "xbt/str.h" + +#define mytest(name, input, expected) \ + xbt_test_add0(name); \ + d=xbt_str_split_quoted(input); \ + s=xbt_str_join(d,"XXX"); \ + xbt_test_assert3(!strcmp(s,expected),\ + "Input (%s) leads to (%s) instead of (%s)", \ + input,s,expected);\ + free(s); \ + xbt_dynar_free(&d); + +XBT_TEST_UNIT("xbt_str_split_quoted", test_split_quoted,"test the function xbt_str_split_quoted") +{ + xbt_dynar_t d; + char *s; + + mytest("Empty", "", ""); + mytest("Basic test", "toto tutu", "totoXXXtutu"); + mytest("Useless backslashes", "\\t\\o\\t\\o \\t\\u\\t\\u", "totoXXXtutu"); + mytest("Protected space", "toto\\ tutu", "toto tutu"); + mytest("Several spaces", "toto tutu", "totoXXXtutu"); + mytest("LTriming", " toto tatu", "totoXXXtatu"); + mytest("Triming", " toto tutu ", "totoXXXtutu"); + mytest("Single quotes", "'toto tutu' tata", "toto tutuXXXtata"); + mytest("Double quotes", "\"toto tutu\" tata", "toto tutuXXXtata"); + mytest("Mixed quotes", "\"toto' 'tutu\" tata", "toto' 'tutuXXXtata"); + mytest("Backslashed quotes", "\\'toto tutu\\' tata", + "'totoXXXtutu'XXXtata"); + mytest("Backslashed quotes + quotes", "'toto \\'tutu' tata", + "toto 'tutuXXXtata"); + +} + +#define mytest_str(name, input, separator, expected) \ + xbt_test_add0(name); \ + d=xbt_str_split_str(input, separator); \ + s=xbt_str_join(d,"XXX"); \ + xbt_test_assert3(!strcmp(s,expected),\ + "Input (%s) leads to (%s) instead of (%s)", \ + input,s,expected);\ + free(s); \ + xbt_dynar_free(&d); + +XBT_TEST_UNIT("xbt_str_split_str", test_split_str,"test the function xbt_str_split_str") +{ + xbt_dynar_t d; + char *s; + + mytest_str("Empty string and separator", "", "", ""); + mytest_str("Empty string", "", "##", ""); + mytest_str("Empty separator", "toto", "", "toto"); + mytest_str("String with no separator in it", "toto", "##", "toto"); + mytest_str("Basic test", "toto##tutu", "##", "totoXXXtutu"); +} +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/xbt_strbuff_unit.c b/src/xbt_strbuff_unit.c new file mode 100644 index 0000000000..8a8cc2c011 --- /dev/null +++ b/src/xbt_strbuff_unit.c @@ -0,0 +1,150 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 293 "/home/navarrop/Developments/simgrid/src/xbt/xbt_strbuff.c" +#include "xbt/strbuff.h" + +/* buffstr have 512 chars by default. Adding 1000 chars like this will force a resize, allowing us to test that b->used and b->size are consistent */ +#define force_resize \ + "1.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "2.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "3.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "4.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "5.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "6.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "7.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "8.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "9.........1.........2.........3.........4.........5.........6.........7.........8.........9........." \ + "0.........1.........2.........3.........4.........5.........6.........7.........8.........9........." + +static void mytest(const char *input, const char *patterns, + const char *expected) +{ + xbt_dynar_t dyn_patterns; /* splited string */ + xbt_dict_t p; /* patterns */ + unsigned int cpt; + char *str; /*foreach */ + xbt_strbuff_t sb; /* what we test */ + + p = xbt_dict_new(); + dyn_patterns = xbt_str_split(patterns, " "); + xbt_dynar_foreach(dyn_patterns, cpt, str) { + xbt_dynar_t keyvals = xbt_str_split(str, "="); + char *key = xbt_dynar_get_as(keyvals, 0, char *); + char *val = xbt_dynar_get_as(keyvals, 1, char *); + xbt_str_subst(key, '_', ' ', 0); // to put space in names without breaking the enclosing dynar_foreach + xbt_dict_set(p, key, xbt_strdup(val), free); + xbt_dynar_free(&keyvals); + } + xbt_dynar_free(&dyn_patterns); + sb = xbt_strbuff_new(); + xbt_strbuff_append(sb, input); + xbt_strbuff_varsubst(sb, p); + xbt_dict_free(&p); + xbt_test_assert4(!strcmp(sb->data, expected), + "Input (%s) with patterns (%s) leads to (%s) instead of (%s)", + input, patterns, sb->data, expected); + xbt_strbuff_free(sb); +} + +XBT_TEST_UNIT("xbt_strbuff_substitute", test_strbuff_substitute,"test the function xbt_strbuff_substitute") +{ + xbt_test_add0("Empty"); + mytest("", "", ""); + + xbt_test_add0("Value shorter, no braces, only variable"); + mytest("$tutu", "tutu=t", "t"); + xbt_test_add0("Value shorter, braces, only variable"); + mytest("${tutu}", "tutu=t", "t"); + xbt_test_add0("Value shorter, no braces, data after"); + mytest("$tutu toto", "tutu=t", "t toto"); + xbt_test_add0("Value shorter, braces, data after"); + mytest("${tutu} toto", "tutu=t", "t toto"); + xbt_test_add0("Value shorter, no braces, data before"); + mytest("toto $tutu", "tutu=t", "toto t"); + xbt_test_add0("Value shorter, braces, data before"); + mytest("toto ${tutu}", "tutu=t", "toto t"); + xbt_test_add0("Value shorter, no braces, data before and after"); + mytest("toto $tutu tata", "tutu=t", "toto t tata"); + xbt_test_add0("Value shorter, braces, data before and after"); + mytest("toto ${tutu} tata", "tutu=t", "toto t tata"); + + xbt_test_add0("Value as long, no braces, only variable"); + mytest("$tutu", "tutu=12345", "12345"); + xbt_test_add0("Value as long, braces, only variable"); + mytest("${tutu}", "tutu=1234567", "1234567"); + xbt_test_add0("Value as long, no braces, data after"); + mytest("$tutu toto", "tutu=12345", "12345 toto"); + xbt_test_add0("Value as long, braces, data after"); + mytest("${tutu} toto", "tutu=1234567", "1234567 toto"); + xbt_test_add0("Value as long, no braces, data before"); + mytest("toto $tutu", "tutu=12345", "toto 12345"); + xbt_test_add0("Value as long, braces, data before"); + mytest("toto ${tutu}", "tutu=1234567", "toto 1234567"); + xbt_test_add0("Value as long, no braces, data before and after"); + mytest("toto $tutu tata", "tutu=12345", "toto 12345 tata"); + xbt_test_add0("Value as long, braces, data before and after"); + mytest("toto ${tutu} tata", "tutu=1234567", "toto 1234567 tata"); + + xbt_test_add0("Value longer, no braces, only variable"); + mytest("$t", "t=tututu", "tututu"); + xbt_test_add0("Value longer, braces, only variable"); + mytest("${t}", "t=tututu", "tututu"); + xbt_test_add0("Value longer, no braces, data after"); + mytest("$t toto", "t=tututu", "tututu toto"); + xbt_test_add0("Value longer, braces, data after"); + mytest("${t} toto", "t=tututu", "tututu toto"); + xbt_test_add0("Value longer, no braces, data before"); + mytest("toto $t", "t=tututu", "toto tututu"); + xbt_test_add0("Value longer, braces, data before"); + mytest("toto ${t}", "t=tututu", "toto tututu"); + xbt_test_add0("Value longer, no braces, data before and after"); + mytest("toto $t tata", "t=tututu", "toto tututu tata"); + xbt_test_add0("Value longer, braces, data before and after"); + mytest("toto ${t} tata", "t=tututu", "toto tututu tata"); + + xbt_test_add0("Value much longer, no braces, only variable"); + mytest("$t", "t=" force_resize, force_resize); + xbt_test_add0("Value much longer, no braces, data after"); + mytest("$t toto", "t=" force_resize, force_resize " toto"); + xbt_test_add0("Value much longer, braces, data after"); + mytest("${t} toto", "t=" force_resize, force_resize " toto"); + xbt_test_add0("Value much longer, no braces, data before"); + mytest("toto $t", "t=" force_resize, "toto " force_resize); + xbt_test_add0("Value much longer, braces, data before"); + mytest("toto ${t}", "t=" force_resize, "toto " force_resize); + xbt_test_add0("Value much longer, no braces, data before and after"); + mytest("toto $t tata", "t=" force_resize, "toto " force_resize " tata"); + xbt_test_add0("Value much longer, braces, data before and after"); + mytest("toto ${t} tata", "t=" force_resize, "toto " force_resize " tata"); + + xbt_test_add0("Escaped $"); + mytest("\\$tutu", "tutu=t", "\\$tutu"); + xbt_test_add0("Space in var name (with braces)"); + mytest("${tu ti}", "tu_ti=t", "t"); + + xbt_test_add0("Two variables"); + mytest("$toto $tutu", "toto=1 tutu=2", "1 2"); + + // Commented: I'm too lazy to do a memmove in var name to remove the backslash after use. + // Users should use braces. + // xbt_test_add0("Escaped space in var name", "$tu\\ ti", "tu_ti=t", "t"); + + xbt_test_add0("Default value"); + mytest("${t:-toto}", "", "toto"); + xbt_test_add0("Useless default value (variable already defined)"); + mytest("${t:-toto}", "t=TRUC", "TRUC"); + +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + diff --git a/src/xbt_synchro_unit.c b/src/xbt_synchro_unit.c new file mode 100644 index 0000000000..0dcc5ab0b7 --- /dev/null +++ b/src/xbt_synchro_unit.c @@ -0,0 +1,49 @@ +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +#include +#include "xbt.h" +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + +# 58 "/home/navarrop/Developments/simgrid/src/xbt/xbt_synchro.c" +#define NB_ELEM 50 +#include "xbt/synchro.h" + +XBT_LOG_EXTERNAL_CATEGORY(xbt_dyn); +XBT_LOG_DEFAULT_CATEGORY(xbt_dyn); + +static void add100(int rank,void *data) { + //INFO2("Thread%d: Add 100 to %d",rank,*(int*)data); + *(int*)data +=100; +} + +XBT_TEST_UNIT("dopar", test_dynar_dopar, "do parallel on dynars of integers") +{ + xbt_dynar_t d; + int i, cpt; + unsigned int cursor; + + xbt_test_add1("==== Push %d int, add 100 to each of them in parallel and check the results", NB_ELEM); + d = xbt_dynar_new(sizeof(int), NULL); + for (cpt = 0; cpt < NB_ELEM; cpt++) { + xbt_dynar_push_as(d, int, cpt); /* This is faster (and possible only with scalars) */ + xbt_test_log2("Push %d, length=%lu", cpt, xbt_dynar_length(d)); + } + xbt_dynar_dopar(d,add100); + cpt = 100; + xbt_dynar_foreach(d, cursor, i) { + xbt_test_assert2(i == cpt, + "The retrieved value is not the expected one (%d!=%d)", + i, cpt); + cpt++; + } + xbt_dynar_free(&d); +} + +/*******************************/ +/* GENERATED FILE, DO NOT EDIT */ +/*******************************/ + -- 2.20.1