Skip to content

Commit

Permalink
added assertion macros and a way to parse unit test results and deter…
Browse files Browse the repository at this point in the history
…mine failure/success
  • Loading branch information
FlareCoding committed Sep 10, 2024
1 parent d2910e2 commit 0a1d3a9
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 15 deletions.
35 changes: 30 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ else
QEMU_FLAGS += -cpu qemu64
endif

# Unit test execution duration timeout (all tests)
UNIT_TESTS_RUN_TIMEOUT := 1m

# Name of the unit test result output file
UNIT_TESTS_LOG_FILENAME := dev_os_output.log

# Targets
.PHONY: all bootloader kernel buildimg run run-headless clean

Expand All @@ -65,7 +71,7 @@ buildimg: $(DISK_IMG)

$(DISK_IMG): bootloader kernel
@mkdir -p $(@D)
dd if=/dev/zero of=$(DISK_IMG) bs=512 count=93750
dd if=/dev/zero of=$(DISK_IMG) bs=512 count=93750 > /dev/null 2>&1
mkfs -t vfat $(DISK_IMG)
mmd -i $(DISK_IMG) ::/EFI
mmd -i $(DISK_IMG) ::/EFI/BOOT
Expand Down Expand Up @@ -94,13 +100,32 @@ run-debug-headless: $(DISK_IMG)
connect-gdb:
gdb -ex "source ./gdb_setup.gdb" -ex "target remote localhost:4554" -ex "add-symbol-file kernel/bin/kernel.elf" -ex "b _kentry"

# Run tests target
run-unit-tests: $(DISK_IMG)
$(QEMU_EMULATOR) $(QEMU_FLAGS) -nographic | tee dev_os_output.log
# Builds and runs a clean image of the OS with appropriate unit test flags
execute-unit-tests:
@echo "[LOG] Preparing a clean build environment"
@$(MAKE) clean > /dev/null

@echo "[LOG] Building the kernel with unit tests"
@$(MAKE) KRUN_UNIT_TESTS=1 > /dev/null

@echo "[LOG] Launching the StelluxOS image in a VM"
@timeout $(UNIT_TESTS_RUN_TIMEOUT) setsid bash -c '$(QEMU_EMULATOR) $(QEMU_FLAGS) -nographic | tee $(UNIT_TESTS_LOG_FILENAME)'

@echo ""
@echo "[LOG] Parsing unit test results"

# Grouping commands in a single shell to preserve RESULT and handle cleanup
@bash -c '\
bash parse_unit_test_results.sh; \
RESULT=$$?; \
echo "[LOG] Cleaning up"; \
$(MAKE) clean > /dev/null; \
exit $$RESULT \
'

# Clean target
clean:
rm -rf $(BIN_DIR)
$(MAKE) -C $(BOOTLOADER_DIR) clean
$(MAKE) -C $(KERNEL_DIR) clean
rm -rf com1.serial com2.serial dev_os_output.log
rm -rf com1.serial com2.serial $(UNIT_TESTS_LOG_FILENAME)
Binary file modified efi/OVMF_VARS.fd
Binary file not shown.
8 changes: 5 additions & 3 deletions kernel/src/entry/tests/kernel_unit_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
typedef int (*testFunc_t)();

// Macro for registering a test with a name and adding it to the section
#ifdef KRUN_UNIT_TESTS
#define DECLARE_UNIT_TEST(testName, testFunc) \
int testFunc(); \
static const KUnitTest __UNIT_TEST testStruct_##testFunc = { #testName, testFunc }; \
int testFunc()

// Macro to place each test into the .unit_test section using the given attribute
#define __UNIT_TEST __attribute__((used, section(".unit_test")))
#else
#define DECLARE_UNIT_TEST(testName, testFunc) \
int testFunc()
#endif

// Structure to hold test information (name and function pointer)
struct KUnitTest {
Expand Down
10 changes: 3 additions & 7 deletions kernel/src/entry/tests/memory_allocation.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@

#define ALLOC_SIZE (PAGE_SIZE * 10)

int kheapAllocateUnitTest() {
DECLARE_UNIT_TEST("Heap Allocate Test", kheapAllocateUnitTest) {
void* ptr = kmalloc(ALLOC_SIZE);
ASSERT_TRUE_CRITICAL(ptr, "Allocated memory pointer was null");

return UNIT_TEST_SUCCESS;
}

int kheapAllocateAlignedUnitTest() {
DECLARE_UNIT_TEST("Heap Allocate Aligned Test", kheapAllocateAlignedUnitTest) {
void* ptr = kmalloc(ALLOC_SIZE);
ASSERT_TRUE_CRITICAL(ptr, "Allocated memory pointer was null");

return UNIT_TEST_SUCCESS;
}

int kheapAllocateAndFreeUnitTest() {
DECLARE_UNIT_TEST("Heap Allocate and Free Test", kheapAllocateAndFreeUnitTest) {
void* ptr = kmalloc(ALLOC_SIZE);
ASSERT_TRUE_CRITICAL(ptr, "Allocated memory pointer was null");

Expand All @@ -31,7 +31,3 @@ int kheapAllocateAndFreeUnitTest() {

return UNIT_TEST_SUCCESS;
}

DECLARE_UNIT_TEST("Heap Allocate Test", kheapAllocateUnitTest);
DECLARE_UNIT_TEST("Heap Allocate Aligned Test", kheapAllocateAlignedUnitTest);
DECLARE_UNIT_TEST("Heap Allocate and Free Test", kheapAllocateAndFreeUnitTest);
63 changes: 63 additions & 0 deletions parse_unit_test_results.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/bash

# File that contains the output log
log_file="dev_os_output.log"

# Initialize arrays to store test results
passed_tests=()
failed_tests=()

# Check if log file exists
if [[ ! -f "$log_file" ]]; then
echo "Error: $log_file not found."
exit 1
fi

# Read the log file line by line
while IFS= read -r line; do
# Look for passed tests
if [[ "$line" == *"Test"* && "$line" == *"passed"* ]]; then
# Extract test name inside the quotes
test_name=$(echo "$line" | sed -n 's/.*Test "\(.*\)" passed.*/\1/p')
passed_tests+=("$test_name")

# Look for failed tests
elif [[ "$line" == *"Test"* && "$line" == *"failed"* ]]; then
# Extract test name inside the quotes
test_name=$(echo "$line" | sed -n 's/.*Test "\(.*\)" failed.*/\1/p')
failed_tests+=("$test_name")
fi
done < "$log_file"

# Print the results
echo "Test Results:"
echo "============="

# Print passed tests
if [ ${#passed_tests[@]} -gt 0 ]; then
echo -e "\nPassed Tests:"
for test in "${passed_tests[@]}"; do
echo " - $test"
done
else
echo "No tests passed."
fi

# Print failed tests
if [ ${#failed_tests[@]} -gt 0 ]; then
echo -e "\nFailed Tests:"
for test in "${failed_tests[@]}"; do
echo " - $test"
done
else
echo "No tests failed."
fi

# Exit with code 1 if any test failed, otherwise 0
if [ ${#failed_tests[@]} -gt 0 ]; then
echo -e "\n[FAIL] Some tests failed."
exit 1
else
echo -e "\n[OK] All tests passed successfully."
exit 0
fi

0 comments on commit 0a1d3a9

Please sign in to comment.