zvfs: testcase重写
This commit is contained in:
42
test/Makefile
Executable file
42
test/Makefile
Executable file
@@ -0,0 +1,42 @@
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -Wall -Wextra -std=gnu11
|
||||
|
||||
SRCS := $(sort $(wildcard test_*.c))
|
||||
BIN_DIR ?= bin
|
||||
BIN_NAMES := $(SRCS:.c=)
|
||||
BINS := $(addprefix $(BIN_DIR)/,$(BIN_NAMES))
|
||||
RUN_DIR ?= /tmp/zvfs-test
|
||||
RUN_BINS ?= test_basic test_lseek test_dual_open_same_file test_two_files \
|
||||
test_single_file_perf test_single_file_random_perf \
|
||||
test_single_file_random_noaligned_perf test_write_file test_read_delete_file
|
||||
|
||||
.PHONY: all clean list run-test
|
||||
|
||||
all: $(BINS)
|
||||
|
||||
$(BIN_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(BIN_DIR)/%: %.c test_utils.h | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
list:
|
||||
@printf "%s\n" $(BINS)
|
||||
|
||||
run-test: all
|
||||
@mkdir -p $(RUN_DIR)
|
||||
@pass=0; fail=0; \
|
||||
for t in $(RUN_BINS); do \
|
||||
printf "\n[RUN] %s\n" "$$t"; \
|
||||
if ./$(BIN_DIR)/$$t $(RUN_DIR); then \
|
||||
pass=$$((pass + 1)); \
|
||||
else \
|
||||
fail=$$((fail + 1)); \
|
||||
fi; \
|
||||
done; \
|
||||
printf "\n=== run-test summary: PASS=%d FAIL=%d ===\n" $$pass $$fail; \
|
||||
test $$fail -eq 0
|
||||
|
||||
clean:
|
||||
$(RM) $(BINS)
|
||||
-rmdir $(BIN_DIR)
|
||||
51
test/test_basic.c
Executable file
51
test/test_basic.c
Executable file
@@ -0,0 +1,51 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_basic(const char *path)
|
||||
{
|
||||
printf("\n=== test_basic ===\n");
|
||||
|
||||
printf("open: %s\n", path);
|
||||
int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||
if (fd < 0) { perror("open"); return 1; }
|
||||
|
||||
const char *msg = "ABCDEFGHIJKL";
|
||||
ssize_t w = write(fd, msg, strlen(msg));
|
||||
if (w < 0) { perror("write"); return 2; }
|
||||
printf("write: %zd\n", w);
|
||||
|
||||
const char *msg2 = "MNOPQRSTUVWXYZ";
|
||||
ssize_t w2 = write(fd, msg2, strlen(msg2));
|
||||
if (w2 < 0) { perror("write"); return 2; }
|
||||
printf("write: %zd\n", w2);
|
||||
|
||||
close(fd);
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) { perror("open R"); return 3; }
|
||||
|
||||
char buf[10];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ssize_t r = read(fd, buf, sizeof(buf));
|
||||
if (r < 0) { perror("read"); return 4; }
|
||||
printf("read: %zd bytes: %.*s\n", r, (int)r, buf);
|
||||
|
||||
char buf2[512];
|
||||
memset(buf2, 0, sizeof(buf2));
|
||||
ssize_t r2 = read(fd, buf2, sizeof(buf2));
|
||||
if (r2 < 0) { perror("read"); return 4; }
|
||||
printf("read: %zd bytes: %.*s\n", r2, (int)r2, buf2);
|
||||
|
||||
close(fd);
|
||||
|
||||
if (unlink(path) != 0) { perror("unlink"); return 5; }
|
||||
printf("unlink: ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_basic(path);
|
||||
return report_result("test_basic", rc);
|
||||
}
|
||||
50
test/test_dual_open_same_file.c
Executable file
50
test/test_dual_open_same_file.c
Executable file
@@ -0,0 +1,50 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_dual_open_same_file(const char *path)
|
||||
{
|
||||
printf("\n=== test_dual_open_same_file ===\n");
|
||||
|
||||
int fd_init = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||
if (fd_init < 0) { perror("open init"); return 1; }
|
||||
const char *init = "0123456789";
|
||||
if (write(fd_init, init, 10) != 10) { perror("write init"); return 2; }
|
||||
close(fd_init);
|
||||
|
||||
int fd_w = open(path, O_WRONLY);
|
||||
if (fd_w < 0) { perror("open W"); return 3; }
|
||||
|
||||
int fd_r = open(path, O_RDONLY);
|
||||
if (fd_r < 0) { perror("open R"); return 4; }
|
||||
|
||||
printf("fd_w=%d fd_r=%d\n", fd_w, fd_r);
|
||||
|
||||
if (write(fd_w, "HELLO", 5) != 5) { perror("write"); return 5; }
|
||||
printf("write via fd_w: HELLO (overwrite first 5 bytes)\n");
|
||||
|
||||
char buf[32] = {0};
|
||||
lseek(fd_r, 0, SEEK_SET);
|
||||
ssize_t r = read(fd_r, buf, sizeof(buf));
|
||||
printf("read via fd_r: %zd bytes: %.*s (expect: HELLO56789)\n", r, (int)r, buf);
|
||||
|
||||
lseek(fd_w, 0, SEEK_END);
|
||||
if (write(fd_w, "!!!", 3) != 3) { perror("write append"); return 6; }
|
||||
printf("write append via fd_w: !!!\n");
|
||||
|
||||
lseek(fd_r, 10, SEEK_SET);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
r = read(fd_r, buf, sizeof(buf));
|
||||
printf("read appended via fd_r: %zd bytes: %.*s (expect: !!!)\n", r, (int)r, buf);
|
||||
|
||||
close(fd_w);
|
||||
close(fd_r);
|
||||
unlink(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_dual_open_same_file(path);
|
||||
return report_result("test_dual_open_same_file", rc);
|
||||
}
|
||||
55
test/test_lseek.c
Executable file
55
test/test_lseek.c
Executable file
@@ -0,0 +1,55 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_lseek(const char *path)
|
||||
{
|
||||
printf("\n=== test_lseek ===\n");
|
||||
|
||||
int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||
if (fd < 0) { perror("open"); return 1; }
|
||||
|
||||
const char *alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
if (write(fd, alpha, 26) != 26) { perror("write"); return 2; }
|
||||
printf("write 26 bytes: %s\n", alpha);
|
||||
|
||||
off_t pos = lseek(fd, 0, SEEK_SET);
|
||||
printf("lseek SEEK_SET 0 -> %ld\n", (long)pos);
|
||||
char buf[32] = {0};
|
||||
ssize_t r = read(fd, buf, 5);
|
||||
printf("read 5 bytes: %.*s (expect: ABCDE)\n", (int)r, buf);
|
||||
|
||||
pos = lseek(fd, 3, SEEK_CUR);
|
||||
printf("lseek SEEK_CUR +3 -> %ld\n", (long)pos);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
r = read(fd, buf, 5);
|
||||
printf("read 5 bytes: %.*s (expect: IJKLM)\n", (int)r, buf);
|
||||
|
||||
pos = lseek(fd, -5, SEEK_END);
|
||||
printf("lseek SEEK_END -5 -> %ld\n", (long)pos);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
r = read(fd, buf, 10);
|
||||
printf("read %zd bytes: %.*s (expect: VWXYZ)\n", r, (int)r, buf);
|
||||
|
||||
pos = lseek(fd, 30, SEEK_SET);
|
||||
printf("lseek SEEK_SET 30 -> %ld\n", (long)pos);
|
||||
if (write(fd, "!", 1) != 1) { perror("write hole"); return 3; }
|
||||
|
||||
lseek(fd, 26, SEEK_SET);
|
||||
memset(buf, 0xAA, sizeof(buf));
|
||||
r = read(fd, buf, 5);
|
||||
printf("read hole+1: %zd bytes, hole[0]=%02X hole[1]=%02X hole[2]=%02X "
|
||||
"hole[3]=%02X last='%c' (expect: 00 00 00 00 '!')\n",
|
||||
r, (unsigned char)buf[0], (unsigned char)buf[1],
|
||||
(unsigned char)buf[2], (unsigned char)buf[3], buf[4]);
|
||||
|
||||
close(fd);
|
||||
unlink(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_lseek(path);
|
||||
return report_result("test_lseek", rc);
|
||||
}
|
||||
31
test/test_read_delete_file.c
Executable file
31
test/test_read_delete_file.c
Executable file
@@ -0,0 +1,31 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_read_delete_file(const char *path)
|
||||
{
|
||||
printf("\n=== test_read_delete_file ===\n");
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0) { perror("open"); return 1; }
|
||||
printf("open: %s fd=%d\n", path, fd);
|
||||
|
||||
char buf[256] = {0};
|
||||
ssize_t r = read(fd, buf, sizeof(buf));
|
||||
if (r < 0) { perror("read"); close(fd); return 2; }
|
||||
printf("read: %zd bytes: %.*s\n", r, (int)r, buf);
|
||||
|
||||
close(fd);
|
||||
printf("close: ok\n");
|
||||
|
||||
if (unlink(path) != 0) { perror("unlink"); return 3; }
|
||||
printf("unlink: ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_read_delete_file(path);
|
||||
return report_result("test_read_delete_file", rc);
|
||||
}
|
||||
92
test/test_single_file_perf.c
Executable file
92
test/test_single_file_perf.c
Executable file
@@ -0,0 +1,92 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_single_file_perf(const char *path)
|
||||
{
|
||||
size_t io_size = 128 * 1024;
|
||||
size_t max_size = 2ULL * 1024 * 1024 * 1024;
|
||||
size_t max_count = max_size / io_size;
|
||||
int test_sec = 10;
|
||||
int direct = 0;
|
||||
|
||||
printf("\n=== test_single_file_perf ===\n");
|
||||
printf("Path : %s\n", path);
|
||||
printf("IO size : %zu KB\n", io_size / 1024);
|
||||
printf("Max file: %zu MB\n", max_size / 1024 / 1024);
|
||||
printf("Duration: %d sec\n", test_sec);
|
||||
|
||||
unlink(path);
|
||||
char *buf = aligned_alloc(4096, io_size);
|
||||
if (!buf) { perror("aligned_alloc"); return 1; }
|
||||
memset(buf, 'A', io_size);
|
||||
|
||||
struct timespec t1, t2, now;
|
||||
|
||||
int fd = open(path, O_CREAT | O_RDWR | direct, 0644);
|
||||
if (fd < 0) { perror("open write"); free(buf); return 1; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
size_t wcount = 0;
|
||||
size_t wpos = 0;
|
||||
do {
|
||||
if (wpos >= max_count) {
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
wpos = 0;
|
||||
}
|
||||
if (write(fd, buf, io_size) != (ssize_t)io_size) {
|
||||
perror("write");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 2;
|
||||
}
|
||||
wcount++;
|
||||
wpos++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double wsec = time_diff_sec(t1, t2);
|
||||
double wmb = (double)(wcount * io_size) / (1024.0 * 1024.0);
|
||||
printf("\nWRITE:\n");
|
||||
printf(" total : %.1f MB\n", wmb);
|
||||
printf(" time : %.3f sec\n", wsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", wcount / wsec);
|
||||
printf(" BW : %.2f MB/s\n", wmb / wsec);
|
||||
|
||||
fd = open(path, O_RDONLY | direct);
|
||||
if (fd < 0) { perror("open read"); free(buf); return 3; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
size_t rcount = 0;
|
||||
do {
|
||||
ssize_t r = read(fd, buf, io_size);
|
||||
if (r <= 0) {
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
continue;
|
||||
}
|
||||
rcount++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double rsec = time_diff_sec(t1, t2);
|
||||
double rmb = (double)(rcount * io_size) / (1024.0 * 1024.0);
|
||||
printf("\nREAD:\n");
|
||||
printf(" total : %.1f MB\n", rmb);
|
||||
printf(" time : %.3f sec\n", rsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", rcount / rsec);
|
||||
printf(" BW : %.2f MB/s\n", rmb / rsec);
|
||||
|
||||
unlink(path);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_single_file_perf(path);
|
||||
return report_result("test_single_file_perf", rc);
|
||||
}
|
||||
116
test/test_single_file_random_noaligned_perf.c
Executable file
116
test/test_single_file_random_noaligned_perf.c
Executable file
@@ -0,0 +1,116 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_single_file_random_noaligned_perf(const char *path)
|
||||
{
|
||||
size_t io_size = 128 * 1024;
|
||||
size_t max_size = 2ULL * 1024 * 1024 * 1024;
|
||||
int test_sec = 10;
|
||||
int direct = 0;
|
||||
|
||||
printf("\n=== test_single_file_random_noaligned_perf ===\n");
|
||||
printf("Path : %s\n", path);
|
||||
printf("IO size : %zu KB\n", io_size / 1024);
|
||||
printf("Range : %zu MB\n", max_size / 1024 / 1024);
|
||||
printf("Duration: %d sec\n", test_sec);
|
||||
|
||||
srand(0x1234);
|
||||
|
||||
char *buf = aligned_alloc(4096, io_size);
|
||||
if (!buf) { perror("aligned_alloc"); return 1; }
|
||||
memset(buf, 'A', io_size);
|
||||
|
||||
struct timespec t1, t2, now;
|
||||
|
||||
unlink(path);
|
||||
|
||||
int fd = open(path, O_CREAT | O_RDWR | direct, 0644);
|
||||
if (fd < 0) { perror("open rand write"); free(buf); return 2; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
|
||||
size_t wcount = 0;
|
||||
do {
|
||||
off_t offset = (off_t)(rand() % (max_size - io_size));
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) < 0) {
|
||||
perror("lseek rand write");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (write(fd, buf, io_size) != (ssize_t)io_size) {
|
||||
perror("rand write");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 4;
|
||||
}
|
||||
|
||||
wcount++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double wsec = time_diff_sec(t1, t2);
|
||||
double wmb = (double)wcount * io_size / 1024 / 1024;
|
||||
|
||||
printf("\nRANDOM WRITE:\n");
|
||||
printf(" total : %.1f MB\n", wmb);
|
||||
printf(" time : %.3f sec\n", wsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", wcount / wsec);
|
||||
printf(" BW : %.2f MB/s\n", wmb / wsec);
|
||||
|
||||
fd = open(path, O_RDONLY | direct);
|
||||
if (fd < 0) { perror("open rand read"); free(buf); return 5; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
|
||||
size_t rcount = 0;
|
||||
do {
|
||||
off_t offset = (off_t)(rand() % (max_size - io_size));
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) < 0) {
|
||||
perror("lseek rand read");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 6;
|
||||
}
|
||||
|
||||
ssize_t r = read(fd, buf, io_size);
|
||||
if (r < 0) {
|
||||
perror("rand read");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 7;
|
||||
}
|
||||
|
||||
rcount++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double rsec = time_diff_sec(t1, t2);
|
||||
double rmb = (double)rcount * io_size / 1024 / 1024;
|
||||
|
||||
printf("\nRANDOM READ:\n");
|
||||
printf(" total : %.1f MB\n", rmb);
|
||||
printf(" time : %.3f sec\n", rsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", rcount / rsec);
|
||||
printf(" BW : %.2f MB/s\n", rmb / rsec);
|
||||
|
||||
unlink(path);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_single_file_random_noaligned_perf(path);
|
||||
return report_result("test_single_file_random_noaligned_perf", rc);
|
||||
}
|
||||
119
test/test_single_file_random_perf.c
Executable file
119
test/test_single_file_random_perf.c
Executable file
@@ -0,0 +1,119 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_single_file_random_perf(const char *path)
|
||||
{
|
||||
size_t io_size = 128 * 1024;
|
||||
size_t max_size = 2ULL * 1024 * 1024 * 1024;
|
||||
size_t max_count = max_size / io_size;
|
||||
int test_sec = 10;
|
||||
int direct = 0;
|
||||
|
||||
printf("\n=== test_single_file_random_perf ===\n");
|
||||
printf("Path : %s\n", path);
|
||||
printf("IO size : %zu KB\n", io_size / 1024);
|
||||
printf("Range : %zu MB\n", max_size / 1024 / 1024);
|
||||
printf("Duration: %d sec\n", test_sec);
|
||||
|
||||
srand(0x1234);
|
||||
|
||||
char *buf = aligned_alloc(4096, io_size);
|
||||
if (!buf) { perror("aligned_alloc"); return 1; }
|
||||
memset(buf, 'A', io_size);
|
||||
|
||||
struct timespec t1, t2, now;
|
||||
|
||||
unlink(path);
|
||||
|
||||
int fd = open(path, O_CREAT | O_RDWR | direct, 0644);
|
||||
if (fd < 0) { perror("open rand write"); free(buf); return 2; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
|
||||
size_t wcount = 0;
|
||||
do {
|
||||
size_t blk = rand() % max_count;
|
||||
off_t offset = (off_t)blk * io_size;
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) < 0) {
|
||||
perror("lseek rand write");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (write(fd, buf, io_size) != (ssize_t)io_size) {
|
||||
perror("rand write");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 4;
|
||||
}
|
||||
|
||||
wcount++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double wsec = time_diff_sec(t1, t2);
|
||||
double wmb = (double)wcount * io_size / 1024 / 1024;
|
||||
|
||||
printf("\nRANDOM WRITE:\n");
|
||||
printf(" total : %.1f MB\n", wmb);
|
||||
printf(" time : %.3f sec\n", wsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", wcount / wsec);
|
||||
printf(" BW : %.2f MB/s\n", wmb / wsec);
|
||||
|
||||
fd = open(path, O_RDONLY | direct);
|
||||
if (fd < 0) { perror("open rand read"); free(buf); return 5; }
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
|
||||
size_t rcount = 0;
|
||||
do {
|
||||
size_t blk = rand() % max_count;
|
||||
off_t offset = (off_t)blk * io_size;
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) < 0) {
|
||||
perror("lseek rand read");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 6;
|
||||
}
|
||||
|
||||
ssize_t r = read(fd, buf, io_size);
|
||||
if (r < 0) {
|
||||
perror("rand read");
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 7;
|
||||
}
|
||||
|
||||
rcount++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
} while (time_diff_sec(t1, now) < test_sec);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
close(fd);
|
||||
|
||||
double rsec = time_diff_sec(t1, t2);
|
||||
double rmb = (double)rcount * io_size / 1024 / 1024;
|
||||
|
||||
printf("\nRANDOM READ:\n");
|
||||
printf(" total : %.1f MB\n", rmb);
|
||||
printf(" time : %.3f sec\n", rsec);
|
||||
printf(" IOPS : %.0f ops/sec\n", rcount / rsec);
|
||||
printf(" BW : %.2f MB/s\n", rmb / rsec);
|
||||
|
||||
unlink(path);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_single_file_random_perf(path);
|
||||
return report_result("test_single_file_random_perf", rc);
|
||||
}
|
||||
78
test/test_two_files.c
Executable file
78
test/test_two_files.c
Executable file
@@ -0,0 +1,78 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_two_files(const char *path_a, const char *path_b)
|
||||
{
|
||||
printf("\n=== test_two_files ===\n");
|
||||
|
||||
int fd_a = open(path_a, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||
if (fd_a < 0) { perror("open A"); return 1; }
|
||||
|
||||
int fd_b = open(path_b, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||
if (fd_b < 0) { perror("open B"); return 2; }
|
||||
|
||||
printf("fd_a=%d fd_b=%d\n", fd_a, fd_b);
|
||||
|
||||
const char *data_a = "File-A: Hello World!";
|
||||
const char *data_b = "File-B: Goodbye World!";
|
||||
if (write(fd_a, data_a, strlen(data_a)) < 0) { perror("write A"); return 3; }
|
||||
if (write(fd_b, data_b, strlen(data_b)) < 0) { perror("write B"); return 4; }
|
||||
printf("write A: %s\n", data_a);
|
||||
printf("write B: %s\n", data_b);
|
||||
|
||||
lseek(fd_a, 0, SEEK_SET);
|
||||
lseek(fd_b, 0, SEEK_SET);
|
||||
|
||||
char buf_a[64] = {0};
|
||||
char buf_b[64] = {0};
|
||||
ssize_t r_a = read(fd_a, buf_a, sizeof(buf_a));
|
||||
ssize_t r_b = read(fd_b, buf_b, sizeof(buf_b));
|
||||
|
||||
printf("read A: %zd bytes: %.*s\n", r_a, (int)r_a, buf_a);
|
||||
printf("read B: %zd bytes: %.*s\n", r_b, (int)r_b, buf_b);
|
||||
|
||||
int ok = 1;
|
||||
if (strncmp(buf_a, data_a, strlen(data_a)) != 0) {
|
||||
printf("FAIL: A content mismatch!\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (strncmp(buf_b, data_b, strlen(data_b)) != 0) {
|
||||
printf("FAIL: B content mismatch!\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (ok) {
|
||||
printf("PASS: both files read back correctly\n");
|
||||
}
|
||||
|
||||
lseek(fd_a, 0, SEEK_END);
|
||||
if (write(fd_a, "[A-TAIL]", 8) != 8) { perror("append A"); return 5; }
|
||||
|
||||
lseek(fd_b, 8, SEEK_SET);
|
||||
if (write(fd_b, "Hi! ", 7) != 7) { perror("overwrite B"); return 6; }
|
||||
|
||||
lseek(fd_a, 0, SEEK_SET);
|
||||
lseek(fd_b, 0, SEEK_SET);
|
||||
memset(buf_a, 0, sizeof(buf_a));
|
||||
memset(buf_b, 0, sizeof(buf_b));
|
||||
r_a = read(fd_a, buf_a, sizeof(buf_a));
|
||||
r_b = read(fd_b, buf_b, sizeof(buf_b));
|
||||
printf("after cross-write:\n");
|
||||
printf(" A: %.*s\n", (int)r_a, buf_a);
|
||||
printf(" B: %.*s\n", (int)r_b, buf_b);
|
||||
|
||||
close(fd_a);
|
||||
close(fd_b);
|
||||
unlink(path_a);
|
||||
unlink(path_b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path_a[PATH_MAX];
|
||||
char path_b[PATH_MAX];
|
||||
const char *dir = argc >= 2 ? argv[1] : NULL;
|
||||
make_path(path_a, sizeof(path_a), dir, "file_a.dat");
|
||||
make_path(path_b, sizeof(path_b), dir, "file_b.dat");
|
||||
int rc = test_two_files(path_a, path_b);
|
||||
return report_result("test_two_files", rc);
|
||||
}
|
||||
40
test/test_utils.h
Executable file
40
test/test_utils.h
Executable file
@@ -0,0 +1,40 @@
|
||||
#ifndef TEST_UTILS_H
|
||||
#define TEST_UTILS_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
static inline double time_diff_sec(struct timespec a, struct timespec b)
|
||||
{
|
||||
return (b.tv_sec - a.tv_sec) + (b.tv_nsec - a.tv_nsec) / 1000000000.0;
|
||||
}
|
||||
|
||||
static inline void make_path(char *out, size_t out_sz, const char *dir, const char *name)
|
||||
{
|
||||
if (dir && dir[0] != 0) {
|
||||
snprintf(out, out_sz, "%s/%s", dir, name);
|
||||
} else {
|
||||
snprintf(out, out_sz, "/tmp/%s", name);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int report_result(const char *name, int rc)
|
||||
{
|
||||
printf("\n=== %s %s ===\n", name, rc == 0 ? "PASSED" : "FAILED");
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
27
test/test_write_file.c
Executable file
27
test/test_write_file.c
Executable file
@@ -0,0 +1,27 @@
|
||||
#include "test_utils.h"
|
||||
|
||||
static int test_write_file(const char *path)
|
||||
{
|
||||
printf("\n=== test_write_file ===\n");
|
||||
|
||||
int fd = open(path, O_CREAT | O_RDWR, 0644);
|
||||
if (fd < 0) { perror("open"); return 1; }
|
||||
printf("open: %s fd=%d\n", path, fd);
|
||||
|
||||
const char *msg = "Hello, zvfs!";
|
||||
ssize_t w = write(fd, msg, strlen(msg));
|
||||
if (w < 0) { perror("write"); close(fd); return 2; }
|
||||
printf("write: %zd bytes: %s\n", w, msg);
|
||||
|
||||
close(fd);
|
||||
printf("close: ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
make_path(path, sizeof(path), argc >= 2 ? argv[1] : NULL, "file.dat");
|
||||
int rc = test_write_file(path);
|
||||
return report_result("test_write_file", rc);
|
||||
}
|
||||
Reference in New Issue
Block a user