From 0270951009fcdf8c48f9b477b1ea14f5bd16725d Mon Sep 17 00:00:00 2001
From: Miklos Szeredi <miklos@szeredi.hu>
Date: Wed, 3 Aug 2005 14:14:47 +0000
Subject: [PATCH] add testcases for open()

---
 test/test.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 185 insertions(+), 4 deletions(-)

diff --git a/test/test.c b/test/test.c
index dfc9fea..97dace5 100644
--- a/test/test.c
+++ b/test/test.c
@@ -16,9 +16,11 @@ static char testdir[1024];
 static char testdir2[1024];
 static char testname[256];
 static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
+static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
 static const char *testdir_files[] = { "f1", "f2", NULL};
 static char zerodata[4096];
 static int testdatalen = sizeof(testdata) - 1;
+static int testdata2len = sizeof(testdata2) - 1;
 
 #define MAX_ENTRIES 1024
 
@@ -135,6 +137,15 @@ static int check_nonexist(const char *path)
     return 0;
 }
 
+static int check_buffer(const char *buf, const char *data, unsigned len)
+{
+    if (memcmp(buf, data, len) != 0) {
+        ERROR("data mismatch");
+        return -1;
+    }
+    return 0;
+}
+
 static int check_data(const char *path, const char *data, int offset,
                       unsigned len)
 {
@@ -163,8 +174,7 @@ static int check_data(const char *path, const char *data, int offset,
             close(fd);
             return -1;
         }
-        if (memcmp(buf, data, rdlen) != 0) {
-            ERROR("data mismatch");
+        if (check_buffer(buf, data, rdlen) != 0) {
             close(fd);
             return -1;
         }
@@ -183,7 +193,7 @@ static int check_dir_contents(const char *path, const char **contents)
 {
     int i;
     int res;
-    int err = 0;;
+    int err = 0;
     int found[MAX_ENTRIES];
     const char *cont[MAX_ENTRIES];
     DIR *dp;
@@ -455,6 +465,154 @@ static int test_create(void)
     return 0;
 }
 
+#define test_open(exist, flags, mode)  do_test_open(exist, flags, #flags, mode)
+
+static int do_test_open(int exist, int flags, const char *flags_str, int mode)
+{
+    char buf[4096];
+    const char *data = testdata;
+    int datalen = testdatalen;
+    unsigned currlen = 0;
+    int err = 0;
+    int res;
+    int fd;
+    off_t off;
+
+    start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
+    unlink(testfile);
+    if (exist) {
+        res = create_file(testfile, testdata2, testdata2len);
+        if (res == -1)
+            return -1;
+        
+        currlen = testdata2len;
+    }
+    
+    fd = open(testfile, flags, mode);
+    if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
+        if (fd != -1) {
+            ERROR("open should have failed");
+            close(fd);
+            return -1;
+        } else if (errno == EEXIST)
+            goto succ;
+    }
+    if (!(flags & O_CREAT) && !exist) {
+        if (fd != -1) {
+            ERROR("open should have failed");
+            close(fd);
+            return -1;
+        } else if (errno == ENOENT)
+            goto succ;
+    }
+    if (fd == -1) {
+        PERROR("open");
+        return -1;
+    }
+
+    if (flags & O_TRUNC)
+        currlen = 0;
+    
+    err += check_type(testfile, S_IFREG);
+    if (exist)
+        err += check_mode(testfile, 0644);
+    else
+        err += check_mode(testfile, mode);        
+    err += check_nlink(testfile, 1);
+    err += check_size(testfile, currlen);
+    if (exist && !(flags & O_TRUNC) && (mode & 0400))
+        err += check_data(testfile, testdata2, 0, testdata2len);
+
+    res = write(fd, data, datalen);
+    if ((flags & O_ACCMODE) != O_RDONLY) {
+        if (res == -1) {
+            PERROR("write");
+            err --;
+        } else if (res != datalen) {
+            ERROR("write is short: %u instead of %u", res, datalen);
+            err --;
+        } else {
+            if (datalen > (int) currlen)
+                currlen = datalen;
+
+            err += check_size(testfile, currlen);
+            
+            if (mode & 0400) {
+                err += check_data(testfile, data, 0, datalen);
+                if (exist && !(flags & O_TRUNC) && testdata2len > datalen)
+                    err += check_data(testfile, testdata2 + datalen, datalen,
+                                      testdata2len - datalen);
+            }
+        }
+    } else {
+        if (res != -1) {
+            ERROR("write should have failed");
+            err --;
+        } else if (errno != EBADF) {
+            PERROR("write");
+            err --;
+        }
+    }
+    off = lseek(fd, SEEK_SET, 0);
+    if (off == (off_t) -1) {
+        PERROR("lseek");
+        err--;
+    } else if (off != 0) {
+        ERROR("offset should have returned 0");
+        err --;
+    }
+    res = read(fd, buf, sizeof(buf));
+    if ((flags & O_ACCMODE) != O_WRONLY) {
+        if (res == -1) {
+            PERROR("read");
+            err--;
+        } else {
+            int readsize = currlen < sizeof(buf) ? currlen : sizeof(buf);
+            if (res != readsize) {
+                ERROR("read is short: %i instead of %u", res, readsize);
+                err--;
+            } else {
+                if ((flags & O_ACCMODE) != O_RDONLY) {
+                    err += check_buffer(buf, data, datalen);
+                    if (exist && !(flags & O_TRUNC) && testdata2len > datalen)
+                        err += check_buffer(buf + datalen, testdata2 + datalen,
+                                            testdata2len - datalen);
+                } else if (exist)
+                    err += check_buffer(buf, testdata2, testdata2len);
+            }
+        }
+    } else {
+        if (res != -1) {
+            ERROR("read should have failed");
+            err --;
+        } else if (errno != EBADF) {
+            PERROR("read");
+            err --;
+        }
+    }
+
+    res = close(fd);
+    if (res == -1) {
+        PERROR("close");
+        return -1;
+    }
+    res = unlink(testfile);
+    if (res == -1) {
+        PERROR("unlink");
+        return -1;
+    }
+    res = check_nonexist(testfile);
+    if (res == -1)
+        return -1;
+    if (err)
+        return -1;
+
+ succ:
+    success();
+    return 0;
+}
+
+
 static int test_symlink(void)
 {
     char buf[1024];
@@ -669,13 +827,14 @@ int main(int argc, char *argv[])
     const char *basepath;
     int err = 0;
 
+    umask(0);
     if (argc != 2) {
         fprintf(stderr, "usage: %s testdir\n", argv[0]);
         return 1;
     }
     basepath = argv[1];
     assert(strlen(basepath) < 512);
-
+    
     sprintf(testfile, "%s/testfile", basepath);
     sprintf(testfile2, "%s/testfile2", basepath);
     sprintf(testdir, "%s/testdir", basepath);
@@ -690,6 +849,28 @@ int main(int argc, char *argv[])
     err += test_truncate(testdatalen / 2);
     err += test_truncate(testdatalen);
     err += test_truncate(testdatalen + 100);
+    err += test_open(0, O_RDONLY, 0);
+    err += test_open(1, O_RDONLY, 0);
+    err += test_open(1, O_RDWR, 0);
+    err += test_open(1, O_WRONLY, 0);
+    err += test_open(0, O_RDWR | O_CREAT, 0600);
+    err += test_open(1, O_RDWR | O_CREAT, 0600);
+    err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    err += test_open(0, O_RDONLY | O_CREAT, 0600);
+    err += test_open(0, O_RDONLY | O_CREAT, 0400);
+    err += test_open(0, O_RDONLY | O_CREAT, 0200);
+    err += test_open(0, O_RDONLY | O_CREAT, 0000);
+    err += test_open(0, O_WRONLY | O_CREAT, 0600);
+    err += test_open(0, O_WRONLY | O_CREAT, 0400);
+    err += test_open(0, O_WRONLY | O_CREAT, 0200);
+    err += test_open(0, O_WRONLY | O_CREAT, 0000);
+    err += test_open(0, O_RDWR | O_CREAT, 0400);
+    err += test_open(0, O_RDWR | O_CREAT, 0200);
+    err += test_open(0, O_RDWR | O_CREAT, 0000);
+    err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
+    err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
+    
     unlink(testfile);
     unlink(testfile2);
     rmdir(testdir);
-- 
2.30.2