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:
committed by
Treehugger Robot
parent
1d9055b834
commit
e6c9473f25
@@ -1,5 +1,5 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# 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
|
LDLIBS := -llz4 -lzstd -lcrypto -lpthread -fsanitize=address
|
||||||
TEST_GEN_PROGS := incfs_test incfs_stress incfs_perf
|
TEST_GEN_PROGS := incfs_test incfs_stress incfs_perf
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,6 @@
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
int file;
|
int file;
|
||||||
int test;
|
|
||||||
bool verbose;
|
bool verbose;
|
||||||
} options;
|
} options;
|
||||||
|
|
||||||
@@ -935,12 +934,13 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file)
|
|||||||
struct incfs_fill_blocks fill_blocks = {
|
struct incfs_fill_blocks fill_blocks = {
|
||||||
.count = file->mtree_block_count,
|
.count = file->mtree_block_count,
|
||||||
};
|
};
|
||||||
struct incfs_fill_block *fill_block_array =
|
struct incfs_fill_block *fill_block_array;
|
||||||
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
|
|
||||||
|
|
||||||
if (fill_blocks.count == 0)
|
if (fill_blocks.count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fill_block_array =
|
||||||
|
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
|
||||||
if (!fill_block_array)
|
if (!fill_block_array)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
|
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(index_path);
|
||||||
free(dst_name);
|
free(dst_name);
|
||||||
free(filename_in_index);
|
free(filename_in_index);
|
||||||
|
free(file_path);
|
||||||
if (umount(mount_dir) != 0) {
|
if (umount(mount_dir) != 0) {
|
||||||
print_error("Can't unmout FS");
|
print_error("Can't unmout FS");
|
||||||
goto failure;
|
goto failure;
|
||||||
@@ -1082,6 +1083,7 @@ failure:
|
|||||||
free(dst_name);
|
free(dst_name);
|
||||||
free(index_path);
|
free(index_path);
|
||||||
free(filename_in_index);
|
free(filename_in_index);
|
||||||
|
free(file_path);
|
||||||
close(cmd_fd);
|
close(cmd_fd);
|
||||||
umount(mount_dir);
|
umount(mount_dir);
|
||||||
return TEST_FAILURE;
|
return TEST_FAILURE;
|
||||||
@@ -1353,9 +1355,13 @@ static int basic_file_ops_test(const char *mount_dir)
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(subdir1);
|
||||||
|
free(subdir2);
|
||||||
return TEST_SUCCESS;
|
return TEST_SUCCESS;
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
|
free(subdir1);
|
||||||
|
free(subdir2);
|
||||||
close(cmd_fd);
|
close(cmd_fd);
|
||||||
umount(mount_dir);
|
umount(mount_dir);
|
||||||
return TEST_FAILURE;
|
return TEST_FAILURE;
|
||||||
@@ -2637,13 +2643,14 @@ static int emit_partial_test_file_hash(const char *mount_dir,
|
|||||||
struct incfs_fill_blocks fill_blocks = {
|
struct incfs_fill_blocks fill_blocks = {
|
||||||
.count = 1,
|
.count = 1,
|
||||||
};
|
};
|
||||||
struct incfs_fill_block *fill_block_array =
|
struct incfs_fill_block *fill_block_array;
|
||||||
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
|
|
||||||
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
|
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
|
||||||
|
|
||||||
if (file->size <= 4096 / 32 * 4096)
|
if (file->size <= 4096 / 32 * 4096)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fill_block_array =
|
||||||
|
calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
|
||||||
if (!fill_block_array)
|
if (!fill_block_array)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
|
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)
|
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;
|
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;
|
int fd;
|
||||||
struct incfs_filled_range ranges[128];
|
struct incfs_filled_range ranges[128];
|
||||||
struct incfs_get_filled_blocks_args fba = {
|
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)
|
if (file->size <= 4096 / 32 * 4096)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
filename = concat_file_name(mount_dir, file->name);
|
||||||
fd = open(filename, O_RDONLY | O_CLOEXEC);
|
fd = open(filename, O_RDONLY | O_CLOEXEC);
|
||||||
free(filename);
|
free(filename);
|
||||||
if (fd <= 0)
|
if (fd <= 0)
|
||||||
@@ -2805,12 +2813,8 @@ static int large_file_test(const char *mount_dir)
|
|||||||
int result = TEST_FAILURE, ret;
|
int result = TEST_FAILURE, ret;
|
||||||
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
|
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
|
||||||
int block_count = THREE_GB / INCFS_DATA_FILE_BLOCK_SIZE;
|
int block_count = THREE_GB / INCFS_DATA_FILE_BLOCK_SIZE;
|
||||||
struct incfs_fill_block *block_buf =
|
struct incfs_fill_block *block_buf = NULL;
|
||||||
calloc(block_count, sizeof(struct incfs_fill_block));
|
struct incfs_fill_blocks fill_blocks;
|
||||||
struct incfs_fill_blocks fill_blocks = {
|
|
||||||
.count = block_count,
|
|
||||||
.fill_blocks = ptr_to_u64(block_buf),
|
|
||||||
};
|
|
||||||
incfs_uuid_t id;
|
incfs_uuid_t id;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct statvfs svfs;
|
struct statvfs svfs;
|
||||||
@@ -2846,6 +2850,14 @@ static int large_file_test(const char *mount_dir)
|
|||||||
NULL) < 0)
|
NULL) < 0)
|
||||||
goto failure;
|
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++) {
|
for (i = 0; i < block_count; i++) {
|
||||||
block_buf[i].compression = COMPRESSION_NONE;
|
block_buf[i].compression = COMPRESSION_NONE;
|
||||||
block_buf[i].block_index = i;
|
block_buf[i].block_index = i;
|
||||||
@@ -2872,6 +2884,7 @@ failure:
|
|||||||
unlink("very_large_file");
|
unlink("very_large_file");
|
||||||
umount(mount_dir);
|
umount(mount_dir);
|
||||||
free(backing_dir);
|
free(backing_dir);
|
||||||
|
free(block_buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3429,7 +3442,7 @@ out:
|
|||||||
|
|
||||||
static int is_close(struct timespec *start, int expected_ms)
|
static int is_close(struct timespec *start, int expected_ms)
|
||||||
{
|
{
|
||||||
const int allowed_variance = 100;
|
const int allowed_variance = 500;
|
||||||
int result = TEST_FAILURE;
|
int result = TEST_FAILURE;
|
||||||
struct timespec finish;
|
struct timespec finish;
|
||||||
int diff;
|
int diff;
|
||||||
@@ -3438,7 +3451,11 @@ static int is_close(struct timespec *start, int expected_ms)
|
|||||||
diff = (finish.tv_sec - start->tv_sec) * 1000 +
|
diff = (finish.tv_sec - start->tv_sec) * 1000 +
|
||||||
(finish.tv_nsec - start->tv_nsec) / 1000000;
|
(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);
|
TESTCOND(diff <= expected_ms + allowed_variance);
|
||||||
result = TEST_SUCCESS;
|
result = TEST_SUCCESS;
|
||||||
out:
|
out:
|
||||||
@@ -3519,13 +3536,13 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
|
|||||||
purt_set[0].max_pending_time_us);
|
purt_set[0].max_pending_time_us);
|
||||||
|
|
||||||
/* Still 1000 in UID 2 */
|
/* Still 1000 in UID 2 */
|
||||||
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
|
||||||
TEST(pid = fork(), pid != -1);
|
TEST(pid = fork(), pid != -1);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
TESTEQUAL(setuid(2), 0);
|
TESTEQUAL(setuid(2), 0);
|
||||||
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
|
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
||||||
TESTNE(wait(&status), -1);
|
TESTNE(wait(&status), -1);
|
||||||
TESTEQUAL(WEXITSTATUS(status), 0);
|
TESTEQUAL(WEXITSTATUS(status), 0);
|
||||||
TESTEQUAL(is_close(&start, 1000), 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)
|
static int validate_verity(const char *mount_dir, struct test_file *file)
|
||||||
{
|
{
|
||||||
int result = TEST_FAILURE;
|
int result = TEST_FAILURE;
|
||||||
char *filename = concat_file_name(mount_dir, file->name);
|
char *filename = 0;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
struct fsverity_digest *digest;
|
struct fsverity_digest *digest;
|
||||||
@@ -4226,6 +4243,8 @@ static int mmap_test(const char *mount_dir)
|
|||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
char *addr = (void *)-1;
|
char *addr = (void *)-1;
|
||||||
|
int pid = -1;
|
||||||
|
int status;
|
||||||
|
|
||||||
TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
|
TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
|
||||||
TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
|
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(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
|
||||||
TEST(addr = mmap(NULL, file.size, PROT_READ, MAP_PRIVATE, fd, 0),
|
TEST(addr = mmap(NULL, file.size, PROT_READ, MAP_PRIVATE, fd, 0),
|
||||||
addr != (void *) -1);
|
addr != (void *) -1);
|
||||||
TESTEQUAL(mlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
|
TESTEQUAL(addr[0], 57);
|
||||||
TESTEQUAL(munlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
|
|
||||||
TESTEQUAL(mlock(addr + shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE,
|
TEST(pid = fork(), pid != -1);
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE), -1);
|
if (pid == 0) {
|
||||||
TESTEQUAL(mlock(addr + (shas_per_block - 1) *
|
fclose(stderr);
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE,
|
TESTEQUAL(addr[shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE],
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE), 0);
|
-71);
|
||||||
TESTEQUAL(munlock(addr + (shas_per_block - 1) *
|
exit(0);
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE,
|
}
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE), 0);
|
TESTNE(wait(&status), -1);
|
||||||
TESTEQUAL(mlock(addr + (shas_per_block - 1) *
|
TESTEQUAL(status, 256);
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE,
|
|
||||||
INCFS_DATA_FILE_BLOCK_SIZE * 2), -1);
|
TESTEQUAL(addr[(shas_per_block - 1) * INCFS_DATA_FILE_BLOCK_SIZE], 76);
|
||||||
TESTEQUAL(munmap(addr, file.size), 0);
|
TESTEQUAL(munmap(addr, file.size), 0);
|
||||||
|
addr = (void *) -1;
|
||||||
|
|
||||||
result = TEST_SUCCESS;
|
result = TEST_SUCCESS;
|
||||||
out:
|
out:
|
||||||
|
if (addr != (void *) -1)
|
||||||
|
munmap(addr, file.size);
|
||||||
free(file.mtree);
|
free(file.mtree);
|
||||||
close(fd);
|
close(fd);
|
||||||
free(filename);
|
free(filename);
|
||||||
@@ -4677,7 +4699,50 @@ static char *setup_mount_dir()
|
|||||||
return 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;
|
signed char c;
|
||||||
|
|
||||||
@@ -4688,7 +4753,7 @@ int parse_options(int argc, char *const *argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
options.test = strtol(optarg, NULL, 10);
|
parse_range(optarg, run_test, tests);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
@@ -4728,9 +4793,6 @@ int main(int argc, char *argv[])
|
|||||||
int i;
|
int i;
|
||||||
int fd, count;
|
int fd, count;
|
||||||
|
|
||||||
if (parse_options(argc, argv))
|
|
||||||
ksft_exit_fail_msg("Bad options\n");
|
|
||||||
|
|
||||||
// Seed randomness pool for testing on QEMU
|
// Seed randomness pool for testing on QEMU
|
||||||
// NOTE - this abuses the concept of randomness - do *not* ever do this
|
// 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
|
// 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),
|
MAKE_TEST(stacked_mount_test),
|
||||||
};
|
};
|
||||||
#undef MAKE_TEST
|
#undef MAKE_TEST
|
||||||
|
bool run_test[ARRAY_SIZE(cases)];
|
||||||
|
|
||||||
if (options.test) {
|
for (int i = 0; i < ARRAY_SIZE(cases); ++i)
|
||||||
if (options.test <= 0 || options.test > ARRAY_SIZE(cases))
|
run_test[i] = true;
|
||||||
ksft_exit_fail_msg("Invalid test\n");
|
|
||||||
|
|
||||||
ksft_set_plan(1);
|
if (parse_options(argc, argv, run_test, ARRAY_SIZE(cases)))
|
||||||
run_one_test(mount_dir, &cases[options.test - 1]);
|
ksft_exit_fail_msg("Bad options\n");
|
||||||
} else {
|
|
||||||
ksft_set_plan(ARRAY_SIZE(cases));
|
ksft_set_plan(ARRAY_SIZE(cases));
|
||||||
for (i = 0; i < ARRAY_SIZE(cases); ++i)
|
for (i = 0; i < ARRAY_SIZE(run_test); ++i)
|
||||||
|
if (run_test[i])
|
||||||
run_one_test(mount_dir, &cases[i]);
|
run_one_test(mount_dir, &cases[i]);
|
||||||
}
|
else
|
||||||
|
ksft_cnt.ksft_xskip++;
|
||||||
|
|
||||||
umount2(mount_dir, MNT_FORCE);
|
umount2(mount_dir, MNT_FORCE);
|
||||||
rmdir(mount_dir);
|
rmdir(mount_dir);
|
||||||
|
|||||||
Reference in New Issue
Block a user