1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 16 * distribution. 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. 20 * 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. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "CUnit/Basic.h" 37 38 #include "common/lib/test_env.c" 39 40 #include "spdk_cunit.h" 41 #include "blobfs/blobfs.c" 42 #include "blobfs/tree.c" 43 44 #include "unit/lib/blob/bs_dev_common.c" 45 46 struct spdk_filesystem *g_fs; 47 struct spdk_file *g_file; 48 int g_fserrno; 49 50 /* Return NULL to test hardcoded defaults. */ 51 struct spdk_conf_section * 52 spdk_conf_find_section(struct spdk_conf *cp, const char *name) 53 { 54 return NULL; 55 } 56 57 /* Return -1 to test hardcoded defaults. */ 58 int 59 spdk_conf_section_get_intval(struct spdk_conf_section *sp, const char *key) 60 { 61 return -1; 62 } 63 64 static void 65 _fs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) 66 { 67 fn(ctx); 68 } 69 70 static void 71 fs_op_complete(void *ctx, int fserrno) 72 { 73 g_fserrno = fserrno; 74 } 75 76 static void 77 fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno) 78 { 79 g_fs = fs; 80 g_fserrno = fserrno; 81 } 82 83 static void 84 fs_init(void) 85 { 86 struct spdk_filesystem *fs; 87 struct spdk_bs_dev *dev; 88 89 dev = init_dev(); 90 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 91 92 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 93 CU_ASSERT(g_fs != NULL); 94 CU_ASSERT(g_fserrno == 0); 95 fs = g_fs; 96 97 g_fserrno = 1; 98 spdk_fs_unload(fs, fs_op_complete, NULL); 99 CU_ASSERT(g_fserrno == 0); 100 101 spdk_free_thread(); 102 } 103 104 static void 105 create_cb(void *ctx, int fserrno) 106 { 107 g_fserrno = fserrno; 108 } 109 110 static void 111 open_cb(void *ctx, struct spdk_file *f, int fserrno) 112 { 113 g_fserrno = fserrno; 114 g_file = f; 115 } 116 117 static void 118 delete_cb(void *ctx, int fserrno) 119 { 120 g_fserrno = fserrno; 121 } 122 123 static void 124 fs_open(void) 125 { 126 struct spdk_filesystem *fs; 127 spdk_fs_iter iter; 128 struct spdk_bs_dev *dev; 129 struct spdk_file *file; 130 char name[257] = {'\0'}; 131 132 dev = init_dev(); 133 memset(name, 'a', sizeof(name) - 1); 134 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 135 136 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 137 CU_ASSERT(g_fs != NULL); 138 CU_ASSERT(g_fserrno == 0); 139 fs = g_fs; 140 141 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); 145 146 g_fserrno = 0; 147 spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL); 148 CU_ASSERT(g_fserrno == -ENOENT); 149 150 g_file = NULL; 151 g_fserrno = 1; 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); 157 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); 165 166 g_fserrno = 0; 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)); 171 172 g_fserrno = 1; 173 spdk_file_close_async(g_file, fs_op_complete, NULL); 174 CU_ASSERT(g_fserrno == 0); 175 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 176 177 g_fserrno = 1; 178 spdk_fs_unload(fs, fs_op_complete, NULL); 179 CU_ASSERT(g_fserrno == 0); 180 181 spdk_free_thread(); 182 } 183 184 static void 185 fs_create(void) 186 { 187 struct spdk_filesystem *fs; 188 struct spdk_bs_dev *dev; 189 char name[257] = {'\0'}; 190 191 dev = init_dev(); 192 memset(name, 'a', sizeof(name) - 1); 193 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 194 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); 198 fs = g_fs; 199 200 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); 204 205 g_fserrno = 1; 206 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 207 CU_ASSERT(g_fserrno == 0); 208 209 g_fserrno = 1; 210 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 211 CU_ASSERT(g_fserrno == -EEXIST); 212 213 g_fserrno = 1; 214 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 215 CU_ASSERT(g_fserrno == 0); 216 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 217 218 g_fserrno = 1; 219 spdk_fs_unload(fs, fs_op_complete, NULL); 220 CU_ASSERT(g_fserrno == 0); 221 222 spdk_free_thread(); 223 } 224 225 static void 226 fs_truncate(void) 227 { 228 struct spdk_filesystem *fs; 229 struct spdk_bs_dev *dev; 230 231 dev = init_dev(); 232 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 233 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); 237 fs = g_fs; 238 239 g_file = NULL; 240 g_fserrno = 1; 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); 244 245 g_fserrno = 1; 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); 249 250 g_fserrno = 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); 254 255 g_fserrno = 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); 259 260 g_fserrno = 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); 264 265 g_fserrno = 1; 266 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 267 CU_ASSERT(g_fserrno == 0); 268 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 269 270 g_fserrno = 1; 271 spdk_fs_unload(fs, fs_op_complete, NULL); 272 CU_ASSERT(g_fserrno == 0); 273 274 spdk_free_thread(); 275 } 276 277 static void 278 fs_rename(void) 279 { 280 struct spdk_filesystem *fs; 281 struct spdk_file *file, *file2; 282 struct spdk_bs_dev *dev; 283 284 dev = init_dev(); 285 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 286 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); 290 fs = g_fs; 291 292 g_fserrno = 1; 293 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 294 CU_ASSERT(g_fserrno == 0); 295 296 g_file = NULL; 297 g_fserrno = 1; 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); 302 303 file = g_file; 304 g_file = NULL; 305 g_fserrno = 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); 309 310 g_file = NULL; 311 g_fserrno = 1; 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); 316 317 file2 = g_file; 318 g_file = NULL; 319 g_fserrno = 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); 323 324 /* 325 * Do a 3-way rename. This should delete the old "file2", then rename 326 * "file1" to "file2". 327 */ 328 g_fserrno = 1; 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); 335 336 g_fserrno = 0; 337 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 338 CU_ASSERT(g_fserrno == -ENOENT); 339 CU_ASSERT(!TAILQ_EMPTY(&fs->files)); 340 341 g_fserrno = 1; 342 spdk_fs_delete_file_async(fs, "file2", delete_cb, NULL); 343 CU_ASSERT(g_fserrno == 0); 344 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 345 346 g_fserrno = 1; 347 spdk_fs_unload(fs, fs_op_complete, NULL); 348 CU_ASSERT(g_fserrno == 0); 349 350 spdk_free_thread(); 351 } 352 353 static void 354 tree_find_buffer_ut(void) 355 { 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; 364 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); 377 378 level1_0->level = 1; 379 level0_0_0->level = 0; 380 level0_0_12->level = 0; 381 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); 385 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); 389 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); 394 395 buffer = spdk_tree_find_buffer(NULL, 0); 396 CU_ASSERT(buffer == NULL); 397 398 buffer = spdk_tree_find_buffer(level0_0_0, 0); 399 CU_ASSERT(buffer == NULL); 400 401 buffer = spdk_tree_find_buffer(level0_0_0, CACHE_TREE_LEVEL_SIZE(0) + 1); 402 CU_ASSERT(buffer == NULL); 403 404 buffer = spdk_tree_find_buffer(level0_0_0, leaf_0_0_4->offset); 405 CU_ASSERT(buffer == leaf_0_0_4); 406 407 buffer = spdk_tree_find_buffer(level1_0, leaf_0_0_4->offset); 408 CU_ASSERT(buffer == leaf_0_0_4); 409 410 buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset); 411 CU_ASSERT(buffer == leaf_0_12_8); 412 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); 415 416 buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset - 1); 417 CU_ASSERT(buffer == NULL); 418 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); 427 free(root); 428 } 429 430 static void 431 channel_ops(void) 432 { 433 struct spdk_filesystem *fs; 434 struct spdk_bs_dev *dev; 435 struct spdk_io_channel *channel; 436 437 dev = init_dev(); 438 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 439 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); 443 fs = g_fs; 444 445 channel = spdk_fs_alloc_io_channel(fs); 446 CU_ASSERT(channel != NULL); 447 448 spdk_fs_free_io_channel(channel); 449 450 g_fserrno = 1; 451 spdk_fs_unload(fs, fs_op_complete, NULL); 452 CU_ASSERT(g_fserrno == 0); 453 g_fs = NULL; 454 455 spdk_free_thread(); 456 } 457 458 static void 459 channel_ops_sync(void) 460 { 461 struct spdk_filesystem *fs; 462 struct spdk_bs_dev *dev; 463 struct spdk_io_channel *channel; 464 465 dev = init_dev(); 466 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 467 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); 471 fs = g_fs; 472 473 channel = spdk_fs_alloc_io_channel_sync(fs); 474 CU_ASSERT(channel != NULL); 475 476 spdk_fs_free_io_channel(channel); 477 478 g_fserrno = 1; 479 spdk_fs_unload(fs, fs_op_complete, NULL); 480 CU_ASSERT(g_fserrno == 0); 481 g_fs = NULL; 482 483 spdk_free_thread(); 484 } 485 486 int main(int argc, char **argv) 487 { 488 CU_pSuite suite = NULL; 489 unsigned int num_failures; 490 491 if (CU_initialize_registry() != CUE_SUCCESS) { 492 return CU_get_error(); 493 } 494 495 suite = CU_add_suite("blobfs_async_ut", NULL, NULL); 496 if (suite == NULL) { 497 CU_cleanup_registry(); 498 return CU_get_error(); 499 } 500 501 if ( 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 510 ) { 511 CU_cleanup_registry(); 512 return CU_get_error(); 513 } 514 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(); 520 free(g_dev_buffer); 521 return num_failures; 522 } 523