Bläddra i källkod

Added tests for resizable entries and custom attributes

Also found some bugs. Should now have a good amount of confidence in
these features.
Christopher Haster 7 år sedan
förälder
incheckning
61f454b008
6 ändrade filer med 605 tillägg och 64 borttagningar
  1. 3 2
      Makefile
  2. 71 61
      lfs.c
  3. 1 1
      tests/test.py
  4. 292 0
      tests/test_attrs.sh
  5. 220 0
      tests/test_entries.sh
  6. 18 0
      tests/test_paths.sh

+ 3 - 2
Makefile

@@ -33,8 +33,9 @@ size: $(OBJ)
 	$(SIZE) -t $^
 
 .SUFFIXES:
-test: test_format test_dirs test_files test_seek test_truncate \
-	test_interspersed test_alloc test_paths test_orphan test_move test_corrupt
+test: test_format test_dirs test_files test_seek test_truncate test_entries \
+	test_interspersed test_alloc test_paths test_attrs \
+	test_orphan test_move test_corrupt
 test_%: tests/test_%.sh
 ifdef QUIET
 	@./$< | sed -n '/^[-=]/p'

+ 71 - 61
lfs.c

@@ -1739,87 +1739,87 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
 }
 
 int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
-        int err = lfs_file_sync(lfs, file);
+    int err = lfs_file_sync(lfs, file);
 
-        // remove from list of files
-        for (lfs_file_t **p = &lfs->files; *p; p = &(*p)->next) {
-            if (*p == file) {
-                *p = file->next;
-                break;
-            }
+    // remove from list of files
+    for (lfs_file_t **p = &lfs->files; *p; p = &(*p)->next) {
+        if (*p == file) {
+            *p = file->next;
+            break;
         }
+    }
 
-        // clean up memory
-        if (!lfs->cfg->file_buffer) {
-            lfs_free(file->cache.buffer);
-        }
+    // clean up memory
+    if (!lfs->cfg->file_buffer) {
+        lfs_free(file->cache.buffer);
+    }
 
+    return err;
+}
+
+static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
+relocate:;
+    // just relocate what exists into new block
+    lfs_block_t nblock;
+    int err = lfs_alloc(lfs, &nblock);
+    if (err) {
         return err;
     }
 
-    static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
-    relocate:;
-        // just relocate what exists into new block
-        lfs_block_t nblock;
-        int err = lfs_alloc(lfs, &nblock);
+    err = lfs_bd_erase(lfs, nblock);
+    if (err) {
+        if (err == LFS_ERR_CORRUPT) {
+            goto relocate;
+        }
+        return err;
+    }
+
+    // either read from dirty cache or disk
+    for (lfs_off_t i = 0; i < file->off; i++) {
+        uint8_t data;
+        err = lfs_cache_read(lfs, &lfs->rcache, &file->cache,
+                file->block, i, &data, 1);
         if (err) {
             return err;
         }
 
-        err = lfs_bd_erase(lfs, nblock);
+        err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache,
+                nblock, i, &data, 1);
         if (err) {
             if (err == LFS_ERR_CORRUPT) {
                 goto relocate;
             }
             return err;
         }
+    }
 
-        // either read from dirty cache or disk
-        for (lfs_off_t i = 0; i < file->off; i++) {
-            uint8_t data;
-            err = lfs_cache_read(lfs, &lfs->rcache, &file->cache,
-                    file->block, i, &data, 1);
-            if (err) {
-                return err;
-            }
-
-            err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache,
-                    nblock, i, &data, 1);
-            if (err) {
-                if (err == LFS_ERR_CORRUPT) {
-                    goto relocate;
-                }
-                return err;
-            }
-        }
+    // copy over new state of file
+    memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->prog_size);
+    file->cache.block = lfs->pcache.block;
+    file->cache.off = lfs->pcache.off;
+    lfs->pcache.block = 0xffffffff;
 
-        // copy over new state of file
-        memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->prog_size);
-        file->cache.block = lfs->pcache.block;
-        file->cache.off = lfs->pcache.off;
-        lfs->pcache.block = 0xffffffff;
+    file->block = nblock;
+    return 0;
+}
 
-        file->block = nblock;
-        return 0;
+static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
+    if (file->flags & LFS_F_READING) {
+        file->flags &= ~LFS_F_READING;
     }
 
