src/server/test/vfs.c

changeset 415
d938228c382e
parent 323
dc5b0fee49df
child 490
d218607f5a7e
equal deleted inserted replaced
414:99a34860c105 415:d938228c382e
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <errno.h> 31 #include <errno.h>
32 32
33 #include <ucx/string.h> 33 #include <cx/string.h>
34 #include <ucx/list.h> 34 #include <cx/list.h>
35 #include <ucx/map.h> 35 #include <cx/map.h>
36 36
37 #include "../daemon/session.h" 37 #include "../daemon/session.h"
38 38
39 #include "testutils.h" 39 #include "testutils.h"
40 40
41 #include "vfs.h" 41 #include "vfs.h"
42 42
43 typedef struct TestVFS { 43 typedef struct TestVFS {
44 UcxMap *files; 44 CxMap *files;
45 int count_unlink; 45 int count_unlink;
46 int count_rmdir; 46 int count_rmdir;
47 } TestVFS; 47 } TestVFS;
48 48
49 typedef struct TestVFSFile { 49 typedef struct TestVFSFile {
50 VFSFile file; 50 VFSFile file;
51 sstr_t path; 51 cxmutstr path;
52 int isdir; 52 int isdir;
53 UcxBuffer *content; 53 CxBuffer content;
54 } TestVFSFile; 54 } TestVFSFile;
55 55
56 typedef struct TestVFSDir { 56 typedef struct TestVFSDir {
57 VFSDir dir; 57 VFSDir dir;
58 TestVFSFile *file; 58 TestVFSFile *file;
59 UcxMapIterator i; 59 CxIterator i;
60 sstr_t name; 60 cxmutstr name;
61 } TestVFSDir; 61 } TestVFSDir;
62 62
63 /* dir io */ 63 /* dir io */
64 64
65 static char* test_resource_name(char *url) { 65 static const char* test_resource_name(char *url) {
66 sstr_t urlstr = sstr(url); 66 cxstring urlstr = cx_str(url);
67 if(urlstr.ptr[urlstr.length-1] == '/') { 67 if(urlstr.ptr[urlstr.length-1] == '/') {
68 urlstr.length--; 68 urlstr.length--;
69 } 69 }
70 sstr_t resname = sstrrchr(urlstr, '/'); 70 cxstring resname = cx_strrchr(urlstr, '/');
71 if(resname.length > 1) { 71 if(resname.length > 1) {
72 return resname.ptr+1; 72 return resname.ptr+1;
73 } else { 73 } else {
74 return url; 74 return url;
75 } 75 }
77 77
78 int testvfs_readdir(VFS_DIR dir, VFS_ENTRY *entry, int getstat) { 78 int testvfs_readdir(VFS_DIR dir, VFS_ENTRY *entry, int getstat) {
79 TestVFS *vfs = dir->ctx->vfs->instance; 79 TestVFS *vfs = dir->ctx->vfs->instance;
80 TestVFSDir *vfsdir = (TestVFSDir*)dir; 80 TestVFSDir *vfsdir = (TestVFSDir*)dir;
81 81
82 sstr_t prefix = sstrcat(2, vfsdir->file->path, S("/")); 82 cxmutstr prefix = cx_strcat(2, vfsdir->file->path, cx_str("/"));
83 83
84 // not the most efficient file system implementation ever, but it is only
85 // for testing
86 // check every entry in vfs->files and return, if the parent path
87 // matches the open directory
84 TestVFSFile *file = NULL; 88 TestVFSFile *file = NULL;
85 UCX_MAP_FOREACH(key, file, vfsdir->i) { 89 cx_foreach(TestVFSFile *, entry, vfsdir->i) {
86 sstr_t file_path = sstrcat( 90 if(file) break;
91 cxmutstr file_path = cx_strcat(
87 2, 92 2,
88 prefix, 93 prefix,
89 sstr(test_resource_name(file->path.ptr))); 94 cx_str(test_resource_name(entry->path.ptr)));
90 void *m = ucx_map_get(vfs->files, ucx_key(file_path.ptr, file_path.length)); 95 file = cxMapGet(vfs->files, cx_hash_key(file_path.ptr, file_path.length));
91 // don't ask why alfree and not free() 96 free(file_path.ptr);
92 alfree(ucx_default_allocator(), file_path.ptr);
93 if(m) {
94 break;
95 } else {
96 file = NULL;
97 }
98 } 97 }
99 free(prefix.ptr); 98 free(prefix.ptr);
100 99
101 if(file) { 100 if(file) {
102 vfsdir->name = sstrdup_a( 101 vfsdir->name = cx_strdup_a(
103 session_get_allocator(dir->ctx->sn), 102 pool_allocator(dir->ctx->sn->pool),
104 sstr(test_resource_name(file->path.ptr))); 103 cx_str(test_resource_name(file->path.ptr)));
105 ZERO(entry, sizeof(VFS_ENTRY)); 104 ZERO(entry, sizeof(VFS_ENTRY));
106 entry->name = vfsdir->name.ptr; 105 entry->name = vfsdir->name.ptr;
107 106
108 if(getstat) { 107 if(getstat) {
109 ZERO(&entry->stat, sizeof(struct stat)); 108 ZERO(&entry->stat, sizeof(struct stat));
124 123
125 } 124 }
126 125
127 ssize_t testvfs_read(SYS_FILE fd, void *buf, size_t nbyte) { 126 ssize_t testvfs_read(SYS_FILE fd, void *buf, size_t nbyte) {
128 TestVFSFile *file = (TestVFSFile*)fd; 127 TestVFSFile *file = (TestVFSFile*)fd;
129 return (ssize_t)ucx_buffer_read(buf, 1, nbyte, file->content); 128 return (ssize_t)cxBufferRead(buf, 1, nbyte, &file->content);
130 } 129 }
131 130
132 ssize_t testvfs_write(SYS_FILE fd, const void *buf, size_t nbyte) { 131 ssize_t testvfs_write(SYS_FILE fd, const void *buf, size_t nbyte) {
133 TestVFSFile *file = (TestVFSFile*)fd; 132 TestVFSFile *file = (TestVFSFile*)fd;
134 return (ssize_t)ucx_buffer_write(buf, 1, nbyte, file->content); 133 return (ssize_t)cxBufferWrite(buf, 1, nbyte, &file->content);
135 } 134 }
136 135
137 ssize_t testvfs_pread(SYS_FILE fd, void *buf, size_t nbyte, off_t offset) { 136 ssize_t testvfs_pread(SYS_FILE fd, void *buf, size_t nbyte, off_t offset) {
138 TestVFSFile *file = (TestVFSFile*)fd; 137 TestVFSFile *file = (TestVFSFile*)fd;
139 file->content->pos = (size_t)offset; 138 file->content.pos = (size_t)offset;
140 return testvfs_read(fd, buf, nbyte); 139 return testvfs_read(fd, buf, nbyte);
141 } 140 }
142 141
143 ssize_t testvfs_pwrite(SYS_FILE fd, const void *buf, size_t nbyte, off_t offset) { 142 ssize_t testvfs_pwrite(SYS_FILE fd, const void *buf, size_t nbyte, off_t offset) {
144 TestVFSFile *file = (TestVFSFile*)fd; 143 TestVFSFile *file = (TestVFSFile*)fd;
145 file->content->pos = (size_t)offset; 144 file->content.pos = (size_t)offset;
146 return testvfs_write(fd, buf, nbyte); 145 return testvfs_write(fd, buf, nbyte);
147 } 146 }
148 147
149 off_t testvfs_seek(SYS_FILE fd, off_t offset, int whence) { 148 off_t testvfs_seek(SYS_FILE fd, off_t offset, int whence) {
150 TestVFSFile *file = (TestVFSFile*)fd; 149 TestVFSFile *file = (TestVFSFile*)fd;
151 ucx_buffer_seek(file->content, offset, whence); 150 cxBufferSeek(&file->content, offset, whence);
152 return (off_t)file->content->pos; 151 return (off_t)file->content.pos;
153 } 152 }
154 153
155 void testvfs_close(SYS_FILE fd) { 154 void testvfs_close(SYS_FILE fd) {
156 TestVFSFile *file = (TestVFSFile*)fd; 155 TestVFSFile *file = (TestVFSFile*)fd;
157 file->content->pos = 0; 156 file->content.pos = 0;
158 } 157 }
159 158
160 VFS_IO test_file_io = { 159 VFS_IO test_file_io = {
161 testvfs_read, 160 testvfs_read,
162 testvfs_write, 161 testvfs_write,
178 177
179 SYS_FILE testvfs_open(VFSContext *ctx, const char *path, int oflags) { 178 SYS_FILE testvfs_open(VFSContext *ctx, const char *path, int oflags) {
180 TestVFS *vfs = ctx->vfs->instance; 179 TestVFS *vfs = ctx->vfs->instance;
181 TestVFSFile *file = NULL; 180 TestVFSFile *file = NULL;
182 181
183 sstr_t s_path = sstr((char*)path); 182 cxstring s_path = cx_str((char*)path);
184 if(sstrsuffix(s_path, S("/"))) { 183 if(cx_strsuffix(s_path, cx_str("/"))) {
185 s_path.length--; 184 s_path.length--;
186 } 185 }
187 186
188 file = ucx_map_sstr_get(vfs->files, s_path); 187 file = cxMapGet(vfs->files, cx_hash_key_bytes((const unsigned char*)s_path.ptr, s_path.length));
189 if(!file) { 188 if(!file) {
190 if((oflags & O_CREAT) == O_CREAT) { 189 if((oflags & O_CREAT) == O_CREAT) {
191 file = pool_malloc(ctx->sn->pool, sizeof(TestVFSFile)); 190 file = pool_malloc(ctx->sn->pool, sizeof(TestVFSFile));
192 ZERO(file, sizeof(TestVFSFile)); 191 ZERO(file, sizeof(TestVFSFile));
193 file->file.ctx = ctx; 192 file->file.ctx = ctx;
194 file->path = sstrdup_a(session_get_allocator(ctx->sn), s_path); 193 file->path = cx_strdup_a(pool_allocator(ctx->sn->pool), s_path);
195 file->file.io = &test_file_io; 194 file->file.io = &test_file_io;
196 195
197 file->content = pool_calloc(ctx->sn->pool, 1, sizeof(UcxBuffer)); 196 cxBufferInit(&file->content, pool_malloc(ctx->sn->pool, 2048), 2048, pool_allocator(ctx->sn->pool), 0);
198 file->content->capacity = 2048;
199 file->content->space = pool_malloc(ctx->sn->pool, file->content->capacity);
200 file->content->flags = 0;
201 file->content->pos = 0;
202 file->content->size = 0;
203 197
204 ucx_map_sstr_put(vfs->files, s_path, file); 198 cxMapPut(vfs->files, cx_hash_key((void*)s_path.ptr, s_path.length), file);
205 } else { 199 } else {
206 ctx->vfs_errno = ENOENT; 200 ctx->vfs_errno = ENOENT;
207 } 201 }
208 } 202 }
209 203
212 206
213 int testvfs_stat(VFSContext *ctx, const char *path, struct stat *buf) { 207 int testvfs_stat(VFSContext *ctx, const char *path, struct stat *buf) {
214 TestVFS *vfs = ctx->vfs->instance; 208 TestVFS *vfs = ctx->vfs->instance;
215 TestVFSFile *file = NULL; 209 TestVFSFile *file = NULL;
216 210
217 sstr_t s_path = sstr((char*)path); 211 cxstring s_path = cx_str((char*)path);
218 if(sstrsuffix(s_path, S("/"))) { 212 if(cx_strsuffix(s_path, cx_str("/"))) {
219 s_path.length--; 213 s_path.length--;
220 } 214 }
221 215
222 file = ucx_map_sstr_get(vfs->files, s_path); 216 file = cxMapGet(vfs->files, cx_hash_key((void*)s_path.ptr, s_path.length));
223 if(!file) { 217 if(!file) {
224 ctx->vfs_errno = ENOENT; 218 ctx->vfs_errno = ENOENT;
225 return 1; 219 return 1;
226 } 220 }
227 221
239 233
240 VFS_DIR testvfs_opendir(VFSContext *ctx, const char *path) { 234 VFS_DIR testvfs_opendir(VFSContext *ctx, const char *path) {
241 TestVFS *vfs = ctx->vfs->instance; 235 TestVFS *vfs = ctx->vfs->instance;
242 TestVFSFile *file = NULL; 236 TestVFSFile *file = NULL;
243 237
244 sstr_t s_path = sstr((char*)path); 238 cxstring s_path = cx_str((char*)path);
245 if(sstrsuffix(s_path, S("/"))) { 239 if(cx_strsuffix(s_path, cx_str("/"))) {
246 s_path.length--; 240 s_path.length--;
247 } 241 }
248 242
249 file = ucx_map_sstr_get(vfs->files, s_path); 243 file = cxMapGet(vfs->files, cx_hash_key((void*)s_path.ptr, s_path.length));
250 if(!file) { 244 if(!file) {
251 ctx->vfs_errno = ENOENT; 245 ctx->vfs_errno = ENOENT;
252 return NULL; 246 return NULL;
253 } 247 }
254 248
257 } 251 }
258 252
259 TestVFSDir *dir = pool_malloc(ctx->sn->pool, sizeof(TestVFSDir)); 253 TestVFSDir *dir = pool_malloc(ctx->sn->pool, sizeof(TestVFSDir));
260 ZERO(dir, sizeof(TestVFSDir)); 254 ZERO(dir, sizeof(TestVFSDir));
261 dir->file = file; 255 dir->file = file;
262 dir->i = ucx_map_iterator(vfs->files); 256 dir->i = cxMapIteratorValues(vfs->files);
263 257
264 dir->dir.ctx = ctx; 258 dir->dir.ctx = ctx;
265 dir->dir.io = &test_dir_io; 259 dir->dir.io = &test_dir_io;
266 260
267 return (VFS_DIR)dir; 261 return (VFS_DIR)dir;
275 } 269 }
276 270
277 TestVFSDir *dir = pool_malloc(ctx->sn->pool, sizeof(TestVFSDir)); 271 TestVFSDir *dir = pool_malloc(ctx->sn->pool, sizeof(TestVFSDir));
278 ZERO(dir, sizeof(TestVFSDir)); 272 ZERO(dir, sizeof(TestVFSDir));
279 dir->file = file; 273 dir->file = file;
280 dir->i = ucx_map_iterator(vfs->files); 274 dir->i = cxMapIteratorValues(vfs->files);
281 275
282 dir->dir.ctx = ctx; 276 dir->dir.ctx = ctx;
283 dir->dir.io = &test_dir_io; 277 dir->dir.io = &test_dir_io;
284 278
285 return (VFS_DIR)dir; 279 return (VFS_DIR)dir;
297 return 0; 291 return 0;
298 } 292 }
299 293
300 int testvfs_unlink(VFSContext *ctx, const char *path) { 294 int testvfs_unlink(VFSContext *ctx, const char *path) {
301 TestVFS *vfs = ctx->vfs->instance; 295 TestVFS *vfs = ctx->vfs->instance;
302 TestVFSFile *file = ucx_map_cstr_get(vfs->files, path); 296 CxHashKey path_key = cx_hash_key_str(path);
297 TestVFSFile *file = cxMapGet(vfs->files, path_key);
303 if(!file) { 298 if(!file) {
304 return 1; 299 return 1;
305 } 300 }
306 301
307 if(file->isdir) { 302 if(file->isdir) {
308 return 1; 303 return 1;
309 } 304 }
310 305
311 ucx_map_cstr_remove(vfs->files, path); 306 (void)cxMapRemove(vfs->files, path_key);
312 vfs->count_unlink++; 307 vfs->count_unlink++;
313 return 0; 308 return 0;
314 } 309 }
315 310
316 int testvfs_rmdir(VFSContext *ctx, const char *path) { 311 int testvfs_rmdir(VFSContext *ctx, const char *path) {
317 TestVFS *vfs = ctx->vfs->instance; 312 TestVFS *vfs = ctx->vfs->instance;
318 TestVFSFile *dir = ucx_map_cstr_get(vfs->files, path); 313 CxHashKey path_key = cx_hash_key_str(path);
314 TestVFSFile *dir = cxMapGet(vfs->files, path_key);
319 if(!dir) { 315 if(!dir) {
320 ctx->vfs_errno = ENOENT; 316 ctx->vfs_errno = ENOENT;
321 return 1; 317 return 1;
322 } 318 }
323 319
324 if(!dir->isdir) { 320 if(!dir->isdir) {
325 return 1; 321 return 1;
326 } 322 }
327 323
328 UcxMapIterator i = ucx_map_iterator(vfs->files); 324 CxIterator i = cxMapIteratorValues(vfs->files);
329 TestVFSFile *f; 325 cx_foreach(TestVFSFile *, f, i) {
330 UCX_MAP_FOREACH(key, f, i) { 326 if(f->path.length > dir->path.length && cx_strprefix(cx_strcast(f->path), cx_strcast(dir->path))){
331 if(f->path.length > dir->path.length && sstrprefix(f->path, dir->path)){
332 return 1; // dir not empty 327 return 1; // dir not empty
333 } 328 }
334 } 329 }
335 330
336 ucx_map_cstr_remove(vfs->files, path); 331 (void)cxMapRemove(vfs->files, path_key);
337 vfs->count_rmdir++; 332 vfs->count_rmdir++;
338 return 0; 333 return 0;
339 } 334 }
340 335
341 static VFS testVFSClass = { 336 static VFS testVFSClass = {
354 349
355 VFS* testvfs_create(Session *sn) { 350 VFS* testvfs_create(Session *sn) {
356 TestVFS *vfs = pool_malloc(sn->pool, sizeof(TestVFS)); 351 TestVFS *vfs = pool_malloc(sn->pool, sizeof(TestVFS));
357 vfs->count_unlink = 0; 352 vfs->count_unlink = 0;
358 vfs->count_rmdir = 0; 353 vfs->count_rmdir = 0;
359 vfs->files = ucx_map_new_a(session_get_allocator(sn), 64); 354 vfs->files = cxHashMapCreate(pool_allocator(sn->pool), 64);
360 355
361 testVFSClass.instance = vfs; 356 testVFSClass.instance = vfs;
362 return &testVFSClass; 357 return &testVFSClass;
363 } 358 }
364 359
450 UCX_TEST_ASSERT(vfs_open(vfs, "/dir/file4", O_CREAT), "creation of file4 failed"); 445 UCX_TEST_ASSERT(vfs_open(vfs, "/dir/file4", O_CREAT), "creation of file4 failed");
451 446
452 VFSDir *dir = vfs_opendir(vfs, "/dir"); 447 VFSDir *dir = vfs_opendir(vfs, "/dir");
453 UCX_TEST_ASSERT(dir, "dir not opened"); 448 UCX_TEST_ASSERT(dir, "dir not opened");
454 449
455 UcxMap *files = ucx_map_new(8); 450 CxMap *files = cxHashMapCreate(cxDefaultAllocator, 8);
456 451
457 VFSEntry entry; 452 VFSEntry entry;
458 while(vfs_readdir(dir, &entry)) { 453 while(vfs_readdir(dir, &entry)) {
459 ucx_map_cstr_put(files, entry.name, dir); 454 cxMapPut(files, cx_hash_key_str(entry.name), dir);
460 } 455 }
461 456
462 UCX_TEST_ASSERT(files->count == 4, "wrong files count"); 457 UCX_TEST_ASSERT(files->size == 4, "wrong files count");
463 UCX_TEST_ASSERT(ucx_map_cstr_get(files, "file1"), "file1 missing"); 458 UCX_TEST_ASSERT(cxMapGet(files, cx_hash_key_str("file1")), "file1 missing");
464 UCX_TEST_ASSERT(ucx_map_cstr_get(files, "file2"), "file2 missing"); 459 UCX_TEST_ASSERT(cxMapGet(files, cx_hash_key_str("file2")), "file2 missing");
465 UCX_TEST_ASSERT(ucx_map_cstr_get(files, "file3"), "file3 missing"); 460 UCX_TEST_ASSERT(cxMapGet(files, cx_hash_key_str("file3")), "file3 missing");
466 UCX_TEST_ASSERT(ucx_map_cstr_get(files, "file4"), "file4 missing"); 461 UCX_TEST_ASSERT(cxMapGet(files, cx_hash_key_str("file4")), "file4 missing");
467 462
468 ucx_map_free(files); 463 cxMapDestroy(files);
469 464
470 UCX_TEST_END; 465 UCX_TEST_END;
471 466
472 testutil_destroy_session(sn); 467 testutil_destroy_session(sn);
473 } 468 }

mercurial