/* * simple unit test for utils_io.c (blockwise low level functions) * * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include "utils_io.h" enum fn_enum { READ_BUFFER = 0, WRITE_BUFFER, READ_BLOCKWISE, WRITE_BLOCKWISE, READ_LSEEK_BLOCKWISE, WRITE_LSEEK_BLOCKWISE } test_fn; char *test_file; size_t test_bsize; size_t test_alignment; size_t test_length; off_t test_offset; //FIXME: check for proper 64bit support (and test it!) size_t test_mem_alignment = 4096; static int test_read_buffer(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_read_buffer\n"); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_RDONLY | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = read_buffer(fd, buffer, test_length); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static int test_write_buffer(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_write_buffer\n"); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_WRONLY | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = write_buffer(fd, buffer, test_length); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static int test_read_blockwise(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_read_blockwise "); //printf("test_bsize: %zu, test_length: %zu\n", test_bsize, test_length); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_RDONLY | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = read_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static int test_write_blockwise(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_write_blockwise\n"); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_RDWR | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = write_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static int test_read_lseek_blockwise(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_read_lseek_blockwise\n"); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_RDONLY | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = read_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static int test_write_lseek_blockwise(void) { void *buffer = NULL; int fd = -1; ssize_t ret = -EINVAL; //printf("Entering test_write_lseek_blockwise\n"); if (posix_memalign(&buffer, test_mem_alignment, test_length)) { fprintf(stderr, "Failed to allocate aligned buffer.\n"); goto out; } fd = open(test_file, O_RDWR | O_DIRECT); if (fd < 0) { fprintf(stderr, "Failed to open %s.\n", test_file); goto out; } ret = write_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset); if (ret < 0) goto out; ret = (size_t) ret == test_length ? 0 : -EIO; out: if (fd >= 0) close(fd); free(buffer); return ret; } static void usage(void) { fprintf(stderr, "Use:\tunit-utils-io file/device blockwise_fn length [bsize] [offset].\n"); } static int parse_input_params(int argc, char **argv) { struct stat st; unsigned long offset; if (argc < 4) { usage(); return 1; } if (stat(argv[1], &st)) { fprintf(stderr, "File/device %s is missing?\n", argv[1]); return 1; } test_file = argv[1]; if (sscanf(argv[3], "%zu", &test_length) != 1) return 1; if (argc >= 5 && sscanf(argv[4], "%zu", &test_bsize) != 1) return 1; if (argc >= 6) { if (sscanf(argv[5], "%ld", &offset) != 1) return 1; test_offset = offset; } if (!strcmp(argv[2], "read_buffer")) test_fn = READ_BUFFER; else if (!strcmp(argv[2], "write_buffer")) test_fn = WRITE_BUFFER; else if (!strcmp(argv[2], "read_blockwise")) { if (argc < 5) { usage(); return 1; } test_fn = READ_BLOCKWISE; } else if (!strcmp(argv[2], "write_blockwise")) { if (argc < 5) { usage(); return 1; } test_fn = WRITE_BLOCKWISE; } else if (!strcmp(argv[2], "read_lseek_blockwise")) { if (argc < 6) { usage(); return 1; } test_fn = READ_LSEEK_BLOCKWISE; } else if (!strcmp(argv[2], "write_lseek_blockwise")) { if (argc < 6) { usage(); return 1; } test_fn = WRITE_LSEEK_BLOCKWISE; } else { usage(); return 1; } /* printf("function '%s': length %zu", argv[2], test_length); if (argc >= 5) printf(", bsize %zu", test_bsize); if (argc >= 6) printf(", offset %llu", test_offset); printf("\n"); */ return 0; } int main(int argc, char **argv) { long ps; int r = EXIT_FAILURE; #ifndef NO_CRYPTSETUP_PATH if (getenv("CRYPTSETUP_PATH")) { printf("Cannot run this test with CRYPTSETUP_PATH set.\n"); exit(77); } #endif if (parse_input_params(argc, argv)) return r; ps = sysconf(_SC_PAGESIZE); if (ps > 0) test_mem_alignment = (size_t)ps; switch (test_fn) { case READ_BUFFER: r = test_read_buffer(); break; case WRITE_BUFFER: r = test_write_buffer(); break; case READ_BLOCKWISE: r = test_read_blockwise(); break; case WRITE_BLOCKWISE: r = test_write_blockwise(); break; case READ_LSEEK_BLOCKWISE: r = test_read_lseek_blockwise(); break; case WRITE_LSEEK_BLOCKWISE: r = test_write_lseek_blockwise(); break; default : fprintf(stderr, "Internal test error.\n"); return r; } return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }