Skip to content

Commit a03b069

Browse files
authored
Tests and coverage (#128)
* printf() cleanup to support qtest * machine instance for stm32f030 * Initial GPIO module test * patch qtest to support non-bool IRQs and intercepting named GPIOs * Add unit test workflow * Add coverage badge
1 parent 22ee6ca commit a03b069

30 files changed

+793
-256
lines changed

.github/workflows/tests.yml

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# This is a basic workflow to help you get started with Actions
2+
3+
name: Unit Tests
4+
5+
# Controls when the action will run. Triggers the workflow on push or pull request
6+
# events but only for the master branch
7+
on:
8+
push:
9+
branches: [ MINI404 ]
10+
pull_request:
11+
branches: [ MINI404 ]
12+
13+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
14+
jobs:
15+
# This workflow contains a single job called "build"
16+
build_linux:
17+
# The type of runner that the job will run on
18+
runs-on: ubuntu-latest
19+
# if: "!contains(github.event.head_commit.message, 'NO_BUILD')"
20+
# # Steps represent a sequence of tasks that will be executed as part of the job
21+
steps:
22+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
23+
- name: Checkout ${{ github.event.pull_request.head.ref }}
24+
uses: actions/checkout@v3
25+
if: ${{ github.event.pull_request }}
26+
with:
27+
repository: ${{ github.repository }}
28+
ref: ${{ github.event.pull_request.head.sha }}
29+
submodules: false
30+
31+
- name: Checkout ${{ github.event.ref }}
32+
uses: actions/checkout@v3
33+
if: ${{ !github.event.pull_request }}
34+
with:
35+
repository: ${{ github.repository }}
36+
ref: ${{ github.event.ref }}
37+
submodules: false
38+
39+
- name: Cache packages
40+
uses: actions/cache@v3.0.11
41+
id: cache-pkgs
42+
with:
43+
path: "packages"
44+
key: "${{ runner.os }}-packages-1_0_0"
45+
restore-keys: ${{ runner.os }}-packages-
46+
47+
- name: Setup cache dir
48+
if: ${{ ! steps.cache-valgrind.outputs.cache-hit }}
49+
run: mkdir -p packages/partial
50+
51+
- name: Install packages
52+
run: |
53+
sudo apt-get update
54+
sudo apt-get -o Dir::Cache::Archives=`pwd`/packages install libelf-dev libglew-dev freeglut3-dev ninja-build libusb-1.0.0-dev libgtk-3-dev lcov
55+
56+
- name: Cache permissions
57+
run: sudo chmod -R 744 packages
58+
59+
- name: Test Symlink
60+
run: ln -s ${{ runner.workspace }}/MINI404/hw/arm/prusa ${{ runner.workspace }}/MINI404/tests/qtest/
61+
62+
- name: Configure build
63+
run: cd ${{ runner.workspace }}/MINI404 && ./configure --target-list="buddy-softmmu" --enable-libusb --enable-gtk --enable-gcov
64+
65+
- name: Build qemu-system-buddy
66+
run: cd ${{ runner.workspace }}/MINI404/build && ninja
67+
68+
# Right now this will fail some tests due to SIGABRT from the CPU crashing. Ignore it until that's fixed.
69+
- name: Run QTest
70+
run: cd ${{ runner.workspace }}/MINI404/build && make check-qtest-buddy -j4
71+
continue-on-error: true
72+
73+
- name: Generate Coverage report
74+
run: cd ${{ runner.workspace }}/MINI404/build && make coverage-html -j4
75+
76+
- name: Strip down Coverage report
77+
run: cd ${{ runner.workspace }}/MINI404/build/meson-logs && lcov -extract coverage.info '*/arm/prusa/*' --rc lcov_branch_coverage=1 --output-file=c2.info
78+
79+
- name: Upload to codecov.io
80+
uses: codecov/codecov-action@v3
81+
with:
82+
# Comma-separated list of files to upload
83+
files: ${{ runner.workspace }}/MINI404/build/meson-logs/c2.info
84+
# Specify whether or not CI build should fail if Codecov runs into an error during upload
85+
fail_ci_if_error: true
86+
# Comma-separated list, see the README for options and their usage
87+
# functionalities: # optional
88+
# Specify whether the Codecov output should be verbose
89+
verbose: true
90+
91+
92+
93+

.vscode/tasks.json

+51
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818
},
1919
"problemMatcher": []
2020
},
21+
{
22+
"label": "Configure QEMU (coverage)",
23+
"type": "shell",
24+
"command": "./configure --target-list=buddy-softmmu --disable-docs --enable-libusb --enable-gcov",
25+
"group": "build",
26+
"presentation": {
27+
"echo": true,
28+
"reveal": "always",
29+
"focus": false,
30+
"panel": "shared",
31+
"showReuseMessage": true,
32+
"clear": true
33+
},
34+
"problemMatcher": []
35+
},
2136
{
2237
"label": "Configure QEMU (Debugging)",
2338
"type": "shell",
@@ -146,6 +161,42 @@
146161
"showReuseMessage": true,
147162
"clear": true
148163
}
164+
},
165+
{
166+
"label": "Run Tests",
167+
"type": "shell",
168+
"command": "make check-qtest-buddy -j10",
169+
"group": "build",
170+
"problemMatcher": [
171+
"$gcc"
172+
],
173+
"presentation": {
174+
"echo": true,
175+
"reveal": "always",
176+
"focus": false,
177+
"panel": "shared",
178+
"showReuseMessage": true,
179+
"clear": true
180+
}
181+
},
182+
{
183+
"label": "Make HTML Report",
184+
"type": "shell",
185+
"command": "make coverage-html -j10",
186+
// lcov -extract coverage.info '*/arm/prusa/*' --rc lcov_branch_coverage=1 --output-file=c2.info
187+
// genhtml --output-directory c2 --legend --show-details --branch-coverage c2.info
188+
"group": "build",
189+
"problemMatcher": [
190+
"$gcc"
191+
],
192+
"presentation": {
193+
"echo": true,
194+
"reveal": "always",
195+
"focus": false,
196+
"panel": "shared",
197+
"showReuseMessage": true,
198+
"clear": true
199+
}
149200
}
150201
]
151202
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Remaining To-Dos of note:
1010

