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 91 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 92 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 93 CU_ASSERT(g_fserrno == 0); 94 fs = g_fs; 95 96 g_fserrno = 1; 97 spdk_fs_unload(fs, fs_op_complete, NULL); 98 CU_ASSERT(g_fserrno == 0); 99 } 100 101 static void 102 create_cb(void *ctx, int fserrno) 103 { 104 g_fserrno = fserrno; 105 } 106 107 static void 108 open_cb(void *ctx, struct spdk_file *f, int fserrno) 109 { 110 g_fserrno = fserrno; 111 g_file = f; 112 } 113 114 static void 115 delete_cb(void *ctx, int fserrno) 116 { 117 g_fserrno = fserrno; 118 } 119 120 static void 121 fs_open(void) 122 { 123 struct spdk_filesystem *fs; 124 spdk_fs_iter iter; 125 struct spdk_bs_dev *dev; 126 struct spdk_file *file; 127 char name[257] = {'\0'}; 128 129 dev = init_dev(); 130 memset(name, 'a', sizeof(name) - 1); 131 132 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 133 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 134 CU_ASSERT(g_fserrno == 0); 135 fs = g_fs; 136 137 g_fserrno = 0; 138 /* Open should fail, because the file name is too long. */ 139 spdk_fs_open_file_async(fs, name, SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); 140 CU_ASSERT(g_fserrno == -ENAMETOOLONG); 141 142 g_fserrno = 0; 143 spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL); 144 CU_ASSERT(g_fserrno == -ENOENT); 145 146 g_file = NULL; 147 g_fserrno = 1; 148 spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); 149 CU_ASSERT(g_fserrno == 0); 150 SPDK_CU_ASSERT_FATAL(g_file != NULL); 151 CU_ASSERT(!strcmp("file1", g_file->name)); 152 CU_ASSERT(g_file->ref_count == 1); 153 154 iter = spdk_fs_iter_first(fs); 155 CU_ASSERT(iter != NULL); 156 file = spdk_fs_iter_get_file(iter); 157 SPDK_CU_ASSERT_FATAL(file != NULL); 158 CU_ASSERT(!strcmp("file1", file->name)); 159 iter = spdk_fs_iter_next(iter); 160 CU_ASSERT(iter == NULL); 161 162 g_fserrno = 0; 163 /* Delete should successful, we will mark the file as deleted. */ 164 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 165 CU_ASSERT(g_fserrno == 0); 166 CU_ASSERT(!TAILQ_EMPTY(&fs->files)); 167 168 g_fserrno = 1; 169 spdk_file_close_async(g_file, fs_op_complete, NULL); 170 CU_ASSERT(g_fserrno == 0); 171 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 172 173 g_fserrno = 1; 174 spdk_fs_unload(fs, fs_op_complete, NULL); 175 CU_ASSERT(g_fserrno == 0); 176 } 177 178 static void 179 fs_create(void) 180 { 181 struct spdk_filesystem *fs; 182 struct spdk_bs_dev *dev; 183 char name[257] = {'\0'}; 184 185 dev = init_dev(); 186 memset(name, 'a', sizeof(name) - 1); 187 188 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 189 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 190 CU_ASSERT(g_fserrno == 0); 191 fs = g_fs; 192 193 g_fserrno = 0; 194 /* Create should fail, because the file name is too long. */ 195 spdk_fs_create_file_async(fs, name, create_cb, NULL); 196 CU_ASSERT(g_fserrno == -ENAMETOOLONG); 197 198 g_fserrno = 1; 199 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 200 CU_ASSERT(g_fserrno == 0); 201 202 g_fserrno = 1; 203 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 204 CU_ASSERT(g_fserrno == -EEXIST); 205 206 g_fserrno = 1; 207 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 208 CU_ASSERT(g_fserrno == 0); 209 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 210 211 g_fserrno = 1; 212 spdk_fs_unload(fs, fs_op_complete, NULL); 213 CU_ASSERT(g_fserrno == 0); 214 } 215 216 static void 217 fs_truncate(void) 218 { 219 struct spdk_filesystem *fs; 220 struct spdk_bs_dev *dev; 221 222 dev = init_dev(); 223 224 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 225 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 226 CU_ASSERT(g_fserrno == 0); 227 fs = g_fs; 228 229 g_file = NULL; 230 g_fserrno = 1; 231 spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); 232 CU_ASSERT(g_fserrno == 0); 233 SPDK_CU_ASSERT_FATAL(g_file != NULL); 234 235 g_fserrno = 1; 236 spdk_file_truncate_async(g_file, 18 * 1024 * 1024 + 1, fs_op_complete, NULL); 237 CU_ASSERT(g_fserrno == 0); 238 CU_ASSERT(g_file->length == 18 * 1024 * 1024 + 1); 239 240 g_fserrno = 1; 241 spdk_file_truncate_async(g_file, 1, fs_op_complete, NULL); 242 CU_ASSERT(g_fserrno == 0); 243 CU_ASSERT(g_file->length == 1); 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_close_async(g_file, fs_op_complete, NULL); 252 CU_ASSERT(g_fserrno == 0); 253 CU_ASSERT(g_file->ref_count == 0); 254 255 g_fserrno = 1; 256 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 257 CU_ASSERT(g_fserrno == 0); 258 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 259 260 g_fserrno = 1; 261 spdk_fs_unload(fs, fs_op_complete, NULL); 262 CU_ASSERT(g_fserrno == 0); 263 } 264 265 static void 266 fs_rename(void) 267 { 268 struct spdk_filesystem *fs; 269 struct spdk_file *file, *file2; 270 struct spdk_bs_dev *dev; 271 272 dev = init_dev(); 273 274 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 275 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 276 CU_ASSERT(g_fserrno == 0); 277 fs = g_fs; 278 279 g_fserrno = 1; 280 spdk_fs_create_file_async(fs, "file1", create_cb, NULL); 281 CU_ASSERT(g_fserrno == 0); 282 283 g_file = NULL; 284 g_fserrno = 1; 285 spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL); 286 CU_ASSERT(g_fserrno == 0); 287 SPDK_CU_ASSERT_FATAL(g_file != NULL); 288 CU_ASSERT(g_file->ref_count == 1); 289 290 file = g_file; 291 g_file = NULL; 292 g_fserrno = 1; 293 spdk_file_close_async(file, fs_op_complete, NULL); 294 CU_ASSERT(g_fserrno == 0); 295 SPDK_CU_ASSERT_FATAL(file->ref_count == 0); 296 297 g_file = NULL; 298 g_fserrno = 1; 299 spdk_fs_open_file_async(fs, "file2", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); 300 CU_ASSERT(g_fserrno == 0); 301 SPDK_CU_ASSERT_FATAL(g_file != NULL); 302 CU_ASSERT(g_file->ref_count == 1); 303 304 file2 = g_file; 305 g_file = NULL; 306 g_fserrno = 1; 307 spdk_file_close_async(file2, fs_op_complete, NULL); 308 CU_ASSERT(g_fserrno == 0); 309 SPDK_CU_ASSERT_FATAL(file2->ref_count == 0); 310 311 /* 312 * Do a 3-way rename. This should delete the old "file2", then rename 313 * "file1" to "file2". 314 */ 315 g_fserrno = 1; 316 spdk_fs_rename_file_async(fs, "file1", "file2", fs_op_complete, NULL); 317 CU_ASSERT(g_fserrno == 0); 318 CU_ASSERT(file->ref_count == 0); 319 CU_ASSERT(!strcmp(file->name, "file2")); 320 CU_ASSERT(TAILQ_FIRST(&fs->files) == file); 321 CU_ASSERT(TAILQ_NEXT(file, tailq) == NULL); 322 323 g_fserrno = 0; 324 spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); 325 CU_ASSERT(g_fserrno == -ENOENT); 326 CU_ASSERT(!TAILQ_EMPTY(&fs->files)); 327 328 g_fserrno = 1; 329 spdk_fs_delete_file_async(fs, "file2", delete_cb, NULL); 330 CU_ASSERT(g_fserrno == 0); 331 CU_ASSERT(TAILQ_EMPTY(&fs->files)); 332 333 g_fserrno = 1; 334 spdk_fs_unload(fs, fs_op_complete, NULL); 335 CU_ASSERT(g_fserrno == 0); 336 } 337 338 static void 339 tree_find_buffer_ut(void) 340 { 341 struct cache_tree *root; 342 struct cache_tree *level1_0; 343 struct cache_tree *level0_0_0; 344 struct cache_tree *level0_0_12; 345 struct cache_buffer *leaf_0_0_4; 346 struct cache_buffer *leaf_0_12_8; 347 struct cache_buffer *leaf_9_23_15; 348 struct cache_buffer *buffer; 349 350 level1_0 = calloc(1, sizeof(struct cache_tree)); 351 SPDK_CU_ASSERT_FATAL(level1_0 != NULL); 352 level0_0_0 = calloc(1, sizeof(struct cache_tree)); 353 SPDK_CU_ASSERT_FATAL(level0_0_0 != NULL); 354 level0_0_12 = calloc(1, sizeof(struct cache_tree)); 355 SPDK_CU_ASSERT_FATAL(level0_0_12 != NULL); 356 leaf_0_0_4 = calloc(1, sizeof(struct cache_buffer)); 357 SPDK_CU_ASSERT_FATAL(leaf_0_0_4 != NULL); 358 leaf_0_12_8 = calloc(1, sizeof(struct cache_buffer)); 359 SPDK_CU_ASSERT_FATAL(leaf_0_12_8 != NULL); 360 leaf_9_23_15 = calloc(1, sizeof(struct cache_buffer)); 361 SPDK_CU_ASSERT_FATAL(leaf_9_23_15 != NULL); 362 363 level1_0->level = 1; 364 level0_0_0->level = 0; 365 level0_0_12->level = 0; 366 367 leaf_0_0_4->offset = CACHE_BUFFER_SIZE * 4; 368 level0_0_0->u.buffer[4] = leaf_0_0_4; 369 level0_0_0->present_mask |= (1ULL << 4); 370 371 leaf_0_12_8->offset = CACHE_TREE_LEVEL_SIZE(1) * 12 + CACHE_BUFFER_SIZE * 8; 372 level0_0_12->u.buffer[8] = leaf_0_12_8; 373 level0_0_12->present_mask |= (1ULL << 8); 374 375 level1_0->u.tree[0] = level0_0_0; 376 level1_0->present_mask |= (1ULL << 0); 377 level1_0->u.tree[12] = level0_0_12; 378 level1_0->present_mask |= (1ULL << 12); 379 380 buffer = spdk_tree_find_buffer(NULL, 0); 381 CU_ASSERT(buffer == NULL); 382 383 buffer = spdk_tree_find_buffer(level0_0_0, 0); 384 CU_ASSERT(buffer == NULL); 385 386 buffer = spdk_tree_find_buffer(level0_0_0, CACHE_TREE_LEVEL_SIZE(0) + 1); 387 CU_ASSERT(buffer == NULL); 388 389 buffer = spdk_tree_find_buffer(level0_0_0, leaf_0_0_4->offset); 390 CU_ASSERT(buffer == leaf_0_0_4); 391 392 buffer = spdk_tree_find_buffer(level1_0, leaf_0_0_4->offset); 393 CU_ASSERT(buffer == leaf_0_0_4); 394 395 buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset); 396 CU_ASSERT(buffer == leaf_0_12_8); 397 398 buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset + CACHE_BUFFER_SIZE - 1); 399 CU_ASSERT(buffer == leaf_0_12_8); 400 401 buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset - 1); 402 CU_ASSERT(buffer == NULL); 403 404 leaf_9_23_15->offset = CACHE_TREE_LEVEL_SIZE(2) * 9 + 405 CACHE_TREE_LEVEL_SIZE(1) * 23 + 406 CACHE_BUFFER_SIZE * 15; 407 root = spdk_tree_insert_buffer(level1_0, leaf_9_23_15); 408 CU_ASSERT(root != level1_0); 409 buffer = spdk_tree_find_buffer(root, leaf_9_23_15->offset); 410 CU_ASSERT(buffer == leaf_9_23_15); 411 spdk_tree_free_buffers(root); 412 free(root); 413 } 414 415 static void 416 channel_ops(void) 417 { 418 struct spdk_filesystem *fs; 419 struct spdk_bs_dev *dev; 420 struct spdk_io_channel *channel; 421 422 dev = init_dev(); 423 424 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 425 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 426 CU_ASSERT(g_fserrno == 0); 427 fs = g_fs; 428 429 channel = spdk_fs_alloc_io_channel(fs); 430 CU_ASSERT(channel != NULL); 431 432 spdk_fs_free_io_channel(channel); 433 434 g_fserrno = 1; 435 spdk_fs_unload(fs, fs_op_complete, NULL); 436 CU_ASSERT(g_fserrno == 0); 437 g_fs = NULL; 438 } 439 440 static void 441 channel_ops_sync(void) 442 { 443 struct spdk_filesystem *fs; 444 struct spdk_bs_dev *dev; 445 struct spdk_io_channel *channel; 446 447 dev = init_dev(); 448 449 spdk_fs_init(dev, NULL, NULL, fs_op_with_handle_complete, NULL); 450 SPDK_CU_ASSERT_FATAL(g_fs != NULL); 451 CU_ASSERT(g_fserrno == 0); 452 fs = g_fs; 453 454 channel = spdk_fs_alloc_io_channel_sync(fs); 455 CU_ASSERT(channel != NULL); 456 457 spdk_fs_free_io_channel(channel); 458 459 g_fserrno = 1; 460 spdk_fs_unload(fs, fs_op_complete, NULL); 461 CU_ASSERT(g_fserrno == 0); 462 g_fs = NULL; 463 } 464 465 int main(int argc, char **argv) 466 { 467 CU_pSuite suite = NULL; 468 unsigned int num_failures; 469 470 if (CU_initialize_registry() != CUE_SUCCESS) { 471 return CU_get_error(); 472 } 473 474 suite = CU_add_suite("blobfs_async_ut", NULL, NULL); 475 if (suite == NULL) { 476 CU_cleanup_registry(); 477 return CU_get_error(); 478 } 479 480 if ( 481 CU_add_test(suite, "fs_init", fs_init) == NULL || 482 CU_add_test(suite, "fs_open", fs_open) == NULL || 483 CU_add_test(suite, "fs_create", fs_create) == NULL || 484 CU_add_test(suite, "fs_truncate", fs_truncate) == NULL || 485 CU_add_test(suite, "fs_rename", fs_rename) == NULL || 486 CU_add_test(suite, "tree_find_buffer", tree_find_buffer_ut) == NULL || 487 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 488 CU_add_test(suite, "channel_ops_sync", channel_ops_sync) == NULL 489 ) { 490 CU_cleanup_registry(); 491 return CU_get_error(); 492 } 493 494 spdk_allocate_thread(_fs_send_msg, NULL, NULL, NULL, "thread0"); 495 496 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 497 CU_basic_set_mode(CU_BRM_VERBOSE); 498 CU_basic_run_tests(); 499 num_failures = CU_get_number_of_failures(); 500 CU_cleanup_registry(); 501 free(g_dev_buffer); 502 spdk_free_thread(); 503 return num_failures; 504 } 505