Blame library/test.c

Packit Service 6d40f9
/*
Packit Service 6d40f9
 * Copyright (c) 2013, Red Hat Inc.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Redistribution and use in source and binary forms, with or without
Packit Service 6d40f9
 * modification, are permitted provided that the following conditions
Packit Service 6d40f9
 * are met:
Packit Service 6d40f9
 *
Packit Service 6d40f9
 *     * Redistributions of source code must retain the above
Packit Service 6d40f9
 *       copyright notice, this list of conditions and the
Packit Service 6d40f9
 *       following disclaimer.
Packit Service 6d40f9
 *     * Redistributions in binary form must reproduce the
Packit Service 6d40f9
 *       above copyright notice, this list of conditions and
Packit Service 6d40f9
 *       the following disclaimer in the documentation and/or
Packit Service 6d40f9
 *       other materials provided with the distribution.
Packit Service 6d40f9
 *     * The names of contributors to this software may not be
Packit Service 6d40f9
 *       used to endorse or promote products derived from this
Packit Service 6d40f9
 *       software without specific prior written permission.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6d40f9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6d40f9
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit Service 6d40f9
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit Service 6d40f9
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service 6d40f9
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
Packit Service 6d40f9
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Packit Service 6d40f9
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Packit Service 6d40f9
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit Service 6d40f9
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
Packit Service 6d40f9
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
Packit Service 6d40f9
 * DAMAGE.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Author: Stef Walter <stefw@redhat.com>
Packit Service 6d40f9
 */
Packit Service 6d40f9
Packit Service 6d40f9
#include "config.h"
Packit Service 6d40f9
Packit Service 6d40f9
#define TEST_SOURCE 1
Packit Service 6d40f9
Packit Service 6d40f9
#include "test.h"
Packit Service 6d40f9
Packit Service 6d40f9
#include <assert.h>
Packit Service 6d40f9
#include <setjmp.h>
Packit Service 6d40f9
#include <stdarg.h>
Packit Service 6d40f9
#include <stdio.h>
Packit Service 6d40f9
#include <stdlib.h>
Packit Service 6d40f9
#include <string.h>
Packit Service 6d40f9
Packit Service 6d40f9
enum {
Packit Service 6d40f9
	FIXTURE,
Packit Service 6d40f9
	TEST,
Packit Service 6d40f9
};
Packit Service 6d40f9
Packit Service 6d40f9
typedef void (*func_with_arg) (void *);
Packit Service 6d40f9
Packit Service 6d40f9
typedef struct _test_item {
Packit Service 6d40f9
	int type;
Packit Service 6d40f9
Packit Service 6d40f9
	union {
Packit Service 6d40f9
		struct {
Packit Service 6d40f9
			char name[1024];
Packit Service 6d40f9
			func_with_arg func;
Packit Service 6d40f9
			void *argument;
Packit Service 6d40f9
			int failed;
Packit Service 6d40f9
		} test;
Packit Service 6d40f9
		struct {
Packit Service 6d40f9
			func_with_arg setup;
Packit Service 6d40f9
			func_with_arg teardown;
Packit Service 6d40f9
		} fix;
Packit Service 6d40f9
	} x;
Packit Service 6d40f9
Packit Service 6d40f9
	struct _test_item *next;
Packit Service 6d40f9
} test_item;
Packit Service 6d40f9
Packit Service 6d40f9
struct {
Packit Service 6d40f9
	test_item *suite;
Packit Service 6d40f9
	test_item *last;
Packit Service 6d40f9
	int number;
Packit Service 6d40f9
	jmp_buf jump;
Packit Service 6d40f9
} gl = { NULL, NULL, 0, };
Packit Service 6d40f9
Packit Service 6d40f9
void
Packit Service 6d40f9
test_fail (const char *filename,
Packit Service 6d40f9
           int line,
Packit Service 6d40f9
           const char *function,
Packit Service 6d40f9
           const char *message,
Packit Service 6d40f9
           ...)
