diff options
Diffstat (limited to 'libiot/pthread/test')
| -rw-r--r-- | libiot/pthread/test/pthread-cleanup.c | 200 | ||||
| -rw-r--r-- | libiot/pthread/test/pthread-cond.c | 107 | ||||
| -rw-r--r-- | libiot/pthread/test/pthread-join.c | 85 | ||||
| -rw-r--r-- | libiot/pthread/test/pthread-once.c | 68 |
4 files changed, 460 insertions, 0 deletions
diff --git a/libiot/pthread/test/pthread-cleanup.c b/libiot/pthread/test/pthread-cleanup.c new file mode 100644 index 0000000..c11aeb4 --- /dev/null +++ b/libiot/pthread/test/pthread-cleanup.c @@ -0,0 +1,200 @@ +#include "unity.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> + +#include <sys/delay.h> + +#define NUM_TERMS 4 + +static int term[NUM_TERMS]; + +void term_0(void *args) { + term[0] = 0; +} + +void term_1(void *args) { + term[1] = 1; +} + +void term_2(void *args) { + term[2] = 2; +} + +void term_3(void *args) { + term[3] = 3; +} + +// Test that handlers are called in reverse order +static void *thread1(void *args) { + int count = 0; + + memset(term, -1, sizeof(term)); + + pthread_cleanup_push(term_0, NULL); + pthread_cleanup_push(term_1, NULL); + pthread_cleanup_push(term_2, NULL); + pthread_cleanup_push(term_3, NULL); + + for (count = 0; count < 100; count++) { + // Simulate some work + usleep(1000); + } + + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + + TEST_ASSERT(term[0] == 0); + TEST_ASSERT(term[1] == 1); + TEST_ASSERT(term[2] == 2); + TEST_ASSERT(term[3] == 3); + + return NULL; +} + +// Test that only handlers poped with execute argument set to true are +// executed +static void *thread2(void *args) { + int count = 0; + + memset(term, -1, sizeof(term)); + + pthread_cleanup_push(term_0, NULL); + pthread_cleanup_push(term_1, NULL); + pthread_cleanup_push(term_2, NULL); + pthread_cleanup_push(term_3, NULL); + + for (count = 0; count < 100; count++) { + // Simulate some work + usleep(1000); + } + + pthread_cleanup_pop(0); + pthread_cleanup_pop(1); + pthread_cleanup_pop(0); + pthread_cleanup_pop(1); + + TEST_ASSERT(term[0] == 0); + TEST_ASSERT(term[1] == -1); + TEST_ASSERT(term[2] == 2); + TEST_ASSERT(term[3] == -1); + + pthread_exit(NULL); +} + +// Test that pthread_exit execute the cleanups +static void *thread3(void *args) { + int count = 0; + + memset(term, -1, sizeof(term)); + + pthread_cleanup_push(term_0, NULL); + pthread_cleanup_push(term_1, NULL); + pthread_cleanup_push(term_2, NULL); + pthread_cleanup_push(term_3, NULL); + + for (count = 0; count < 100; count++) { + // Simulate some work + usleep(1000); + + if (count == 50) { + pthread_exit(NULL); + } + } + + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + + // This point is never reached + TEST_ASSERT(0); + + pthread_exit(NULL); +} + +// Test that when exit from thread with return don't execute the cleanups +static void *thread4(void *args) { + int count = 0; + + memset(term, -1, sizeof(term)); + + pthread_cleanup_push(term_0, NULL); + pthread_cleanup_push(term_1, NULL); + pthread_cleanup_push(term_2, NULL); + pthread_cleanup_push(term_3, NULL); + + for (count = 0; count < 100; count++) { + // Simulate some work + usleep(1000); + + if (count == 50) { + return NULL; + } + } + + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + + // This point is never reached + TEST_ASSERT(0); + + return NULL; +} + +TEST_CASE("pthread cleanup", "[pthread]") { + pthread_attr_t attr; + pthread_t th; + int ret; + + pthread_attr_init(&attr); + + // Test that handlers are called in reverse order + ret = pthread_create(&th, &attr, thread1, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_join(th, NULL); + TEST_ASSERT(ret == 0); + + // Test that only handlers poped with execute argument set to true are + // executed + ret = pthread_create(&th, &attr, thread2, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_join(th, NULL); + TEST_ASSERT(ret == 0); + + // Test that pthread_exit execute the cleanups + ret = pthread_create(&th, &attr, thread3, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_join(th, NULL); + TEST_ASSERT(ret == 0); + + TEST_ASSERT(term[0] == 0); + TEST_ASSERT(term[1] == 1); + TEST_ASSERT(term[2] == 2); + TEST_ASSERT(term[3] == 3); + + // Test that when exit from thread with return don't execute the cleanups + ret = pthread_create(&th, &attr, thread4, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_join(th, NULL); + TEST_ASSERT(ret == 0); + + TEST_ASSERT(term[0] == -1); + TEST_ASSERT(term[1] == -1); + TEST_ASSERT(term[2] == -1); + TEST_ASSERT(term[3] == -1); + + ret = pthread_attr_destroy(&attr); + TEST_ASSERT(ret == 0); +} diff --git a/libiot/pthread/test/pthread-cond.c b/libiot/pthread/test/pthread-cond.c new file mode 100644 index 0000000..8e1ce41 --- /dev/null +++ b/libiot/pthread/test/pthread-cond.c @@ -0,0 +1,107 @@ +#include "unity.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include <pthread.h> + +#include <sys/delay.h> + +#define NUM_THREADS 3 +#define COUNT_LIMIT 12 +#define TCOUNT 10 + +static int count = 0; +static pthread_t threads[NUM_THREADS]; +static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t count_threshold_cv = PTHREAD_COND_INITIALIZER; + +static void *inc_count(void *args) { + int i; + int ret; + + for (i=0; i< TCOUNT; i++) { + ret = pthread_mutex_lock(&count_mutex); + TEST_ASSERT(ret == 0); + + count++; + + // If condition is reached signal condition + if (count == COUNT_LIMIT) { + ret = pthread_cond_signal(&count_threshold_cv); + TEST_ASSERT(ret == 0); + } + + ret = pthread_mutex_unlock(&count_mutex); + TEST_ASSERT(ret == 0); + + // Simulate some work + usleep(1000); + } + + return NULL; + } + +static void *watch_count(void *args) { + int ret; + + ret = pthread_mutex_lock(&count_mutex); + TEST_ASSERT(ret == 0); + + while (count < COUNT_LIMIT) { + ret = pthread_cond_wait(&count_threshold_cv, &count_mutex); + TEST_ASSERT(ret == 0); + } + + count += 125; + TEST_ASSERT (count == 125 + COUNT_LIMIT); + + ret = pthread_mutex_unlock(&count_mutex); + TEST_ASSERT(ret == 0); + + return NULL; +} + +TEST_CASE("pthread conditions", "[pthread]") { + pthread_attr_t attr; + int i, ret; + + // Initialize mutex and condition variable objects + ret = pthread_mutex_init(&count_mutex, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_cond_init(&count_threshold_cv, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_attr_init(&attr); + TEST_ASSERT(ret == 0); + + ret = pthread_attr_setstacksize(&attr, 10240); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[0], &attr, watch_count, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[1], &attr, inc_count, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[2], &attr, inc_count, NULL); + TEST_ASSERT(ret == 0); + + // Wait for all threads completion + for (i=0; i< NUM_THREADS; i++) { + ret = pthread_join(threads[i], NULL); + TEST_ASSERT(ret == 0); + } + + // Clean up + ret = pthread_attr_destroy(&attr); + TEST_ASSERT(ret == 0); + + ret = pthread_mutex_destroy(&count_mutex); + TEST_ASSERT(ret == 0); + + ret = pthread_cond_destroy(&count_threshold_cv); + TEST_ASSERT(ret == 0); +} diff --git a/libiot/pthread/test/pthread-join.c b/libiot/pthread/test/pthread-join.c new file mode 100644 index 0000000..ba5f976 --- /dev/null +++ b/libiot/pthread/test/pthread-join.c @@ -0,0 +1,85 @@ +#include "unity.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include <pthread.h> + +#include <sys/delay.h> + +#define NUM_THREADS 2 + +static pthread_t threads[NUM_THREADS]; + +static void *thread1(void *args) { + int count = 0; + + for (count = 0; count < 100; count++) { + // Simulate some work + usleep(1000); + } + + int *ret = malloc(sizeof(int)); + *ret = count; + + pthread_exit(ret); + } + +static void *thread2(void *args) { + int count; + + for (count = 0; count < 50; count++) { + // Simulate some work + usleep(1000); + } + + int *ret = malloc(sizeof(int)); + *ret = count; + + pthread_exit(ret); + } + + +TEST_CASE("pthread join", "[pthread]") { + pthread_attr_t attr; + int i, ret; + int *res; + + ret = pthread_attr_init(&attr); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[0], &attr, thread1, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[1], &attr, thread2, NULL); + TEST_ASSERT(ret == 0); + + // Wait for all threads completion + for (i=0; i< NUM_THREADS; i++) { + ret = pthread_join(threads[i], (void **)&res); + TEST_ASSERT(ret == 0); + + if (i == 0) { + TEST_ASSERT(*res == 100); + } else if (i == 1) { + TEST_ASSERT(*res == 50); + } + + free(res); + } + + // Check that a detached thread is not joinable + ret = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[0], &attr, thread1, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_join(threads[0], (void **)&res); + TEST_ASSERT(ret == EINVAL); + + // Clean up + ret = pthread_attr_destroy(&attr); + TEST_ASSERT(ret == 0); +} diff --git a/libiot/pthread/test/pthread-once.c b/libiot/pthread/test/pthread-once.c new file mode 100644 index 0000000..d3a3db6 --- /dev/null +++ b/libiot/pthread/test/pthread-once.c @@ -0,0 +1,68 @@ +#include "unity.h" + +#include <pthread.h> +#include <sys/delay.h> + +#define NUM_THREADS 2 + +static pthread_t threads[NUM_THREADS]; + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static int execs; + +static void init() { + int ret; + + ret = pthread_mutex_lock(&mutex); + TEST_ASSERT(ret == 0); + + execs++; + + ret = pthread_mutex_unlock(&mutex); + TEST_ASSERT(ret == 0); +} + +static void *thread1(void *args) { + int ret; + + ret = pthread_once(&once, init); + TEST_ASSERT(ret == 0); + + // Simulate some work + usleep(1000); + + pthread_exit(NULL); + } + +TEST_CASE("pthread once", "[pthread]") { + pthread_attr_t attr; + int i, ret; + + ret = pthread_attr_init(&attr); + TEST_ASSERT(ret == 0); + + ret = pthread_mutex_init(&mutex, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[0], &attr, thread1, NULL); + TEST_ASSERT(ret == 0); + + ret = pthread_create(&threads[1], &attr, thread1, NULL); + TEST_ASSERT(ret == 0); + + // Wait for all threads completion + for (i=0; i< NUM_THREADS; i++) { + ret = pthread_join(threads[i], NULL); + TEST_ASSERT(ret == 0); + } + + TEST_ASSERT(execs == 1); + + // Clean up + ret = pthread_attr_destroy(&attr); + TEST_ASSERT(ret == 0); + + ret = pthread_mutex_destroy(&mutex); + TEST_ASSERT(ret == 0); +} |
