forked from vieter-v/libvieter
				
			test: add structure & framework for writing tests
							parent
							
								
									3da95a63fb
								
							
						
					
					
						commit
						c018d8d86c
					
				
							
								
								
									
										34
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										34
									
								
								Makefile
								
								
								
								
							|  | @ -2,12 +2,18 @@ LIB_FILENAME ?= libvieter.a | |||
| 
 | ||||
| BUILD_DIR ?= build | ||||
| SRC_DIR ?= src | ||||
| TEST_DIR ?= test | ||||
| INC_DIRS ?= include | ||||
| 
 | ||||
| SRCS != find '$(SRC_DIR)' -iname '*.c' | ||||
| SRCS_H != find $(INC_DIRS) -iname '*.h' | ||||
| SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' | ||||
| 
 | ||||
| OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) | ||||
| DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) | ||||
| OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o) | ||||
| DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d) | ||||
| 
 | ||||
| BINS_TEST := $(OBJS_TEST:%.c.o=%) | ||||
| 
 | ||||
| INC_FLAGS := $(addprefix -I,$(INC_DIRS)) | ||||
| 
 | ||||
|  | @ -16,7 +22,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) | |||
| #  object file is also recompiled if only a header is changed.
 | ||||
| # -MP: generate a dummy target for every header file (according to the  docs it
 | ||||
| #  prevents some errors when removing header files)
 | ||||
| CFLAGS ?= $(INC_FLAGS) -O3 -MMD -MP -Wall -Werror -Wextra | ||||
| CFLAGS ?= $(INC_FLAGS) -MMD -MP -Wall -Werror -Wextra | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: vieter | ||||
|  | @ -28,19 +34,37 @@ vieter: $(BUILD_DIR)/$(LIB_FILENAME) | |||
| $(BUILD_DIR)/$(LIB_FILENAME): $(OBJS) | ||||
| 	ar -rcs $@ $(OBJS) | ||||
| 
 | ||||
