source: mainline/uspace/lib/fmgt/test/fmgt.c@ 0cf3d5f

Last change on this file since 0cf3d5f was 0cf3d5f, checked in by Jiri Svoboda <jiri@…>, 4 weeks ago

Allow creating sparse files in Navigator and newfile.

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <fmgt.h>
30#include <pcut/pcut.h>
31#include <stdio.h>
32#include <str.h>
33#include <vfs/vfs.h>
34
35PCUT_INIT;
36
37PCUT_TEST_SUITE(fmgt);
38
39#define TEMP_DIR "/tmp"
40
41static void test_fmgt_progress(void *, fmgt_progress_t *);
42
43static fmgt_cb_t test_fmgt_cb = {
44 .progress = test_fmgt_progress
45};
46
47typedef struct {
48 unsigned nupdates;
49} test_resp_t;
50
51/** Create and destroy file management object succeeds. */
52PCUT_TEST(create_destroy)
53{
54 fmgt_t *fmgt = NULL;
55 errno_t rc;
56
57 rc = fmgt_create(&fmgt);
58 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
59 PCUT_ASSERT_NOT_NULL(fmgt);
60
61 fmgt_destroy(fmgt);
62}
63
64/** Suggesting new file name succeeds and returns unique name. */
65PCUT_TEST(new_file_suggest)
66{
67 FILE *f = NULL;
68 char *fname1 = NULL;
69 char *fname2 = NULL;
70 errno_t rc;
71 int rv;
72
73 rc = vfs_cwd_set(TEMP_DIR);
74 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
75
76 /* Suggest unique file name. */
77 rc = fmgt_new_file_suggest(&fname1);
78 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
79
80 /* See if we can actually create the file. */
81 f = fopen(fname1, "wx");
82 PCUT_ASSERT_NOT_NULL(f);
83 (void) fclose(f);
84
85 /* Now suggest another unique file name. */
86 rc = fmgt_new_file_suggest(&fname2);
87 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
88
89 /* They should be different. */
90 PCUT_ASSERT_FALSE(str_cmp(fname1, fname2) == 0);
91
92 /* Remove the file. */
93 rv = remove(fname1);
94 PCUT_ASSERT_INT_EQUALS(0, rv);
95
96 free(fname1);
97 free(fname2);
98}
99
100/** New empty file can be created. */
101PCUT_TEST(new_file_empty)
102{
103 fmgt_t *fmgt = NULL;
104 char *fname = NULL;
105 errno_t rc;
106 int rv;
107
108 rc = vfs_cwd_set(TEMP_DIR);
109 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
110
111 rc = fmgt_create(&fmgt);
112 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
113
114 /* Suggest unique file name. */
115 rc = fmgt_new_file_suggest(&fname);
116 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
117
118 rc = fmgt_new_file(fmgt, fname, 0, nf_none);
119 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
120
121 /* Remove the file [this also verifies the file exists]. */
122 rv = remove(fname);
123 PCUT_ASSERT_INT_EQUALS(0, rv);
124
125 free(fname);
126 fmgt_destroy(fmgt);
127}
128
129/** New zero-filled file can be created. */
130PCUT_TEST(new_file_zerofill)
131{
132 FILE *f = NULL;
133 fmgt_t *fmgt = NULL;
134 char *fname = NULL;
135 char buf[128];
136 errno_t rc;
137 size_t nr;
138 size_t total_rd;
139 size_t i;
140 int rv;
141
142 rc = vfs_cwd_set(TEMP_DIR);
143 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
144
145 rc = fmgt_create(&fmgt);
146 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
147
148 /* Suggest unique file name. */
149 rc = fmgt_new_file_suggest(&fname);
150 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
151
152 rc = fmgt_new_file(fmgt, fname, 20000, nf_none);
153 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
154
155 /* Verify the file. */
156 f = fopen(fname, "rb");
157 PCUT_ASSERT_NOT_NULL(f);
158 total_rd = 0;
159 do {
160 nr = fread(buf, 1, sizeof(buf), f);
161 for (i = 0; i < nr; i++)
162 PCUT_ASSERT_INT_EQUALS(0, buf[i]);
163
164 total_rd += nr;
165 } while (nr > 0);
166
167 PCUT_ASSERT_INT_EQUALS(20000, total_rd);
168
169 (void)fclose(f);
170
171 /* Remove the file. */
172 rv = remove(fname);
173 PCUT_ASSERT_INT_EQUALS(0, rv);
174
175 free(fname);
176 fmgt_destroy(fmgt);
177}
178
179/** New sparse file can be created. */
180PCUT_TEST(new_file_sparse)
181{
182 FILE *f = NULL;
183 fmgt_t *fmgt = NULL;
184 char *fname = NULL;
185 char buf[128];
186 errno_t rc;
187 size_t nr;
188 size_t total_rd;
189 size_t i;
190 int rv;
191
192 rc = vfs_cwd_set(TEMP_DIR);
193 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
194
195 rc = fmgt_create(&fmgt);
196 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
197
198 /* Suggest unique file name. */
199 rc = fmgt_new_file_suggest(&fname);
200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
201
202 rc = fmgt_new_file(fmgt, fname, 20000, nf_sparse);
203 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
204
205 /* Verify the file. */
206 f = fopen(fname, "rb");
207 PCUT_ASSERT_NOT_NULL(f);
208 total_rd = 0;
209 do {
210 nr = fread(buf, 1, sizeof(buf), f);
211 for (i = 0; i < nr; i++)
212 PCUT_ASSERT_INT_EQUALS(0, buf[i]);
213
214 total_rd += nr;
215 } while (nr > 0);
216
217 PCUT_ASSERT_INT_EQUALS(20000, total_rd);
218
219 (void)fclose(f);
220
221 /* Remove the file. */
222 rv = remove(fname);
223 PCUT_ASSERT_INT_EQUALS(0, rv);
224
225 free(fname);
226 fmgt_destroy(fmgt);
227}
228
229/** Initial update provided when requested while creating new file. */
230PCUT_TEST(new_file_init_upd)
231{
232 FILE *f = NULL;
233 fmgt_t *fmgt = NULL;
234 char *fname = NULL;
235 char buf[128];
236 errno_t rc;
237 size_t nr;
238 size_t total_rd;
239 size_t i;
240 test_resp_t resp;
241 int rv;
242
243 rc = vfs_cwd_set(TEMP_DIR);
244 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
245
246 rc = fmgt_create(&fmgt);
247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
248
249 fmgt_set_cb(fmgt, &test_fmgt_cb, (void *)&resp);
250 resp.nupdates = 0;
251
252 fmgt_set_init_update(fmgt, true);
253
254 /* Suggest unique file name. */
255 rc = fmgt_new_file_suggest(&fname);
256 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
257
258 rc = fmgt_new_file(fmgt, fname, 20000, nf_none);
259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
260
261 /* Verify the file. */
262 f = fopen(fname, "rb");
263 PCUT_ASSERT_NOT_NULL(f);
264 total_rd = 0;
265 do {
266 nr = fread(buf, 1, sizeof(buf), f);
267 for (i = 0; i < nr; i++)
268 PCUT_ASSERT_INT_EQUALS(0, buf[i]);
269
270 total_rd += nr;
271 } while (nr > 0);
272
273 PCUT_ASSERT_INT_EQUALS(20000, total_rd);
274
275 (void)fclose(f);
276
277 PCUT_ASSERT_TRUE(resp.nupdates > 0);
278
279 /* Remove the file. */
280 rv = remove(fname);
281 PCUT_ASSERT_INT_EQUALS(0, rv);
282
283 free(fname);
284 fmgt_destroy(fmgt);
285}
286
287static void test_fmgt_progress(void *arg, fmgt_progress_t *progress)
288{
289 test_resp_t *resp = (test_resp_t *)arg;
290
291 (void)progress;
292 ++resp->nupdates;
293}
294
295PCUT_EXPORT(fmgt);
Note: See TracBrowser for help on using the repository browser.