From d50f5ea694faa07c1b232d96deda4f9803ffdfbd Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 18:38:47 -0400 Subject: [PATCH 01/12] added unit tests for utils --- include/villas/utils.h | 2 +- lib/kernel/kernel.c | 2 +- lib/utils.c | 2 +- tests/utils.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/utils.c diff --git a/include/villas/utils.h b/include/villas/utils.h index 82b7cabb7..d6faadff2 100644 --- a/include/villas/utils.h +++ b/include/villas/utils.h @@ -180,7 +180,7 @@ struct version { }; /** Compare two versions. */ -int version_compare(struct version *a, struct version *b); +int version_cmp(struct version *a, struct version *b); /** Parse a dotted version string. */ int version_parse(const char *s, struct version *v); diff --git a/lib/kernel/kernel.c b/lib/kernel/kernel.c index 6548dbf49..b2c9b94cc 100644 --- a/lib/kernel/kernel.c +++ b/lib/kernel/kernel.c @@ -101,7 +101,7 @@ int kernel_has_version(int maj, int min) if (version_parse(uts.release, ¤t)) return -1; - return version_compare(¤t, &required) < 0; + return version_cmp(¤t, &required) < 0; } int kernel_is_rt() diff --git a/lib/utils.c b/lib/utils.c index eff72a954..5fba36038 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -35,7 +35,7 @@ int version_parse(const char *s, struct version *v) return sscanf(s, "%u.%u", &v->major, &v->minor) != 2; } -int version_compare(struct version *a, struct version *b) { +int version_cmp(struct version *a, struct version *b) { int major = a->major - b->major; int minor = a->minor - b->minor; diff --git a/tests/utils.c b/tests/utils.c new file mode 100644 index 000000000..6999cd70e --- /dev/null +++ b/tests/utils.c @@ -0,0 +1,64 @@ +/** Unit tests for utilities + * + * @author Steffen Vogel + * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include + +#include "utils.h" + +Test(utils, is_aligned) +{ + /* Positive */ + cr_assert(IS_ALIGNED(1, 1)); + cr_assert(IS_ALIGNED(128, 64)); + + /* Negative */ + cr_assert(!IS_ALIGNED(55, 16)); + cr_assert(!IS_ALIGNED(55, 55)); + cr_assert(!IS_ALIGNED(1128, 256)); +} + +Test(utils, ceil) +{ + cr_assert_eq(CEIL(10, 3), 4); + cr_assert_eq(CEIL(10, 5), 2); + cr_assert_eq(CEIL(4, 3), 2); +} + +Test(utils, is_pow2) +{ + /* Positive */ + cr_assert(IS_POW2(1)); + cr_assert(IS_POW2(2)); + cr_assert(IS_POW2(64)); + + /* Negative */ + cr_assert(!IS_POW2(0)); + cr_assert(!IS_POW2(3)); + cr_assert(!IS_POW2(11111)); + cr_assert(!IS_POW2(-1)); +} + +struct version_param { + const char *v1, *v2; + int result; +}; + +Test(utils, version) +{ + struct version v1, v2, v3, v4; + + version_parse("1.2", &v1); + version_parse("1.3", &v2); + version_parse("55", &v3); + version_parse("66", &v4); + + cr_assert_lt(version_cmp(&v1, &v2), 0); + cr_assert_eq(version_cmp(&v1, &v1), 0); + cr_assert_gt(version_cmp(&v2, &v1), 0); + cr_assert_lt(version_cmp(&v3, &v4), 0); +} \ No newline at end of file From f13c6c14e413daf408a28e105edd521a2360db99 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 18:39:22 -0400 Subject: [PATCH 02/12] added unit tests for memory functions --- include/villas/memory.h | 1 + tests/memory.c | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/memory.c diff --git a/include/villas/memory.h b/include/villas/memory.h index d66955727..b21d1b1a4 100644 --- a/include/villas/memory.h +++ b/include/villas/memory.h @@ -8,6 +8,7 @@ */ #include +#include #ifndef _MEMORY_H_ #define _MEMORY_H_ diff --git a/tests/memory.c b/tests/memory.c new file mode 100644 index 000000000..fc40bd610 --- /dev/null +++ b/tests/memory.c @@ -0,0 +1,42 @@ +/** Unit tests for memory management + * + * @author Steffen Vogel + * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include +#include + +#include + +#include "memory.h" +#include "utils.h" + +#define HUGEPAGESIZE (1 << 21) + +TheoryDataPoints(memory, aligned) = { +// DataPoints(size_t, 1, 32, 55, 1 << 10, 1 << 20), + DataPoints(size_t, 1<<12), + DataPoints(size_t, 1, 8, 1 << 12), + DataPoints(const struct memtype *, &memtype_heap, &memtype_hugepage) +}; + +Theory((size_t len, size_t align, const struct memtype *m), memory, aligned) { + int ret; + void *ptr; + + ptr = memory_alloc_aligned(m, len, align); + cr_assert_neq(ptr, NULL, "Failed to allocate memory"); + + //cr_assert(IS_ALIGNED(ptr, align)); + + if (m == &memtype_hugepage) { + cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE)); + len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */ + } + + ret = memory_free(m, ptr, len); + cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", ret, ptr, len, strerror(errno)); +} \ No newline at end of file From 7baffe66c0494464e237ee4acafa8c9e586b9164 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 19:40:31 -0400 Subject: [PATCH 03/12] move munmap() workaround to from unit test to memory_free_hugepage() --- include/villas/memory.h | 2 ++ lib/memory.c | 2 ++ tests/memory.c | 7 ++----- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/villas/memory.h b/include/villas/memory.h index b21d1b1a4..cf1d7acd5 100644 --- a/include/villas/memory.h +++ b/include/villas/memory.h @@ -13,6 +13,8 @@ #ifndef _MEMORY_H_ #define _MEMORY_H_ +#define HUGEPAGESIZE (1 << 21) + typedef void *(*memzone_allocator_t)(size_t len); typedef int (*memzone_deallocator_t)(void *ptr, size_t len); diff --git a/lib/memory.c b/lib/memory.c index df4eccd7e..7525a1c0c 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -65,6 +65,8 @@ static void * memory_hugepage_alloc(size_t len) static int memory_hugepage_free(void *ptr, size_t len) { + len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */ + return munmap(ptr, len); } diff --git a/tests/memory.c b/tests/memory.c index fc40bd610..234e6defd 100644 --- a/tests/memory.c +++ b/tests/memory.c @@ -14,8 +14,6 @@ #include "memory.h" #include "utils.h" -#define HUGEPAGESIZE (1 << 21) - TheoryDataPoints(memory, aligned) = { // DataPoints(size_t, 1, 32, 55, 1 << 10, 1 << 20), DataPoints(size_t, 1<<12), @@ -31,12 +29,11 @@ Theory((size_t len, size_t align, const struct memtype *m), memory, aligned) { cr_assert_neq(ptr, NULL, "Failed to allocate memory"); //cr_assert(IS_ALIGNED(ptr, align)); - + if (m == &memtype_hugepage) { cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE)); - len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */ } - + ret = memory_free(m, ptr, len); cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", ret, ptr, len, strerror(errno)); } \ No newline at end of file From 4e7011bba6f2348044bac1c6747b7f7b81b5ca21 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 19:40:50 -0400 Subject: [PATCH 04/12] added unit tests for pool --- tests/pool.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/pool.c diff --git a/tests/pool.c b/tests/pool.c new file mode 100644 index 000000000..68a8956fd --- /dev/null +++ b/tests/pool.c @@ -0,0 +1,62 @@ +/** Unit tests for memory pool + * + * @author Steffen Vogel + * @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include +#include + +#include + +#include "pool.h" +#include "utils.h" + +struct param { + int thread_count; + int pool_size; + size_t block_size; + const struct memtype *memtype; +}; + +ParameterizedTestParameters(pool, basic) +{ + static struct param params[] = { + { 1, 4096, 150, &memtype_heap }, + { 1, 128, 8, &memtype_hugepage }, + { 1, 4, 8192, &memtype_hugepage }, + { 1, 1 << 13,4, &memtype_heap } + }; + + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); +} + +ParameterizedTest(struct param *p, pool, basic) +{ + int ret; + struct pool pool; + + void *ptr, *ptrs[p->pool_size]; + + ret = pool_init(&pool, p->pool_size, p->block_size, p->memtype); + cr_assert_eq(ret, 0, "Failed to create pool"); + + ptr = pool_get(&pool); + cr_assert_neq(ptr, NULL); + + memset(ptr, 1, p->block_size); /* check that we dont get a seg fault */ + + for (int i = 1; i < p->pool_size; i++) { + ptrs[i] = pool_get(&pool); + cr_assert_neq(ptrs[i], NULL); + } + + ptr = pool_get(&pool); + cr_assert_eq(ptr, NULL); + + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0, "Failed to destroy pool"); + +} \ No newline at end of file From 0d366fb556dac562a79092efef7953c7ebc6e041 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 19:43:22 -0400 Subject: [PATCH 05/12] speedup of unit tests (see https://github.com/Snaipe/Criterion/issues/172) --- tests/pool.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/pool.c b/tests/pool.c index 68a8956fd..8654ad6ea 100644 --- a/tests/pool.c +++ b/tests/pool.c @@ -27,7 +27,7 @@ ParameterizedTestParameters(pool, basic) { 1, 4096, 150, &memtype_heap }, { 1, 128, 8, &memtype_hugepage }, { 1, 4, 8192, &memtype_hugepage }, - { 1, 1 << 13,4, &memtype_heap } + { 1, 1 << 13, 4, &memtype_heap } }; return cr_make_param_array(struct param, params, ARRAY_LEN(params)); @@ -48,11 +48,17 @@ ParameterizedTest(struct param *p, pool, basic) memset(ptr, 1, p->block_size); /* check that we dont get a seg fault */ - for (int i = 1; i < p->pool_size; i++) { + int i; + for (i = 1; i < p->pool_size; i++) { ptrs[i] = pool_get(&pool); - cr_assert_neq(ptrs[i], NULL); + + if (ptrs[i] == NULL) + break; } + if (i < p->pool_size) + cr_assert_neq(ptrs[i], NULL); + ptr = pool_get(&pool); cr_assert_eq(ptr, NULL); From c0645ab839dd051f4f91581615ee2887e250fddd Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 19:46:42 -0400 Subject: [PATCH 06/12] use latest Criterion version for some required bug fixes --- thirdparty/criterion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thirdparty/criterion b/thirdparty/criterion index 1b687a9f6..101d0e0f3 160000 --- a/thirdparty/criterion +++ b/thirdparty/criterion @@ -1 +1 @@ -Subproject commit 1b687a9f6a0e51c9e9b0a047e1fcd6c94de7a080 +Subproject commit 101d0e0f3a71c414c7d2a7a2a2fa465969b6b667 From 1cfa7f05d9c57de0532d1a17faab3644e579e7f0 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 20:04:17 -0400 Subject: [PATCH 07/12] added missing defines --- include/villas/utils.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/villas/utils.h b/include/villas/utils.h index d6faadff2..8a50b6754 100644 --- a/include/villas/utils.h +++ b/include/villas/utils.h @@ -57,6 +57,12 @@ #define CEIL(x, y) ((x + y - 1) / y) +/** Get nearest up-rounded power of 2 */ +#define LOG2_CEIL(x) (1 << (log2i((x) - 1) + 1)) + +/** Check if the number is a power of 2 */ +#define IS_POW2(x) (((x) != 0) && !((x) & ((x) - 1))) + /** Calculate the number of elements in an array. */ #define ARRAY_LEN(a) ( sizeof (a) / sizeof (a)[0] ) From f2bdba06d071de149f4a54ca43d1a156c61aa222 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 20:07:47 -0400 Subject: [PATCH 08/12] fix submodule url for upstream bleeding branch --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index a61e863eb..79fac9332 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,7 @@ url = https://github.com/warmcat/libwebsockets [submodule "thirdparty/criterion"] path = thirdparty/criterion - url = https://github.com/stv0g/Criterion + url = https://github.com/Snaipe/Criterion [submodule "thirdparty/libnl"] path = thirdparty/libnl url = https://github.com/thom311/libnl.git From 6c23cd23d321357899ec048c3da8c312a390b451 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 20:12:48 -0400 Subject: [PATCH 09/12] add 'git submodule sync' to CI script to update changed .gitmodules --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 449be5384..8530cdc7a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,8 @@ docker-image: stage: prepare # Must match the docker version on the build machine! before_script: - - git submodule update --init --recursive + - git submodule sync --recursive + - git submodule update --recursive --init - docker info script: - docker build -t $DOCKER_REGISTRY/$DOCKER_IMAGE . From cbf74f931c355cbc0a59d8f4d9400ca4d3550294 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 20:58:27 -0400 Subject: [PATCH 10/12] make sure we have enough huge pages reserved for CI tests --- .gitlab-ci.yml | 3 +-- tests/Makefile.inc | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8530cdc7a..e9a1324ab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -79,8 +79,7 @@ unit: dependencies: - build script: - - make tests - - build/release/testsuite + - make run-tests image: $DOCKER_REGISTRY/$DOCKER_IMAGE tags: - docker diff --git a/tests/Makefile.inc b/tests/Makefile.inc index facbef13f..9bac51525 100644 --- a/tests/Makefile.inc +++ b/tests/Makefile.inc @@ -7,6 +7,10 @@ TEST_LDLIBS = $(LDLIBS) -lcriterion -lvillas -pthread tests: $(BUILDDIR)/testsuite +run-tests: tests + echo 25 > /proc/sys/vm/nr_hugepages + $(BUILDDIR)/testsuite + # Compile $(BUILDDIR)/tests/%.o: tests/%.c | $$(dir $$@) $(CC) $(TEST_CFLAGS) -c $< -o $@ @@ -25,4 +29,4 @@ install-tests: clean-tests: rm -rf $(BUILDDIR)/tests $(BUILDDIR)/testsuite -.PHONY: tests install-tests clean-tests \ No newline at end of file +.PHONY: tests install-tests clean-tests run-tests \ No newline at end of file From 1cede55db57671a259142f8ae89af8acf94bf359 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 21:14:48 -0400 Subject: [PATCH 11/12] make timer unit test more robust --- tests/timing.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/timing.c b/tests/timing.c index 82fb8bf6f..92974d1be 100644 --- a/tests/timing.c +++ b/tests/timing.c @@ -86,6 +86,8 @@ Test(timing, timerfd_create_rate, .timeout = 20) cr_assert(tfd > 0); + timerfd_wait(tfd); + for (int i = 0; i < 10; i++) { start = time_now(); From 2ca9193c8570eaa46b19eb9a050ec818147e1352 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 30 Oct 2016 21:21:07 -0400 Subject: [PATCH 12/12] still not robust enough (Criterion cr_assert_ calls show high latency :-S) --- tests/timing.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/timing.c b/tests/timing.c index 92974d1be..89866c07f 100644 --- a/tests/timing.c +++ b/tests/timing.c @@ -7,6 +7,7 @@ *********************************************************************************/ #include +#include #include #include "timing.h" @@ -88,7 +89,8 @@ Test(timing, timerfd_create_rate, .timeout = 20) timerfd_wait(tfd); - for (int i = 0; i < 10; i++) { + int i; + for (i = 0; i < 10; i++) { start = time_now(); timerfd_wait(tfd); @@ -96,9 +98,13 @@ Test(timing, timerfd_create_rate, .timeout = 20) end = time_now(); waited = time_delta(&start, &end); - cr_assert_float_eq(waited, 1.0 / rate, 10e-3, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i); + if (fabs(waited - 1.0 / rate) > 10e-3) + break; } + if (i < 10) + cr_assert_float_eq(waited, 1.0 / rate, 10e-3, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i); + close(tfd); }