| $(BUILD_DIR)/%.c.o: %.c | ||||
| $(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c | ||||
| 	mkdir -p $(dir $@) | ||||
| 	$(CC) $(CFLAGS) -c $< -o $@ | ||||
| 
 | ||||
| 
 | ||||
| # =====TESTING=====
 | ||||
| .PHONY: test | ||||
| test: build-test | ||||
| 	@ $(foreach bin,$(BINS_TEST),./$(bin);) | ||||
| 
 | ||||
| .PHONY: build-test | ||||
| build-test: $(BINS_TEST) | ||||
| 
 | ||||
| # For simplicity, we link every object file to each of the test files. This
 | ||||
| # might be changed later if this starts to become too slow.
 | ||||
| $(BINS_TEST): %: %.c.o $(OBJS) | ||||
| 	$(CC) $^ -o $@ | ||||
| 
 | ||||
| # Each test includes the test directory, which contains the acutest header file
 | ||||
| $(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c | ||||
| 	mkdir -p $(dir $@) | ||||
| 	$(CC) $(CFLAGS) -I$(TEST_DIR) -c $< -o $@ | ||||
| 
 | ||||
| # =====MAINTENANCE=====
 | ||||
| .PHONY: lint | ||||
| lint: | ||||
| 	clang-format -n --Werror $(SRCS) $(SRCS_H) | ||||
| 	clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_TEST) | ||||
| 
 | ||||
| .PHONY: fmt | ||||
| fmt: | ||||
| 	clang-format -i $(SRCS) $(SRCS_H) | ||||
| 	clang-format -i $(SRCS) $(SRCS_H) $(SRCS_TEST) | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
|  |  | |||
							
								
								
									
										16
									
								
								README.md
								
								
								
								
							
							
						
						
									
										16
									
								
								README.md
								
								
								
								
							|  | @ -13,6 +13,21 @@ Currently it contains the following: | |||
| 
 | ||||
| ## Development | ||||
| 
 | ||||
| ### Compilation | ||||
| 
 | ||||
| Everything is handled by the provided Makefile. To compile the static library, | ||||
| simply run `make`. | ||||
| 
 | ||||
| ### Testing | ||||
| 
 | ||||
| This library uses [Acutest](https://github.com/mity/acutest) for its tests. | ||||
| Tests should be placed in the `test` subdirectory, further divided into | ||||
| directories that correspond those in `src`. Test files should begin with | ||||
| `test_`, and their format should follow the expected format for Acutest. | ||||
| 
 | ||||
| To run the tests, simply run `make test`. If you wish to only run a specific | ||||
| test binary, you can find them in `build/test`. | ||||
| 
 | ||||
| ### `compile_commands.json` | ||||
| 
 | ||||
| Clangd requires a `compile_commands.json` to function properly. You can | ||||
|  | @ -21,6 +36,7 @@ generate it using [bear](https://github.com/rizsotto/Bear): | |||
| ```sh | ||||
| make clean | ||||
| bear -- make | ||||
| bear --append -- make build-test | ||||
| ``` | ||||
| 
 | ||||
| This will create a `compile_commands.json` file in the current directory. | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,69 @@ | |||
| #include "acutest.h" | ||||
| #include "vieter_cron.h" | ||||
| 
 | ||||
| void test_tutorial(void) { | ||||
|   void *mem; | ||||
| 
 | ||||
|   mem = malloc(10); | ||||
|   TEST_CHECK(mem != NULL); | ||||
| 
 | ||||
|   mem = realloc(mem, 20); | ||||
|   TEST_CHECK(mem != NULL); | ||||
| 
 | ||||
|   free(mem); | ||||
| } | ||||
| 
 | ||||
| void test_fail(void) { | ||||
|   int a, b; | ||||
| 
 | ||||
|   /* This condition is designed to fail so you can see what the failed test
 | ||||
|    * output looks like. */ | ||||
|   a = 1; | ||||
|   b = 2; | ||||
|   TEST_CHECK(a + b == 5); | ||||
| 
 | ||||
|   /* Here is TEST_CHECK_ in action. */ | ||||
|   TEST_CHECK_(a + b == 5, "%d + %d == 5", a, b); | ||||
| 
 | ||||
|   /* We may also show more information about the failure. */ | ||||
|   if (!TEST_CHECK(a + b == 5)) { | ||||
|     TEST_MSG("a: %d", a); | ||||
|     TEST_MSG("b: %d", b); | ||||
|   } | ||||
| 
 | ||||
|   /* The macro TEST_MSG() only outputs something when the preceding
 | ||||
|    * condition fails, so we can avoid the 'if' statement. */ | ||||
|   TEST_CHECK(a + b == 3); | ||||
|   TEST_MSG("a: %d", a); | ||||
|   TEST_MSG("b: %d", b); | ||||
| } | ||||
| 
 | ||||
| static void helper(void) { | ||||
|   /* Kill the current test with a condition which is never true. */ | ||||
|   TEST_ASSERT(1 == 2); | ||||
| 
 | ||||
|   /* This never happens because the test is aborted above. */ | ||||
|   TEST_CHECK(1 + 2 == 2 + 1); | ||||
| } | ||||
| 
 | ||||
| void test_abort(void) { | ||||
|   helper(); | ||||
| 
 | ||||
|   /* This test never happens because the test is aborted inside the helper()
 | ||||
|    * function. */ | ||||
|   TEST_CHECK(1 * 2 == 2 * 1); | ||||
| } | ||||
| 
 | ||||
| void test_crash(void) { | ||||
|   int *invalid = ((int *)NULL) + 0xdeadbeef; | ||||
| 
 | ||||
|   *invalid = 42; | ||||
|   TEST_CHECK_(1 == 1, "This should never execute, due to a write into " | ||||
|                       "an invalid address."); | ||||
| } | ||||
| 
 | ||||
| TEST_LIST = {{"tutorial", test_tutorial}, | ||||
|              {"fail", test_fail}, | ||||
|              {"abort", test_abort}, | ||||
|              {"crash", test_crash}, | ||||
|              {NULL, NULL}}; | ||||
		Loading…
	
		Reference in New Issue