diff --git a/.gitignore b/.gitignore index 0a25736..547e49a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,9 @@ latex/ *.so *.la *.a -drow-engine -main +/drow-engine +/main +/test # junk core diff --git a/Makefile b/Makefile index 093b938..8d46141 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ all: $(MAKE) -C src all +test: + $(MAKE) -C src test + doc: doxygen @@ -9,7 +12,7 @@ doc-pdf: doc clean: $(MAKE) -C src clean - rm -rf drown-engine + rm -rf drown-engine test install: $(MAKE) -C install @@ -18,4 +21,4 @@ uninstall: $(MAKE) -C uninstall -.PHONY: all doc doc-pdf clean install uninstall +.PHONY: all doc doc-pdf clean install test uninstall diff --git a/src/Makefile b/src/Makefile index d7cf6c5..1a252af 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,7 +16,7 @@ endif TARGET = drow-engine HEADERS = err.h common.h print.h filereader.h gl_draw.h vector.h half_edge.h -OBJECTS = main.o print.o filereader.o gl_draw.o vector.o half_edge.o +OBJECTS = print.o filereader.o gl_draw.o vector.o half_edge.o INCS = -I. CFLAGS += $(shell $(PKG_CONFIG) --cflags gl glu glib-2.0) @@ -37,8 +37,16 @@ INSTALL_LIBDIR = $(PREFIX)/$(LIBDIR) all: $(TARGET) -$(TARGET): $(HEADERS) $(OBJECTS) - $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o ../$(TARGET) $(OBJECTS) $(LDFLAGS) $(LIBS) +drow-engine.a: $(OBJECTS) + $(AR) rcu $@ $^ + +test: drow-engine.a + $(MAKE) -C test + +$(TARGET): $(HEADERS) drow-engine.a main.o + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) \ + -o ../$(TARGET) \ + main.o drow-engine.a $(LDFLAGS) $(LIBS) install: $(TARGET) $(INSTALL_DIR) "$(DESTDIR)$(INSTALL_BINDIR)" @@ -48,7 +56,8 @@ uninstall: rm "$(DESTDIR)$(INSTALL_BINDIR)/$(TARGET)" clean: - rm -f *.o $(TARGET) core vgcore* + $(MAKE) -C test clean + rm -f *.o drow-engine.a $(TARGET) core vgcore* -.PHONY: all clean install uninstall +.PHONY: all clean install test uninstall diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 0000000..d731ae6 --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,52 @@ +# compiler, tools +CC = clang +PKG_CONFIG ?= pkg-config + +# flags +CFLAGS ?= -march=native -O2 -pipe +CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function +ifeq ($(shell $(CC) -v 2>&1 | grep 'gcc version' &>/dev/null && echo 1),1) +CFLAGS += -Wno-unused-but-set-variable +endif +LDFLAGS ?= -Wl,-O1 -Wl,--as-needed -Wl,--hash-style=gnu + +ifndef NODEBUG +CFLAGS += -O0 -g3 +endif + +TARGET = test +HEADERS = cunit.h +OBJECTS = cunit.o cunit_filereader.o cunit_half_edge.o +INCS = -I. -I.. + +CFLAGS += $(shell $(PKG_CONFIG) --cflags gl glu glib-2.0) +LIBS = $(shell $(PKG_CONFIG) --libs gl glu glib-2.0) -lglut -lm -lcunit +CPPFLAGS += -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED -D_GNU_SOURCE + +# install variables +INSTALL = install +INSTALL_BIN = install -m755 +INSTALL_DIR = install -d +PREFIX = /usr/local +LIBDIR = lib64 +INSTALL_BINDIR = $(PREFIX)/bin +INSTALL_LIBDIR = $(PREFIX)/$(LIBDIR) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -c $*.c + +all: $(TARGET) + +drow-engine.a: + $(MAKE) -C .. $@ + +$(TARGET): $(HEADERS) $(OBJECTS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o ../../$(TARGET) \ + $(OBJECTS) ../drow-engine.a $(LDFLAGS) $(LIBS) + +clean: + rm -f *.o $(TARGET) core vgcore* + + +.PHONY: all clean drow-engine.a install uninstall + diff --git a/src/test/cunit.c b/src/test/cunit.c new file mode 100644 index 0000000..95a89b4 --- /dev/null +++ b/src/test/cunit.c @@ -0,0 +1,123 @@ +/* + * Copyright 2011-2014 hasufell + * + * This file is part of a hasufell project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cunit.h" + +#include +#include +#include +#include +#include +#include + + +int init_suite(void) +{ + return 0; +} + +int clean_suite(void) +{ + return 0; +} + +int main(void) +{ + CU_pSuite pSuite = NULL; + int my_stderr; + + /* initialize the CUnit test registry */ + if (CUE_SUCCESS != CU_initialize_registry()) + return CU_get_error(); + + /* add a suite to the registry */ + pSuite = CU_add_suite("filereader tests", + init_suite, + clean_suite); + if (NULL == pSuite) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* add the tests to the suite */ + if ( + (NULL == CU_add_test(pSuite, "test1 reading plain text file", + test_read_text_file1)) || + (NULL == CU_add_test(pSuite, "test2 reading plain text file", + test_read_text_file2)) || + (NULL == CU_add_test(pSuite, "test3 reading plain text file", + test_read_text_file3)) || + (NULL == CU_add_test(pSuite, "test4 reading plain text file", + test_read_text_file4)) || + (NULL == CU_add_test(pSuite, "test1 reading obj file", + test_read_obj_file1)) || + (NULL == CU_add_test(pSuite, "test2 reading obj file", + test_read_obj_file2)) || + (NULL == CU_add_test(pSuite, "test3 reading obj file", + test_read_obj_file3)) + + ) { + + CU_cleanup_registry(); + return CU_get_error(); + } + + /* add a suite to the registry */ + pSuite = CU_add_suite("half edge tests", + init_suite, + clean_suite); + if (NULL == pSuite) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* add the tests to the suite */ + if ( + (NULL == CU_add_test(pSuite, "test1 parsing .obj", + test_parse_obj1)) || + (NULL == CU_add_test(pSuite, "test2 parsing .obj", + test_parse_obj2)) || + (NULL == CU_add_test(pSuite, "test3 parsing .obj", + test_parse_obj3)) || + (NULL == CU_add_test(pSuite, "test4 parsing .obj", + test_parse_obj4)) + ) { + + CU_cleanup_registry(); + return CU_get_error(); + } + + /* save stderr stream and close it */ + my_stderr = dup(STDERR_FILENO); + close(STDERR_FILENO); + + /* Run all tests using the basic interface */ + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + printf("\n"); + CU_basic_show_failures(CU_get_failure_list()); + printf("\n\n"); + + /* Clean up registry and return */ + CU_cleanup_registry(); + + /* restore stderr stream */ + dup2(my_stderr, STDERR_FILENO); + + return CU_get_error(); +} diff --git a/src/test/cunit.h b/src/test/cunit.h new file mode 100644 index 0000000..c55e485 --- /dev/null +++ b/src/test/cunit.h @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2014 hasufell + * + * This file is part of a hasufell project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * filereader tests + */ +void test_read_text_file1(void); +void test_read_text_file2(void); +void test_read_text_file3(void); +void test_read_text_file4(void); + +void test_read_obj_file1(void); +void test_read_obj_file2(void); +void test_read_obj_file3(void); + +/* + * half_edge tests + */ +void test_parse_obj1(void); +void test_parse_obj2(void); +void test_parse_obj3(void); +void test_parse_obj4(void); diff --git a/src/test/cunit_filereader.c b/src/test/cunit_filereader.c new file mode 100644 index 0000000..ff3a6fe --- /dev/null +++ b/src/test/cunit_filereader.c @@ -0,0 +1,267 @@ +/* + * Copyright 2011-2014 hasufell + * + * This file is part of a hasufell project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "filereader.h" +#include "half_edge.h" + +#include +#include +#include +#include +#include + + +/** + * Read a valid text file and compare it with the correct expected + * string. + */ +void test_read_text_file1(void) +{ + char *actual_string = read_file("src/test/test-file.txt"), + *expected_string = "This test file is a test file.\n"; + + + CU_ASSERT_PTR_NOT_NULL(actual_string); + CU_ASSERT_EQUAL((strcmp(actual_string, expected_string)), 0); +} + +/** + * Read a valid text file and compare it with an uncorrect expected + * string. + */ +void test_read_text_file2(void) +{ + char *actual_string = read_file("src/test/test-file.txt"), + *expected_string = "foo"; + + CU_ASSERT_PTR_NOT_NULL(actual_string); + CU_ASSERT_NOT_EQUAL((strcmp(actual_string, expected_string)), 0); +} + +/** + * Read an invalid text file. + */ +void test_read_text_file3(void) +{ + char *actual_string = actual_string = read_file("asd"); + + CU_ASSERT_PTR_NULL(actual_string); +} + +/** + * Pass NULL to the read_file() function. + */ +void test_read_text_file4(void) +{ + char *actual_string = actual_string = read_file(NULL); + + CU_ASSERT_PTR_NULL(actual_string); +} + +/** + * Read a valid .obj file and test the whole HE_obj structure + * for correctness. + */ +void test_read_obj_file1(void) +{ + HE_obj *obj = read_obj_file("obj/testcube_trans.obj"); + + CU_ASSERT_PTR_NOT_NULL(obj); + + CU_ASSERT_EQUAL(obj->vertices[0].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[0].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[0].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[1].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[1].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[1].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[2].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[2].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[2].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[3].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[4].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[4].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[4].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[5].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[6].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[6].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[6].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[7].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[7].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[7].z, 9.0); + + CU_ASSERT_EQUAL(obj->vc, 8); + + /* + * The following relies on faces always saving the + * last listed vertice as their edge member. + */ + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->fc, 6); + + CU_ASSERT_EQUAL(obj->ec, 24); +} + +/** + * Read an invalid .obj file. + */ +void test_read_obj_file2(void) +{ + HE_obj *obj = read_obj_file("objfoo"); + + CU_ASSERT_PTR_NULL(obj); +} + +/** + * Pass NULL to read_obj_file(). + */ +void test_read_obj_file3(void) +{ + HE_obj *obj = read_obj_file(NULL); + + CU_ASSERT_PTR_NULL(obj); +} diff --git a/src/test/cunit_half_edge.c b/src/test/cunit_half_edge.c new file mode 100644 index 0000000..810d7c0 --- /dev/null +++ b/src/test/cunit_half_edge.c @@ -0,0 +1,429 @@ +/* + * Copyright 2011-2014 hasufell + * + * This file is part of a hasufell project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "half_edge.h" + +#include +#include +#include +#include + +/** + * Use a valid string representing an .obj file + * and test the whole HE_obj structure for correctness. + */ +void test_parse_obj1(void) +{ + char const * const string = "" + "v 9.0 10.0 11.0\n" + "v 11.0 10.0 11.0\n" + "v 9.0 11.0 11.0\n" + "v 11.0 11.0 11.0\n" + "v 9.0 11.0 9.0\n" + "v 11.0 11.0 9.0\n" + "v 9.0 10.0 9.0\n" + "v 11.0 10.0 9.0\n" + "f 1 2 4 3\n" + "f 3 4 6 5\n" + "f 5 6 8 7\n" + "f 7 8 2 1\n" + "f 2 8 6 4\n" + "f 7 1 3 5\n"; + + HE_obj *obj = parse_obj(string); + + CU_ASSERT_PTR_NOT_NULL(obj); + + CU_ASSERT_EQUAL(obj->vertices[0].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[0].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[0].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[1].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[1].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[1].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[2].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[2].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[2].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[3].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[4].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[4].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[4].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[5].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[6].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[6].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[6].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[7].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[7].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[7].z, 9.0); + + CU_ASSERT_EQUAL(obj->vc, 8); + + /* + * The following relies on faces always saving the + * last listed vertice as their edge member. + */ + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->fc, 6); + + CU_ASSERT_EQUAL(obj->ec, 24); +} + +/** + * Test if the parser correctly ignores comments and other + * junk. + */ +void test_parse_obj2(void) +{ + char const * const string = "" + "v 9.0 10.0 11.0\n" + "v 11.0 10.0 11.0\n" + "v 9.0 11.0 11.0\n" + "v 11.0 11.0 11.0\n" + "v 9.0 11.0 9.0\n" + "v 11.0 11.0 9.0\n" + "# blah\n" + "v 9.0 10.0 9.0\n" + "v 11.0 10.0 9.0\n" + "f 1 2 4 3\n" + "f 3 4 6 5\n" + "kkldsakl sakdjl\n" + "f 5 6 8 7\n" + "f 7 8 2 1\n" + "f 2 8 6 4\n" + "f 7 1 3 5\n" + "998032lkk\n"; + + HE_obj *obj = parse_obj(string); + + CU_ASSERT_PTR_NOT_NULL(obj); + + CU_ASSERT_EQUAL(obj->vertices[0].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[0].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[0].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[1].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[1].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[1].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[2].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[2].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[2].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[3].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[3].z, 11.0); + + CU_ASSERT_EQUAL(obj->vertices[4].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[4].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[4].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[5].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].y, 11.0); + CU_ASSERT_EQUAL(obj->vertices[5].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[6].x, 9.0); + CU_ASSERT_EQUAL(obj->vertices[6].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[6].z, 9.0); + + CU_ASSERT_EQUAL(obj->vertices[7].x, 11.0); + CU_ASSERT_EQUAL(obj->vertices[7].y, 10.0); + CU_ASSERT_EQUAL(obj->vertices[7].z, 9.0); + + CU_ASSERT_EQUAL(obj->vc, 8); + + /* + * The following relies on faces always saving the + * last listed vertice as their edge member. + */ + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[0].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[1].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[2].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[3].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->x, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[4].edge->next->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->y, 10.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->vert->z, 11.0); + + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->x, 9.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->y, 11.0); + CU_ASSERT_EQUAL(obj->faces[5].edge->next->next->next->next->vert->z, 9.0); + + CU_ASSERT_EQUAL(obj->fc, 6); + + CU_ASSERT_EQUAL(obj->ec, 24); +} + +/** + * Test if the parser correctly aborts when passed + * an empty string. + */ +void test_parse_obj3(void) +{ + char const * const string = ""; + + HE_obj *obj = parse_obj(string); + + CU_ASSERT_PTR_NULL(obj); +} + +/** + * Test if the parser correctly aborts when passed + * a NULL pointer. + */ +void test_parse_obj4(void) +{ + HE_obj *obj = parse_obj(NULL); + + CU_ASSERT_PTR_NULL(obj); +} diff --git a/src/test/test-file.txt b/src/test/test-file.txt new file mode 100644 index 0000000..abc2699 --- /dev/null +++ b/src/test/test-file.txt @@ -0,0 +1 @@ +This test file is a test file.