Added simple unit/integration test framework and corresponding test program.

Added a simple C-based test framework and an example program
that uses it to run through some simple unit tests.

This is new code inspired primarily by the approaches of Google
Test, Boost Test, JUnit and TestNG. Factors of others were also
considered during design and implementation.

Signed-off-by: Jon A. Cruz <jonc@osg.samsung.com>
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
Jon A. Cruz
2015-07-02 23:36:44 -07:00
committed by Pekka Paalanen
parent 492c12fb8b
commit 5a75a41d07
17 changed files with 4524 additions and 3 deletions
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
/*
* Common main() for test programs.
*/
#include <stdio.h>
#include <stdlib.h>
#include "zunitc/zunitc.h"
int
main(int argc, char* argv[])
{
bool helped = false;
int rc = zuc_initialize(&argc, argv, &helped);
if ((rc == EXIT_SUCCESS) && !helped) {
/* Stop if any unrecognized parameters were encountered. */
if (argc > 1) {
printf("%s: unrecognized option '%s'\n",
argv[0], argv[1]);
printf("Try '%s --help' for more information.\n",
argv[0]);
rc = EXIT_FAILURE;
} else {
rc = ZUC_RUN_TESTS();
}
}
zuc_cleanup();
return rc;
}
+404
View File
@@ -0,0 +1,404 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include "zuc_base_logger.h"
#include <memory.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include "zuc_event_listener.h"
#include "zuc_types.h"
#include "shared/zalloc.h"
/* a few sequences for rudimentary ANSI graphics. */
#define CSI_GRN "\x1b[0;32m"
#define CSI_RED "\x1b[0;31m"
#define CSI_YLW "\x1b[0;33m"
#define CSI_RST "\x1b[m"
/**
* Logical mappings of style levels.
*/
enum style_level {
STYLE_GOOD,
STYLE_WARN,
STYLE_BAD
};
/**
* Structure for internal context.
*/
struct base_data {
bool use_color;
};
/**
* Prints a formatted string with optional ANSI coloring.
*
* @param use_color true to colorize the output, false to output normally.
* @param slevel the logical type to color for.
* @param fmt the format string to print with.
*/
static void
styled_printf(bool use_color, enum style_level slevel, const char *fmt, ...);
static void
destroy(void *data);
static void
pre_run(void *data, int pass_count, int pass_num, int seed, const char *filter);
static void
run_started(void *data, int live_case_count,
int live_test_count, int disabled_count);
static void
run_ended(void *data, int case_count, struct zuc_case **cases,
int live_case_count, int live_test_count, int total_passed,
int total_failed, int total_disabled, long total_elapsed);
static void
case_started(void *data, struct zuc_case *test_case, int live_test_count,
int disabled_count);
static void
case_ended(void *data, struct zuc_case *test_case);
static void
test_started(void *data, struct zuc_test *test);
static void
test_ended(void *data, struct zuc_test *test);
static void
check_triggered(void *data, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2,
const char *expr1, const char *expr2);
struct zuc_event_listener *
zuc_base_logger_create(void)
{
struct zuc_event_listener *listener =
zalloc(sizeof(struct zuc_event_listener));
listener->data = zalloc(sizeof(struct base_data));
listener->destroy = destroy;
listener->pre_run = pre_run;
listener->run_started = run_started;
listener->run_ended = run_ended;
listener->case_started = case_started;
listener->case_ended = case_ended;
listener->test_started = test_started;
listener->test_ended = test_ended;
listener->check_triggered = check_triggered;
return listener;
}
void
styled_printf(bool use_color, enum style_level slevel, const char *fmt, ...)
{
va_list argp;
if (use_color)
switch (slevel) {
case STYLE_GOOD:
printf(CSI_GRN);
break;
case STYLE_WARN:
printf(CSI_YLW);
break;
case STYLE_BAD:
printf(CSI_RED);
break;
default:
break;
}
va_start(argp, fmt);
vprintf(fmt, argp);
va_end(argp);
if (use_color)
printf(CSI_RST);
}
void
destroy(void *data)
{
free(data);
}
void
pre_run(void *data, int pass_count, int pass_num, int seed, const char *filter)
{
struct base_data *bdata = data;
bdata->use_color = isatty(fileno(stdout))
&& getenv("TERM") && strcmp(getenv("TERM"), "dumb");
if (pass_count > 1)
printf("\nRepeating all tests (iteration %d) . . .\n\n",
pass_num);
if (filter && filter[0])
styled_printf(bdata->use_color, STYLE_WARN,
"Note: test filter = %s\n",
filter);
if (seed > 0)
styled_printf(bdata->use_color, STYLE_WARN,
"Note: Randomizing tests' orders"
" with a seed of %u .\n",
seed);
}
void
run_started(void *data, int live_case_count,
int live_test_count, int disabled_count)
{
struct base_data *bdata = data;
styled_printf(bdata->use_color, STYLE_GOOD, "[==========]");
printf(" Running %d %s from %d test %s.\n",
live_test_count,
(live_test_count == 1) ? "test" : "tests",
live_case_count,
(live_case_count == 1) ? "case" : "cases");
}
void
run_ended(void *data, int case_count, struct zuc_case **cases,
int live_case_count, int live_test_count, int total_passed,
int total_failed, int total_disabled, long total_elapsed)
{
struct base_data *bdata = data;
styled_printf(bdata->use_color, STYLE_GOOD, "[==========]");
printf(" %d %s from %d test %s ran. (%ld ms)\n",
live_test_count,
(live_test_count == 1) ? "test" : "tests",
live_case_count,
(live_case_count == 1) ? "case" : "cases",
total_elapsed);
if (total_passed) {
styled_printf(bdata->use_color, STYLE_GOOD, "[ PASSED ]");
printf(" %d %s.\n", total_passed,
(total_passed == 1) ? "test" : "tests");
}
if (total_failed) {
int case_num;
styled_printf(bdata->use_color, STYLE_BAD, "[ FAILED ]");
printf(" %d %s, listed below:\n",
total_failed, (total_failed == 1) ? "test" : "tests");
for (case_num = 0; case_num < case_count; ++case_num) {
int i;
for (i = 0; i < cases[case_num]->test_count; ++i) {
struct zuc_test *curr =
cases[case_num]->tests[i];
if (curr->failed || curr->fatal) {
styled_printf(bdata->use_color,
STYLE_BAD,
"[ FAILED ]");
printf(" %s.%s\n",
cases[case_num]->name,
curr->name);
}
}
}
}
if (total_failed || total_disabled)
printf("\n");
if (total_failed)
printf(" %d FAILED %s\n",
total_failed,
(total_failed == 1) ? "TEST" : "TESTS");
if (total_disabled)
styled_printf(bdata->use_color, STYLE_WARN,
" YOU HAVE %d DISABLED %s\n",
total_disabled,
(total_disabled == 1) ? "TEST" : "TESTS");
}
void
case_started(void *data, struct zuc_case *test_case, int live_test_count,
int disabled_count)
{
struct base_data *bdata = data;
styled_printf(bdata->use_color, STYLE_GOOD, "[----------]");
printf(" %d %s from %s.\n",
live_test_count,
(live_test_count == 1) ? "test" : "tests",
test_case->name);
}
void
case_ended(void *data, struct zuc_case *test_case)
{
struct base_data *bdata = data;
styled_printf(bdata->use_color, STYLE_GOOD, "[----------]");
printf(" %d %s from %s (%ld ms)\n",
test_case->test_count,
(test_case->test_count == 1) ? "test" : "tests",
test_case->name,
test_case->elapsed);
printf("\n");
}
void
test_started(void *data, struct zuc_test *test)
{
struct base_data *bdata = data;
styled_printf(bdata->use_color, STYLE_GOOD, "[ RUN ]");
printf(" %s.%s\n", test->test_case->name, test->name);
}
void
test_ended(void *data, struct zuc_test *test)
{
struct base_data *bdata = data;
if (test->failed || test->fatal) {
styled_printf(bdata->use_color, STYLE_BAD, "[ FAILED ]");
printf(" %s.%s (%ld ms)\n",
test->test_case->name, test->name, test->elapsed);
} else {
styled_printf(bdata->use_color, STYLE_GOOD, "[ OK ]");
printf(" %s.%s (%ld ms)\n",
test->test_case->name, test->name, test->elapsed);
}
}
const char *
zuc_get_opstr(enum zuc_check_op op)
{
switch (op) {
case ZUC_OP_EQ:
return "=";
break;
case ZUC_OP_NE:
return "!=";
break;
case ZUC_OP_GE:
return ">=";
break;
case ZUC_OP_GT:
return ">";
break;
case ZUC_OP_LE:
return "<=";
break;
case ZUC_OP_LT:
return "<";
break;
default:
return "???";
}
}
void
check_triggered(void *data, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2,
const char *expr1, const char *expr2)
{
switch (op) {
case ZUC_OP_TRUE:
printf("%s:%d: error: Value of: %s\n", file, line, expr1);
printf(" Actual: false\n");
printf("Expected: true\n");
break;
case ZUC_OP_FALSE:
printf("%s:%d: error: Value of: %s\n", file, line, expr1);
printf(" Actual: true\n");
printf("Expected: false\n");
break;
case ZUC_OP_NULL:
printf("%s:%d: error: Value of: %s\n", file, line, expr1);
printf(" Actual: %p\n", (void *)val1);
printf("Expected: %p\n", NULL);
break;
case ZUC_OP_NOT_NULL:
printf("%s:%d: error: Value of: %s\n", file, line, expr1);
printf(" Actual: %p\n", (void *)val1);
printf("Expected: not %p\n", NULL);
break;
case ZUC_OP_EQ:
if (valtype == ZUC_VAL_CSTR) {
printf("%s:%d: error: Value of: %s\n", file, line,
expr2);
printf(" Actual: %s\n", (const char *)val2);
printf("Expected: %s\n", expr1);
printf("Which is: %s\n", (const char *)val1);
} else {
printf("%s:%d: error: Value of: %s\n", file, line,
expr2);
printf(" Actual: %ld\n", val2);
printf("Expected: %s\n", expr1);
printf("Which is: %ld\n", val1);
}
break;
case ZUC_OP_NE:
if (valtype == ZUC_VAL_CSTR) {
printf("%s:%d: error: ", file, line);
printf("Expected: (%s) %s (%s), actual: %s == %s\n",
expr1, zuc_get_opstr(op), expr2,
(char *)val1, (char *)val2);
} else {
printf("%s:%d: error: ", file, line);
printf("Expected: (%s) %s (%s), actual: %ld vs %ld\n",
expr1, zuc_get_opstr(op), expr2, val1, val2);
}
break;
case ZUC_OP_TERMINATE: {
char const *level = (val1 == 0) ? "error"
: (val1 == 1) ? "warning"
: "note";
printf("%s:%d: %s: %s\n", file, line, level, expr1);
break;
}
case ZUC_OP_TRACEPOINT:
printf("%s:%d: note: %s\n", file, line, expr1);
break;
default:
printf("%s:%d: error: ", file, line);
printf("Expected: (%s) %s (%s), actual: %ld vs %ld\n",
expr1, zuc_get_opstr(op), expr2, val1, val2);
}
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_BASE_LOGGER_H
#define ZUC_BASE_LOGGER_H
struct zuc_event_listener;
/**
* Creates a new logger that outputs data to console in the default
* format.
*/
struct zuc_event_listener *
zuc_base_logger_create(void);
#endif /* ZUC_BASE_LOGGER_H */
+427
View File
@@ -0,0 +1,427 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include "zuc_collector.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "shared/zalloc.h"
#include "zuc_event_listener.h"
#include "zunitc/zunitc_impl.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/**
* @file
* General handling of collecting events during testing to pass back to
* main tracking of fork()'d tests.
*
* @note implementation of zuc_process_message() is included here so that
* all child->parent IPC is in a single source file for easier maintenance
* and updating.
*/
/**
* Internal data struct for processing.
*/
struct collector_data
{
int *fd; /**< file descriptor to output to. */
struct zuc_test *test; /**< current test, or NULL. */
};
/**
* Stores an int32_t into the given buffer.
*
* @param ptr the buffer to store to.
* @param val the value to store.
* @return a pointer to the position in the buffer after the stored value.
*/
static char *
pack_int32(char *ptr, int32_t val);
/**
* Stores an intptr_t into the given buffer.
*
* @param ptr the buffer to store to.
* @param val the value to store.
* @return a pointer to the position in the buffer after the stored value.
*/
static char *
pack_intptr_t(char *ptr, intptr_t val);
/**
* Extracts a int32_t from the given buffer.
*
* @param ptr the buffer to extract from.
* @param val the value to set.
* @return a pointer to the position in the buffer after the extracted
* value.
*/
static char const *
unpack_int32(char const *ptr, int32_t *val);
/**
* Extracts a intptr_t from the given buffer.
*
* @param ptr the buffer to extract from.
* @param val the value to set.
* @return a pointer to the position in the buffer after the extracted
* value.
*/
static char const *
unpack_intptr_t(char const *ptr, intptr_t *val);
/**
* Extracts a length-prefixed string from the given buffer.
*
* @param ptr the buffer to extract from.
* @param str the value to set.
* @return a pointer to the position in the buffer after the extracted
* value.
*/
static char const *
unpack_string(char const *ptr, char **str);
/**
* Extracts an event from the given buffer.
*
* @param ptr the buffer to extract from.
* @param len the length of the given buffer.
* @return an event that was packed in the buffer
*/
static struct zuc_event *
unpack_event(char const *ptr, int32_t len);
/**
* Handles an event by either attaching it directly or sending it over IPC
* as needed.
*/
static void
store_event(struct collector_data *cdata,
enum zuc_event_type event_type, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2, const char *expr1, const char *expr2);
static void
destroy(void *data);
static void
test_started(void *data, struct zuc_test *test);
static void
test_ended(void *data, struct zuc_test *test);
static void
check_triggered(void *data, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2,
const char *expr1, const char *expr2);
static void
collect_event(void *data, char const *file, int line, const char *expr1);
struct zuc_event_listener *
zuc_collector_create(int *pipe_fd)
{
struct zuc_event_listener *listener =
zalloc(sizeof(struct zuc_event_listener));
listener->data = zalloc(sizeof(struct collector_data));
((struct collector_data *)listener->data)->fd = pipe_fd;
listener->destroy = destroy;
listener->test_started = test_started;
listener->test_ended = test_ended;
listener->check_triggered = check_triggered;
listener->collect_event = collect_event;
return listener;
}
char *
pack_int32(char *ptr, int32_t val)
{
memcpy(ptr, &val, sizeof(val));
return ptr + sizeof(val);
}
char *
pack_intptr_t(char *ptr, intptr_t val)
{
memcpy(ptr, &val, sizeof(val));
return ptr + sizeof(val);
}
static char *
pack_cstr(char *ptr, intptr_t val, int len)
{
if (val == 0) { /* a null pointer */
ptr = pack_int32(ptr, -1);
} else {
ptr = pack_int32(ptr, len);
memcpy(ptr, (const char *)val, len);
ptr += len;
}
return ptr;
}
void
destroy(void *data)
{
free(data);
}
void
test_started(void *data, struct zuc_test *test)
{
struct collector_data *cdata = data;
cdata->test = test;
}
void
test_ended(void *data, struct zuc_test *test)
{
struct collector_data *cdata = data;
cdata->test = NULL;
}
void
check_triggered(void *data, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2,
const char *expr1, const char *expr2)
{
struct collector_data *cdata = data;
if (op != ZUC_OP_TRACEPOINT)
store_event(cdata, ZUC_EVENT_IMMEDIATE, file, line, state, op,
valtype,
val1, val2, expr1, expr2);
}
void
collect_event(void *data, char const *file, int line, const char *expr1)
{
struct collector_data *cdata = data;
store_event(cdata, ZUC_EVENT_DEFERRED, file, line, ZUC_CHECK_OK,
ZUC_OP_TRACEPOINT, ZUC_VAL_INT,
0, 0, expr1, "");
}
void
store_event(struct collector_data *cdata,
enum zuc_event_type event_type, char const *file, int line,
enum zuc_fail_state state, enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1, intptr_t val2, const char *expr1, const char *expr2)
{
struct zuc_event *event = zalloc(sizeof(*event));
event->file = strdup(file);
event->line = line;
event->state = state;
event->op = op;
event->valtype = valtype;
event->val1 = val1;
event->val2 = val2;
if (valtype == ZUC_VAL_CSTR) {
if (val1)
event->val1 = (intptr_t)strdup((const char *)val1);
if (val2)
event->val2 = (intptr_t)strdup((const char *)val2);
}
event->expr1 = strdup(expr1);
event->expr2 = strdup(expr2);
zuc_attach_event(cdata->test, event, event_type, false);
if (*cdata->fd == -1) {
} else {
/* Need to pass it back */
int sent;
int count;
int expr1_len = strlen(expr1);
int expr2_len = strlen(expr2);
int val1_len =
((valtype == ZUC_VAL_CSTR) && val1) ?
strlen((char *)val1) : 0;
int val2_len =
((valtype == ZUC_VAL_CSTR) && val2) ?
strlen((char *)val2) : 0;
int file_len = strlen(file);
int len = (sizeof(int32_t) * 9) + file_len
+ (sizeof(intptr_t) * 2)
+ ((valtype == ZUC_VAL_CSTR) ?
(sizeof(int32_t) * 2) + val1_len + val2_len : 0)
+ expr1_len + expr2_len;
char *buf = zalloc(len);
char *ptr = pack_int32(buf, len - 4);
ptr = pack_int32(ptr, event_type);
ptr = pack_int32(ptr, file_len);
memcpy(ptr, file, file_len);
ptr += file_len;
ptr = pack_int32(ptr, line);
ptr = pack_int32(ptr, state);
ptr = pack_int32(ptr, op);
ptr = pack_int32(ptr, valtype);
if (valtype == ZUC_VAL_CSTR) {
ptr = pack_cstr(ptr, val1, val1_len);
ptr = pack_cstr(ptr, val2, val2_len);
} else {
ptr = pack_intptr_t(ptr, val1);
ptr = pack_intptr_t(ptr, val2);
}
ptr = pack_int32(ptr, expr1_len);
if (expr1_len) {
memcpy(ptr, expr1, expr1_len);
ptr += expr1_len;
}
ptr = pack_int32(ptr, expr2_len);
if (expr2_len) {
memcpy(ptr, expr2, expr2_len);
ptr += expr2_len;
}
sent = 0;
while (sent < len) {
count = write(*cdata->fd, buf, len);
if (count == -1)
break;
sent += count;
}
free(buf);
}
}
char const *
unpack_int32(char const *ptr, int32_t *val)
{
memcpy(val, ptr, sizeof(*val));
return ptr + sizeof(*val);
}
char const *
unpack_intptr_t(char const *ptr, intptr_t *val)
{
memcpy(val, ptr, sizeof(*val));
return ptr + sizeof(*val);
}
char const *
unpack_string(char const *ptr, char **str)
{
int32_t len = 0;
ptr = unpack_int32(ptr, &len);
*str = zalloc(len + 1);
if (len)
memcpy(*str, ptr, len);
ptr += len;
return ptr;
}
static char const *
unpack_cstr(char const *ptr, char **str)
{
int32_t len = 0;
ptr = unpack_int32(ptr, &len);
if (len < 0) {
*str = NULL;
} else {
*str = zalloc(len + 1);
if (len)
memcpy(*str, ptr, len);
ptr += len;
}
return ptr;
}
struct zuc_event *
unpack_event(char const *ptr, int32_t len)
{
int32_t val = 0;
struct zuc_event *evt = zalloc(sizeof(*evt));
char const *tmp = unpack_string(ptr, &evt->file);
tmp = unpack_int32(tmp, &evt->line);
tmp = unpack_int32(tmp, &val);
evt->state = val;
tmp = unpack_int32(tmp, &val);
evt->op = val;
tmp = unpack_int32(tmp, &val);
evt->valtype = val;
if (evt->valtype == ZUC_VAL_CSTR) {
char *ptr = NULL;
tmp = unpack_cstr(tmp, &ptr);
evt->val1 = (intptr_t)ptr;
tmp = unpack_cstr(tmp, &ptr);
evt->val2 = (intptr_t)ptr;
} else {
tmp = unpack_intptr_t(tmp, &evt->val1);
tmp = unpack_intptr_t(tmp, &evt->val2);
}
tmp = unpack_string(tmp, &evt->expr1);
tmp = unpack_string(tmp, &evt->expr2);
return evt;
}
int
zuc_process_message(struct zuc_test *test, int fd)
{
char buf[4] = {};
int got = read(fd, buf, 4);
if (got == 4) {
enum zuc_event_type event_type = ZUC_EVENT_IMMEDIATE;
int32_t val = 0;
int32_t len = 0;
const char *tmp = NULL;
char *raw = NULL;
unpack_int32(buf, &len);
raw = zalloc(len);
got = read(fd, raw, len);
tmp = unpack_int32(raw, &val);
event_type = val;
struct zuc_event *evt = unpack_event(tmp, len - (tmp - raw));
zuc_attach_event(test, evt, event_type, true);
free(raw);
}
return got;
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_COLLECTOR_H
#define ZUC_COLLECTOR_H
struct zuc_event_listener;
struct zuc_test;
/**
* Creates a new instance of an even collector that will attatch events
* to the current test directly or via connection from child to parent.
*
* @param pipe_fd pointer to the file descriptor to use for communication if
* needed. If the value is -1 the events will be attached directly to the
* current test. Otherwise events will be passed back via IPC over this
* pipe with the expectation that the payload will be handled in the parent
* process via zuc_process_message().
* @return a new collector intance.
* @see zuc_process_message()
*/
struct zuc_event_listener *
zuc_collector_create(int *pipe_fd);
/**
* Reads events from the given pipe and processes them.
*
* @param test the currently active test to attache events for.
* @param pipe_fd the file descriptor of the pipe to read from.
* @return a positive value if a message was received, 0 if the end has
* been reached and -1 if an error has occurred.
*/
int
zuc_process_message(struct zuc_test *test, int pipe_fd);
#endif /* ZUC_COLLECTOR_H */
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_CONTEXT_H
#define ZUC_CONTEXT_H
#include "zuc_types.h"
struct zuc_slinked;
/**
* Internal context for processing.
* Collecting data members here minimizes use of globals.
*/
struct zuc_context {
int case_count;
struct zuc_case **cases;
bool fatal;
int repeat;
int random;
unsigned int seed;
bool spawn;
bool break_on_failure;
bool output_tap;
bool output_junit;
int fds[2];
char *filter;
struct zuc_slinked *listeners;
struct zuc_case *curr_case;
struct zuc_test *curr_test;
};
#endif /* ZUC_CONTEXT_H */
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_EVENT_H
#define ZUC_EVENT_H
#include <stdint.h>
#include "zunitc/zunitc_impl.h"
/**
*
*/
enum zuc_event_type
{
ZUC_EVENT_IMMEDIATE,
ZUC_EVENT_DEFERRED
};
/**
* Status enum for posted events.
*/
enum zuc_fail_state
{
ZUC_CHECK_OK, /**< no problem. */
ZUC_CHECK_SKIP, /**< runtime skip directive encountered. */
ZUC_CHECK_FAIL, /**< non-fatal check fails. */
ZUC_CHECK_FATAL, /**< fatal assertion/check fails. */
ZUC_CHECK_ERROR /**< internal level problem. */
};
/**
* Record of an event that occurs during testing such as assert macro
* failures.
*/
struct zuc_event
{
char *file;
int32_t line;
enum zuc_fail_state state;
enum zuc_check_op op;
enum zuc_check_valtype valtype;
intptr_t val1;
intptr_t val2;
char *expr1;
char *expr2;
struct zuc_event *next;
};
/**
* Attaches an event to the specified test.
*
* @param test the test to attach to.
* @param event the event to attach.
* @param event_type of event (immediate or deferred) to attach.
* @param transferred true if the event has been processed elsewhere and
* is being transferred for storage, false otherwise.
*/
void
zuc_attach_event(struct zuc_test *test, struct zuc_event *event,
enum zuc_event_type event_type, bool transferred);
#endif /* ZUC_EVENT_H */
+174
View File
@@ -0,0 +1,174 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_EVENT_HANDLER_H
#define ZUC_EVENT_HANDLER_H
#include <stdint.h>
#include "zuc_context.h"
#include "zuc_event.h"
struct zuc_test;
struct zuc_case;
/**
* Interface to allow components to process testing events as they occur.
*
* Event listeners that will stream output as testing progresses are often
* named "*_logger" whereas those that produce their output upon test run
* completion are named "*_reporter".
*/
struct zuc_event_listener {
/**
* User data pointer.
*/
void *data;
/**
* Destructor.
* @param data the user data associated with this instance.
*/
void (*destroy)(void *data);
/**
* Handler for simple pre-run state.
*
* @param pass_count total number of expected test passes.
* @param pass_num current pass iteration number.
* @param seed random seed being used, or 0 for no randomization.
* @param filter filter string used for tests, or NULL/blank for none.
*/
void (*pre_run)(void *data,
int pass_count,
int pass_num,
int seed,
const char *filter);
/**
* Handler for test runs starting.
*
* @param data the user data associated with this instance.
* @param live_case_count number of active test cases in this run.
* @param live_test_count number of active tests in this run.
* @param disabled_count number of disabled tests in this run.
*/
void (*run_started)(void *data,
int live_case_count,
int live_test_count,
int disabled_count);
/**
* Handler for test runs ending.
*
* @param data the user data associated with this instance.
*/
void (*run_ended)(void *data,
int case_count,
struct zuc_case** cases,
int live_case_count,
int live_test_count,
int total_passed,
int total_failed,
int total_disabled,
long total_elapsed);
/**
* Handler for test case starting.
*
* @param data the user data associated with this instance.
*/
void (*case_started)(void *data,
struct zuc_case *test_case,
int live_test_count,
int disabled_count);
/**
* Handler for test case ending.
*
* @param data the user data associated with this instance.
*/
void (*case_ended)(void *data,
struct zuc_case *test_case);
/**
* Handler for test starting.
*
* @param data the user data associated with this instance.
*/
void (*test_started)(void *data,
struct zuc_test *test);
/**
* Handler for test ending.
*
* @param data the user data associated with this instance.
*/
void (*test_ended)(void *data,
struct zuc_test *test);
/**
* Handler for disabled test notification.
*
* @param data the user data associated with this instance.
*/
void (*test_disabled)(void *data,
struct zuc_test *test);
/**
* Handler for check/assertion fired due to failure, warning, etc.
*
* @param data the user data associated with this instance.
*/
void (*check_triggered)(void *data,
char const *file,
int line,
enum zuc_fail_state state,
enum zuc_check_op op,
enum zuc_check_valtype valtype,
intptr_t val1,
intptr_t val2,
const char *expr1,
const char *expr2);
/**
* Handler for tracepoints and such that may be displayed later.
*
* @param data the user data associated with this instance.
*/
void (*collect_event)(void *data,
char const *file,
int line,
const char *expr1);
};
/**
* Registers an event listener instance to be called.
*/
void
zuc_add_event_listener(struct zuc_event_listener *event_listener);
#endif /* ZUC_EVENT_HANDLER_H */
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ZUC_TYPES_H
#define ZUC_TYPES_H
#include "zunitc/zunitc_impl.h"
struct zuc_case;
/**
* Represents a specific test.
*/
struct zuc_test
{
int order;
struct zuc_case *test_case;
zucimpl_test_fn fn;
zucimpl_test_fn_f fn_f;
char *name;
int disabled;
int skipped;
int failed;
int fatal;
long elapsed;
struct zuc_event *events;
struct zuc_event *deferred;
};
/**
* Represents a test case that can hold a collection of tests.
*/
struct zuc_case
{
int order;
char *name;
const struct zuc_fixture* fxt;
int disabled;
int skipped;
int failed;
int fatal;
int passed;
long elapsed;
int test_count;
struct zuc_test **tests;
};
/**
* Returns a human-readable version of the comparison opcode.
*
* @param op the opcode to get a string version of.
* @return a human-readable string of the opcode.
* (This value should not be freed)
*/
const char *
zuc_get_opstr(enum zuc_check_op op);
#endif /* ZUC_TYPES_H */
File diff suppressed because it is too large Load Diff