Imported Upstream version 2.3.3
[platform/upstream/cryptsetup.git] / tests / unit-utils-io.c
1 /*
2  * simple unit test for utils_io.c (blockwise low level functions)
3  *
4  * Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "utils_io.h"
31
32 enum fn_enum {
33         READ_BUFFER = 0,
34         WRITE_BUFFER,
35         READ_BLOCKWISE,
36         WRITE_BLOCKWISE,
37         READ_LSEEK_BLOCKWISE,
38         WRITE_LSEEK_BLOCKWISE
39 } test_fn;
40
41 char            *test_file;
42 size_t          test_bsize;
43 size_t          test_alignment;
44 size_t          test_length;
45 off_t           test_offset; //FIXME: check for proper 64bit support (and test it!)
46 size_t          test_mem_alignment = 4096;
47
48 static int test_read_buffer(void)
49 {
50         void *buffer = NULL;
51         int fd = -1;
52         ssize_t ret = -EINVAL;
53
54         //printf("Entering test_read_buffer\n");
55
56         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
57                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
58                 goto out;
59         }
60
61         fd = open(test_file, O_RDONLY | O_DIRECT);
62         if (fd < 0) {
63                 fprintf(stderr, "Failed to open %s.\n", test_file);
64                 goto out;
65         }
66
67         ret = read_buffer(fd, buffer, test_length);
68         if (ret < 0)
69                 goto out;
70
71         ret = (size_t) ret == test_length ? 0 : -EIO;
72 out:
73         if (fd >= 0)
74                 close(fd);
75         free(buffer);
76         return ret;
77 }
78
79 static int test_write_buffer(void)
80 {
81         void *buffer = NULL;
82         int fd = -1;
83         ssize_t ret = -EINVAL;
84
85         //printf("Entering test_write_buffer\n");
86
87         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
88                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
89                 goto out;
90         }
91
92         fd = open(test_file, O_WRONLY | O_DIRECT);
93         if (fd < 0) {
94                 fprintf(stderr, "Failed to open %s.\n", test_file);
95                 goto out;
96         }
97
98         ret = write_buffer(fd, buffer, test_length);
99         if (ret < 0)
100                 goto out;
101
102         return (size_t) ret == test_length ? 0 : -EIO;
103 out:
104         if (fd >= 0)
105                 close(fd);
106         free(buffer);
107         return ret;
108 }
109
110 static int test_read_blockwise(void)
111 {
112         void *buffer = NULL;
113         int fd = -1;
114         ssize_t ret = -EINVAL;
115
116         //printf("Entering test_read_blockwise ");
117         //printf("test_bsize: %zu, test_length: %zu\n", test_bsize, test_length);
118
119         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
120                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
121                 goto out;
122         }
123
124         fd = open(test_file, O_RDONLY | O_DIRECT);
125         if (fd < 0) {
126                 fprintf(stderr, "Failed to open %s.\n", test_file);
127                 goto out;
128         }
129
130
131         ret = read_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length);
132         if (ret < 0)
133                 goto out;
134
135         ret = (size_t) ret == test_length ? 0 : -EIO;
136 out:
137         if (fd >= 0)
138                 close(fd);
139         free(buffer);
140         return ret;
141 }
142
143 static int test_write_blockwise(void)
144 {
145         void *buffer = NULL;
146         int fd = -1;
147         ssize_t ret = -EINVAL;
148
149         //printf("Entering test_write_blockwise\n");
150
151         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
152                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
153                 goto out;
154         }
155
156         fd = open(test_file, O_RDWR | O_DIRECT);
157         if (fd < 0) {
158                 fprintf(stderr, "Failed to open %s.\n", test_file);
159                 goto out;
160         }
161
162         ret = write_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length);
163         if (ret < 0)
164                 goto out;
165
166         ret = (size_t) ret == test_length ? 0 : -EIO;
167 out:
168         if (fd >= 0)
169                 close(fd);
170         free(buffer);
171         return ret;
172 }
173
174 static int test_read_lseek_blockwise(void)
175 {
176         void *buffer = NULL;
177         int fd = -1;
178         ssize_t ret = -EINVAL;
179
180         //printf("Entering test_read_lseek_blockwise\n");
181
182         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
183                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
184                 goto out;
185         }
186
187         fd = open(test_file, O_RDONLY | O_DIRECT);
188         if (fd < 0) {
189                 fprintf(stderr, "Failed to open %s.\n", test_file);
190                 goto out;
191         }
192
193         ret = read_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset);
194         if (ret < 0)
195                 goto out;
196
197         ret = (size_t) ret == test_length ? 0 : -EIO;
198 out:
199         if (fd >= 0)
200                 close(fd);
201         free(buffer);
202         return ret;
203 }
204
205 static int test_write_lseek_blockwise(void)
206 {
207         void *buffer = NULL;
208         int fd = -1;
209         ssize_t ret = -EINVAL;
210
211         //printf("Entering test_write_lseek_blockwise\n");
212
213         if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
214                 fprintf(stderr, "Failed to allocate aligned buffer.\n");
215                 goto out;
216         }
217
218         fd = open(test_file, O_RDWR | O_DIRECT);
219         if (fd < 0) {
220                 fprintf(stderr, "Failed to open %s.\n", test_file);
221                 goto out;
222         }
223
224         ret = write_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset);
225         if (ret < 0)
226                 goto out;
227
228         ret = (size_t) ret == test_length ? 0 : -EIO;
229 out:
230         if (fd >= 0)
231                 close(fd);
232         free(buffer);
233         return ret;
234 }
235
236 static void usage(void)
237 {
238         fprintf(stderr, "Use:\tunit-utils-io file/device blockwise_fn length  [bsize] [offset].\n");
239 }
240
241 static int parse_input_params(int argc, char **argv)
242 {
243         struct stat st;
244         unsigned long offset;
245
246         if (argc < 4) {
247                 usage();
248                 return 1;
249         }
250
251         if (stat(argv[1], &st)) {
252                 fprintf(stderr, "File/device %s is missing?\n", argv[1]);
253                 return 1;
254         }
255         test_file = argv[1];
256         if (sscanf(argv[3], "%zu", &test_length) != 1)
257                 return 1;
258         if (argc >= 5 && sscanf(argv[4], "%zu", &test_bsize) != 1)
259                 return 1;
260         if (argc >= 6) {
261                 if (sscanf(argv[5], "%ld", &offset) != 1)
262                         return 1;
263                 test_offset = offset;
264         }
265
266         if (!strcmp(argv[2], "read_buffer"))
267                 test_fn = READ_BUFFER;
268         else if (!strcmp(argv[2], "write_buffer"))
269                 test_fn = WRITE_BUFFER;
270         else if (!strcmp(argv[2], "read_blockwise")) {
271                 if (argc < 5) {
272                         usage();
273                         return 1;
274                 }
275                 test_fn = READ_BLOCKWISE;
276         } else if (!strcmp(argv[2], "write_blockwise")) {
277                 if (argc < 5) {
278                         usage();
279                         return 1;
280                 }
281                 test_fn = WRITE_BLOCKWISE;
282         } else if (!strcmp(argv[2], "read_lseek_blockwise")) {
283                 if (argc < 6) {
284                         usage();
285                         return 1;
286                 }
287                 test_fn = READ_LSEEK_BLOCKWISE;
288         } else if (!strcmp(argv[2], "write_lseek_blockwise")) {
289                 if (argc < 6) {
290                         usage();
291                         return 1;
292                 }
293                 test_fn = WRITE_LSEEK_BLOCKWISE;
294         } else {
295                 usage();
296                 return 1;
297         }
298
299         /* printf("function '%s': length %zu", argv[2], test_length);
300         if (argc >= 5)
301                 printf(", bsize %zu", test_bsize);
302         if (argc >= 6)
303                 printf(", offset %llu", test_offset);
304         printf("\n"); */
305
306         return 0;
307 }
308
309 int main(int argc, char **argv)
310 {
311         long ps;
312         int r = EXIT_FAILURE;
313
314         if (parse_input_params(argc, argv))
315                 return r;
316
317         ps = sysconf(_SC_PAGESIZE);
318         if (ps > 0)
319                 test_mem_alignment = (size_t)ps;
320
321         switch (test_fn) {
322         case READ_BUFFER:
323                 r = test_read_buffer();
324                 break;
325         case WRITE_BUFFER:
326                 r = test_write_buffer();
327                 break;
328         case READ_BLOCKWISE:
329                 r = test_read_blockwise();
330                 break;
331         case WRITE_BLOCKWISE:
332                 r = test_write_blockwise();
333                 break;
334         case READ_LSEEK_BLOCKWISE:
335                 r = test_read_lseek_blockwise();
336                 break;
337         case WRITE_LSEEK_BLOCKWISE:
338                 r = test_write_lseek_blockwise();
339                 break;
340         default :
341                 fprintf(stderr, "Internal test error.\n");
342                 return r;
343         }
344
345         return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
346 }