Removed concept of geometries from test/bench runners

This turned out to not be all that useful.

Tests already take quite a bit to run, which is a good thing! We have a
lot of tests! 942.68s or ~15 minutes of tests at the time of writing to
be exact. But simply multiplying the number of tests by some number of
geometries is heavy handed and not a great use of testing time.

Instead, tests where different geometries are relevant can parameterize
READ_SIZE/PROG_SIZE/BLOCK_SIZE at the suite level where needed. The
geometry system was just another define parameterization layer anyways.

Testing different geometries can still be done in CI by overriding the
relevant defines anyways, and it _might_ be interesting there.
This commit is contained in:
Christopher Haster
2023-11-29 13:51:40 -06:00
parent b8d3a5ef46
commit d485795336
6 changed files with 104 additions and 602 deletions
+24 -254
View File
@@ -110,11 +110,6 @@ static uintmax_t leb16_parse(const char *s, char **tail) {
// bench_runner types
typedef struct bench_geometry {
const char *name;
bench_define_t defines[BENCH_GEOMETRY_DEFINE_COUNT];
} bench_geometry_t;
typedef struct bench_id {
const char *name;
const bench_define_t *defines;
@@ -155,9 +150,9 @@ intmax_t bench_define_lit(void *data, size_t i) {
#define BENCH_DEFINE_MAP_OVERRIDE 0
#define BENCH_DEFINE_MAP_EXPLICIT 1
#define BENCH_DEFINE_MAP_CASE 2
#define BENCH_DEFINE_MAP_GEOMETRY 3
#define BENCH_DEFINE_MAP_IMPLICIT 4
#define BENCH_DEFINE_MAP_COUNT 5
#define BENCH_DEFINE_MAP_IMPLICIT 3
#define BENCH_DEFINE_MAP_COUNT 4
bench_define_map_t bench_define_maps[BENCH_DEFINE_MAP_COUNT] = {
[BENCH_DEFINE_MAP_IMPLICIT] = {
@@ -334,14 +329,6 @@ void bench_define_case(
}
}
// geometry updates
const bench_geometry_t *bench_geometry = NULL;
void bench_define_geometry(const bench_geometry_t *geometry) {
bench_define_maps[BENCH_DEFINE_MAP_GEOMETRY] = (bench_define_map_t){
geometry->defines, BENCH_GEOMETRY_DEFINE_COUNT};
}
// override updates
typedef struct bench_override {
const char *name;
@@ -451,9 +438,6 @@ void bench_define_cleanup(void) {
// bench state
extern const bench_geometry_t *bench_geometries;
extern size_t bench_geometry_count;
const bench_id_t *bench_ids = (const bench_id_t[]) {
{NULL, NULL, 0},
};
@@ -846,23 +830,18 @@ static void case_forperm(
// define case permutation
bench_define_case(suite, case_, k);
for (size_t g = 0; g < bench_geometry_count; g++) {
// define geometry
bench_define_geometry(&bench_geometries[g]);
size_t permutations = bench_define_permutationpermutations();
for (size_t p = 0; p < permutations; p++) {
// define permutation permutation
bench_define_permutation(p);
size_t permutations = bench_define_permutationpermutations();
for (size_t p = 0; p < permutations; p++) {
// define permutation permutation
bench_define_permutation(p);
// have we seen this permutation before?
bool was_seen = bench_seen_insert(&seen);
if (!(k == 0 && g == 0 && p == 0) && was_seen) {
continue;
}
cb(data, suite, case_);
// have we seen this permutation before?
bool was_seen = bench_seen_insert(&seen);
if (!(k == 0 && p == 0) && was_seen) {
continue;
}
cb(data, suite, case_);
}
}
@@ -1224,8 +1203,6 @@ void perm_list_permutation_defines(
}
}
extern const bench_geometry_t builtin_geometries[];
static void list_defines(void) {
struct list_defines_defines defines = {NULL, 0, 0};
@@ -1324,17 +1301,11 @@ static void list_implicit_defines(void) {
// yes we do need to define a suite, this does a bit of bookeeping
// such as setting up the define cache
bench_define_suite(&(const struct bench_suite){0});
bench_define_permutation(0);
// make sure to include builtin geometries here
extern const bench_geometry_t builtin_geometries[];
for (size_t g = 0; builtin_geometries[g].name; g++) {
bench_define_geometry(&builtin_geometries[g]);
bench_define_permutation(0);
// add implicit defines
for (size_t d = 0; d < BENCH_IMPLICIT_DEFINE_COUNT; d++) {
list_defines_add(&defines, d);
}
// add implicit defines
for (size_t d = 0; d < BENCH_IMPLICIT_DEFINE_COUNT; d++) {
list_defines_add(&defines, d);
}
for (size_t i = 0; i < defines.define_count; i++) {
@@ -1356,57 +1327,6 @@ static void list_implicit_defines(void) {
// geometries to bench
const bench_geometry_t builtin_geometries[] = {
#define BENCH_GEO(name, read_size, prog_size, block_size) \
{name, { \
BENCH_CONST(read_size), \
BENCH_CONST(prog_size), \
BENCH_CONST(block_size), \
}},
BENCH_GEOMETRIES
#undef BENCH_GEO
{NULL, {{0}, {0}, {0}}},
};
const bench_geometry_t *bench_geometries = builtin_geometries;
size_t bench_geometry_count = 5;
static void list_geometries(void) {
// at least size so that names fit
unsigned name_width = 23;
for (size_t g = 0; builtin_geometries[g].name; g++) {
size_t len = strlen(builtin_geometries[g].name);
if (len > name_width) {
name_width = len;
}
}
name_width = 4*((name_width+1+4-1)/4)-1;
// yes we do need to define a suite, this does a bit of bookeeping
// such as setting up the define cache
bench_define_suite(&(const struct bench_suite){0});
printf("%-*s %7s %7s %7s %7s %11s\n",
name_width, "geometry", "read", "prog", "erase", "count", "size");
for (size_t g = 0; builtin_geometries[g].name; g++) {
bench_define_geometry(&builtin_geometries[g]);
bench_define_permutation(0);
printf("%-*s %7ju %7ju %7ju %7ju %11ju\n",
name_width,
builtin_geometries[g].name,
READ_SIZE,
PROG_SIZE,
BLOCK_SIZE,
BLOCK_COUNT,
DISK_SIZE);
}
}
// global bench step count
size_t bench_step = 0;
@@ -1522,21 +1442,19 @@ enum opt_flags {
OPT_LIST_DEFINES = 3,
OPT_LIST_PERMUTATION_DEFINES = 4,
OPT_LIST_IMPLICIT_DEFINES = 5,
OPT_LIST_GEOMETRIES = 6,
OPT_DEFINE = 'D',
OPT_GEOMETRY = 'G',
OPT_STEP = 's',
OPT_DISK = 'd',
OPT_TRACE = 't',
OPT_TRACE_BACKTRACE = 7,
OPT_TRACE_PERIOD = 8,
OPT_TRACE_FREQ = 9,
OPT_READ_SLEEP = 10,
OPT_PROG_SLEEP = 11,
OPT_ERASE_SLEEP = 12,
OPT_TRACE_BACKTRACE = 6,
OPT_TRACE_PERIOD = 7,
OPT_TRACE_FREQ = 8,
OPT_READ_SLEEP = 9,
OPT_PROG_SLEEP = 10,
OPT_ERASE_SLEEP = 11,
};
const char *short_opts = "hYlLD:G:s:d:t:";
const char *short_opts = "hYlLD:s:d:t:";
const struct option long_opts[] = {
{"help", no_argument, NULL, OPT_HELP},
@@ -1550,9 +1468,7 @@ const struct option long_opts[] = {
no_argument, NULL, OPT_LIST_PERMUTATION_DEFINES},
{"list-implicit-defines",
no_argument, NULL, OPT_LIST_IMPLICIT_DEFINES},
{"list-geometries", no_argument, NULL, OPT_LIST_GEOMETRIES},
{"define", required_argument, NULL, OPT_DEFINE},
{"geometry", required_argument, NULL, OPT_GEOMETRY},
{"step", required_argument, NULL, OPT_STEP},
{"disk", required_argument, NULL, OPT_DISK},
{"trace", required_argument, NULL, OPT_TRACE},
@@ -1575,9 +1491,7 @@ const char *const help_text[] = {
"List all defines in this bench-runner.",
"List explicit defines in this bench-runner.",
"List implicit defines in this bench-runner.",
"List the available disk geometries.",
"Override a bench define.",
"Comma-separated list of disk geometries to bench.",
"Comma-separated range of bench permutations to run (start,stop,step).",
"Direct block device operations to this file.",
"Direct trace output to this file.",
@@ -1593,7 +1507,6 @@ int main(int argc, char **argv) {
void (*op)(void) = run;
size_t bench_override_capacity = 0;
size_t bench_geometry_capacity = 0;
size_t bench_id_capacity = 0;
// parse options
@@ -1681,9 +1594,6 @@ int main(int argc, char **argv) {
case OPT_LIST_IMPLICIT_DEFINES:
op = list_implicit_defines;
break;
case OPT_LIST_GEOMETRIES:
op = list_geometries;
break;
// configuration
case OPT_DEFINE: {
// allocate space
@@ -1834,143 +1744,6 @@ invalid_define:
fprintf(stderr, "error: invalid define: %s\n", optarg);
exit(-1);
}
case OPT_GEOMETRY: {
// reset our geometry scenarios
if (bench_geometry_capacity > 0) {
free((bench_geometry_t*)bench_geometries);
}
bench_geometries = NULL;
bench_geometry_count = 0;
bench_geometry_capacity = 0;
// parse the comma separated list of disk geometries
while (*optarg) {
// allocate space
bench_geometry_t *geometry = mappend(
(void**)&bench_geometries,
sizeof(bench_geometry_t),
&bench_geometry_count,
&bench_geometry_capacity);
// parse the disk geometry
optarg += strspn(optarg, " ");
// named disk geometry
size_t len = strcspn(optarg, " ,");
for (size_t i = 0; builtin_geometries[i].name; i++) {
if (len == strlen(builtin_geometries[i].name)
&& memcmp(optarg,
builtin_geometries[i].name,
len) == 0) {
*geometry = builtin_geometries[i];
optarg += len;
goto geometry_next;
}
}
// comma-separated read/prog/erase
if (*optarg == '{') {
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (count < 3) {
char *parsed = NULL;
sizes[count] = strtoumax(s, &parsed, 0);
count += 1;
s = parsed + strspn(parsed, " ");
if (*s == ',') {
s += 1;
continue;
} else if (*s == '}') {
s += 1;
break;
} else {
goto geometry_unknown;
}
}
// allow implicit r=p and p=e for common geometries
memset(geometry, 0, sizeof(bench_geometry_t));
if (count >= 3) {
geometry->defines[READ_SIZE_i]
= BENCH_LIT(sizes[0]);
geometry->defines[PROG_SIZE_i]
= BENCH_LIT(sizes[1]);
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[2]);
} else if (count >= 2) {
geometry->defines[PROG_SIZE_i]
= BENCH_LIT(sizes[0]);
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[1]);
} else {
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[0]);
}
optarg = s;
goto geometry_next;
}
// leb16-encoded read/prog/erase/count
if (*optarg == ':') {
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (true) {
char *parsed = NULL;
uintmax_t x = leb16_parse(s, &parsed);
if (parsed == s || count >= 3) {
break;
}
sizes[count] = x;
count += 1;
s = parsed;
}
// allow implicit r=p and p=e for common geometries
memset(geometry, 0, sizeof(bench_geometry_t));
if (count >= 3) {
geometry->defines[READ_SIZE_i]
= BENCH_LIT(sizes[0]);
geometry->defines[PROG_SIZE_i]
= BENCH_LIT(sizes[1]);
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[2]);
} else if (count >= 2) {
geometry->defines[PROG_SIZE_i]
= BENCH_LIT(sizes[0]);
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[1]);
} else {
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[0]);
}
optarg = s;
goto geometry_next;
}
geometry_unknown:
// unknown scenario?
fprintf(stderr, "error: unknown disk geometry: %s\n",
optarg);
exit(-1);
geometry_next:
optarg += strspn(optarg, " ");
if (*optarg == ',') {
optarg += 1;
} else if (*optarg == '\0') {
break;
} else {
goto geometry_unknown;
}
}
break;
}
case OPT_STEP: {
char *parsed = NULL;
bench_step_start = strtoumax(optarg, &parsed, 0);
@@ -2168,9 +1941,6 @@ getopt_done: ;
}
free((void*)bench_overrides);
}
if (bench_geometry_capacity) {
free((void*)bench_geometries);
}
if (bench_id_capacity) {
for (size_t i = 0; i < bench_id_count; i++) {
free((void*)bench_ids[i].defines);
+20 -29
View File
@@ -112,25 +112,24 @@ intmax_t bench_define(size_t define);
// a few preconfigured defines that control how benches run
#define BENCH_IMPLICIT_DEFINE_COUNT 16
#define BENCH_GEOMETRY_DEFINE_COUNT 3
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define INLINE_SIZE_i 6
#define SHRUB_SIZE_i 7
#define FRAGMENT_SIZE_i 8
#define CRYSTAL_SIZE_i 9
#define LOOKAHEAD_SIZE_i 10
#define BLOCK_CYCLES_i 11
#define ERASE_VALUE_i 12
#define ERASE_CYCLES_i 13
#define BADBLOCK_BEHAVIOR_i 14
#define POWERLOSS_BEHAVIOR_i 15
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define INLINE_SIZE_i 6
#define SHRUB_SIZE_i 7
#define FRAGMENT_SIZE_i 8
#define CRYSTAL_SIZE_i 9
#define LOOKAHEAD_SIZE_i 10
#define BLOCK_CYCLES_i 11
#define ERASE_VALUE_i 12
#define ERASE_CYCLES_i 13
#define BADBLOCK_BEHAVIOR_i 14
#define POWERLOSS_BEHAVIOR_i 15
#define BENCH_IMPLICIT_DEFINE_COUNT 16
#define READ_SIZE bench_define(READ_SIZE_i)
#define PROG_SIZE bench_define(PROG_SIZE_i)
@@ -151,9 +150,9 @@ intmax_t bench_define(size_t define);
#define BENCH_IMPLICIT_DEFINES \
/* name value (overridable) */ \
BENCH_DEF(READ_SIZE, PROG_SIZE ) \
BENCH_DEF(PROG_SIZE, BLOCK_SIZE ) \
BENCH_DEF(BLOCK_SIZE, 0 ) \
BENCH_DEF(READ_SIZE, 1 ) \
BENCH_DEF(PROG_SIZE, 1 ) \
BENCH_DEF(BLOCK_SIZE, 4096 ) \
BENCH_DEF(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \
BENCH_DEF(DISK_SIZE, 1024*1024 ) \
BENCH_DEF(CACHE_SIZE, lfs_max(16, lfs_max(READ_SIZE, PROG_SIZE))) \
@@ -168,14 +167,6 @@ intmax_t bench_define(size_t define);
BENCH_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR ) \
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP )
#define BENCH_GEOMETRIES \
/* name read_size prog_size block_size */ \
BENCH_GEO("default", 16, 16, 512 ) \
BENCH_GEO("eeprom", 1, 1, 512 ) \
BENCH_GEO("emmc", 512, 512, 512 ) \
BENCH_GEO("nor", 1, 1, 4096 ) \
BENCH_GEO("nand", 4096, 4096, 32768 )
#define BENCH_CFG \
.read_size = READ_SIZE, \
.prog_size = PROG_SIZE, \
+38 -266
View File
@@ -110,11 +110,6 @@ static uintmax_t leb16_parse(const char *s, char **tail) {
// test_runner types
typedef struct test_geometry {
const char *name;
test_define_t defines[TEST_GEOMETRY_DEFINE_COUNT];
} test_geometry_t;
typedef struct test_powerloss {
const char *name;
void (*run)(
@@ -168,9 +163,9 @@ intmax_t test_define_lit(void *data, size_t i) {
#define TEST_DEFINE_MAP_OVERRIDE 0
#define TEST_DEFINE_MAP_EXPLICIT 1
#define TEST_DEFINE_MAP_CASE 2
#define TEST_DEFINE_MAP_GEOMETRY 3
#define TEST_DEFINE_MAP_IMPLICIT 4
#define TEST_DEFINE_MAP_COUNT 5
#define TEST_DEFINE_MAP_IMPLICIT 3
#define TEST_DEFINE_MAP_COUNT 4
test_define_map_t test_define_maps[TEST_DEFINE_MAP_COUNT] = {
[TEST_DEFINE_MAP_IMPLICIT] = {
@@ -187,6 +182,7 @@ test_define_map_t test_define_maps[TEST_DEFINE_MAP_COUNT] = {
#define TEST_DEFINE_NAMES_SUITE 0
#define TEST_DEFINE_NAMES_IMPLICIT 1
#define TEST_DEFINE_NAMES_COUNT 2
test_define_names_t test_define_names[TEST_DEFINE_NAMES_COUNT] = {
@@ -347,14 +343,6 @@ void test_define_case(
}
}
// geometry updates
const test_geometry_t *test_geometry = NULL;
void test_define_geometry(const test_geometry_t *geometry) {
test_define_maps[TEST_DEFINE_MAP_GEOMETRY] = (test_define_map_t){
geometry->defines, TEST_GEOMETRY_DEFINE_COUNT};
}
// override updates
typedef struct test_override {
const char *name;
@@ -464,9 +452,6 @@ void test_define_cleanup(void) {
// test state
extern const test_geometry_t *test_geometries;
extern size_t test_geometry_count;
extern const test_powerloss_t *test_powerlosses;
extern size_t test_powerloss_count;
size_t test_pls = 0;
@@ -800,36 +785,31 @@ static void case_forperm(
// define case permutation
test_define_case(suite, case_, k);
for (size_t g = 0; g < test_geometry_count; g++) {
// define geometry
test_define_geometry(&test_geometries[g]);
size_t permutations = test_define_permutationpermutations();
for (size_t p = 0; p < permutations; p++) {
// define permutation permutation
test_define_permutation(p);
size_t permutations = test_define_permutationpermutations();
for (size_t p = 0; p < permutations; p++) {
// define permutation permutation
test_define_permutation(p);
// have we seen this permutation before?
bool was_seen = test_seen_insert(&seen);
if (!(k == 0 && p == 0) && was_seen) {
continue;
}
// have we seen this permutation before?
bool was_seen = test_seen_insert(&seen);
if (!(k == 0 && g == 0 && p == 0) && was_seen) {
continue;
}
if (cycles) {
cb(data, suite, case_, &(test_powerloss_t){
.run=run_powerloss_cycles,
.cycles=cycles,
.cycle_count=cycle_count});
} else {
for (size_t p = 0; p < test_powerloss_count; p++) {
// skip non-reentrant tests when powerloss testing
if (test_powerlosses[p].run != run_powerloss_none
&& !(case_->flags & TEST_REENTRANT)) {
continue;
}
cb(data, suite, case_, &test_powerlosses[p]);
if (cycles) {
cb(data, suite, case_, &(test_powerloss_t){
.run=run_powerloss_cycles,
.cycles=cycles,
.cycle_count=cycle_count});
} else {
for (size_t p = 0; p < test_powerloss_count; p++) {
// skip non-reentrant tests when powerloss testing
if (test_powerlosses[p].run != run_powerloss_none
&& !(case_->flags & TEST_REENTRANT)) {
continue;
}
cb(data, suite, case_, &test_powerlosses[p]);
}
}
}
@@ -1211,8 +1191,6 @@ void perm_list_permutation_defines(
}
}
extern const test_geometry_t builtin_geometries[];
static void list_defines(void) {
struct list_defines_defines defines = {NULL, 0, 0};
@@ -1315,17 +1293,11 @@ static void list_implicit_defines(void) {
// yes we do need to define a suite, this does a bit of bookeeping
// such as setting up the define cache
test_define_suite(&(const struct test_suite){0});
test_define_permutation(0);
// make sure to include builtin geometries here
extern const test_geometry_t builtin_geometries[];
for (size_t g = 0; builtin_geometries[g].name; g++) {
test_define_geometry(&builtin_geometries[g]);
test_define_permutation(0);
// add implicit defines
for (size_t d = 0; d < TEST_IMPLICIT_DEFINE_COUNT; d++) {
list_defines_add(&defines, d);
}
// add implicit defines
for (size_t d = 0; d < TEST_IMPLICIT_DEFINE_COUNT; d++) {
list_defines_add(&defines, d);
}
for (size_t i = 0; i < defines.define_count; i++) {
@@ -1347,56 +1319,6 @@ static void list_implicit_defines(void) {
// geometries to test
const test_geometry_t builtin_geometries[] = {
#define TEST_GEO(name, read_size, prog_size, block_size) \
{name, { \
TEST_CONST(read_size), \
TEST_CONST(prog_size), \
TEST_CONST(block_size), \
}},
TEST_GEOMETRIES
#undef TEST_GEO
{NULL, {{0}, {0}, {0}}},
};
const test_geometry_t *test_geometries = builtin_geometries;
size_t test_geometry_count = 5;
static void list_geometries(void) {
// at least size so that names fit
unsigned name_width = 23;
for (size_t g = 0; builtin_geometries[g].name; g++) {
size_t len = strlen(builtin_geometries[g].name);
if (len > name_width) {
name_width = len;
}
}
name_width = 4*((name_width+1+4-1)/4)-1;
// yes we do need to define a suite, this does a bit of bookeeping
// such as setting up the define cache
test_define_suite(&(const struct test_suite){0});
printf("%-*s %7s %7s %7s %7s %11s\n",
name_width, "geometry", "read", "prog", "erase", "count", "size");
for (size_t g = 0; builtin_geometries[g].name; g++) {
test_define_geometry(&builtin_geometries[g]);
test_define_permutation(0);
printf("%-*s %7ju %7ju %7ju %7ju %11ju\n",
name_width,
builtin_geometries[g].name,
READ_SIZE,
PROG_SIZE,
BLOCK_SIZE,
BLOCK_COUNT,
DISK_SIZE);
}
}
// scenarios to run tests under power-loss
static void run_powerloss_none(
@@ -1998,23 +1920,21 @@ enum opt_flags {
OPT_LIST_DEFINES = 3,
OPT_LIST_PERMUTATION_DEFINES = 4,
OPT_LIST_IMPLICIT_DEFINES = 5,
OPT_LIST_GEOMETRIES = 6,
OPT_LIST_POWERLOSSES = 7,
OPT_LIST_POWERLOSSES = 6,
OPT_DEFINE = 'D',
OPT_GEOMETRY = 'G',
OPT_POWERLOSS = 'P',
OPT_STEP = 's',
OPT_DISK = 'd',
OPT_TRACE = 't',
OPT_TRACE_BACKTRACE = 8,
OPT_TRACE_PERIOD = 9,
OPT_TRACE_FREQ = 10,
OPT_READ_SLEEP = 11,
OPT_PROG_SLEEP = 12,
OPT_ERASE_SLEEP = 13,
OPT_TRACE_BACKTRACE = 7,
OPT_TRACE_PERIOD = 8,
OPT_TRACE_FREQ = 9,
OPT_READ_SLEEP = 10,
OPT_PROG_SLEEP = 11,
OPT_ERASE_SLEEP = 12,
};
const char *short_opts = "hYlLD:G:P:s:d:t:";
const char *short_opts = "hYlLD:P:s:d:t:";
const struct option long_opts[] = {
{"help", no_argument, NULL, OPT_HELP},
@@ -2028,10 +1948,8 @@ const struct option long_opts[] = {
no_argument, NULL, OPT_LIST_PERMUTATION_DEFINES},
{"list-implicit-defines",
no_argument, NULL, OPT_LIST_IMPLICIT_DEFINES},
{"list-geometries", no_argument, NULL, OPT_LIST_GEOMETRIES},
{"list-powerlosses", no_argument, NULL, OPT_LIST_POWERLOSSES},
{"define", required_argument, NULL, OPT_DEFINE},
{"geometry", required_argument, NULL, OPT_GEOMETRY},
{"powerloss", required_argument, NULL, OPT_POWERLOSS},
{"step", required_argument, NULL, OPT_STEP},
{"disk", required_argument, NULL, OPT_DISK},
@@ -2055,10 +1973,8 @@ const char *const help_text[] = {
"List all defines in this test-runner.",
"List explicit defines in this test-runner.",
"List implicit defines in this test-runner.",
"List the available disk geometries.",
"List the available power-loss scenarios.",
"Override a test define.",
"Comma-separated list of disk geometries to test.",
"Comma-separated list of power-loss scenarios to test.",
"Comma-separated range of test permutations to run (start,stop,step).",
"Direct block device operations to this file.",
@@ -2075,7 +1991,6 @@ int main(int argc, char **argv) {
void (*op)(void) = run;
size_t test_override_capacity = 0;
size_t test_geometry_capacity = 0;
size_t test_powerloss_capacity = 0;
size_t test_id_capacity = 0;
@@ -2164,9 +2079,6 @@ int main(int argc, char **argv) {
case OPT_LIST_IMPLICIT_DEFINES:
op = list_implicit_defines;
break;
case OPT_LIST_GEOMETRIES:
op = list_geometries;
break;
case OPT_LIST_POWERLOSSES:
op = list_powerlosses;
break;
@@ -2320,143 +2232,6 @@ invalid_define:
fprintf(stderr, "error: invalid define: %s\n", optarg);
exit(-1);
}
case OPT_GEOMETRY: {
// reset our geometry scenarios
if (test_geometry_capacity > 0) {
free((test_geometry_t*)test_geometries);
}
test_geometries = NULL;
test_geometry_count = 0;
test_geometry_capacity = 0;
// parse the comma separated list of disk geometries
while (*optarg) {
// allocate space
test_geometry_t *geometry = mappend(
(void**)&test_geometries,
sizeof(test_geometry_t),
&test_geometry_count,
&test_geometry_capacity);
// parse the disk geometry
optarg += strspn(optarg, " ");
// named disk geometry
size_t len = strcspn(optarg, " ,");
for (size_t i = 0; builtin_geometries[i].name; i++) {
if (len == strlen(builtin_geometries[i].name)
&& memcmp(optarg,
builtin_geometries[i].name,
len) == 0) {
*geometry = builtin_geometries[i];
optarg += len;
goto geometry_next;
}
}
// comma-separated read/prog/erase
if (*optarg == '{') {
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (count < 3) {
char *parsed = NULL;
sizes[count] = strtoumax(s, &parsed, 0);
count += 1;
s = parsed + strspn(parsed, " ");
if (*s == ',') {
s += 1;
continue;
} else if (*s == '}') {
s += 1;
break;
} else {
goto geometry_unknown;
}
}
// allow implicit r=p and p=e for common geometries
memset(geometry, 0, sizeof(test_geometry_t));
if (count >= 3) {
geometry->defines[READ_SIZE_i]
= TEST_LIT(sizes[0]);
geometry->defines[PROG_SIZE_i]
= TEST_LIT(sizes[1]);
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[2]);
} else if (count >= 2) {
geometry->defines[PROG_SIZE_i]
= TEST_LIT(sizes[0]);
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[1]);
} else {
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[0]);
}
optarg = s;
goto geometry_next;
}
// leb16-encoded read/prog/erase/count
if (*optarg == ':') {
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (true) {
char *parsed = NULL;
uintmax_t x = leb16_parse(s, &parsed);
if (parsed == s || count >= 3) {
break;
}
sizes[count] = x;
count += 1;
s = parsed;
}
// allow implicit r=p and p=e for common geometries
memset(geometry, 0, sizeof(test_geometry_t));
if (count >= 3) {
geometry->defines[READ_SIZE_i]
= TEST_LIT(sizes[0]);
geometry->defines[PROG_SIZE_i]
= TEST_LIT(sizes[1]);
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[2]);
} else if (count >= 2) {
geometry->defines[PROG_SIZE_i]
= TEST_LIT(sizes[0]);
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[1]);
} else {
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[0]);
}
optarg = s;
goto geometry_next;
}
geometry_unknown:
// unknown scenario?
fprintf(stderr, "error: unknown disk geometry: %s\n",
optarg);
exit(-1);
geometry_next:
optarg += strspn(optarg, " ");
if (*optarg == ',') {
optarg += 1;
} else if (*optarg == '\0') {
break;
} else {
goto geometry_unknown;
}
}
break;
}
case OPT_POWERLOSS: {
// reset our powerloss scenarios
if (test_powerloss_capacity > 0) {
@@ -2822,9 +2597,6 @@ getopt_done: ;
}
free((void*)test_overrides);
}
if (test_geometry_capacity) {
free((void*)test_geometries);
}
if (test_powerloss_capacity) {
for (size_t i = 0; i < test_powerloss_count; i++) {
free((void*)test_powerlosses[i].cycles);
+21 -30
View File
@@ -78,7 +78,7 @@ extern size_t test_pls;
#define TEST_PLS test_pls
// deterministic prng for pseudo-randomness in testes
// deterministic prng for pseudo-randomness in tests
uint32_t test_prng(uint32_t *state);
#define TEST_PRNG(state) test_prng(state)
@@ -98,25 +98,24 @@ intmax_t test_define(size_t define);
// a few preconfigured defines that control how tests run
#define TEST_IMPLICIT_DEFINE_COUNT 16
#define TEST_GEOMETRY_DEFINE_COUNT 3
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define INLINE_SIZE_i 6
#define SHRUB_SIZE_i 7
#define FRAGMENT_SIZE_i 8
#define CRYSTAL_SIZE_i 9
#define LOOKAHEAD_SIZE_i 10
#define BLOCK_CYCLES_i 11
#define ERASE_VALUE_i 12
#define ERASE_CYCLES_i 13
#define BADBLOCK_BEHAVIOR_i 14
#define POWERLOSS_BEHAVIOR_i 15
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define INLINE_SIZE_i 6
#define SHRUB_SIZE_i 7
#define FRAGMENT_SIZE_i 8
#define CRYSTAL_SIZE_i 9
#define LOOKAHEAD_SIZE_i 10
#define BLOCK_CYCLES_i 11
#define ERASE_VALUE_i 12
#define ERASE_CYCLES_i 13
#define BADBLOCK_BEHAVIOR_i 14
#define POWERLOSS_BEHAVIOR_i 15
#define TEST_IMPLICIT_DEFINE_COUNT 16
#define READ_SIZE TEST_DEFINE(READ_SIZE_i)
#define PROG_SIZE TEST_DEFINE(PROG_SIZE_i)
@@ -137,9 +136,9 @@ intmax_t test_define(size_t define);
#define TEST_IMPLICIT_DEFINES \
/* name value (overridable) */ \
TEST_DEF(READ_SIZE, PROG_SIZE ) \
TEST_DEF(PROG_SIZE, BLOCK_SIZE ) \
TEST_DEF(BLOCK_SIZE, 0 ) \
TEST_DEF(READ_SIZE, 1 ) \
TEST_DEF(PROG_SIZE, 1 ) \
TEST_DEF(BLOCK_SIZE, 4096 ) \
TEST_DEF(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \
TEST_DEF(DISK_SIZE, 1024*1024 ) \
TEST_DEF(CACHE_SIZE, lfs_max(16, lfs_max(READ_SIZE, PROG_SIZE)) ) \
@@ -154,14 +153,6 @@ intmax_t test_define(size_t define);
TEST_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR ) \
TEST_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP )
#define TEST_GEOMETRIES \
/* name read_size prog_size block_size */ \
TEST_GEO("default", 16, 16, 512 ) \
TEST_GEO("eeprom", 1, 1, 512 ) \
TEST_GEO("emmc", 512, 512, 512 ) \
TEST_GEO("nor", 1, 1, 4096 ) \
TEST_GEO("nand", 4096, 4096, 32768 )
#define TEST_CFG \
.read_size = READ_SIZE, \
.prog_size = PROG_SIZE, \
+1 -12
View File
@@ -640,8 +640,6 @@ def find_runner(runner, id=None, **args):
'-o%s' % args['perf']]))
# other context
if args.get('geometry'):
cmd.append('-G%s' % args['geometry'])
if args.get('disk'):
cmd.append('-d%s' % args['disk'])
if args.get('trace'):
@@ -902,7 +900,6 @@ def list_(runner, bench_ids=[], **args):
cmd.append('--list-permutation-defines')
if args.get('list_implicit_defines'):
cmd.append('--list-implicit-defines')
if args.get('list_geometries'): cmd.append('--list-geometries')
if args.get('verbose'):
print(' '.join(shlex.quote(c) for c in cmd))
@@ -1439,8 +1436,7 @@ def main(**args):
or args.get('list_case_paths')
or args.get('list_defines')
or args.get('list_permutation_defines')
or args.get('list_implicit_defines')
or args.get('list_geometries')):
or args.get('list_implicit_defines')):
return list_(**args)
else:
return run(**args)
@@ -1508,17 +1504,10 @@ if __name__ == "__main__":
'--list-implicit-defines',
action='store_true',
help="List implicit defines in this bench-runner.")
bench_parser.add_argument(
'--list-geometries',
action='store_true',
help="List the available disk geometries.")
bench_parser.add_argument(
'-D', '--define',
action='append',
help="Override a bench define.")
bench_parser.add_argument(
'-G', '--geometry',
help="Comma-separated list of disk geometries to bench.")
bench_parser.add_argument(
'-d', '--disk',
help="Direct block device operations to this file.")
-11
View File
@@ -647,8 +647,6 @@ def find_runner(runner, id=None, **args):
'-o%s' % args['perf']]))
# other context
if args.get('geometry'):
cmd.append('-G%s' % args['geometry'])
if args.get('powerloss'):
cmd.append('-P%s' % args['powerloss'])
if args.get('disk'):
@@ -911,7 +909,6 @@ def list_(runner, test_ids=[], **args):
cmd.append('--list-permutation-defines')
if args.get('list_implicit_defines'):
cmd.append('--list-implicit-defines')
if args.get('list_geometries'): cmd.append('--list-geometries')
if args.get('list_powerlosses'): cmd.append('--list-powerlosses')
if args.get('verbose'):
@@ -1446,7 +1443,6 @@ def main(**args):
or args.get('list_defines')
or args.get('list_permutation_defines')
or args.get('list_implicit_defines')
or args.get('list_geometries')
or args.get('list_powerlosses')):
return list_(**args)
else:
@@ -1515,10 +1511,6 @@ if __name__ == "__main__":
'--list-implicit-defines',
action='store_true',
help="List implicit defines in this test-runner.")
test_parser.add_argument(
'--list-geometries',
action='store_true',
help="List the available disk geometries.")
test_parser.add_argument(
'--list-powerlosses',
action='store_true',
@@ -1527,9 +1519,6 @@ if __name__ == "__main__":
'-D', '--define',
action='append',
help="Override a test define.")
test_parser.add_argument(
'-G', '--geometry',
help="Comma-separated list of disk geometries to test.")
test_parser.add_argument(
'-P', '--powerloss',
help="Comma-separated list of power-loss scenarios to test.")