// /************************************************************************************************** * IOWOW library * * MIT License * * Copyright (c) 2012-2020 Softmotions Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *************************************************************************************************/ #include "iowow.h" #include "log/iwlog.h" #include "fs/iwfsmfile.h" #include "utils/iwutils.h" #include "platform/iwp.h" #include "iwcfg.h" #include #include #include #include #include static pthread_mutex_t records_mtx; #define UNLINK() \ unlink("test_fsm_open_close.fsm"); \ unlink("test_fsm_uniform_alloc.fsm"); \ unlink("test_block_allocation1.fsm"); \ unlink("test_block_allocation2.fsm") int init_suite(void) { pthread_mutex_init(&records_mtx, 0); int rc = iw_init(); UNLINK(); return rc; } int clean_suite(void) { pthread_mutex_destroy(&records_mtx); UNLINK(); return 0; } uint64_t iwfs_fsmdbg_number_of_free_areas(IWFS_FSM *f); uint64_t iwfs_fsmdbg_find_next_set_bit(const uint64_t *addr, uint64_t offset_bit, uint64_t max_offset_bit, int *found); uint64_t iwfs_fsmdbg_find_prev_set_bit(const uint64_t *addr, uint64_t offset_bit, uint64_t min_offset_bit, int *found); void iwfs_fsmdbg_dump_fsm_tree(IWFS_FSM *f, const char *hdr); iwrc iwfs_fsmdbg_state(IWFS_FSM *f, IWFS_FSMDBG_STATE *d); iwrc iwfs_fsmdb_dump_fsm_bitmap(IWFS_FSM *f, int blimit); void test_fsm_bitmap(void) { #define BMSZ1 16 uint64_t buf[BMSZ1]; memset(buf, 0, BMSZ1 * sizeof(uint64_t)); int found = 0; uint64_t val = IW_HTOILL(0x3UL); /* 0000011 */ uint64_t res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 0); res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 1); res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 0); CU_ASSERT_EQUAL(res, 0); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 3, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 3); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 4, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 0); CU_ASSERT_EQUAL(res, 0); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_prev_set_bit(&val, 2, 0, &found); CU_ASSERT_EQUAL(found, 0); CU_ASSERT_EQUAL(res, 0); val = 0x3UL << 2; /* 0001100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_prev_set_bit(&val, 3, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = 0x2UL; /* 00000010 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 1); val = 0x2UL; /* 00000010 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 1); val = 0x4UL; /* 00000100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 0, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = 0x4UL; /* 00000100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 1, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = 0x4UL; /* 00000100 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_next_set_bit(&val, 2, sizeof(uint64_t) * 8, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); val = ~0UL; val = IW_HTOILL(val); res = iwfs_fsmdbg_find_prev_set_bit(&val, 0, 0, &found); CU_ASSERT_EQUAL(found, 0); CU_ASSERT_EQUAL(res, 0); val = 0x1UL; /* 00000001 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_prev_set_bit(&val, 1, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 0); val = 0x2UL; /* 00000010 */ val = IW_HTOILL(val); res = iwfs_fsmdbg_find_prev_set_bit(&val, 10, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 1); buf[0] = IW_HTOILL(0x1UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 0); buf[0] = IW_HTOILL(0x2UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 1); buf[0] = IW_HTOILL(0x4UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); buf[0] = IW_HTOILL(0x8UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 15, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 3); buf[1] = IW_HTOILL(0x2UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, 2 * sizeof(uint64_t) * 8 + 17, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 64 + 1); /* 0[0100000000000..|00]000 */ buf[0] = IW_HTOILL(0x4UL); buf[1] = IW_HTOILL(0x0UL); buf[2] = IW_HTOILL(0x0UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, (sizeof(uint64_t) * 8 + 2), 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 2); buf[0] = IW_HTOILL(0x4UL); buf[1] = IW_HTOILL(0x4UL); buf[2] = IW_HTOILL(0x0UL); res = iwfs_fsmdbg_find_prev_set_bit(buf, sizeof(uint64_t) * 8 + 5, 0, &found); CU_ASSERT_EQUAL(found, 1); CU_ASSERT_EQUAL(res, 64 + 2); } void test_fsm_open_close(void) { iwrc rc; IWFS_FSM_OPTS opts = { .exfile = { .file = {.path = "test_fsm_open_close.fsm", .lock_mode = IWP_WLOCK}, .rspolicy = iw_exfile_szpolicy_fibo, .initial_size = 0 }, .bpow = 6, .hdrlen = 64, .oflags = IWFSM_STRICT }; size_t aunit = iwp_alloc_unit(); IWFS_FSMDBG_STATE state1, state2; IWFS_FSM fsm; rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmdbg_state(&fsm, &state1); CU_ASSERT_FALSE(rc); CU_ASSERT_TRUE((aunit * 8 - state1.lfbklen) * 64 == 2 * aunit); // allocated first 2 pages rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmdbg_state(&fsm, &state2); CU_ASSERT_FALSE(rc); CU_ASSERT_TRUE((aunit * 8 - state2.lfbklen) * 64 == 2 * aunit); CU_ASSERT_EQUAL(state1.bmlen, state2.bmlen); CU_ASSERT_EQUAL(state1.bmoff, state2.bmoff); CU_ASSERT_EQUAL(state1.lfbklen, state2.lfbklen); CU_ASSERT_EQUAL(state1.lfbkoff, state2.lfbkoff); CU_ASSERT_EQUAL(state1.state.block_size, state2.state.block_size); CU_ASSERT_EQUAL(state1.state.blocks_num, state2.state.blocks_num); CU_ASSERT_EQUAL(state1.state.hdrlen, state2.state.hdrlen); CU_ASSERT_EQUAL(state1.state.oflags, state2.state.oflags); CU_ASSERT_EQUAL(state1.state.exfile.fsize, state2.state.exfile.fsize); CU_ASSERT_EQUAL(state1.state.exfile.fsize, 2 * aunit); rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); } void test_fsm_uniform_alloc_impl(int mmap_all); void test_fsm_uniform_alloc(void) { test_fsm_uniform_alloc_impl(0); } void test_fsm_uniform_alloc_mmap_all(void) { test_fsm_uniform_alloc_impl(1); } void test_fsm_uniform_alloc_impl(int mmap_all) { iwrc rc; IWFS_FSMDBG_STATE state1, state2; IWFS_FSM_OPTS opts = { .exfile = { .file = { .path = "test_fsm_uniform_alloc.fsm", .lock_mode = IWP_WLOCK, .omode = IWFS_OTRUNC }, .rspolicy = iw_exfile_szpolicy_fibo }, .bpow = 6, .hdrlen = 64, .oflags = IWFSM_STRICT, .mmap_all = mmap_all }; typedef struct { off_t addr; off_t len; } ASLOT; const int bsize = 512; #define bcnt 4096 ASLOT aslots[bcnt]; IWFS_FSM fsm; rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmdbg_state(&fsm, &state1); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL_FATAL(state1.state.exfile.file.ostatus, IWFS_OPEN_NEW); for (int i = 0; i < bcnt; ++i) { aslots[i].addr = 0; rc = fsm.allocate(&fsm, bsize, &aslots[i].addr, &aslots[i].len, 0); CU_ASSERT_FALSE_FATAL(rc); } rc = iwfs_fsmdbg_state(&fsm, &state1); CU_ASSERT_FALSE_FATAL(rc); if (iwp_alloc_unit() == 4096) { // todo check for system with different alloc units CU_ASSERT_EQUAL(state1.bmlen, 8192); CU_ASSERT_EQUAL(state1.bmoff, 2097152); CU_ASSERT_EQUAL(state1.lfbklen, 32632); CU_ASSERT_EQUAL(state1.lfbkoff, 32904); CU_ASSERT_EQUAL(state1.state.blocks_num, 65536); CU_ASSERT_EQUAL(state1.state.free_segments_num, 2); CU_ASSERT_EQUAL(state1.state.avg_alloc_size, 8); CU_ASSERT_EQUAL(state1.state.alloc_dispersion, 0); } rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); opts.exfile.file.omode = IWFS_OREAD; rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmdbg_state(&fsm, &state2); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL_FATAL(state2.state.exfile.file.ostatus, IWFS_OPEN_EXISTING); CU_ASSERT_FALSE(state2.state.exfile.file.opts.omode & IWFS_OWRITE); CU_ASSERT_EQUAL(state1.bmlen, state2.bmlen); CU_ASSERT_EQUAL(state1.bmoff, state2.bmoff); CU_ASSERT_EQUAL(state1.lfbklen, state2.lfbklen); CU_ASSERT_EQUAL(state1.lfbkoff, state2.lfbkoff); CU_ASSERT_EQUAL(state1.state.blocks_num, state2.state.blocks_num); CU_ASSERT_EQUAL(state1.state.free_segments_num, state2.state.free_segments_num); CU_ASSERT_EQUAL(state1.state.avg_alloc_size, state2.state.avg_alloc_size); CU_ASSERT_EQUAL(state1.state.alloc_dispersion, state2.state.alloc_dispersion); uint32_t ibuf; off_t ilen; rc = fsm.allocate(&fsm, sizeof(ibuf), (void *) &ibuf, &ilen, 0); CU_ASSERT_EQUAL(rc, IW_ERROR_READONLY); rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); opts.exfile.file.omode = IWFS_OWRITE; rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); rc = iwfs_fsmdbg_state(&fsm, &state1); CU_ASSERT_FALSE_FATAL(rc); if (iwp_alloc_unit() == 4096) { // todo check for system with different alloc units CU_ASSERT_EQUAL(state1.bmlen, 8192); CU_ASSERT_EQUAL(state1.bmoff, 2097152); CU_ASSERT_EQUAL(state1.lfbklen, 32632); CU_ASSERT_EQUAL(state1.lfbkoff, 32904); CU_ASSERT_EQUAL(state1.state.blocks_num, 65536); CU_ASSERT_EQUAL(state1.state.free_segments_num, 2); CU_ASSERT_EQUAL(state1.state.avg_alloc_size, 8); CU_ASSERT_EQUAL(state1.state.alloc_dispersion, 0); } int i = 0; for (; i < bcnt; ++i) { rc = fsm.deallocate(&fsm, aslots[i].addr, aslots[i].len); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_FALSE_FATAL(rc); } rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); if (iwp_alloc_unit() == 4096) { IWP_FILE_STAT st; rc = iwp_fstat("test_fsm_uniform_alloc.fsm", &st); CU_ASSERT_EQUAL_FATAL(rc, 0); CU_ASSERT_EQUAL(st.size, iwp_alloc_unit() * 3); } } typedef struct FSMREC { int64_t offset; int64_t length; int locked; struct FSMREC *prev; struct FSMREC *next; } FSMREC; typedef struct { int maxrecs; int avgrecsz; IWFS_FSM *fsm; volatile int numrecs; FSMREC *reclist; FSMREC *head; int blkpow; } FSMRECTASK; //!!!! TODO this test is not good for multithreaded env, refactoring needed static void *recordsthr(void *op) { FSMRECTASK *task = op; iwrc rc; FSMREC *rec, *tmp; IWFS_FSM *fsm = task->fsm; size_t sp; const int maxrsize = IW_ROUNDUP(task->avgrecsz * 3, 1 << task->blkpow); char *rdata = malloc(maxrsize); char *rdata2 = malloc(maxrsize); int numrec; int a, i = 0; pthread_mutex_lock(&records_mtx); numrec = task->numrecs; pthread_mutex_unlock(&records_mtx); while (numrec < task->maxrecs) { ++i; rec = malloc(sizeof(*rec)); memset(rec, 0, sizeof(*rec)); rec->locked = 1; do { rec->length = iwu_rand_dnorm((double) task->avgrecsz, task->avgrecsz / 3.0); } while (rec->length <= 0 || rec->length > maxrsize); /* Allocate record */ rc = fsm->allocate(fsm, rec->length, &rec->offset, &rec->length, 0); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_FALSE_FATAL(rc); memset(rdata, (rec->offset >> task->blkpow), maxrsize); CU_ASSERT_TRUE_FATAL(maxrsize >= rec->length); rc = fsm->write(fsm, rec->offset, rdata, rec->length, &sp); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL_FATAL(rec->length, sp); pthread_mutex_lock(&records_mtx); if (task->reclist != rec) { tmp = task->reclist; task->reclist = rec; task->reclist->prev = tmp; tmp->next = task->reclist; rec->locked = 0; } ++(task->numrecs); numrec = task->numrecs; pthread_mutex_unlock(&records_mtx); } rec = task->reclist; i = 0; while (rec && rec->prev) { ++i; a = rand() % 3; if (a == 0 || a == 1) { /* realloc */ pthread_mutex_lock(&records_mtx); if (rec->locked) { rec = rec->next; pthread_mutex_unlock(&records_mtx); continue; } rec->locked = 1; pthread_mutex_unlock(&records_mtx); rc = fsm->deallocate(fsm, rec->offset, rec->length); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_FALSE_FATAL(rc); /* allocate */ do { rec->length = iwu_rand_dnorm((double) task->avgrecsz, task->avgrecsz / 3.0); } while (rec->length <= 0 || rec->length > maxrsize); rc = fsm->allocate(fsm, rec->length, &rec->offset, &rec->length, 0); if (rc) { iwlog_ecode_error3(rc); CU_ASSERT_FALSE(rc); break; } if (rec->length <= maxrsize) { /* Write a record */ memset(rdata, (rec->offset >> task->blkpow), maxrsize); rc = fsm->write(fsm, rec->offset, rdata, rec->length, &sp); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_FALSE_FATAL(rc); } else { /* printf("Ops %lld %lld\n\n", rl >> task->blkpow, rec->length >> * task->blkpow); */ CU_ASSERT_TRUE_FATAL(0); assert(0); } pthread_mutex_lock(&records_mtx); rec->locked = 0; pthread_mutex_unlock(&records_mtx); } else { // TODO // rc = fsm->lread(fsm, rec->offset, rdata, rec->length, &sp); // CU_ASSERT_FALSE_FATAL(rc); // CU_ASSERT_EQUAL_FATAL(sp, rec->length); // memset(rdata2, (rec->offset >> task->blkpow), maxrsize); // int cmp = memcmp(rdata, rdata2, rec->length); // CU_ASSERT_FALSE_FATAL(cmp); } rec = rec->prev; } free(rdata); free(rdata2); return 0; } void test_block_allocation_impl(int mmap_all, int nthreads, int numrec, int avgrecsz, int blkpow, const char *path) { iwrc rc; pthread_t *tlist = malloc(nthreads * sizeof(pthread_t)); IWFS_FSM_OPTS opts = { .exfile = { .file = {.path = path, .omode = IWFS_OTRUNC}, .rspolicy = iw_exfile_szpolicy_fibo }, .bpow = blkpow, .oflags = IWFSM_STRICT, .mmap_all = mmap_all }; FSMRECTASK task; FSMREC *rec, *prev; IWFS_FSM fsm; rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); memset(&task, 0, sizeof(task)); task.numrecs = 0; task.maxrecs = numrec; task.avgrecsz = avgrecsz; task.fsm = &fsm; task.reclist = malloc(sizeof(*task.reclist)); memset(task.reclist, 0, sizeof(*task.reclist)); task.head = task.reclist; task.blkpow = opts.bpow; for (int i = 0; i < nthreads; ++i) { CU_ASSERT_EQUAL_FATAL(pthread_create(&tlist[i], 0, recordsthr, &task), 0); } for (int i = 0; i < nthreads; ++i) { pthread_join(tlist[i], 0); } /* Cleanup */ rec = task.reclist; while (rec) { prev = rec->prev; free(rec); rec = prev; } rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); free(tlist); } void test_block_allocation1_impl(int mmap_all); void test_block_allocation1(void) { test_block_allocation1_impl(0); } void test_block_allocation1_mmap_all(void) { test_block_allocation1_impl(1); } void test_block_allocation1_impl(int mmap_all) { iwrc rc; IWFS_FSM fsm; int psize = iwp_alloc_unit(); IWFS_FSM_OPTS opts = { .exfile = { .file = { .path = "test_block_allocation1.fsm", .omode = IWFS_OTRUNC } }, .hdrlen = psize - 2 * 64, .bpow = 6, .oflags = IWFSM_STRICT, .mmap_all = mmap_all }; off_t oaddr = 0; off_t olen; // off_t sp, sp2; int bsize = (1 << opts.bpow); /* byte block */ const int hoff = (2 * psize); rc = iwfs_fsmfile_open(&fsm, &opts); CU_ASSERT_FALSE_FATAL(rc); /* Next alloc status: xxxxxxx */ rc = fsm.allocate(&fsm, 3 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 0); CU_ASSERT_EQUAL(olen, 3 * bsize); rc = fsm.allocate(&fsm, 4 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 3 * bsize); CU_ASSERT_EQUAL(olen, 4 * bsize); rc = fsm.deallocate(&fsm, 1 * bsize, 1 * bsize); CU_ASSERT_EQUAL(rc, IWFS_ERROR_FSM_SEGMENTATION); /* Next alloc status: x*xxxxx */ rc = fsm.deallocate(&fsm, hoff + 1 * bsize, 1 * bsize); CU_ASSERT_FALSE_FATAL(rc); /* Next alloc status: xxxxxxx */ rc = fsm.allocate(&fsm, 1 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize); CU_ASSERT_EQUAL(olen, 1 * bsize); /* Next alloc status: x**xxxx */ rc = fsm.deallocate(&fsm, oaddr, 2 * bsize); CU_ASSERT_FALSE_FATAL(rc); /* Next alloc status: x**x**x */ rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 2 * bsize); CU_ASSERT_FALSE_FATAL(rc); oaddr = hoff + 5 * bsize; /* Test a free block location suggestion */ rc = fsm.allocate(&fsm, 2 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 4 * bsize); CU_ASSERT_EQUAL(olen, 2 * bsize); /* Next alloc status: x**x**x */ rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 2 * bsize); CU_ASSERT_FALSE_FATAL(rc); /* Next alloc status: x*****x */ CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 3); rc = fsm.deallocate(&fsm, hoff + 3 * bsize, 1 * bsize); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2); /* Next alloc status: xxxxxxx */ oaddr = hoff; rc = fsm.allocate(&fsm, 5 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize); CU_ASSERT_EQUAL(olen, 5 * bsize); CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 1); // Test reallocate /* Next alloc status: *xxx*** */ rc = fsm.deallocate(&fsm, hoff + 4 * bsize, 3 * bsize); CU_ASSERT_FALSE_FATAL(rc); rc = fsm.deallocate(&fsm, hoff, 1 * bsize); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2); /* Next alloc status: *xx**** */ oaddr = hoff + 1 * bsize; olen = 3 * bsize; rc = fsm.reallocate(&fsm, 2 * bsize, &oaddr, &olen, 0); CU_ASSERT_FALSE_FATAL(rc); CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize); CU_ASSERT_EQUAL(olen, 2 * bsize); CU_ASSERT_EQUAL(iwfs_fsmdbg_number_of_free_areas(&fsm), 2); /* Next alloc status: *xxxxxx */ // rc = fsm.reallocate(&fsm, 6 * bsize, &oaddr, &olen, 0); // CU_ASSERT_FALSE_FATAL(rc); // CU_ASSERT_EQUAL(oaddr, hoff + 1 * bsize); // CU_ASSERT_EQUAL(olen, 6 * bsize); // // /* Next alloc status: // *xx***x */ // rc = fsm.deallocate(&fsm, hoff + 3 * bsize, 3 * bsize); // CU_ASSERT_FALSE_FATAL(rc); // todo // oaddr = hoff + 1 * bsize; // olen = 1 * bsize; // rc = fsm.reallocate(&fsm, 2 * bsize, &oaddr, &olen, 0); // CU_ASSERT_EQUAL(oaddr, hoff); // CU_ASSERT_EQUAL(olen, 2 * bsize); rc = fsm.close(&fsm); CU_ASSERT_FALSE_FATAL(rc); } void test_block_allocation2_impl(int mmap_all); void test_block_allocation2() { test_block_allocation2_impl(0); } void test_block_allocation2_mmap_all() { test_block_allocation2_impl(1); } void test_block_allocation2_impl(int mmap_all) { test_block_allocation_impl(mmap_all, 4, 50000, 493, 6, "test_block_allocation2.fsm"); test_block_allocation_impl(mmap_all, 4, 50000, 5, 6, "test_block_allocation2.fsm"); } int main() { CU_pSuite pSuite = NULL; /* Initialize the CUnit test registry */ if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); /* Add a suite to the registry */ pSuite = CU_add_suite("iwfs_test2", init_suite, clean_suite); if (NULL == pSuite) { CU_cleanup_registry(); return CU_get_error(); } /* Add the tests to the suite */ if ((NULL == CU_add_test(pSuite, "test_fsm_bitmap", test_fsm_bitmap)) || (NULL == CU_add_test(pSuite, "test_fsm_open_close", test_fsm_open_close)) || (NULL == CU_add_test(pSuite, "test_fsm_uniform_alloc", test_fsm_uniform_alloc)) || (NULL == CU_add_test(pSuite, "test_fsm_uniform_alloc_mmap_all", test_fsm_uniform_alloc_mmap_all)) || (NULL == CU_add_test(pSuite, "test_block_allocation1", test_block_allocation1)) || (NULL == CU_add_test(pSuite, "test_block_allocation1_mmap_all", test_block_allocation1_mmap_all)) || (NULL == CU_add_test(pSuite, "test_block_allocation2", test_block_allocation2)) || NULL == CU_add_test(pSuite, "test_block_allocation2_mmap_all", test_block_allocation2_mmap_all) ) { CU_cleanup_registry(); return CU_get_error(); } /* Run all tests using the CUnit Basic interface */ CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests(); int ret = CU_get_error() || CU_get_number_of_failures(); CU_cleanup_registry(); return ret; }