This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via c6ff6eadd9601eb33b28a9999b5fab6d3221ed44 (commit) from a962dc8dcd50368da71a96ace478630c55d7401c (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/c6ff6eadd9601eb33b28a9999b5fab6d3221e...
commit c6ff6eadd9601eb33b28a9999b5fab6d3221ed44 Author: Cyril Hrubis metan@ucw.cz Date: Sat Aug 11 22:15:02 2012 +0200
tests: More work on the test framework.
Added message passing layer + few fixes.
diff --git a/tests/framework/Makefile b/tests/framework/Makefile index 6be6899..901a4fe 100644 --- a/tests/framework/Makefile +++ b/tests/framework/Makefile @@ -8,7 +8,7 @@ LDFLAGS+=-L. LDLIBS+=-ltst_preload -ldl CFLAGS+=
-test: tst_test.o tst_job.o +test: tst_test.o tst_job.o tst_msg.o
APPS=test
diff --git a/tests/framework/test.c b/tests/framework/test.c index da3f13e..f3d5356 100644 --- a/tests/framework/test.c +++ b/tests/framework/test.c @@ -28,6 +28,9 @@
int success_fn(void) { + tst_report(0, "This test does nothing"); + tst_report(0, "But successfully"); + return TST_SUCCESS; }
@@ -50,12 +53,19 @@ int stack_overflow_fn(void)
int timeout_fn(void) { - sleep(10000); + tst_report(0, "Sleeping for ten seconds"); + sleep(10); return TST_SUCCESS; }
int temp_dir_fn(void) { + char buf[256], *res; + + /* log current working directory */ + res = getcwd(buf, sizeof(buf)); + tst_report(0, "CWD is '%s'", res); + return TST_SUCCESS; }
@@ -63,9 +73,13 @@ int malloc_leak_fn(void) { void *p;
- p = malloc(1); + p = malloc(4); p = malloc(3);
+ free(p); + + tst_report(0, "Leaking 1 chunks 4 bytes total"); + return TST_SUCCESS; }
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c index 17166a7..34e0357 100644 --- a/tests/framework/tst_job.c +++ b/tests/framework/tst_job.c @@ -29,11 +29,17 @@ #include <string.h> #include <sys/types.h> #include <sys/wait.h> +#include <stdarg.h>
#include "tst_preload.h" #include "tst_test.h" #include "tst_job.h"
+/* + * Once we child forks to do a job, this points to its job structure. + */ +static struct tst_job *my_job = NULL; + static void start_test(struct tst_job *job) { (void)job; @@ -56,41 +62,42 @@ static void stop_test(struct tst_job *job) { const char *name = job->test->name; int sec, nsec; + const char *result = "";
to_time(&sec, &nsec, &job->start_time, &job->stop_time);
switch (job->result) { case TST_SUCCESS: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;32mSUCCESSe[0m (duration %i.%05is)n", - name, sec, nsec); + result = "e[1;32mSUCCESSe[0m"; break; case TST_INTERR: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;31mINTERNAL ERRORe[0m (duration %i.%05is)n", - name, sec, nsec); + result = "e[1;31mINTERNAL ERRORe[0m"; break; case TST_SIGSEGV: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;31mSEGFAULTe[0m (duration %i.%05is)n", - name, sec, nsec); + result = "e[1;31mSEGFAULTe[0m"; break; case TST_TIMEOUT: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;35mTIMEOUTe[0m (duration %i.%05is}n", - name, sec, nsec); + result = "e[1;35mTIMEOUTe[0m"; break; case TST_MEMLEAK: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;33mMEMLEAKe[0m (duration %i.%05is}n", - name, sec, nsec); + result = "e[1;33mMEMLEAKe[0m"; break; case TST_FAILED: - fprintf(stderr, "Test e[1;37m%se[0m finished with " - "e[1;31mFAILUREe[0m (duration %i.%05is)n", - name, sec, nsec); + result = "e[1;31mFAILUREe[0m"; break; } + + fprintf(stderr, "Test e[1;37m%se[0m finished with %s " + "(duration %i.%09is, cputime %i.%09is)n", + name, result, sec, nsec, + (int)job->cpu_time.tv_sec, + (int)job->cpu_time.tv_nsec); + + if (job->result == TST_MEMLEAK) + tst_malloc_print(&job->malloc_stats); + + /* Now print test message store */ + tst_msg_print(&job->store); }
/* @@ -176,10 +183,35 @@ static void read_timespec(struct tst_job *job, struct timespec *time) time->tv_nsec = *(long*)(ptr); }
-static void child_write(struct tst_job *job, char ch) +static void child_write(struct tst_job *job, char ch, void *ptr, ssize_t size) { if (write(job->pipefd, &ch, 1) != 1) tst_warn("child write() failed: %s", strerror(errno)); + + if (ptr != NULL) { + if (write(job->pipefd, ptr, size) != size) + tst_warn("child write() failed: %s", strerror(errno)); + } +} + +int tst_report(int level, const char *fmt, ...) +{ + va_list va; + int ret; + char buf[258]; + + va_start(va, fmt); + ret = vsnprintf(buf+3, sizeof(buf) - 3, fmt, va); + va_end(va); + + buf[0] = 'm'; + buf[1] = level; + ((unsigned char*)buf)[2] = ret > 255 ? 255 : ret + 1; + + if (my_job != NULL) + write(my_job->pipefd, buf, (int)buf[2] + 3); + + return ret; }
void tst_job_run(struct tst_job *job) @@ -187,10 +219,13 @@ void tst_job_run(struct tst_job *job) int ret; char template[256]; int pipefd[2]; - + /* Write down starting time of the test */ clock_gettime(CLOCK_MONOTONIC, &job->start_time);
+ /* Prepare the test message store */ + tst_msg_init(&job->store); + start_test(job);
if (pipe(pipefd)) { @@ -211,6 +246,7 @@ void tst_job_run(struct tst_job *job) case 0: close(pipefd[0]); job->pipefd = pipefd[1]; + my_job = job; break; default: close(pipefd[1]); @@ -243,17 +279,13 @@ void tst_job_run(struct tst_job *job) ret = job->test->tst_fn();
if (job->test->flags & TST_MALLOC_CHECK) { - size_t size; - unsigned int chunks; - tst_malloc_check_stop(); - - tst_malloc_check_report(&size, &chunks); - - if (size != 0 && ret == TST_SUCCESS) + tst_malloc_check_report(&job->malloc_stats); + + child_write(job, 's', &job->malloc_stats, sizeof(job->malloc_stats)); + + if (job->malloc_stats.lost_chunks != 0 && ret == TST_SUCCESS) ret = TST_MEMLEAK; - - //TODO message? }
/* Send process cpu time to parent */ @@ -265,13 +297,38 @@ void tst_job_run(struct tst_job *job) remove_tmpdir(template);
/* Send the parent we are done */ - child_write(job, 'x'); + child_write(job, 'x', NULL, 0);
close(job->pipefd);
exit(ret); }
+static void parent_read_msg(struct tst_job *job) +{ + unsigned char header[2]; + + if (read(job->pipefd, header, sizeof(header)) != sizeof(header)) + tst_warn("parent: read(message header) failed: %s", + strerror(errno)); + + char buf[header[1]]; + + if (read(job->pipefd, buf, sizeof(buf)) != sizeof(buf)) + tst_warn("parent: read(message) failed: %s", strerror(errno)); + + /* null-terminated the string, to be extra sure */ + buf[header[1] - 1] = '0'; + + tst_msg_append(&job->store, header[0], buf); +} + +static void parent_read(struct tst_job *job, void *ptr, ssize_t size) +{ + if (read(job->pipefd, ptr, size) != size) + tst_warn("parent: read(): %s", strerror(errno)); +} + void tst_job_wait(struct tst_job *job) { int status, ret; @@ -309,6 +366,18 @@ void tst_job_wait(struct tst_job *job) case 'C': read_timespec(job, &job->cpu_time); break; + /* test message as generated by tst_report() */ + case 'm': + parent_read_msg(job); + break; + /* malloc stats */ + case 's': + parent_read(job, &job->malloc_stats, + sizeof(job->malloc_stats)); + break; + default: + //TODO: internal error + break; } }
diff --git a/tests/framework/tst_job.h b/tests/framework/tst_job.h index 28ec869..c18cae8 100644 --- a/tests/framework/tst_job.h +++ b/tests/framework/tst_job.h @@ -22,7 +22,7 @@
/*
- Test job is instance of running test. + Test job is an instance of running test.
*/
@@ -31,6 +31,9 @@
#include <time.h>
+#include "tst_msg.h" +#include "tst_preload.h" + struct tst_test;
struct tst_job { @@ -58,8 +61,17 @@ struct tst_job {
/* test pid */ int pid; - /* result */ - int result; + + /* test result */ + int result; + + /* + * test malloc statistics, filled if TST_MALLOC_CHECK was set. + */ + struct malloc_stats malloc_stats; + + /* store for test messages */ + struct tst_msg_store store; };
/* diff --git a/tests/framework/tst_job.h b/tests/framework/tst_msg.c similarity index 62% copy from tests/framework/tst_job.h copy to tests/framework/tst_msg.c index 28ec869..2d46338 100644 --- a/tests/framework/tst_job.h +++ b/tests/framework/tst_msg.c @@ -20,58 +20,61 @@ * * *****************************************************************************/
- /* - - Test job is instance of running test. +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h>
- */ +#include "tst_test.h"
-#ifndef TST_JOB_H -#define TST_JOB_H +#include "tst_msg.h"
-#include <time.h> +void tst_msg_clear(struct tst_msg_store *self) +{ + struct tst_msg *msg, *prev = NULL;
-struct tst_test; + for (msg = self->first; msg != NULL; msg = msg->next) { + free(prev); + prev = msg; + }
-struct tst_job { - const struct tst_test *test; - - /* - * Pipe fd. - * - * In parent this points to the read side of the pipe so the parent - * recieves data from child. - * - * In child this points to the write side of the pipe so child can - * send data to parent. - */ - int pipefd; - - int running:1; - - /* test execution time */ - struct timespec start_time; - struct timespec stop_time; + free(prev); + + self->first = NULL; + self->last = NULL; +} + +int tst_msg_append(struct tst_msg_store *self, int type, const char *msg_text) +{ + size_t len = strlen(msg_text); + struct tst_msg *msg; - /* test cpu time */ - struct timespec cpu_time; + msg = malloc(sizeof(struct tst_msg) + len + 1); + + if (msg == NULL) { + tst_warn("tst_msg: malloc() failed: %s", strerror(errno)); + return 1; + } + + msg->type = type; + msg->next = NULL; + strcpy(msg->msg, msg_text);
- /* test pid */ - int pid; - /* result */ - int result; -}; + if (self->last == NULL) { + self->first = msg; + self->last = msg; + } else { + self->last->next = msg; + self->last = msg; + }
-/* - * Runs a test job as a separate process. - * - * The test field must point to correct test. - */ -void tst_job_run(struct tst_job *job); + return 0; +}
-/* - * Waits for the test to finish. - */ -void tst_job_wait(struct tst_job *job); +void tst_msg_print(struct tst_msg_store *self) +{ + struct tst_msg *msg;
-#endif /* TST_JOB_H */ + for (msg = self->first; msg != NULL; msg = msg->next) + fprintf(stderr, "%i: %sn", msg->type, msg->msg); +} diff --git a/tests/framework/tst_preload.h b/tests/framework/tst_msg.h similarity index 71% copy from tests/framework/tst_preload.h copy to tests/framework/tst_msg.h index d1eca76..a6a290a 100644 --- a/tests/framework/tst_preload.h +++ b/tests/framework/tst_msg.h @@ -20,22 +20,48 @@ * * *****************************************************************************/
-#ifndef TST_PRELOAD_H -#define TST_PRELOAD_H + /* + + Code to store test messages into a data structure. + + */ + +#ifndef TST_MSG_H +#define TST_MSG_H + +struct tst_msg { + struct tst_msg *next; + int type; + char msg[]; +}; + +struct tst_msg_store { + struct tst_msg *first; + struct tst_msg *last; +}; + +/* + * Initalize message store. + */ +static inline void tst_msg_init(struct tst_msg_store *self) +{ + self->first = NULL; + self->last = NULL; +}
/* - * Starts malloc check. + * Cleans msg store, frees memory. */ -void tst_malloc_check_start(void); +void tst_msg_clear(struct tst_msg_store *self);
/* - * Stops malloc check. + * Appends test message to the store. */ -void tst_malloc_check_stop(void); +int tst_msg_append(struct tst_msg_store *self, int type, const char *msg);
/* - * Reports current malloc status. + * Prints messages in the store. */ -void tst_malloc_check_report(size_t *size, unsigned int *chunks); +void tst_msg_print(struct tst_msg_store *self);
-#endif /* TST_PRELOAD_H */ +#endif /* TST_MSG_H */ diff --git a/tests/framework/tst_preload.c b/tests/framework/tst_preload.c index 4a8f9bb..1ba320e 100644 --- a/tests/framework/tst_preload.c +++ b/tests/framework/tst_preload.c @@ -49,13 +49,17 @@ struct chunk { };
struct chunk chunks[MAX_CHUNKS + 1]; -static size_t total_size; -static unsigned int total_chunks; +static size_t cur_size = 0; +static unsigned int cur_chunks = 0; +static size_t total_size = 0; +static unsigned int total_chunks = 0;
-void tst_malloc_check_report(size_t *size, unsigned int *chunks) +void tst_malloc_check_report(struct malloc_stats *stats) { - *size = total_size; - *chunks = total_chunks; + stats->lost_size = cur_size; + stats->lost_chunks = cur_chunks; + stats->total_size = total_size; + stats->total_chunks = total_chunks; }
static void add_chunk(size_t size, void *ptr) @@ -66,8 +70,10 @@ static void add_chunk(size_t size, void *ptr) if (chunks[i].size == 0) { chunks[i].size = size; chunks[i].ptr = ptr; + cur_size += size; + cur_chunks++; total_size += size; - total_chunks += 1; + total_chunks++; return; } } @@ -85,8 +91,8 @@ static void rem_chunk(void *ptr) break;
if (chunks[i].ptr == ptr) { - total_size -= chunks[i].size; - total_chunks -= 1; + cur_size -= chunks[i].size; + cur_chunks--; chunks[i].size = 0; chunks[i].ptr = NULL; @@ -127,3 +133,10 @@ void free(void *ptr)
real_free(ptr); } + +void tst_malloc_print(struct malloc_stats *stats) +{ + fprintf(stderr, "Total size %zu chunks %u, lost size %zu chunks %un", + stats->total_size, stats->total_chunks, + stats->lost_size, stats->lost_chunks); +} diff --git a/tests/framework/tst_preload.h b/tests/framework/tst_preload.h index d1eca76..36bb41a 100644 --- a/tests/framework/tst_preload.h +++ b/tests/framework/tst_preload.h @@ -33,9 +33,26 @@ void tst_malloc_check_start(void); */ void tst_malloc_check_stop(void);
+struct malloc_stats { + size_t total_size; + unsigned int total_chunks; + + size_t lost_size; + unsigned int lost_chunks; +}; + /* * Reports current malloc status. + * + * Size and chunks are filled with sum and number of currently allocated + * chunks, i.e, chunks that were allocated but not freed. The allocs is + * filled with number of allocations done. + */ +void tst_malloc_check_report(struct malloc_stats *stats); + +/* + * Prints malloc statistics. */ -void tst_malloc_check_report(size_t *size, unsigned int *chunks); +void tst_malloc_print(struct malloc_stats *stats);
#endif /* TST_PRELOAD_H */ diff --git a/tests/framework/tst_test.c b/tests/framework/tst_test.c index 9359f1c..d04caf5 100644 --- a/tests/framework/tst_test.c +++ b/tests/framework/tst_test.c @@ -23,29 +23,13 @@ #include <unistd.h> #include <stdlib.h> #include <stdio.h> -#include <stdarg.h> #include <errno.h> #include <string.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <ctype.h> -#include <dirent.h> +#include <stdarg.h>
#include "tst_job.h" #include "tst_test.h"
-int tst_report(int level, const char *fmt, ...) -{ - va_list va; - int ret; - - va_start(va, fmt); - ret = vfprintf(stderr, fmt, va); - va_end(va); - - return ret; -} - int tst_warn(const char *fmt, ...) { va_list va; @@ -66,7 +50,10 @@ static int run_test(const struct tst_test *test)
tst_job_run(&job); tst_job_wait(&job); - + + /* Free the test message store */ + tst_msg_clear(&job.store); + return job.result; }
-----------------------------------------------------------------------
Summary of changes: tests/framework/Makefile | 2 +- tests/framework/test.c | 18 +++- tests/framework/tst_job.c | 129 +++++++++++++++----- tests/framework/tst_job.h | 18 +++- .../loaders_example.c => tests/framework/tst_msg.c | 65 +++++++---- .../GP_Backends.h => tests/framework/tst_msg.h | 47 +++++--- tests/framework/tst_preload.c | 29 +++-- tests/framework/tst_preload.h | 19 +++- tests/framework/tst_test.c | 23 +--- 9 files changed, 249 insertions(+), 101 deletions(-) copy demos/c_simple/loaders_example.c => tests/framework/tst_msg.c (65%) copy include/backends/GP_Backends.h => tests/framework/tst_msg.h (71%)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.