ANDROID: incremental fs: Add ability to run ranges of tests to incfs_test

Also fix test build, test memory leaks

Test: run various range options
Change-Id: I747b3c02f0eb7da440c9d2c2a67e19164b8c9908
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Bug: 264703896
This commit is contained in:
Paul Lawrence
2022-12-20 10:20:12 -08:00
committed by Treehugger Robot
parent 1d9055b834
commit e6c9473f25
2 changed files with 108 additions and 44 deletions

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS += -D_FILE_OFFSET_BITS=64 -Wall -Werror -I../.. -I../../../../.. -fno-omit-frame-pointer -fsanitize=address -g
CFLAGS += -D_FILE_OFFSET_BITS=64 -Wall -Werror -Wno-deprecated-declarations -I../.. -I../../../../.. -fno-omit-frame-pointer -fsanitize=address -g
LDLIBS := -llz4 -lzstd -lcrypto -lpthread -fsanitize=address
TEST_GEN_PROGS := incfs_test incfs_stress incfs_perf

View File

@@ -60,7 +60,6 @@
struct {
int file;
int test;
bool verbose;
} options;
@@ -935,12 +934,13 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file)
struct incfs_fill_blocks fill_blocks = {
.count = file->mtree_block_count,
};
struct incfs_fill_block *fill_block_array =
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
struct incfs_fill_block *fill_block_array;
if (fill_blocks.count == 0)
return 0;
fill_block_array =
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
if (!fill_block_array)
return -ENOMEM;
fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
@@ -1070,6 +1070,7 @@ static int cant_touch_index_test(const char *mount_dir)
free(index_path);
free(dst_name);
free(filename_in_index);
free(file_path);
if (umount(mount_dir) != 0) {
print_error("Can't unmout FS");
goto failure;
@@ -1082,6 +1083,7 @@ failure:
free(dst_name);
free(index_path);
free(filename_in_index);
free(file_path);
close(cmd_fd);
umount(mount_dir);
return TEST_FAILURE;
@@ -1353,9 +1355,13 @@ static int basic_file_ops_test(const char *mount_dir)
goto failure;
}
free(subdir1);
free(subdir2);
return TEST_SUCCESS;
failure:
free(subdir1);
free(subdir2);
close(cmd_fd);
umount(mount_dir);
return TEST_FAILURE;
@@ -2637,13 +2643,14 @@ static int emit_partial_test_file_hash(const char *mount_dir,
struct incfs_fill_blocks fill_blocks = {
.count = 1,
};
struct incfs_fill_block *fill_block_array =
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
struct incfs_fill_block *fill_block_array;
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
if (file->size <= 4096 / 32 * 4096)
return 0;
fill_block_array =
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
if (!fill_block_array)
return -ENOMEM;
fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
@@ -2678,7 +2685,7 @@ failure:
static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
{
int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
char *filename = concat_file_name(mount_dir, file->name);
char *filename = NULL;
int fd;
struct incfs_filled_range ranges[128];
struct incfs_get_filled_blocks_args fba = {
@@ -2694,6 +2701,7 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
if (file->size <= 4096 / 32 * 4096)
return 0;
filename = concat_file_name(mount_dir, file->name);
fd = open(filename, O_RDONLY | O_CLOEXEC);
free(filename);
if (fd <= 0)
@@ -2805,12 +2813,8 @@ static int large_file_test(const char *mount_dir)
int result = TEST_FAILURE, ret;
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
int block_count = THREE_GB / INCFS_DATA_FILE_BLOCK_SIZE;
struct incfs_fill_block *block_buf =
calloc(block_count, sizeof(struct incfs_fill_block));
struct incfs_fill_blocks fill_blocks = {
.count = block_count,
.fill_blocks = ptr_to_u64(block_buf),
};
struct incfs_fill_block *block_buf = NULL;
struct incfs_fill_blocks fill_blocks;
incfs_uuid_t id;
int fd = -1;
struct statvfs svfs;
@@ -2846,6 +2850,14 @@ static int large_file_test(const char *mount_dir)
NULL) < 0)
goto failure;
block_buf = calloc(block_count, sizeof(struct incfs_fill_block));
if (!block_buf)
goto failure;
fill_blocks = (struct incfs_fill_blocks) {
.count = block_count,
.fill_blocks = ptr_to_u64(block_buf),
};
for (i = 0; i < block_count; i++) {
block_buf[i].compression = COMPRESSION_NONE;
block_buf[i].block_index = i;
@@ -2872,6 +2884,7 @@ failure:
unlink("very_large_file");
umount(mount_dir);
free(backing_dir);
free(block_buf);
return result;
}
@@ -3429,7 +3442,7 @@ out:
static int is_close(struct timespec *start, int expected_ms)
{
const int allowed_variance = 100;
const int allowed_variance = 500;
int result = TEST_FAILURE;
struct timespec finish;
int diff;
@@ -3438,7 +3451,11 @@ static int is_close(struct timespec *start, int expected_ms)
diff = (finish.tv_sec - start->tv_sec) * 1000 +
(finish.tv_nsec - start->tv_nsec) / 1000000;
TESTCOND(diff >= expected_ms - allowed_variance);
if(diff < expected_ms - allowed_variance || diff > expected_ms + allowed_variance) {
printf("%d %d %d\n", diff, expected_ms, allowed_variance);
}
TESTCOND(diff >= expected_ms);
TESTCOND(diff <= expected_ms + allowed_variance);
result = TEST_SUCCESS;
out:
@@ -3519,13 +3536,13 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
purt_set[0].max_pending_time_us);
/* Still 1000 in UID 2 */
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
TEST(pid = fork(), pid != -1);
if (pid == 0) {
TESTEQUAL(setuid(2), 0);
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
exit(0);
}
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
TESTNE(wait(&status), -1);
TESTEQUAL(WEXITSTATUS(status), 0);
TESTEQUAL(is_close(&start, 1000), 0);
@@ -3965,7 +3982,7 @@ static int memzero(const unsigned char *buf, size_t size)
static int validate_verity(const char *mount_dir, struct test_file *file)
{
int result = TEST_FAILURE;
char *filename = concat_file_name(mount_dir, file->name);
char *filename = 0;
int fd = -1;
uint64_t flags;
struct fsverity_digest *digest;
@@ -4226,6 +4243,8 @@ static int mmap_test(const char *mount_dir)
char *filename = NULL;
int fd = -1;
char *addr = (void *)-1;
int pid = -1;
int status;
TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
@@ -4242,23 +4261,26 @@ static int mmap_test(const char *mount_dir)
TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
TEST(addr = mmap(NULL, file.size, PROT_READ, MAP_PRIVATE, fd, 0),
addr != (void *) -1);
TESTEQUAL(mlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
TESTEQUAL(munlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
TESTEQUAL(mlock(addr + shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE,
INCFS_DATA_FILE_BLOCK_SIZE), -1);
TESTEQUAL(mlock(addr + (shas_per_block - 1) *
INCFS_DATA_FILE_BLOCK_SIZE,
INCFS_DATA_FILE_BLOCK_SIZE), 0);
TESTEQUAL(munlock(addr + (shas_per_block - 1) *
INCFS_DATA_FILE_BLOCK_SIZE,
INCFS_DATA_FILE_BLOCK_SIZE), 0);
TESTEQUAL(mlock(addr + (shas_per_block - 1) *
INCFS_DATA_FILE_BLOCK_SIZE,
INCFS_DATA_FILE_BLOCK_SIZE * 2), -1);
TESTEQUAL(addr[0], 57);
TEST(pid = fork(), pid != -1);
if (pid == 0) {
fclose(stderr);
TESTEQUAL(addr[shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE],
-71);
exit(0);
}
TESTNE(wait(&status), -1);
TESTEQUAL(status, 256);
TESTEQUAL(addr[(shas_per_block - 1) * INCFS_DATA_FILE_BLOCK_SIZE], 76);
TESTEQUAL(munmap(addr, file.size), 0);
addr = (void *) -1;
result = TEST_SUCCESS;
out:
if (addr != (void *) -1)
munmap(addr, file.size);
free(file.mtree);
close(fd);
free(filename);
@@ -4677,7 +4699,50 @@ static char *setup_mount_dir()
return mount_dir;
}
int parse_options(int argc, char *const *argv)
static void parse_range(const char *ranges, bool *run_test, size_t tests)
{
size_t i;
char *range;
for (i = 0; i < tests; ++i)
run_test[i] = false;
range = strtok(optarg, ",");
while (range) {
char *dash = strchr(range, '-');
if (dash) {
size_t start = 1, end = tests;
char *end_ptr;
if (dash > range) {
start = strtol(range, &end_ptr, 10);
if (*end_ptr != '-' || start <= 0 || start > tests)
ksft_exit_fail_msg("Bad range\n");
}
if (dash[1]) {
end = strtol(dash + 1, &end_ptr, 10);
if (*end_ptr || end <= start || end > tests)
ksft_exit_fail_msg("Bad range\n");
}
for (i = start; i <= end; ++i)
run_test[i - 1] = true;
} else {
char *end;
long value = strtol(range, &end, 10);
if (*end || value <= 0 || value > tests)
ksft_exit_fail_msg("Bad range\n");
run_test[value - 1] = true;
}
range = strtok(NULL, ",");
}
}
int parse_options(int argc, char *const *argv, bool *run_test,
size_t tests)
{
signed char c;
@@ -4688,7 +4753,7 @@ int parse_options(int argc, char *const *argv)
break;
case 't':
options.test = strtol(optarg, NULL, 10);
parse_range(optarg, run_test, tests);
break;
case 'v':
@@ -4728,9 +4793,6 @@ int main(int argc, char *argv[])
int i;
int fd, count;
if (parse_options(argc, argv))
ksft_exit_fail_msg("Bad options\n");
// Seed randomness pool for testing on QEMU
// NOTE - this abuses the concept of randomness - do *not* ever do this
// on a machine for production use - the device will think it has good
@@ -4784,18 +4846,20 @@ int main(int argc, char *argv[])
MAKE_TEST(stacked_mount_test),
};
#undef MAKE_TEST
bool run_test[ARRAY_SIZE(cases)];
if (options.test) {
if (options.test <= 0 || options.test > ARRAY_SIZE(cases))
ksft_exit_fail_msg("Invalid test\n");
for (int i = 0; i < ARRAY_SIZE(cases); ++i)
run_test[i] = true;
ksft_set_plan(1);
run_one_test(mount_dir, &cases[options.test - 1]);
} else {
ksft_set_plan(ARRAY_SIZE(cases));
for (i = 0; i < ARRAY_SIZE(cases); ++i)
if (parse_options(argc, argv, run_test, ARRAY_SIZE(cases)))
ksft_exit_fail_msg("Bad options\n");
ksft_set_plan(ARRAY_SIZE(cases));
for (i = 0; i < ARRAY_SIZE(run_test); ++i)
if (run_test[i])
run_one_test(mount_dir, &cases[i]);
}
else
ksft_cnt.ksft_xskip++;
umount2(mount_dir, MNT_FORCE);
rmdir(mount_dir);