4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "spdk/stdinc.h"
36 #include "CUnit/Basic.h"
38 #include "common/lib/test_env.c"
40 #include "spdk_cunit.h"
41 #include "blobfs/blobfs.c"
42 #include "blobfs/tree.c"
44 #include "unit/lib/blob/bs_dev_common.c"
46 struct spdk_filesystem
*g_fs
;
47 struct spdk_file
*g_file
;
50 /* Return NULL to test hardcoded defaults. */
51 struct spdk_conf_section
*
52 spdk_conf_find_section(struct spdk_conf
*cp
, const char *name
)
57 /* Return -1 to test hardcoded defaults. */
59 spdk_conf_section_get_intval(struct spdk_conf_section
*sp
, const char *key
)
65 _fs_send_msg(spdk_thread_fn fn
, void *ctx
, void *thread_ctx
)
71 fs_op_complete(void *ctx
, int fserrno
)
77 fs_op_with_handle_complete(void *ctx
, struct spdk_filesystem
*fs
, int fserrno
)
86 struct spdk_filesystem
*fs
;
87 struct spdk_bs_dev
*dev
;
90 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
92 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
93 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
94 CU_ASSERT(g_fserrno
== 0);
98 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
99 CU_ASSERT(g_fserrno
== 0);
105 create_cb(void *ctx
, int fserrno
)
111 open_cb(void *ctx
, struct spdk_file
*f
, int fserrno
)
118 delete_cb(void *ctx
, int fserrno
)
126 struct spdk_filesystem
*fs
;
128 struct spdk_bs_dev
*dev
;
129 struct spdk_file
*file
;
130 char name
[257] = {'\0'};
133 memset(name
, 'a', sizeof(name
) - 1);
134 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
136 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
137 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
138 CU_ASSERT(g_fserrno
== 0);
142 /* Open should fail, because the file name is too long. */
143 spdk_fs_open_file_async(fs
, name
, SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
144 CU_ASSERT(g_fserrno
== -ENAMETOOLONG
);
147 spdk_fs_open_file_async(fs
, "file1", 0, open_cb
, NULL
);
148 CU_ASSERT(g_fserrno
== -ENOENT
);
152 spdk_fs_open_file_async(fs
, "file1", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
153 CU_ASSERT(g_fserrno
== 0);
154 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
155 CU_ASSERT(!strcmp("file1", g_file
->name
));
156 CU_ASSERT(g_file
->ref_count
== 1);
158 iter
= spdk_fs_iter_first(fs
);
159 CU_ASSERT(iter
!= NULL
);
160 file
= spdk_fs_iter_get_file(iter
);
161 SPDK_CU_ASSERT_FATAL(file
!= NULL
);
162 CU_ASSERT(!strcmp("file1", file
->name
));
163 iter
= spdk_fs_iter_next(iter
);
164 CU_ASSERT(iter
== NULL
);
167 /* Delete should successful, we will mark the file as deleted. */
168 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
169 CU_ASSERT(g_fserrno
== 0);
170 CU_ASSERT(!TAILQ_EMPTY(&fs
->files
));
173 spdk_file_close_async(g_file
, fs_op_complete
, NULL
);
174 CU_ASSERT(g_fserrno
== 0);
175 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
178 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
179 CU_ASSERT(g_fserrno
== 0);
187 struct spdk_filesystem
*fs
;
188 struct spdk_bs_dev
*dev
;
189 char name
[257] = {'\0'};
192 memset(name
, 'a', sizeof(name
) - 1);
193 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
195 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
196 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
197 CU_ASSERT(g_fserrno
== 0);
201 /* Create should fail, because the file name is too long. */
202 spdk_fs_create_file_async(fs
, name
, create_cb
, NULL
);
203 CU_ASSERT(g_fserrno
== -ENAMETOOLONG
);
206 spdk_fs_create_file_async(fs
, "file1", create_cb
, NULL
);
207 CU_ASSERT(g_fserrno
== 0);
210 spdk_fs_create_file_async(fs
, "file1", create_cb
, NULL
);
211 CU_ASSERT(g_fserrno
== -EEXIST
);
214 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
215 CU_ASSERT(g_fserrno
== 0);
216 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
219 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
220 CU_ASSERT(g_fserrno
== 0);
228 struct spdk_filesystem
*fs
;
229 struct spdk_bs_dev
*dev
;
232 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
234 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
235 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
236 CU_ASSERT(g_fserrno
== 0);
241 spdk_fs_open_file_async(fs
, "file1", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
242 CU_ASSERT(g_fserrno
== 0);
243 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
246 spdk_file_truncate_async(g_file
, 18 * 1024 * 1024 + 1, fs_op_complete
, NULL
);
247 CU_ASSERT(g_fserrno
== 0);
248 CU_ASSERT(g_file
->length
== 18 * 1024 * 1024 + 1);
251 spdk_file_truncate_async(g_file
, 1, fs_op_complete
, NULL
);
252 CU_ASSERT(g_fserrno
== 0);
253 CU_ASSERT(g_file
->length
== 1);
256 spdk_file_truncate_async(g_file
, 18 * 1024 * 1024 + 1, fs_op_complete
, NULL
);
257 CU_ASSERT(g_fserrno
== 0);
258 CU_ASSERT(g_file
->length
== 18 * 1024 * 1024 + 1);
261 spdk_file_close_async(g_file
, fs_op_complete
, NULL
);
262 CU_ASSERT(g_fserrno
== 0);
263 CU_ASSERT(g_file
->ref_count
== 0);
266 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
267 CU_ASSERT(g_fserrno
== 0);
268 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
271 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
272 CU_ASSERT(g_fserrno
== 0);
280 struct spdk_filesystem
*fs
;
281 struct spdk_file
*file
, *file2
;
282 struct spdk_bs_dev
*dev
;
285 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
287 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
288 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
289 CU_ASSERT(g_fserrno
== 0);
293 spdk_fs_create_file_async(fs
, "file1", create_cb
, NULL
);
294 CU_ASSERT(g_fserrno
== 0);
298 spdk_fs_open_file_async(fs
, "file1", 0, open_cb
, NULL
);
299 CU_ASSERT(g_fserrno
== 0);
300 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
301 CU_ASSERT(g_file
->ref_count
== 1);
306 spdk_file_close_async(file
, fs_op_complete
, NULL
);
307 CU_ASSERT(g_fserrno
== 0);
308 SPDK_CU_ASSERT_FATAL(file
->ref_count
== 0);
312 spdk_fs_open_file_async(fs
, "file2", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
313 CU_ASSERT(g_fserrno
== 0);
314 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
315 CU_ASSERT(g_file
->ref_count
== 1);
320 spdk_file_close_async(file2
, fs_op_complete
, NULL
);
321 CU_ASSERT(g_fserrno
== 0);
322 SPDK_CU_ASSERT_FATAL(file2
->ref_count
== 0);
325 * Do a 3-way rename. This should delete the old "file2", then rename
326 * "file1" to "file2".
329 spdk_fs_rename_file_async(fs
, "file1", "file2", fs_op_complete
, NULL
);
330 CU_ASSERT(g_fserrno
== 0);
331 CU_ASSERT(file
->ref_count
== 0);
332 CU_ASSERT(!strcmp(file
->name
, "file2"));
333 CU_ASSERT(TAILQ_FIRST(&fs
->files
) == file
);
334 CU_ASSERT(TAILQ_NEXT(file
, tailq
) == NULL
);
337 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
338 CU_ASSERT(g_fserrno
== -ENOENT
);
339 CU_ASSERT(!TAILQ_EMPTY(&fs
->files
));
342 spdk_fs_delete_file_async(fs
, "file2", delete_cb
, NULL
);
343 CU_ASSERT(g_fserrno
== 0);
344 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
347 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
348 CU_ASSERT(g_fserrno
== 0);
354 tree_find_buffer_ut(void)
356 struct cache_tree
*root
;
357 struct cache_tree
*level1_0
;
358 struct cache_tree
*level0_0_0
;
359 struct cache_tree
*level0_0_12
;
360 struct cache_buffer
*leaf_0_0_4
;
361 struct cache_buffer
*leaf_0_12_8
;
362 struct cache_buffer
*leaf_9_23_15
;
363 struct cache_buffer
*buffer
;
365 level1_0
= calloc(1, sizeof(struct cache_tree
));
366 SPDK_CU_ASSERT_FATAL(level1_0
!= NULL
);
367 level0_0_0
= calloc(1, sizeof(struct cache_tree
));
368 SPDK_CU_ASSERT_FATAL(level0_0_0
!= NULL
);
369 level0_0_12
= calloc(1, sizeof(struct cache_tree
));
370 SPDK_CU_ASSERT_FATAL(level0_0_12
!= NULL
);
371 leaf_0_0_4
= calloc(1, sizeof(struct cache_buffer
));
372 SPDK_CU_ASSERT_FATAL(leaf_0_0_4
!= NULL
);
373 leaf_0_12_8
= calloc(1, sizeof(struct cache_buffer
));
374 SPDK_CU_ASSERT_FATAL(leaf_0_12_8
!= NULL
);
375 leaf_9_23_15
= calloc(1, sizeof(struct cache_buffer
));
376 SPDK_CU_ASSERT_FATAL(leaf_9_23_15
!= NULL
);
379 level0_0_0
->level
= 0;
380 level0_0_12
->level
= 0;
382 leaf_0_0_4
->offset
= CACHE_BUFFER_SIZE
* 4;
383 level0_0_0
->u
.buffer
[4] = leaf_0_0_4
;
384 level0_0_0
->present_mask
|= (1ULL << 4);
386 leaf_0_12_8
->offset
= CACHE_TREE_LEVEL_SIZE(1) * 12 + CACHE_BUFFER_SIZE
* 8;
387 level0_0_12
->u
.buffer
[8] = leaf_0_12_8
;
388 level0_0_12
->present_mask
|= (1ULL << 8);
390 level1_0
->u
.tree
[0] = level0_0_0
;
391 level1_0
->present_mask
|= (1ULL << 0);
392 level1_0
->u
.tree
[12] = level0_0_12
;
393 level1_0
->present_mask
|= (1ULL << 12);
395 buffer
= spdk_tree_find_buffer(NULL
, 0);
396 CU_ASSERT(buffer
== NULL
);
398 buffer
= spdk_tree_find_buffer(level0_0_0
, 0);
399 CU_ASSERT(buffer
== NULL
);
401 buffer
= spdk_tree_find_buffer(level0_0_0
, CACHE_TREE_LEVEL_SIZE(0) + 1);
402 CU_ASSERT(buffer
== NULL
);
404 buffer
= spdk_tree_find_buffer(level0_0_0
, leaf_0_0_4
->offset
);
405 CU_ASSERT(buffer
== leaf_0_0_4
);
407 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_0_4
->offset
);
408 CU_ASSERT(buffer
== leaf_0_0_4
);
410 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
);
411 CU_ASSERT(buffer
== leaf_0_12_8
);
413 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
+ CACHE_BUFFER_SIZE
- 1);
414 CU_ASSERT(buffer
== leaf_0_12_8
);
416 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
- 1);
417 CU_ASSERT(buffer
== NULL
);
419 leaf_9_23_15
->offset
= CACHE_TREE_LEVEL_SIZE(2) * 9 +
420 CACHE_TREE_LEVEL_SIZE(1) * 23 +
421 CACHE_BUFFER_SIZE
* 15;
422 root
= spdk_tree_insert_buffer(level1_0
, leaf_9_23_15
);
423 CU_ASSERT(root
!= level1_0
);
424 buffer
= spdk_tree_find_buffer(root
, leaf_9_23_15
->offset
);
425 CU_ASSERT(buffer
== leaf_9_23_15
);
426 spdk_tree_free_buffers(root
);
433 struct spdk_filesystem
*fs
;
434 struct spdk_bs_dev
*dev
;
435 struct spdk_io_channel
*channel
;
438 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
440 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
441 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
442 CU_ASSERT(g_fserrno
== 0);
445 channel
= spdk_fs_alloc_io_channel(fs
);
446 CU_ASSERT(channel
!= NULL
);
448 spdk_fs_free_io_channel(channel
);
451 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
452 CU_ASSERT(g_fserrno
== 0);
459 channel_ops_sync(void)
461 struct spdk_filesystem
*fs
;
462 struct spdk_bs_dev
*dev
;
463 struct spdk_io_channel
*channel
;
466 spdk_allocate_thread(_fs_send_msg
, NULL
, NULL
, NULL
, "thread0");
468 spdk_fs_init(dev
, NULL
, NULL
, fs_op_with_handle_complete
, NULL
);
469 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
470 CU_ASSERT(g_fserrno
== 0);
473 channel
= spdk_fs_alloc_io_channel_sync(fs
);
474 CU_ASSERT(channel
!= NULL
);
476 spdk_fs_free_io_channel(channel
);
479 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
480 CU_ASSERT(g_fserrno
== 0);
486 int main(int argc
, char **argv
)
488 CU_pSuite suite
= NULL
;
489 unsigned int num_failures
;
491 if (CU_initialize_registry() != CUE_SUCCESS
) {
492 return CU_get_error();
495 suite
= CU_add_suite("blobfs_async_ut", NULL
, NULL
);
497 CU_cleanup_registry();
498 return CU_get_error();
502 CU_add_test(suite
, "fs_init", fs_init
) == NULL
||
503 CU_add_test(suite
, "fs_open", fs_open
) == NULL
||
504 CU_add_test(suite
, "fs_create", fs_create
) == NULL
||
505 CU_add_test(suite
, "fs_truncate", fs_truncate
) == NULL
||
506 CU_add_test(suite
, "fs_rename", fs_rename
) == NULL
||
507 CU_add_test(suite
, "tree_find_buffer", tree_find_buffer_ut
) == NULL
||
508 CU_add_test(suite
, "channel_ops", channel_ops
) == NULL
||
509 CU_add_test(suite
, "channel_ops_sync", channel_ops_sync
) == NULL
511 CU_cleanup_registry();
512 return CU_get_error();
515 g_dev_buffer
= calloc(1, DEV_BUFFER_SIZE
);
516 CU_basic_set_mode(CU_BRM_VERBOSE
);
517 CU_basic_run_tests();
518 num_failures
= CU_get_number_of_failures();
519 CU_cleanup_registry();