Skip to content

Commit

Permalink
Functional tests (#103)
Browse files Browse the repository at this point in the history
* Structure the functional tests properly.
* Add coverage: ensure we test with and without PAE.
  • Loading branch information
phaubertin authored Dec 7, 2024
1 parent cc2136e commit 047d463
Show file tree
Hide file tree
Showing 23 changed files with 495 additions and 85 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/build-i686.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ jobs:
- name: make testapp
run: ${{ env.MAKE }} testapp

- name: make qemu
run: ${{ env.MAKE }} qemu

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
Expand All @@ -52,5 +49,5 @@ jobs:
userspace/lib/jinue/libjinue-utils.a
userspace/testapp/jinue-testapp-initrd.tar.gz
- name: make qemu-check
run: ${{ env.MAKE }} qemu-check
- name: Run tests
run: ${{ env.MAKE }} check
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@
# pre-processed linker scripts
*.ld

# auto-generated header files
# auto-generated files
*.gen.h
*.gen.sh

# stripped executables
*-stripped
Expand Down
30 changes: 23 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,20 @@ subdirs = \
$(zlib) \
$(bzip2) \
$(qemu) \
$(virtualbox)
$(virtualbox) \
tests

# make all (default target) will build the kernel image
targets.phony = kernel

# main targets
include $(common)

# Run functional tests
.PHONY: check
check:
make -C tests check

# install kernel image in /boot
.PHONY: install
install: $(kernel_img)
Expand Down Expand Up @@ -77,20 +83,30 @@ vbox-run:
qemu:
make -C $(qemu)

# build the ISO file for QEMU and run
# Run test application in QEMU
.PHONY: qemu-run
qemu-run:
make -C $(qemu) run

# build the ISO file for QEMU and run (without VGA display)
# Run test application in QEMU without VGA display
.PHONY: qemu-run-no-display
qemu-run-no-display:
make -C $(qemu) run-no-display

# build the ISO file for QEMU, run and check the output
.PHONY: qemu-check
qemu-check:
make -C $(qemu) check
# Run test application in QEMU and debug in gdb
.PHONY: qemu-debug
qemu-debug:
make -C $(qemu) debug

# Run test application in QEMU without VGA display and debug in gdb
.PHONY: qemu-debug-no-display
qemu-debug-no-display:
make -C $(qemu) debug-no-display

# Connect to the running gdb debugging session
.PHONY: gdb
gdb:
gdb -x $(gdb)/gdbinit

# Run cppcheck on the kernel sources
# Note: there are known failures
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ kernel, such as GRUB.

During the boot process, the user space loader expects an initial RAM
disk to have been loaded in memory by the bootloader. This would usually
be provided by the user in order to use the kernel. However, an initial
RAM disk containing a test application can be built from this
be provided by an operating system built on top of the microkernel. However, an
initial RAM disk containing a test application can be built from this
repository.

Build Requirements
Expand Down Expand Up @@ -77,6 +77,7 @@ make testapp

How to Run in QEMU
-------------------

You can run the kernel and test application in QEMU using the `qemu-run`
make target:

Expand All @@ -96,12 +97,11 @@ make qemu-run-no-display
In either case, this generates a log file called `run-jinue.log` in
`devel/qemu/` with the full kernel and test application output.

Finally, you can run the kernel and test application, and then run a
script that performs checks on the log file by using the `qemu-check`
Finally, you can run the functional tests in QEMU by using the `check`
make target:

```
make qemu-check
make check
```

How to Install
Expand Down
2 changes: 2 additions & 0 deletions devel/gdb/gdbinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
file kernel/interface/i686/kernel
target extended-remote localhost:1234
37 changes: 31 additions & 6 deletions devel/qemu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,10 @@ CMDLINE = \
DEBUG_DUMP_MEMORY_MAP=1 \
DEBUG_DUMP_SYSCALL_IMPLEMENTATION=1 \
DEBUG_DUMP_RAMDISK=1 \
DEBUG_DO_REBOOT=1 \
RUN_TEST_ACPI=1 \
RUN_TEST_IPC=1

run_log = run-jinue.log
check_script = check-log.sh
deps = $(kernel_img) $(testapp_initrd)
targets.phony = all-deps

Expand All @@ -70,6 +68,21 @@ run: $(deps)

.PHONY: run-no-display
run-no-display: $(deps)
qemu-system-i386 \
-cpu $(QEMU_CPU) \
-m $(QEMU_MEM) \
-no-reboot \
-kernel $(kernel_img) \
-initrd $(testapp_initrd) \
-append "$(CMDLINE) DEBUG_DO_REBOOT=1" \
-serial stdio \
-display none \
-smp 1 \
-usb \
-vga std | tee $(run_log)

.PHONY: debug
debug: $(deps)
qemu-system-i386 \
-cpu $(QEMU_CPU) \
-m $(QEMU_MEM) \
Expand All @@ -78,14 +91,26 @@ run-no-display: $(deps)
-initrd $(testapp_initrd) \
-append "$(CMDLINE)" \
-serial stdio \
-display none \
-smp 1 \
-usb \
-s -S \
-vga std | tee $(run_log)

.PHONY: check
check: $(run_log)
./$(check_script) $<
.PHONY: debug-no-display
debug-no-display: $(deps)
qemu-system-i386 \
-cpu $(QEMU_CPU) \
-m $(QEMU_MEM) \
-no-reboot \
-kernel $(kernel_img) \
-initrd $(testapp_initrd) \
-append "$(CMDLINE) DEBUG_DO_REBOOT=1" \
-serial stdio \
-display none \
-smp 1 \
-usb \
-s -S \
-vga std | tee $(run_log)

.PHONY: kernel-image
kernel-image:
Expand Down
1 change: 1 addition & 0 deletions header.mk
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ kernel_img = $(kernel)/interface/i686/jinue
scripts = $(jinue_root)/scripts
userspace = $(jinue_root)/userspace
qemu = $(devel)/qemu
gdb = $(devel)/gdb
virtualbox = $(devel)/virtualbox
lib = $(userspace)/lib
libjinue = $(lib)/jinue
Expand Down
6 changes: 3 additions & 3 deletions kernel/domain/alloc/slab.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ void *slab_cache_alloc_locked(slab_cache_t *cache) {
for(idx = 0; idx < cache->obj_size / sizeof(uint32_t); ++idx) {
if(buffer[idx] != SLAB_POISON_DEAD_VALUE) {
if(dump_lines == 0) {
warning("detected write to freed object, cache: %s buffer: %#p:",
warning("warning: detected write to freed object, cache: %s buffer: %#p:",
cache->name,
buffer
);
Expand All @@ -308,7 +308,7 @@ void *slab_cache_alloc_locked(slab_cache_t *cache) {
* redzone checking even on freed objects. */
if(cache->flags & SLAB_RED_ZONE) {
if(buffer[idx] != SLAB_RED_ZONE_VALUE) {
warning("detected write past the end of freed object, cache: %s buffer: %#p value: %#" PRIx32,
warning("warning: detected write past the end of freed object, cache: %s buffer: %#p value: %#" PRIx32,
cache->name,
buffer,
buffer[idx]
Expand Down Expand Up @@ -396,7 +396,7 @@ void slab_cache_free(void *buffer) {
uint32_t *rz_word = (uint32_t *)((char *)buffer + cache->obj_size);

if(*rz_word != SLAB_RED_ZONE_VALUE) {
warning("detected write past the end of object, cache: %s buffer: %#p value: %#" PRIx32,
warning("warning: detected write past the end of object, cache: %s buffer: %#p value: %#" PRIx32,
cache->name,
buffer,
*rz_word
Expand Down
2 changes: 1 addition & 1 deletion kernel/domain/services/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ void cmdline_report_errors(void) {
return;
}

warning("There are issues with the kernel command line:");
warning("warning: there are issues with the kernel command line:");

if(cmdline_errors & CMDLINE_ERROR_TOO_LONG) {
warning(" Kernel command line is too long");
Expand Down
4 changes: 2 additions & 2 deletions kernel/domain/services/panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ void panic(const char *message) {
case 2:
/* The first two times panic() is entered, a panic message is displayed
* along with a full call stack dump. */
error("KERNEL PANIC%s: %s", (enter_count == 1) ? "" : " (recursive)", message);
error("error: KERNEL PANIC%s: %s", (enter_count == 1) ? "" : " (recursive)", message);
machine_dump_call_stack();
break;
case 3:
/* The third time, a "recursive count exceeded" message is displayed. We
* try to limit the number of actions we take to limit the chances of a
* further panic. */
error("KERNEL PANIC (recursive count exceeded)");
error("error: KERNEL PANIC (recursive count exceeded)");
break;
default:
/* The fourth time, we do nothing but halt the CPU. */
Expand Down
2 changes: 1 addition & 1 deletion kernel/infrastructure/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ typedef struct {
*
* */
static bool check_failed(const char *message) {
error("Invalid ELF binary: %s", message);
error("error: invalid ELF binary: %s", message);
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion kernel/infrastructure/i686/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

void machine_dump_call_stack(void) {
if(!check_bootinfo(false)) {
warning("Cannot dump call stack because boot information structure is invalid.");
warning("warning: cannot dump call stack because boot information structure is invalid.");
return;
}

Expand Down
2 changes: 1 addition & 1 deletion kernel/infrastructure/i686/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ static bool maybe_enable_pae(
}

if(! use_pae) {
warning("Warning: Physical Address Extension (PAE) not enabled. NX protection disabled.");
warning("warning: physical Address Extension (PAE) not enabled. NX protection disabled.");
pmap_set_no_pae();
}
else {
Expand Down
91 changes: 91 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Copyright (C) 2024 Philippe Aubertin.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the author nor the names of other contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

jinue_root = ..
include $(jinue_root)/header.mk

test_script = run-all-tests.gen.sh
run_script = run-test.sh
run_log = run-test.log

deps = $(kernel_img) $(testapp_initrd)

tests = \
test_acpi \
test_boot_nopae \
test_boot_pae \
test_ipc

logs := $(foreach t,$(tests),$(t).log)

target = $(test_script)
unclean.extra = $(logs)

include $(common)

$(test_script): Makefile
echo "#!/bin/bash -e" > $@
echo "# Generated file - see Makefile" >> $@
echo "" >> $@; \
echo "source utils.sh" >> $@; \
echo "" >> $@; \
echo "fail_count=0" >> $@; \
for t in $(tests); do \
echo "" >> $@; \
echo "echo =============================================================" >> $@; \
echo "echo ==== TEST $$t" >> $@; \
echo "echo =============================================================" >> $@; \
echo "./$(run_script) $(kernel_img) $(testapp_initrd) ./$$t.sh $$t.log || fail_count=\$$((fail_count + 1))" >> $@; \
done
echo "" >> $@; \
echo "echo =============================================================" >> $@; \
echo "echo ==== SUMMARY" >> $@; \
echo "echo =============================================================" >> $@; \
echo "echo Total: $(words $(tests))" >> $@; \
echo "echo Success: \$$(($(words $(tests)) - fail_count))" >> $@; \
echo "echo Failures: \$$((fail_count))" >> $@; \
echo '[ "$$fail_count" -gt "0" ] && report_fail' >> $@; \
echo "report_success" >> $@; \
chmod 755 $@

.PHONY: check
check: $(test_script) $(deps)
./$(test_script)

.PHONY: kernel-image
kernel-image:
make -C $(jinue_root)/kernel

.PHONY: testapp-initrd
testapp-initrd:
make -C $(testapp)

$(kernel_img): kernel-image

$(testapp_initrd): testapp-initrd
Loading

0 comments on commit 047d463

Please sign in to comment.