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.
39 #include "CUnit/Basic.h"
41 #include "lib/test_env.c"
43 #include "spdk_cunit.h"
47 #include "lib/blob/bs_dev_common.c"
49 struct spdk_filesystem
*g_fs
;
50 struct spdk_file
*g_file
;
54 fs_op_complete(void *ctx
, int fserrno
)
60 fs_op_with_handle_complete(void *ctx
, struct spdk_filesystem
*fs
, int fserrno
)
69 struct spdk_filesystem
*fs
;
70 struct spdk_bs_dev dev
;
73 spdk_allocate_thread();
75 spdk_fs_init(&dev
, NULL
, fs_op_with_handle_complete
, NULL
);
76 CU_ASSERT(g_fs
!= NULL
);
77 CU_ASSERT(g_fserrno
== 0);
80 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
81 CU_ASSERT(g_fserrno
== 0);
87 create_cb(void *ctx
, int fserrno
)
93 open_cb(void *ctx
, struct spdk_file
*f
, int fserrno
)
100 delete_cb(void *ctx
, int fserrno
)
108 struct spdk_filesystem
*fs
;
110 struct spdk_bs_dev dev
;
111 struct spdk_file
*file
;
114 spdk_allocate_thread();
116 spdk_fs_init(&dev
, NULL
, fs_op_with_handle_complete
, NULL
);
117 CU_ASSERT(g_fs
!= NULL
);
118 CU_ASSERT(g_fserrno
== 0);
122 spdk_fs_open_file_async(fs
, "file1", 0, open_cb
, NULL
);
123 CU_ASSERT(g_fserrno
== -ENOENT
);
127 spdk_fs_open_file_async(fs
, "file1", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
128 CU_ASSERT(g_fserrno
== 0);
129 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
130 CU_ASSERT(!strcmp("file1", g_file
->name
));
131 CU_ASSERT(g_file
->ref_count
== 1);
133 iter
= spdk_fs_iter_first(fs
);
134 CU_ASSERT(iter
!= NULL
);
135 file
= spdk_fs_iter_get_file(iter
);
136 SPDK_CU_ASSERT_FATAL(file
!= NULL
);
137 CU_ASSERT(!strcmp("file1", file
->name
));
138 iter
= spdk_fs_iter_next(iter
);
139 CU_ASSERT(iter
== NULL
);
142 /* Delete should fail, since we have an open reference. */
143 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
144 CU_ASSERT(g_fserrno
== -EBUSY
);
145 CU_ASSERT(!TAILQ_EMPTY(&fs
->files
));
148 spdk_file_close_async(g_file
, fs_op_complete
, NULL
);
149 CU_ASSERT(g_fserrno
== 0);
150 CU_ASSERT(g_file
->ref_count
== 0);
153 spdk_file_close_async(g_file
, fs_op_complete
, NULL
);
154 CU_ASSERT(g_fserrno
== -EBADF
);
155 CU_ASSERT(g_file
->ref_count
== 0);
158 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
159 CU_ASSERT(g_fserrno
== 0);
160 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
162 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
163 CU_ASSERT(g_fserrno
== 0);
171 struct spdk_filesystem
*fs
;
172 struct spdk_bs_dev dev
;
175 spdk_allocate_thread();
177 spdk_fs_init(&dev
, NULL
, fs_op_with_handle_complete
, NULL
);
178 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
179 CU_ASSERT(g_fserrno
== 0);
184 spdk_fs_open_file_async(fs
, "file1", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
185 CU_ASSERT(g_fserrno
== 0);
186 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
189 spdk_file_truncate_async(g_file
, 18 * 1024 * 1024 + 1, fs_op_complete
, NULL
);
190 CU_ASSERT(g_fserrno
== 0);
191 CU_ASSERT(g_file
->length
== 18 * 1024 * 1024 + 1);
194 spdk_file_truncate_async(g_file
, 1, fs_op_complete
, NULL
);
195 CU_ASSERT(g_fserrno
== 0);
196 CU_ASSERT(g_file
->length
== 1);
199 spdk_file_truncate_async(g_file
, 18 * 1024 * 1024 + 1, fs_op_complete
, NULL
);
200 CU_ASSERT(g_fserrno
== 0);
201 CU_ASSERT(g_file
->length
== 18 * 1024 * 1024 + 1);
204 spdk_file_close_async(g_file
, fs_op_complete
, NULL
);
205 CU_ASSERT(g_fserrno
== 0);
206 CU_ASSERT(g_file
->ref_count
== 0);
209 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
210 CU_ASSERT(g_fserrno
== 0);
211 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
213 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
214 CU_ASSERT(g_fserrno
== 0);
222 struct spdk_filesystem
*fs
;
223 struct spdk_file
*file
, *file2
;
224 struct spdk_bs_dev dev
;
227 spdk_allocate_thread();
229 spdk_fs_init(&dev
, NULL
, fs_op_with_handle_complete
, NULL
);
230 SPDK_CU_ASSERT_FATAL(g_fs
!= NULL
);
231 CU_ASSERT(g_fserrno
== 0);
235 spdk_fs_create_file_async(fs
, "file1", create_cb
, NULL
);
236 CU_ASSERT(g_fserrno
== 0);
240 spdk_fs_open_file_async(fs
, "file1", 0, open_cb
, NULL
);
241 CU_ASSERT(g_fserrno
== 0);
242 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
243 CU_ASSERT(g_file
->ref_count
== 1);
248 spdk_file_close_async(file
, fs_op_complete
, NULL
);
249 CU_ASSERT(g_fserrno
== 0);
250 SPDK_CU_ASSERT_FATAL(file
->ref_count
== 0);
254 spdk_fs_open_file_async(fs
, "file2", SPDK_BLOBFS_OPEN_CREATE
, open_cb
, NULL
);
255 CU_ASSERT(g_fserrno
== 0);
256 SPDK_CU_ASSERT_FATAL(g_file
!= NULL
);
257 CU_ASSERT(g_file
->ref_count
== 1);
262 spdk_file_close_async(file2
, fs_op_complete
, NULL
);
263 CU_ASSERT(g_fserrno
== 0);
264 SPDK_CU_ASSERT_FATAL(file2
->ref_count
== 0);
267 * Do a 3-way rename. This should delete the old "file2", then rename
268 * "file1" to "file2".
271 spdk_fs_rename_file_async(fs
, "file1", "file2", fs_op_complete
, NULL
);
272 CU_ASSERT(g_fserrno
== 0);
273 CU_ASSERT(file
->ref_count
== 0);
274 CU_ASSERT(!strcmp(file
->name
, "file2"));
275 CU_ASSERT(TAILQ_FIRST(&fs
->files
) == file
);
276 CU_ASSERT(TAILQ_NEXT(file
, tailq
) == NULL
);
279 spdk_fs_delete_file_async(fs
, "file1", delete_cb
, NULL
);
280 CU_ASSERT(g_fserrno
== -ENOENT
);
281 CU_ASSERT(!TAILQ_EMPTY(&fs
->files
));
284 spdk_fs_delete_file_async(fs
, "file2", delete_cb
, NULL
);
285 CU_ASSERT(g_fserrno
== 0);
286 CU_ASSERT(TAILQ_EMPTY(&fs
->files
));
288 spdk_fs_unload(fs
, fs_op_complete
, NULL
);
289 CU_ASSERT(g_fserrno
== 0);
295 tree_find_buffer_ut(void)
297 struct cache_tree
*root
;
298 struct cache_tree
*level1_0
;
299 struct cache_tree
*level0_0_0
;
300 struct cache_tree
*level0_0_12
;
301 struct cache_buffer
*leaf_0_0_4
;
302 struct cache_buffer
*leaf_0_12_8
;
303 struct cache_buffer
*leaf_9_23_15
;
304 struct cache_buffer
*buffer
;
306 level1_0
= calloc(1, sizeof(struct cache_tree
));
307 SPDK_CU_ASSERT_FATAL(level1_0
!= NULL
);
308 level0_0_0
= calloc(1, sizeof(struct cache_tree
));
309 SPDK_CU_ASSERT_FATAL(level0_0_0
!= NULL
);
310 level0_0_12
= calloc(1, sizeof(struct cache_tree
));
311 SPDK_CU_ASSERT_FATAL(level0_0_12
!= NULL
);
312 leaf_0_0_4
= calloc(1, sizeof(struct cache_buffer
));
313 SPDK_CU_ASSERT_FATAL(leaf_0_0_4
!= NULL
);
314 leaf_0_12_8
= calloc(1, sizeof(struct cache_buffer
));
315 SPDK_CU_ASSERT_FATAL(leaf_0_12_8
!= NULL
);
316 leaf_9_23_15
= calloc(1, sizeof(struct cache_buffer
));
317 SPDK_CU_ASSERT_FATAL(leaf_9_23_15
!= NULL
);
320 level0_0_0
->level
= 0;
321 level0_0_12
->level
= 0;
323 leaf_0_0_4
->offset
= CACHE_BUFFER_SIZE
* 4;
324 level0_0_0
->u
.buffer
[4] = leaf_0_0_4
;
325 level0_0_0
->present_mask
|= (1ULL << 4);
327 leaf_0_12_8
->offset
= CACHE_TREE_LEVEL_SIZE(1) * 12 + CACHE_BUFFER_SIZE
* 8;
328 level0_0_12
->u
.buffer
[8] = leaf_0_12_8
;
329 level0_0_12
->present_mask
|= (1ULL << 8);
331 level1_0
->u
.tree
[0] = level0_0_0
;
332 level1_0
->present_mask
|= (1ULL << 0);
333 level1_0
->u
.tree
[12] = level0_0_12
;
334 level1_0
->present_mask
|= (1ULL << 12);
336 buffer
= spdk_tree_find_buffer(NULL
, 0);
337 CU_ASSERT(buffer
== NULL
);
339 buffer
= spdk_tree_find_buffer(level0_0_0
, 0);
340 CU_ASSERT(buffer
== NULL
);
342 buffer
= spdk_tree_find_buffer(level0_0_0
, CACHE_TREE_LEVEL_SIZE(0) + 1);
343 CU_ASSERT(buffer
== NULL
);
345 buffer
= spdk_tree_find_buffer(level0_0_0
, leaf_0_0_4
->offset
);
346 CU_ASSERT(buffer
== leaf_0_0_4
);
348 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_0_4
->offset
);
349 CU_ASSERT(buffer
== leaf_0_0_4
);
351 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
);
352 CU_ASSERT(buffer
== leaf_0_12_8
);
354 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
+ CACHE_BUFFER_SIZE
- 1);
355 CU_ASSERT(buffer
== leaf_0_12_8
);
357 buffer
= spdk_tree_find_buffer(level1_0
, leaf_0_12_8
->offset
- 1);
358 CU_ASSERT(buffer
== NULL
);
360 leaf_9_23_15
->offset
= CACHE_TREE_LEVEL_SIZE(2) * 9 +
361 CACHE_TREE_LEVEL_SIZE(1) * 23 +
362 CACHE_BUFFER_SIZE
* 15;
363 root
= spdk_tree_insert_buffer(level1_0
, leaf_9_23_15
);
364 CU_ASSERT(root
!= level1_0
);
365 buffer
= spdk_tree_find_buffer(root
, leaf_9_23_15
->offset
);
366 CU_ASSERT(buffer
== leaf_9_23_15
);
367 spdk_tree_free_buffers(root
);
371 int main(int argc
, char **argv
)
373 CU_pSuite suite
= NULL
;
374 unsigned int num_failures
;
376 if (CU_initialize_registry() != CUE_SUCCESS
) {
377 return CU_get_error();
380 suite
= CU_add_suite("blobfs", NULL
, NULL
);
382 CU_cleanup_registry();
383 return CU_get_error();
387 CU_add_test(suite
, "fs_init", fs_init
) == NULL
||
388 CU_add_test(suite
, "fs_open", fs_open
) == NULL
||
389 CU_add_test(suite
, "fs_truncate", fs_truncate
) == NULL
||
390 CU_add_test(suite
, "fs_rename", fs_rename
) == NULL
||
391 CU_add_test(suite
, "tree_find_buffer", tree_find_buffer_ut
) == NULL
393 CU_cleanup_registry();
394 return CU_get_error();
397 g_dev_buffer
= calloc(1, DEV_BUFFER_SIZE
);
398 CU_basic_set_mode(CU_BRM_VERBOSE
);
399 CU_basic_run_tests();
400 num_failures
= CU_get_number_of_failures();
401 CU_cleanup_registry();