-    static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
-        if (file->flags & LFS_F_READING) {
-            file->flags &= ~LFS_F_READING;
-        }
-
-        if (file->flags & LFS_F_WRITING) {
-            lfs_off_t pos = file->pos;
+    if (file->flags & LFS_F_WRITING) {
+        lfs_off_t pos = file->pos;
 
-            if (!(file->flags & LFS_F_INLINE)) {
-                // copy over anything after current branch
-                lfs_file_t orig = {
-                    .head = file->head,
-                    .size = file->size,
-                    .flags = LFS_O_RDONLY,
-                    .pos = file->pos,
-                    .cache = lfs->rcache,
-                };
+        if (!(file->flags & LFS_F_INLINE)) {
+            // copy over anything after current branch
+            lfs_file_t orig = {
+                .head = file->head,
+                .size = file->size,
+                .flags = LFS_O_RDONLY,
+                .pos = file->pos,
+                .cache = lfs->rcache,
+            };
             lfs->rcache.block = 0xffffffff;
 
             while (file->pos < file->size) {
@@ -2270,6 +2270,7 @@ int lfs_file_getattrs(lfs_t *lfs, lfs_file_t *file,
                     return LFS_ERR_RANGE;
                 }
 
+                memset(attrs[j].buffer, 0, attrs[j].size);
                 memcpy(attrs[j].buffer,
                         file->attrs[i].buffer, file->attrs[i].size);
             }
@@ -2281,9 +2282,9 @@ int lfs_file_getattrs(lfs_t *lfs, lfs_file_t *file,
 
 int lfs_file_setattrs(lfs_t *lfs, lfs_file_t *file,
         const struct lfs_attr *attrs, int count) {
-    // just tack to the file, will be written at sync time
-    file->attrs = attrs;
-    file->attrcount = count;
+    if ((file->flags & 3) == LFS_O_RDONLY) {
+        return LFS_ERR_BADF;
+    }
 
     // at least make sure attributes fit
     if (!lfs_pairisnull(file->pair)) {
@@ -2306,6 +2307,11 @@ int lfs_file_setattrs(lfs_t *lfs, lfs_file_t *file,
         }
     }
 
+    // just tack to the file, will be written at sync time
+    file->attrs = attrs;
+    file->attrcount = count;
+    file->flags |= LFS_F_DIRTY;
+
     return 0;
 }
 
@@ -2432,6 +2438,10 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
         return LFS_ERR_NAMETOOLONG;
     }
 
+    if (oldentry.size - oldentry.d.nlen + nlen > lfs->cfg->block_size) {
+        return LFS_ERR_NOSPC;
+    }
+
     // must have same type
     if (prevexists && preventry.d.type != oldentry.d.type) {
         return LFS_ERR_ISDIR;

+ 1 - 1
tests/test.py

@@ -10,7 +10,7 @@ def generate(test):
         template = file.read()
 
     lines = []
-    for line in re.split('(?<=[;{}])\n', test.read()):
+    for line in re.split('(?<=(?:.;| [{}]))\n', test.read()):
         match = re.match('(?: *\n)*( *)(.*)=>(.*);', line, re.DOTALL | re.MULTILINE)
         if match:
             tab, test, expect = match.groups()

+ 292 - 0
tests/test_attrs.sh

@@ -0,0 +1,292 @@
+#!/bin/bash
+set -eu
+
+echo "=== Attr tests ==="
+rm -rf blocks
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_mkdir(&lfs, "hello") => 0;
+    lfs_file_open(&lfs, &file[0], "hello/hello",
+            LFS_O_WRONLY | LFS_O_CREAT) => 0;
+    lfs_file_write(&lfs, &file[0], "hello", strlen("hello"))
+            => strlen("hello");
+    lfs_file_close(&lfs, &file[0]);
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Set/get attribute ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', "aaaa",   4},
+            {'B', "bbbbbb", 6},
+            {'C', "ccccc",  5}}, 3) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "bbbbbb", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'B', "", 0}}, 1) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",         4) => 0;
+    memcmp(buffer+4,  "\0\0\0\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",        5) => 0;
+
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'B', "dddddd", 6}}, 1) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "dddddd", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'B', "eee", 3}}, 1) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "eee\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",     5) => 0;
+
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer, LFS_ATTRS_MAX+1}}, 1) => LFS_ERR_NOSPC;
+    lfs_setattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'B', "fffffffff", 9}}, 1) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
+
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_getattrs(&lfs, "hello", (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  9},
+            {'C', buffer+13, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "fffffffff", 9) => 0;
+    memcmp(buffer+13, "ccccc",     5) => 0;
+
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], buffer, sizeof(buffer)) => strlen("hello");
+    memcmp(buffer, "hello", strlen("hello")) => 0;
+    lfs_file_close(&lfs, &file[0]);
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Set/get fs attribute ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'A', "aaaa",   4},
+            {'B', "bbbbbb", 6},
+            {'C', "ccccc",  5}}, 3) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "bbbbbb", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'B', "", 0}}, 1) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",         4) => 0;
+    memcmp(buffer+4,  "\0\0\0\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",        5) => 0;
+
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'B', "dddddd", 6}}, 1) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "dddddd", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'B', "eee", 3}}, 1) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "eee\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",     5) => 0;
+
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer, LFS_ATTRS_MAX+1}}, 1) => LFS_ERR_NOSPC;
+    lfs_fs_setattrs(&lfs, (struct lfs_attr[]){
+            {'B', "fffffffff", 9}}, 1) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_fs_getattrs(&lfs, (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  9},
+            {'C', buffer+13, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "fffffffff", 9) => 0;
+    memcmp(buffer+13, "ccccc",     5) => 0;
+
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], buffer, sizeof(buffer)) => strlen("hello");
+    memcmp(buffer, "hello", strlen("hello")) => 0;
+    lfs_file_close(&lfs, &file[0]);
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Set/get file attribute ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_WRONLY) => 0;
+
+    struct lfs_attr attr[3];
+    attr[0] = (struct lfs_attr){'A', "aaaa",   4};
+    attr[1] = (struct lfs_attr){'B', "bbbbbb", 6};
+    attr[2] = (struct lfs_attr){'C', "ccccc",  5};
+    lfs_file_setattrs(&lfs, &file[0], attr, 3) => 0;
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "bbbbbb", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+    lfs_file_sync(&lfs, &file[0]) => 0;
+
+    attr[0] = (struct lfs_attr){'B', "", 0};
+    lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",         4) => 0;
+    memcmp(buffer+4,  "\0\0\0\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",        5) => 0;
+    lfs_file_sync(&lfs, &file[0]) => 0;
+
+    attr[0] = (struct lfs_attr){'B', "dddddd", 6};
+    lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",   4) => 0;
+    memcmp(buffer+4,  "dddddd", 6) => 0;
+    memcmp(buffer+10, "ccccc",  5) => 0;
+    lfs_file_sync(&lfs, &file[0]) => 0;
+
+    attr[0] = (struct lfs_attr){'B', "eee", 3};
+    lfs_file_setattrs(&lfs, &file[0], attr, 1);
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "eee\0\0\0", 6) => 0;
+    memcmp(buffer+10, "ccccc",     5) => 0;
+    lfs_file_sync(&lfs, &file[0]) => 0;
+
+    attr[0] = (struct lfs_attr){'A', buffer, LFS_ATTRS_MAX+1};
+    lfs_file_setattrs(&lfs, &file[0], attr, 1) => LFS_ERR_NOSPC;
+    attr[0] = (struct lfs_attr){'B', "fffffffff", 9};
+    lfs_file_open(&lfs, &file[1], "hello/hello", LFS_O_RDONLY) => 0;
+    lfs_file_setattrs(&lfs, &file[1], attr, 1) => LFS_ERR_BADF;
+    lfs_file_close(&lfs, &file[1]) => 0;
+    lfs_file_setattrs(&lfs, &file[0], attr, 1) => 0;
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  6},
+            {'C', buffer+10, 5}}, 3) => LFS_ERR_RANGE;
+
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDONLY) => 0;
+
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'A', buffer,    4},
+            {'B', buffer+4,  9},
+            {'C', buffer+13, 5}}, 3) => 0;
+    memcmp(buffer,    "aaaa",      4) => 0;
+    memcmp(buffer+4,  "fffffffff", 9) => 0;
+    memcmp(buffer+13, "ccccc",     5) => 0;
+
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], buffer, sizeof(buffer)) => strlen("hello");
+    memcmp(buffer, "hello", strlen("hello")) => 0;
+    lfs_file_close(&lfs, &file[0]);
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Deferred file attributes ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "hello/hello", LFS_O_RDWR) => 0;
+    
+    struct lfs_attr attr[] = {
+        {'B', "gggg", 4},
+        {'C', "",     0},
+        {'D', "hhhh", 4},
+    };
+
+    lfs_file_setattrs(&lfs, &file[0], attr, 3) => 0;
+    lfs_file_getattrs(&lfs, &file[0], (struct lfs_attr[]){
+            {'B', buffer,    9},
+            {'C', buffer+9,  9},
+            {'D', buffer+18, 9}}, 3) => 0;
+    memcmp(buffer,    "gggg\0\0\0\0\0",     9) => 0;
+    memcmp(buffer+9,  "\0\0\0\0\0\0\0\0\0", 9) => 0;
+    memcmp(buffer+18, "hhhh\0\0\0\0\0",     9) => 0;
+
+    lfs_getattrs(&lfs, "hello/hello", (struct lfs_attr[]){
+            {'B', buffer,    9},
+            {'C', buffer+9,  9},
+            {'D', buffer+18, 9}}, 3) => 0;
+    memcmp(buffer,    "fffffffff",          9) => 0;
+    memcmp(buffer+9,  "ccccc\0\0\0\0",      9) => 0;
+    memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;
+
+    lfs_file_sync(&lfs, &file[0]) => 0;
+    lfs_getattrs(&lfs, "hello/hello", (struct lfs_attr[]){
+            {'B', buffer,    9},
+            {'C', buffer+9,  9},
+            {'D', buffer+18, 9}}, 3) => 0;
+    memcmp(buffer,    "gggg\0\0\0\0\0",     9) => 0;
+    memcmp(buffer+9,  "\0\0\0\0\0\0\0\0\0", 9) => 0;
+    memcmp(buffer+18, "hhhh\0\0\0\0\0",     9) => 0;
+
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Results ---"
+tests/stats.py

