Rodrigo Arias
1792c650ec
Implements a small language parser to define the emulator events. The event specification is parsed at emulation (when the emulator runs). The ovnidump output now prints the events with the arguments formatted as given in the event description. It also introduces some consistency checks over the event MCVs, which must begin with the model identifier and cannot be duplicated.
163 lines
3.3 KiB
C
163 lines
3.3 KiB
C
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
|
|
#include "ev_spec.h"
|
|
|
|
#include "unittest.h"
|
|
#include "emu_ev.h"
|
|
#include <string.h>
|
|
|
|
struct testcase {
|
|
struct ev_decl decl;
|
|
uint8_t payload[256];
|
|
int ret_compile;
|
|
int ret_print;
|
|
char *output;
|
|
};
|
|
|
|
static void
|
|
test_format(void)
|
|
{
|
|
struct testcase cases[] = {
|
|
/* Bad compile tests */
|
|
{
|
|
/* Test bad MCV */
|
|
.decl = { "O x", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Jumbo but no argument (nonsense) */
|
|
.decl = { "OHx+", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Empty arguments */
|
|
.decl = { "OHx()", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Missing opening parenthesis */
|
|
.decl = { "OHx)", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Typo, 4 MCV char */
|
|
.decl = { "OOHx", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Typo, 2 MCV char */
|
|
.decl = { "Ox", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
{
|
|
/* Typo, 2 MCV char with args */
|
|
.decl = { "Ox(i32 cpu)", "" },
|
|
.ret_compile = -1,
|
|
},
|
|
/* Bad printing tests */
|
|
{
|
|
/* Test missing argument */
|
|
.decl = { "OHx", "hi missing %{cpu}" },
|
|
.ret_print = -1,
|
|
},
|
|
{
|
|
/* Test missing closing bracket */
|
|
.decl = { "OHx(i32 cpu)", "hi missing %{cpu" },
|
|
.ret_print = -1,
|
|
},
|
|
{
|
|
/* Test using parenthesis instead */
|
|
.decl = { "OHx(i32 cpu)", "hi missing %(cpu)" },
|
|
.ret_print = -1,
|
|
},
|
|
/* Good tests */
|
|
{
|
|
/* Test arguments in normal event */
|
|
.decl = {
|
|
"OAr(i32 cpu, i32 tid)",
|
|
"changes the affinity of thread %{tid} to CPU %{cpu}"
|
|
},
|
|
.payload = {
|
|
0x01, 0x00, 0x00, 0x00, /* CPU */
|
|
0x02, 0x00, 0x00, 0x00, /* TID */
|
|
},
|
|
.output = "changes the affinity of thread 2 to CPU 1",
|
|
},
|
|
{
|
|
/* Test custom printf format */
|
|
.decl = {
|
|
"OAr(i32 cpu)",
|
|
"we like the CPU %08d{cpu} well padded"
|
|
},
|
|
.payload = {
|
|
0x03, 0x00, 0x00, 0x00, /* CPU */
|
|
},
|
|
.output = "we like the CPU 00000003 well padded",
|
|
},
|
|
{
|
|
/* Test i32 in jumbo */
|
|
.decl = {
|
|
"ooo+(i32 cpu)", "welcome to CPU %{cpu}"
|
|
},
|
|
.payload = {
|
|
0x00, 0x00, 0x00, 0x00, /* jumbo size,
|
|
ignored */
|
|
0x05, 0x00, 0x00, 0x00, /* cpu */
|
|
},
|
|
.output = "welcome to CPU 5",
|
|
},
|
|
{
|
|
/* Test string in jumbo */
|
|
.decl = {
|
|
"ooo+(str name)", "welcome %{name}!"
|
|
},
|
|
.payload = {
|
|
0x00, 0x00, 0x00, 0x00, /* jumbo size,
|
|
ignored */
|
|
'a', 'l', 'i', 'e', 'n', '\0', /* name */
|
|
},
|
|
.output = "welcome alien!",
|
|
},
|
|
};
|
|
|
|
char buf[1024];
|
|
int bufsize = 1024;
|
|
int n = sizeof(cases) / sizeof(cases[0]);
|
|
for (int i = 0; i < n; i++) {
|
|
struct testcase *c = &cases[i];
|
|
struct ev_spec spec = {0};
|
|
struct ev_decl *decl = &c->decl;
|
|
struct emu_ev ev = {
|
|
.payload = (union ovni_ev_payload *) &c->payload
|
|
};
|
|
if (ev_spec_compile(&spec, decl) != c->ret_compile)
|
|
die("compile return mismatch for %s", decl->signature);
|
|
|
|
/* Only print if compiled worked */
|
|
if (c->ret_compile == 0) {
|
|
if (ev_spec_print(&spec, &ev, buf, bufsize) != c->ret_print)
|
|
die("print return mismatch for %s", decl->signature);
|
|
|
|
/* Only check buffer if print worked */
|
|
if (c->ret_print == 0) {
|
|
if (strcmp(buf, c->output) != 0)
|
|
die("different output: '%s' != '%s'",
|
|
buf, c->output);
|
|
else
|
|
info("same output");
|
|
}
|
|
}
|
|
|
|
info("case %d/%d OK", i, n);
|
|
}
|
|
}
|
|
|
|
|
|
int main(void)
|
|
{
|
|
test_format();
|
|
|
|
return 0;
|
|
}
|