Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
nvll committed Mar 24, 2012
0 parents commit 46ff5d9
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 0 deletions.
37 changes: 37 additions & 0 deletions Makefile
@@ -0,0 +1,37 @@
# Macros
MKDIR = mkdir -p $(dir $@)
GET_PARENT = $(dir $(lastword $(MAKEFILE_LIST)))

# Setup vars for build
CC = ~/src/gcc/bin/gcc-4.6
OUTPUT := runtests
OBJDIR := build
CFLAGS =-O2 -W -Wall -Wno-unused-parameter
DEFINES =
INCLUDE =-I.
ECHO = @

# Src files to build / link in
SRC := main.c
SRC += $(wildcard tests/*.c)

OBJS := $(addprefix $(OBJDIR)/, $(SRC:.c=.o))

DEPS := $(OBJS:.o=.d)
-include $(DEPS)

.PHONY: all

all: $(OUTPUT)

$(OUTPUT): $(OBJS)
@echo "linking $(OUTPUT)"
$(ECHO) $(CC) $^ -o $(OUTPUT)

$(OBJDIR)/%.o: %.c
@$(MKDIR)
@echo "compiling $<"
$(ECHO) $(CC) $(DEFINES) $(CFLAGS) $(INCLUDE) -c $< -MD -MP -MT $@ -MF $(@:%o=%d) -o $@

clean:
rm -rf $(OBJDIR) $(OUTPUT)
145 changes: 145 additions & 0 deletions list.h
@@ -0,0 +1,145 @@
/*
* Copyright (c) 2012, Christopher Anderson
*
* 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 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 __LIST_H
#define __LIST_H

#define offsetof(type, member) __builtin_offsetof(type, member)
#define containerof(list, type, member) (type *) ((uintptr_t)list - offsetof(type, member))

struct list {
struct list *prev;
struct list *next;
};
typedef struct list list_t;

static inline void list_initialize (list_t *list)
{
list->next = list->prev = list;
}

static inline int list_is_empty(list_t *list)
{
return (list->next == list);
}

/* Insertion ops */
static inline void list_add_after(list_t *target, list_t *node)
{
node->next = target->next;
node->prev = target;

target->next = target->next->prev = node;
}

static inline void list_add_head (list_t *list, list_t *node)
{
list_add_after(list, node);
}

static inline void list_add_tail (list_t *list, list_t *node)
{
list_add_after(list->prev, node);
}

/* Removal ops */
static inline list_t *list_remove(list_t *list, list_t *target)
{
if (list == target)
return NULL;

target->prev->next = target->next;
target->next->prev = target->prev;

target->next = target->prev = NULL;

return target;
}

static inline list_t *list_remove_head (list_t *list)
{
return list_remove(list, list->next);
}

#define list_remove_head_type(list, type, member) \
containerof(list_remove_head(list), type, member)

static inline list_t *list_remove_tail (list_t *list)
{
return list_remove(list, list->prev);
}

#define list_remove_tail_type(list, type, member) \
containerof(list_remove_tail(list), type, member)

/* Iteration ops */
static inline list_t *list_next(list_t *list, list_t *cur)
{
if (cur->next == list)
return NULL;

return cur->next;
}

static inline list_t *list_prev(list_t *list, list_t *cur)
{
if (cur->prev == list)
return NULL;

return cur->prev;
}

/* Inspection ops */
static inline list_t *list_peek(list_t *list, list_t *cur)
{
if (cur == list)
return NULL;

return cur;
}

#define list_peek_type(list, type, member) \
containerof(list_peek(list), type, member)

static inline list_t *list_peek_head(list_t *list)
{
return list_peek(list, list->next);
}

#define list_peek_head_type(list, type, member) \
containerof(list_peek_head(list), type, member)

static inline list_t *list_peek_tail(list_t *list)
{
return list_peek(list, list->prev);
}

#define list_peek_tail_type(list, type, member) \
containerof(list_peek_tail(list), type, member)

/* Iteration */
#define list_foreach(list, type, member, current) \
for (current = containerof((list)->next, type, member); \
&(current)->member != list; \
current = containerof((current)->member.next, type, member))

#define list_foreach_safe(list, type, member, current) \
for (list_t *__list_iter_tmp = (current = containerof((list)->next, type, member), current->member.next); \
&(current)->member != list; \
current = containerof(__list_iter_tmp, type, member), __list_iter_tmp = __list_iter_tmp->next)


#endif
54 changes: 54 additions & 0 deletions main.c
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2012, Christopher Anderson
*
* 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 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "units.h"
#include "list.h"

list_t test_list;

__attribute__((constructor)) void test_list_init(void)
{
list_initialize(&test_list);
}

int main (int argc, char *argv[])
{
int pid, status;
unsigned int pass = 0, fail = 0;

while (!list_is_empty(&test_list)) {
entry_t *test = list_remove_head_type(&test_list, entry_t, node);
pid = fork();
if (pid) {
wait(&status);
if (WEXITSTATUS(status) == 0)
pass++;
else
fail++;
} else {
exit(test->func());
}
}

int total = pass + fail;
printf("%d %s run, %d/%d passed\n", total, (total == 1) ? "test" : "tests", pass, total);

return fail;
}
67 changes: 67 additions & 0 deletions tests/example.c
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2012, Christopher Anderson
*
* 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 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 "units.h"
#include "list.h"

typedef struct {
int value;
list_t node;
} list_entry_t;

static units_test_t test_list_init (void)
{
list_t list;

list_initialize(&list);
if (!list_is_empty(&list))
test_fail(1, "list not initialized properly");

test_pass;
}

static units_test_t test_list_insert (void)
{
list_t list;
list_entry_t entry;
list_entry_t *returned;

entry.value = 17;

list_initialize(&list);
list_add_head(&list, &entry.node);

returned = list_peek_head_type(&list, list_entry_t, node);

if (returned->value != entry.value)
test_fail(1, "peeked entry does not match the one inserted");

returned = list_remove_tail_type(&list, list_entry_t, node);

if (returned->value != entry.value)
test_fail(2, "removed tail entry does not match the one inserted");

if (!list_is_empty(&list))
test_fail(3, "list is not empty after removing sole element");

test_pass;
}

start_tests
add_test(test_list_init)
add_test(test_list_insert)
end_tests

56 changes: 56 additions & 0 deletions units.h
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2012, Christopher Anderson
*
* 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 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 __UNITS_H
#define __UNITS_H
#include <stdlib.h>
#include <stdio.h>
#include "list.h"

extern list_t test_list;
struct test_entry {
unsigned int (*func)(void);
list_t node;
};
typedef struct test_entry entry_t;
typedef unsigned int units_test_t;

static inline void _add_test(units_test_t (*func)(void))
{

entry_t *test = malloc(sizeof(entry_t) * sizeof(char));
test->func = func;
list_add_tail(&test_list, &test->node);
}

#define CONCAT(x, y) x##_##y
#define UNIQUE_TEST_NAME(x, y) CONCAT(x, y)

#define start_tests __attribute__((constructor)) static void UNIQUE_TEST_NAME(units_test, __COUNTER__) (void) {
#define add_test(func) _add_test(func);
#define end_tests }
#define test_pass \
do { \
printf("%s: PASS\n", __PRETTY_FUNCTION__); \
return 0; \
} while (0)
#define test_fail(value, string) \
do { \
printf("%s: FAIL (error %d: %s)\n", __PRETTY_FUNCTION__, value, string); \
return value; \
} while (0);

#endif

0 comments on commit 46ff5d9

Please sign in to comment.