+ 220 - 0
tests/test_entries.sh

@@ -0,0 +1,220 @@
+#!/bin/bash
+set -eu
+
+# Note: These tests are intended for 512 byte inline size at different
+# inline sizes they should still pass, but won't be testing anything
+
+echo "=== Directory tests ==="
+function read_file {
+cat << TEST
+
+    size = $2;
+    lfs_file_open(&lfs, &file[0], "$1", LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], rbuffer, size) => size;
+    memcmp(rbuffer, wbuffer, size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+TEST
+}
+
+function write_file {
+cat << TEST
+
+    size = $2;
+    lfs_file_open(&lfs, &file[0], "$1",
+            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
+    memset(wbuffer, 'c', size);
+    lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
+    lfs_file_close(&lfs, &file[0]) => 0;
+TEST
+}
+
+echo "--- Entry grow test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 20)
+    $(write_file "hi1" 20)
+    $(write_file "hi2" 20)
+    $(write_file "hi3" 20)
+
+    $(read_file "hi1" 20)
+    $(write_file "hi1" 200)
+
+    $(read_file "hi0" 20)
+    $(read_file "hi1" 200)
+    $(read_file "hi2" 20)
+    $(read_file "hi3" 20)
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Entry shrink test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 20)
+    $(write_file "hi1" 200)
+    $(write_file "hi2" 20)
+    $(write_file "hi3" 20)
+
+    $(read_file "hi1" 200)
+    $(write_file "hi1" 20)
+
+    $(read_file "hi0" 20)
+    $(read_file "hi1" 20)
+    $(read_file "hi2" 20)
+    $(read_file "hi3" 20)
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Entry spill test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 200)
+    $(write_file "hi1" 200)
+    $(write_file "hi2" 200)
+    $(write_file "hi3" 200)
+
+    $(read_file "hi0" 200)
+    $(read_file "hi1" 200)
+    $(read_file "hi2" 200)
+    $(read_file "hi3" 200)
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Entry push spill test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 200)
+    $(write_file "hi1" 20)
+    $(write_file "hi2" 200)
+    $(write_file "hi3" 200)
+
+    $(read_file "hi1" 20)
+    $(write_file "hi1" 200)
+
+    $(read_file "hi0" 200)
+    $(read_file "hi1" 200)
+    $(read_file "hi2" 200)
+    $(read_file "hi3" 200)
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Entry push spill two test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 200)
+    $(write_file "hi1" 20)
+    $(write_file "hi2" 200)
+    $(write_file "hi3" 200)
+    $(write_file "hi4" 200)
+
+    $(read_file "hi1" 20)
+    $(write_file "hi1" 200)
+
+    $(read_file "hi0" 200)
+    $(read_file "hi1" 200)
+    $(read_file "hi2" 200)
+    $(read_file "hi3" 200)
+    $(read_file "hi4" 200)
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Entry drop test ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    $(write_file "hi0" 200)
+    $(write_file "hi1" 200)
+    $(write_file "hi2" 200)
+    $(write_file "hi3" 200)
+
+    lfs_remove(&lfs, "hi1") => 0;
+    lfs_stat(&lfs, "hi1", &info) => LFS_ERR_NOENT;
+    $(read_file "hi0" 200)
+    $(read_file "hi2" 200)
+    $(read_file "hi3" 200)
+
+    lfs_remove(&lfs, "hi2") => 0;
+    lfs_stat(&lfs, "hi2", &info) => LFS_ERR_NOENT;
+    $(read_file "hi0" 200)
+    $(read_file "hi3" 200)
+
+    lfs_remove(&lfs, "hi3") => 0;
+    lfs_stat(&lfs, "hi3", &info) => LFS_ERR_NOENT;
+    $(read_file "hi0" 200)
+
+    lfs_remove(&lfs, "hi0") => 0;
+    lfs_stat(&lfs, "hi0", &info) => LFS_ERR_NOENT;
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Create too big ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    memset(buffer, 'm', 200);
+    buffer[200] = '\0';
+
+    size = 400;
+    lfs_file_open(&lfs, &file[0], (char*)buffer,
+            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
+    memset(wbuffer, 'c', size);
+    lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
+    lfs_file_close(&lfs, &file[0]) => 0;
+
+    size = 400;
+    lfs_file_open(&lfs, &file[0], (char*)buffer, LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], rbuffer, size) => size;
+    memcmp(rbuffer, wbuffer, size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Resize too big ---"
+tests/test.py << TEST
+    lfs_format(&lfs, &cfg) => 0;
+
+    lfs_mount(&lfs, &cfg) => 0;
+    memset(buffer, 'm', 200);
+    buffer[200] = '\0';
+
+    size = 40;
+    lfs_file_open(&lfs, &file[0], (char*)buffer,
+            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
+    memset(wbuffer, 'c', size);
+    lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
+    lfs_file_close(&lfs, &file[0]) => 0;
+
+    size = 40;
+    lfs_file_open(&lfs, &file[0], (char*)buffer, LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], rbuffer, size) => size;
+    memcmp(rbuffer, wbuffer, size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+
+    size = 400;
+    lfs_file_open(&lfs, &file[0], (char*)buffer,
+            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
+    memset(wbuffer, 'c', size);
+    lfs_file_write(&lfs, &file[0], wbuffer, size) => size;
+    lfs_file_close(&lfs, &file[0]) => 0;
+
+    size = 400;
+    lfs_file_open(&lfs, &file[0], (char*)buffer, LFS_O_RDONLY) => 0;
+    lfs_file_read(&lfs, &file[0], rbuffer, size) => size;
+    memcmp(rbuffer, wbuffer, size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Results ---"
+tests/stats.py

+ 18 - 0
tests/test_paths.sh

@@ -123,5 +123,23 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
 TEST
 
+echo "--- Max path test ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    memset(buffer, 'w', LFS_NAME_MAX+1);
+    buffer[LFS_NAME_MAX+2] = '\0';
+    lfs_mkdir(&lfs, (char*)buffer) => LFS_ERR_NAMETOOLONG;
+    lfs_file_open(&lfs, &file[0], (char*)buffer,
+            LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG;
+
+    memcpy(buffer, "coffee/", strlen("coffee/"));
+    memset(buffer+strlen("coffee/"), 'w', LFS_NAME_MAX+1);
+    buffer[strlen("coffee/")+LFS_NAME_MAX+2] = '\0';
+    lfs_mkdir(&lfs, (char*)buffer) => LFS_ERR_NAMETOOLONG;
+    lfs_file_open(&lfs, &file[0], (char*)buffer,
+            LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG;
+    lfs_unmount(&lfs) => 0;
+TEST
+
 echo "--- Results ---"
 tests/stats.py