Packit Service 6d40f9
{
Packit Service 6d40f9
	const char *pos;
Packit Service 6d40f9
	char *output;
Packit Service 6d40f9
	char *from;
Packit Service 6d40f9
	char *next;
Packit Service 6d40f9
	va_list va;
Packit Service 6d40f9
Packit Service 6d40f9
	assert (gl.last != NULL);
Packit Service 6d40f9
	assert (gl.last->type == TEST);
Packit Service 6d40f9
	gl.last->x.test.failed = 1;
Packit Service 6d40f9
Packit Service 6d40f9
	printf ("not ok %d %s\n", gl.number, gl.last->x.test.name);
Packit Service 6d40f9
Packit Service 6d40f9
	va_start (va, message);
Packit Service 6d40f9
	if (vasprintf (&output, message, va) < 0)
Packit Service 6d40f9
		assert (0 && "vasprintf() failed");
Packit Service 6d40f9
	va_end (va);
Packit Service 6d40f9
Packit Service 6d40f9
	for (from = output; from != NULL; ) {
Packit Service 6d40f9
		next = strchr (from, '\n');
Packit Service 6d40f9
		if (next) {
Packit Service 6d40f9
			next[0] = '\0';
Packit Service 6d40f9
			next += 1;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		printf ("# %s\n", from);
Packit Service 6d40f9
		from = next;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	pos = strrchr (filename, '/');
Packit Service 6d40f9
	if (pos != NULL && pos[1] != '\0')
Packit Service 6d40f9
		filename = pos + 1;
Packit Service 6d40f9
Packit Service 6d40f9
	printf ("# in %s() at %s:%d\n", function, filename, line);
Packit Service 6d40f9
Packit Service 6d40f9
	free (output);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static void
Packit Service 6d40f9
test_push (test_item *it)
Packit Service 6d40f9
{
Packit Service 6d40f9
	test_item *item;
Packit Service 6d40f9
Packit Service 6d40f9
	item = calloc (1, sizeof (test_item));
Packit Service 6d40f9
	assert (item != NULL);
Packit Service 6d40f9
	memcpy (item, it, sizeof (test_item));
Packit Service 6d40f9
Packit Service 6d40f9
	if (!gl.suite)
Packit Service 6d40f9
		gl.suite = item;
Packit Service 6d40f9
	if (gl.last)
Packit Service 6d40f9
		gl.last->next = item;
Packit Service 6d40f9
	gl.last = item;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
void
Packit Service 6d40f9
test_func (void (* function) (void),
Packit Service 6d40f9
           const char *name,
Packit Service 6d40f9
           ...)
Packit Service 6d40f9
{
Packit Service 6d40f9
	test_item item = { TEST, };
Packit Service 6d40f9
	va_list va;
Packit Service 6d40f9
Packit Service 6d40f9
	item.x.test.func = (func_with_arg)function;
Packit Service 6d40f9
Packit Service 6d40f9
	va_start (va, name);
Packit Service 6d40f9
	vsnprintf (item.x.test.name, sizeof (item.x.test.name), name, va);
Packit Service 6d40f9
	va_end (va);
Packit Service 6d40f9
Packit Service 6d40f9
	test_push (&item);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
void
Packit Service 6d40f9
test_funcx (void (* function) (void *),
Packit Service 6d40f9
            void *argument,
Packit Service 6d40f9
            const char *name,
Packit Service 6d40f9
            ...)
Packit Service 6d40f9
{
Packit Service 6d40f9
	test_item item = { TEST, };
Packit Service 6d40f9
	va_list va;
Packit Service 6d40f9
Packit Service 6d40f9
	item.type = TEST;
Packit Service 6d40f9
	item.x.test.func = function;
Packit Service 6d40f9
	item.x.test.argument = argument;
Packit Service 6d40f9
Packit Service 6d40f9
	va_start (va, name);
Packit Service 6d40f9
	vsnprintf (item.x.test.name, sizeof (item.x.test.name), name, va);
Packit Service 6d40f9
	va_end (va);
Packit Service 6d40f9
Packit Service 6d40f9
	test_push (&item);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
void
Packit Service 6d40f9
test_fixture (void (* setup) (void *),
Packit Service 6d40f9
              void (* teardown) (void *))
Packit Service 6d40f9
{
Packit Service 6d40f9
	test_item item;
Packit Service 6d40f9
Packit Service 6d40f9
	item.type = FIXTURE;
Packit Service 6d40f9
	item.x.fix.setup = setup;
Packit Service 6d40f9
	item.x.fix.teardown = teardown;
Packit Service 6d40f9
Packit Service 6d40f9
	test_push (&item);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
int
Packit Service 6d40f9
test_run (int argc,
Packit Service 6d40f9
          char **argv)
Packit Service 6d40f9
{
Packit Service 6d40f9
	test_item *fixture = NULL;
Packit Service 6d40f9
	test_item *item;
Packit Service 6d40f9
	test_item *next;
Packit Service 6d40f9
	int count;
Packit Service 6d40f9
	int ret = 0;
Packit Service 6d40f9
Packit Service 6d40f9
	assert (gl.number == 0);
Packit Service 6d40f9
	gl.last = NULL;
Packit Service 6d40f9
Packit Service 6d40f9
	for (item = gl.suite, count = 0; item != NULL; item = item->next) {
Packit Service 6d40f9
		if (item->type == TEST)
Packit Service 6d40f9
			count++;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (count == 0) {
Packit Service 6d40f9
		printf ("1..0 # No tests\n");
Packit Service 6d40f9
		return 0;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	printf ("1..%d\n", count);
Packit Service 6d40f9
Packit Service 6d40f9
	for (item = gl.suite, gl.number = 0; item != NULL; item = item->next) {
Packit Service 6d40f9
		if (item->type == FIXTURE) {
Packit Service 6d40f9
			fixture = item;
Packit Service 6d40f9
			continue;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		assert (item->type == TEST);
Packit Service 6d40f9
		gl.last = item;
Packit Service 6d40f9
		gl.number++;
Packit Service 6d40f9
Packit Service 6d40f9
		if (setjmp (gl.jump) == 0) {
Packit Service 6d40f9
			if (fixture && fixture->x.fix.setup)
Packit Service 6d40f9
				(fixture->x.fix.setup) (item->x.test.argument);
Packit Service 6d40f9
Packit Service 6d40f9
			assert (item->x.test.func);
Packit Service 6d40f9
			(item->x.test.func)(item->x.test.argument);
Packit Service 6d40f9
Packit Service 6d40f9
			if (fixture && fixture->x.fix.teardown)
Packit Service 6d40f9
				(fixture->x.fix.teardown) (item->x.test.argument);
Packit Service 6d40f9
Packit Service 6d40f9
			printf ("ok %d %s\n", gl.number, item->x.test.name);
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		gl.last = NULL;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	for (item = gl.suite; item != NULL; item = next) {
Packit Service 6d40f9
		if (item->type == TEST) {
Packit Service 6d40f9
			if (item->x.test.failed)
Packit Service 6d40f9
				ret++;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		next = item->next;
Packit Service 6d40f9
		free (item);
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	gl.suite = NULL;
Packit Service 6d40f9
	gl.last = 0;
Packit Service 6d40f9
	gl.number = 0;
Packit Service 6d40f9
	return ret;
Packit Service 6d40f9
}