1111
- ![CI Build](https://github.com/vintagepc/MINI404/workflows/CI%20Build/badge.svg)
1212
- ![Code Lint](https://github.com/vintagepc/MINI404/workflows/Code%20Lint/badge.svg)
13+
- [![Coverage](https://codecov.io/gh/vintagepc/MINI404/branch/master/graph/badge.svg)](https://codecov.io/gh/vintagepc/MINI404)
1314

1415
# Getting Started (Building):
1516

hw/arm/prusa/meson.build

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ endif
3030
pngdep = dependency('libpng', fallback : ['libpng', 'png_dep'])
3131
arm_ss.add(when: 'CONFIG_BUDDYBOARD', if_true: [pngdep])
3232

33+
# Add test sources only if coverage is enabled.
34+
if config_host_data.get('CONFIG_GCOV')
35+
subdir('stm32_tests')
36+
endif
37+
3338
subdir('stm32_common')
3439
subdir('stm32f407')
3540
subdir('stm32f030')

hw/arm/prusa/parts/encoder_input.c

-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ OBJECT_DEFINE_TYPE_SIMPLE_WITH_INTERFACES(InputState, encoder_input, ENCODER_INP
164164

165165
static void encoder_input_finalize(Object *obj)
166166
{
167-
printf("Input_finalize\n");
168167
}
169168

170169
static void encoder_input_reset(DeviceState *dev)

hw/arm/prusa/parts/pinda.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct PindaState {
4949
};
5050

5151
enum {
52-
ACT_SET_MBL,
52+
ACT_SET_MBL,
5353

5454
};
5555

@@ -85,7 +85,7 @@ static void pinda_update(PindaState *s) {
8585

8686
}
8787

88-
static void pinda_move(void *opaque, int n, int level)
88+
static void pinda_move(void *opaque, int n, int level)
8989
{
9090
PindaState *s = PINDA(opaque);
9191
s->current_pos[n] = level;
@@ -95,8 +95,9 @@ static void pinda_move(void *opaque, int n, int level)
9595
}
9696

9797
static void pinda_rebuild_mesh(PindaState *s) {
98-
printf("MBL Grid: \n");
98+
printf("# MBL Grid: \n");
9999
for (int i=0; i<4; i++) {
100+
printf("# ");
100101
for (int j=0; j<4; j++) {
101102
s->step_mesh[i][j] = (s->mesh_mm[i][j])*Z_MM_TO_STEPS;
102103
printf("%f ",s->mesh_mm[i][j]);
@@ -118,7 +119,7 @@ static int pinda_process_action(P404ScriptIF *obj, unsigned int action, script_a
118119
float fZ = scripthost_get_float(args, 2);
119120
if (iX<0 || iY <0 || iX>3 || iY>3 || fZ<-0.99) {
120121
fprintf(stderr, "Scripting error - MBL argument out of range! (index 0-4, z > -1) \n");
121-
return ScriptLS_Error; // Bad input.
122+
return ScriptLS_Error; // Bad input.
122123
} else {
123124
s->mesh_mm[iY][iX] = 1.F + fZ;
124125
pinda_rebuild_mesh(s);

hw/arm/prusa/parts/software_spi.c

-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ static void software_spi_init(Object *obj)
123123
qdev_init_gpio_out_named(dev, &s->miso, "miso", 1);
124124

125125
s->ssi = ssi_create_bus(dev, "ssi");
126-
printf("Init swspi");
127126
}
128127

129128
static void software_spi_class_init(ObjectClass *klass, void *data)

hw/arm/prusa/stm32_common/stm32_common.c

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#include "qemu/osdep.h"
2+
#include "qemu/log.h"
23
#include "qom/object.h"
34
#include "sysemu/block-backend.h"
5+
#include "hw/boards.h"
46
#include "hw/qdev-core.h"
7+
#include "qapi/error.h"
8+
#include "hw/arm/armv7m.h"
9+
#include "hw/arm/boot.h"
510
#include "hw/qdev-properties.h"
611
#include "stm32_common.h"
712
#include "stm32_chip_macros.h"
@@ -248,7 +253,7 @@ extern void stm32_soc_realize_peripheral(DeviceState* soc_state, stm32_periph_t
248253
}
249254
else
250255
{
251-
printf("Warning: Peripheral %s does not support the STM32 Common interface\n", _PERIPHNAMES[id]);
256+
qemu_log_mask(LOG_UNIMP, "Warning: Peripheral %s does not support the STM32 Common interface\n", _PERIPHNAMES[id]);
252257
}
253258
}
254259
if (!sysbus_realize(SYS_BUS_DEVICE(s->perhiperhals[id]), errp)) {
@@ -352,3 +357,20 @@ static void stm32_base_register_types(void)
352357
}
353358

354359
type_init(stm32_base_register_types);
360+
361+
extern void stm32_soc_machine_init(MachineState *machine)
362+
{
363+
DeviceState *dev;
364+
STM32SocMachineClass *smc = STM32_MACHINE_GET_CLASS(OBJECT(machine));
365+
366+
dev = qdev_new(smc->soc_type);
367+
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
368+
qdev_prop_set_string(dev, "cpu-type", smc->cpu_type);
369+
qdev_prop_set_uint32(dev,"sram-size", machine->ram_size);
370+
uint64_t flash_size = stm32_soc_get_flash_size(dev);
371+
sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
372+
373+
armv7m_load_kernel(ARM_CPU(first_cpu),
374+
machine->kernel_filename,
375+
flash_size);
376+
}

hw/arm/prusa/stm32_common/stm32_common.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "qemu/osdep.h"
77
#include "qemu/units.h"
88
#include "sysemu/blockdev.h"
9+
#include "hw/boards.h"
910
#include "hw/sysbus.h"
1011
#include "../utility/macros.h"
1112
#include "stm32_shared.h"
@@ -61,8 +62,20 @@ typedef struct STM32PeripheralClass
6162

6263
// Common class data for variant storage.
6364

64-
// Base class for a SOC with a config blob.
65+
// Machine class templates:
66+
typedef struct STM32SocMachineClass {
67+
MachineClass parent;
68+
69+
const char *soc_type;
70+
const char *cpu_type;
71+
} STM32SocMachineClass;
72+
73+
#define STM32_MACHINE_CLASS(klass) \
74+
OBJECT_CLASS_CHECK(STM32SocMachineClass, (klass), TYPE_STM32_MACHINE)
75+
#define STM32_MACHINE_GET_CLASS(obj) \
76+
OBJECT_GET_CLASS(STM32SocMachineClass, (obj), TYPE_STM32_MACHINE)
6577

78+
// Base class for a SOC with a config blob.
6679
typedef struct STM32SOCClass {
6780
SysBusDeviceClass parent_class;
6881
const struct stm32_soc_cfg_t* cfg; // Chip variant configuration store.
@@ -82,9 +95,10 @@ typedef struct STM32SOC {
8295
bool has_sys_memory;
8396
} STM32SOC;
8497

85-
8698
OBJECT_DECLARE_TYPE(STM32SOC, STM32SOCClass, STM32_SOC);
8799

100+
extern void stm32_soc_machine_init(MachineState *machine);
101+
88102
extern hwaddr stm32_soc_get_flash_size(DeviceState* soc);
89103
extern hwaddr stm32_soc_get_sram_size(DeviceState* soc);
90104
extern hwaddr stm32_soc_get_ccmsram_size(DeviceState* soc);

hw/arm/prusa/stm32_common/stm32_dma.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ static void stm32_common_dma_realize(DeviceState *dev, Error **errp)
494494
COM_STRUCT_NAME(Dma) *s = STM32COM_DMA(dev);
495495
if (s->cpu_mr == NULL)
496496
{
497-
printf("No CPU memory region specified for %s - using global system memory.\n", _PERIPHNAMES[s->parent.periph]);
497+
qemu_log_mask(LOG_UNIMP, "No CPU memory region specified for %s - using global system memory.\n", _PERIPHNAMES[s->parent.periph]);
498498
s->cpu_mr = get_system_memory();
499499
}
500500
gchar* name = g_strdup_printf("STM32COM_DMA_%d", s->parent.periph - STM32_P_DMA_BEGIN);

0 commit comments

Comments
 (0)