/*
 * fop_test_case.c: iml file operation - test cases
 */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include <errno.h>
#include <utime.h>

#include "iml_fop.h"
#include "fop_test.h"

iml__fopc_create_t	fop__fopc_create;
iml__fopc_free_t	fop__fopc_free;

iml_fop_open_t		fop_open;
iml_fop_read_t		fop_read;
iml_fop_readv_t		fop_readv;
iml_fop_write_t		fop_write;
iml_fop_writev_t	fop_writev;
iml_fop_close_t		fop_close;
iml_fop_creat_t		fop_creat;

iml_fop_lseek_t		fop_lseek;

iml_fop_stat_t		fop_stat;
iml_fop_lstat_t		fop_lstat;
iml_fop_fstat_t		fop_fstat;

iml_fop_mkdir_t		fop_mkdir;
iml_fop_rmdir_t		fop_rmdir;

iml_fop_symlink_t	fop_symlink;
iml_fop_readlink_t	fop_readlink;
iml_fop_link_t		fop_link;
iml_fop_unlink_t	fop_unlink;
iml_fop_rename_t	fop_rename;

iml_fop_fcntl_t		fop_fcntl;
iml_fop_truncate_t	fop_truncate;
iml_fop_ftruncate_t	fop_ftruncate;

iml_fop_opendir_t	fop_opendir;
iml_fop_readdir_t	fop_readdir;
iml_fop_closedir_t	fop_closedir;

iml_fop_access_t	fop_access;
iml_fop_chmod_t		fop_chmod;
iml_fop_fchmod_t	fop_fchmod;
iml_fop_chown_t		fop_chown;
iml_fop_lchown_t	fop_lchown;
iml_fop_fchown_t	fop_fchown;
iml_fop_fpathconf_t	fop_fpathconf;
iml_fop_pathconf_t	fop_pathconf;
iml_fop_utime_t		fop_utime;
iml_fop_utimes_t	fop_utimes;

#define BASEDIR		"/var/lib/iiim/le/fop_test"
#define TEST_DIR	"/var/lib/iiim/le/fop_test/dir"

#define TEST_FILE1	"/var/lib/iiim/le/fop_test/dir/test_file1"
#define TEST_FILE2	"/var/lib/iiim/le/fop_test/dir/test_file2"
#define TEST_SYMLINK	"test_file1"

#define TEST_DIR_FILE1	"/var/lib/iiim/le/fop_test/dir/test_dir1/fiiiileeee1"
#define TEST_DIR_FILE2	"/var/lib/iiim/le/fop_test/dir/test_dir1/f2"

#define TEST_DIR1	"/var/lib/iiim/le/fop_test/dir/test_dir1"
#define ABC		"abcdefghijklmnopqrstuvwxyz"

#if !defined(S_IAMB)
#define S_IAMB	0x1FF
#endif /* !S_IAMB */


void
test_prep(void * fopc)
{
    DIR *		dirp;
    struct dirent *	de;
    struct stat		st;
    char		path[PATH_MAX];

    umask(0);

    fop_mkdir(fopc, BASEDIR, 0777);
    dirp = fop_opendir(fopc, BASEDIR);
    while (NULL != (de = fop_readdir(fopc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", BASEDIR, de->d_name);
	fop_stat(fopc, path, &st);
	if (0 == S_ISDIR(st.st_mode)) {
	    fop_unlink(fopc, path);
	} else {
	    fop_rmdir(fopc, path);
	}
    }
    fop_mkdir(fopc, TEST_DIR, 0777);
}


void
test_open(void * fopc)
{
    int		fd;
    struct stat	st;

    fprintf(stderr, "open: ");
    fd = fop_open(fopc, TEST_FILE1, O_RDWR);
    if (0 <= fd) {
	fprintf(stderr, "fail: open should fail on non-existent file\n");
	fop_close(fopc, fd);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0612);
    if (fd < 0) {
	fprintf(stderr, "fail: open should succeed: %d %d\n", fd, errno);
	return;
    }
    fop_close(fopc, fd);

    if (fop_stat(fopc, TEST_FILE1, &st) < 0) {
	fprintf(stderr, "fail: %s does not exist: %d\n", TEST_FILE1, errno);
	return;
    } else {
	if (0612 != (S_IAMB & st.st_mode)) {
	    fprintf(stderr, "fail: mode error: 0%3o\n", (S_IAMB & st.st_mode));
	    return;
	}
    }

    fd = fop_open(fopc, TEST_FILE1, O_RDWR);
    if (fd < 0) {
	fprintf(stderr, "fail: open should succeed (o_RDWR)\n");
	return;
    }
    fop_close(fopc, fd);

    fprintf(stderr, "succeed\n");
}


void
test_read(void * fopc)
{
    char	buf[1024];
    int		fd;
    int		rv;

    fprintf(stderr, "read: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
    fop_write(fopc, fd, "hogera", 7);
    fop_close(fopc, fd);

    memset(buf, 0, sizeof (buf));
    fd = fop_open(fopc, TEST_FILE1, O_RDONLY);
    rv = fop_read(fopc, fd, buf, sizeof (buf));
    fop_close(fopc, fd);

    if (7 != rv) {
	fprintf(stderr, "fail - read length error\n");
	return;
    }

    if (0 != memcmp(buf, "hogera", 7)) {
	fprintf(stderr, "fail - incorrect contents\n");
	return;
    }

    fprintf(stderr, "succeed\n");
}


void
test_readv(void * fopc)
{
    fprintf(stderr, "readv: ");
    fprintf(stderr, "succeed\n");
}


void
test_write(void * fopc)
{
    char	buf[1024];
    int		fd;
    int		rv;

    fprintf(stderr, "write: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);

    rv = fop_write(fopc, fd, "hogera", 7);
    fop_close(fopc, fd);
    if (7 != rv) {
	fprintf(stderr, "fail - write length error\n");
	return;
    }


    memset(buf, 0, sizeof (buf));
    fd = fop_open(fopc, TEST_FILE1, O_RDONLY);
    rv = fop_read(fopc, fd, buf, sizeof (buf));
    fop_close(fopc, fd);

    if (0 != memcmp(buf, "hogera", 7)) {
	fprintf(stderr, "fail - incorrect contents\n");
	return;
    }

     fprintf(stderr, "succeed\n");
}


void
test_writev(void * fopc)
{
    fprintf(stderr, "writev: ");
    fprintf(stderr, "succeed\n");
}


void
test_close(void * fopc)
{
    int	fd;
    int	rv;

    fprintf(stderr, "close: ");

    fd = fop_open(fopc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0777);

    rv = fop_close(fopc, fd);
    if (rv < 0) {
	fprintf(stderr, "fail - close error");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0777);

    rv = fop_close(fopc, fd + 5);
    (void)fop_close(fopc, fd);
    if (0 <= rv) {
	fprintf(stderr, "fail - close should fail");
	return;
    }

    fprintf(stderr, "succeed\n");
}


void
test_creat(void * fopc)
{
    int		fd;
    struct stat	st;

    fprintf(stderr, "creat: ");

    if (0 == fop_stat(fopc, TEST_FILE1, &st)) {
	fop_unlink(fopc, TEST_FILE1);
	if (0 == fop_stat(fopc, TEST_FILE1, &st)) {
	    fprintf(stderr, "fail: can not remove %s\n", TEST_FILE1);
	    return;
	}
    }

    fd = fop_creat(fopc, TEST_FILE1, 0700);
    if (fd < 0) {
	fprintf(stderr, "fail: open should succeed\n");
	return;
    }

    if (fop_stat(fopc, TEST_FILE1, &st) < 0) {
	fprintf(stderr, "fail: %s does not exist\n", TEST_FILE1);
	return;
    } else {
	if (0700 != (S_IAMB & st.st_mode)) {
	    fprintf(stderr, "fail: mode error: %04o\n", st.st_mode);
	    return;
	}
    }

    fop_unlink(fopc, TEST_FILE1);

    fprintf(stderr, "succeed\n");
}


void
test_lseek(void * fopc)
{
    int		fd;
    char	buf[26];

    fprintf(stderr, "lseek: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    fop_write(fopc, fd, ABC, 26);
    fop_close(fopc, fd);

    fd = fop_open(fopc, TEST_FILE1, O_RDONLY);
    fop_lseek(fopc, fd, 3, SEEK_SET);
    fop_read(fopc, fd, buf, 1);
    if ('d' != buf[0]) {
	fprintf(stderr, "fail: SEEK_SET not working\n");
	return;
    }
    fop_lseek(fopc, fd, 3, SEEK_CUR);
    fop_read(fopc, fd, buf, 1);
    if ('h' != buf[0]) {
	fprintf(stderr, "fail: SEEK_CUR not working\n");
	return;
    }
    fop_lseek(fopc, fd, -3, SEEK_END);
    fop_read(fopc, fd, buf, 1);
    if ('x' != buf[0]) {
	fprintf(stderr, "fail: SEEK_END not working\n");
	return;
    }

    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);

    fprintf(stderr, "succeed\n");
}


void
test_stat(void * fopc)
{
    int		fd;
    struct stat	st;

    fprintf(stderr, "stat: ");

    if (0 == fop_stat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: stat should fail on none-existent file\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_write(fopc, fd, "data", 4);
    fop_close(fopc, fd);

    if (0 != fop_stat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: stat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) ||
	(geteuid() != st.st_uid) ||
	(4 != st.st_size)) {
	fprintf(stderr,
		"fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       st.st_mode, st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    fop_unlink(fopc, TEST_FILE1);
    fprintf(stderr, "succeed\n");
}


void
test_lstat(void * fopc)
{
    int		fd;
    struct stat	st;

    fprintf(stderr, "lstat: ");

    if (0 == fop_lstat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: lstat should fail on none-existent file\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_write(fopc, fd, "data", 4);
    fop_close(fopc, fd);

    if (0 != fop_lstat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: lstat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) ||
	(geteuid() != st.st_uid) ||
	(4 != st.st_size)) {
	fprintf(stderr,
		"fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       (S_IAMB & st.st_mode), st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    fop_unlink(fopc, TEST_FILE1);
    fprintf(stderr, "succeed\n");
}


void
test_fstat(void * fopc)
{
    int		fd;
    struct stat	st;
    int		rv;

    fprintf(stderr, "fstat: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_write(fopc, fd, "data", 4);

    rv = fop_fstat(fopc, fd, &st);
    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);

    if (0 != rv) {
	fprintf(stderr, "fail: fstat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) ||
	(geteuid() != st.st_uid) ||
	(4 != st.st_size)) {
	fprintf(stderr,
		"fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       (S_IAMB & st.st_mode), st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    fprintf(stderr, "succeed\n");
}


void
test_mkkdir(void * fopc)
{
    struct stat	st;

    fprintf(stderr, "mkkdir: ");

    if (0 == fop_stat(fopc, TEST_DIR1, &st)) {
	fop_rmdir(fopc, TEST_DIR1);
    }

    fop_mkdir(fopc, TEST_DIR1, 0711);
    fop_stat(fopc, TEST_DIR1, &st);
    fop_rmdir(fopc, TEST_DIR1);

    if (0 == S_ISDIR(st.st_mode)) {
	fprintf(stderr, "fail: not a directory\n");
	return;
    } else if (0711 != (S_IAMB & st.st_mode)) {
	fprintf(stderr,
		"fail: incorrect permission: %04o\n", (S_IAMB & st.st_mode));
	return;
    } else if (getuid() != st.st_uid) {
	fprintf(stderr, "fail: incorrect uid: %d\n", st.st_uid);
	return;
    }

    fprintf(stderr, "succeed\n");
}


void
test_rmdir(void * fopc)
{
    int		rv;
    struct stat	st;

    fprintf(stderr, "rmdir: ");

    rv = fop_rmdir(fopc, TEST_DIR1);
    if (0 == rv) {
	fprintf(stderr, "fail: rmdir should fail on non-existent directory\n");
	return;
    } else if (ENOENT != errno) {
	fprintf(stderr, "fail: errno should be ENOENT\n");
	return;
    }

    fop_mkdir(fopc, TEST_DIR1, 0711);
    rv = fop_rmdir(fopc, TEST_DIR1);
    if (rv < 0) {
	fprintf(stderr, "fail: errno should succeed\n");
	return;
    }
    if (0 == fop_stat(fopc, TEST_DIR1, &st)) {
	fprintf(stderr, "fail: %s exists\n", TEST_DIR1);
	return;
    }

    fprintf(stderr, "succeed\n");
}


void
test_symlink(void * fopc)
{
    int		fd;
    struct stat	st;

    fprintf(stderr, "symlink: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);

    if (0 != fop_symlink(fopc, TEST_SYMLINK, TEST_FILE2)) {
	fprintf(stderr, "fail: symlink failed\n");
	fop_unlink(fopc, TEST_FILE1);
	return;
    }

    if (0 != fop_stat(fopc, TEST_FILE2, &st)) {
	fprintf(stderr, "fail: stat on %s\n", TEST_FILE2);
    } else if (0 != fop_lstat(fopc, TEST_FILE2, &st)) {
	fprintf(stderr, "fail: lstat on %s\n", TEST_FILE2);
    } else if (0 == S_ISLNK(st.st_mode)) {
	fprintf(stderr, "fail: %s is not a symbolic link\n", TEST_FILE2);
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE1);
    fop_unlink(fopc, TEST_FILE2);
}


void
test_readink(void * fopc)
{
    int		rv;
    char	buf[1024];

    fprintf(stderr, "readlink: ");

    if (0 != fop_symlink(fopc, "symbolic link", TEST_FILE1)) {
	fprintf(stderr, "fail: symlink failed\n");
	return;
    }

    rv = fop_readlink(fopc, TEST_FILE1, buf, sizeof (buf));
    fop_unlink(fopc, TEST_FILE1);

    if (0 < rv) {
	fprintf(stderr, "fail: readlink failed\n");
    } else if (0 != strcmp("symlink link", buf)) {
	fprintf(stderr,
		"fail: contents error \"%s\" != \"%s\"\n",
		"symlink link", buf);
    }

    return;
}


void
test_link(void * fopc)
{
    int		fd;
    int		rv;
    struct stat	st;

    fprintf(stderr, "link: ");

    rv = fop_link(fopc, TEST_FILE1, TEST_FILE2);
    if (0 == rv) {
	fprintf(stderr, "error: link should fail\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);

    rv = fop_link(fopc, TEST_FILE1, TEST_FILE2);
    if (0 != rv) {
	fprintf(stderr, "error: link should succeed\n");
	return;
    }

    fop_unlink(fopc, TEST_FILE1);

    if (0 != fop_stat(fopc, TEST_FILE2, &st)) {
	fprintf(stderr, "fail: stat on %s\n", TEST_FILE2);
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE2);
}


void
test_unlink(void * fopc)
{
    int		fd;
    int		rv;

    fprintf(stderr, "unlink: ");

    rv = fop_unlink(fopc, TEST_FILE1);
    if (0 == rv) {
	fprintf(stderr, "error: unlink should fail\n");
	return;
    } else if (ENOENT != errno) {
	fprintf(stderr, "error: errno should be ENOENT\n");
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);

    rv = fop_unlink(fopc, TEST_FILE1);
    if (0 != rv) {
	fprintf(stderr, "error: unlink should succeed\n");
	return;
    }

    fprintf(stderr, "succeed\n");
}


void
test_rename(void * fopc)
{
    int		fd;
    int		rv;
    struct stat	st;

    fprintf(stderr, "rename: ");

    rv = fop_rename(fopc, TEST_FILE1, TEST_FILE2);
    if (0 == rv) {
	fprintf(stderr, "error: rename should fail\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);

    rv = fop_rename(fopc, TEST_FILE1, TEST_FILE2);
    if (0 != rv) {
	fprintf(stderr, "error: rename should succeed\n");
	return;
    }

    if (0 == fop_stat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: stat on \"%s\" should fail\n", TEST_FILE1);
    } else if (0 != fop_stat(fopc, TEST_FILE2, &st)) {
	fprintf(stderr, "fail: stat on \"%s\" should succeed\n", TEST_FILE2);
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE1);
    fop_unlink(fopc, TEST_FILE2);
}


void
test_fcntl(void * fopc)
{
    int		fd;
    int		rv;

    fprintf(stderr, "fcntl: ");

    rv = fop_fcntl(fopc, 99, F_GETFD);
    if (0 <= rv) {
	fprintf(stderr, "error: fcntl on invalid fd should fail\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    fop_fcntl(fopc, fd, F_SETFD, FD_CLOEXEC);
    rv = fop_fcntl(fopc, fd, F_GETFD);
    if (rv < 0) {
	fprintf(stderr, "error: fcntl should succeed\n");
    } else if (FD_CLOEXEC != rv) {
	fprintf(stderr, "error: invalid flags 0x%x\n", rv);
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);
}


void
test_truncate(void * fopc)
{
    int		fd;
    struct stat	st;
    int		rv;

    fprintf(stderr, "truncate: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    fop_write(fopc, fd, ABC, 26);
    fop_close(fopc, fd);

    rv = fop_truncate(fopc, TEST_FILE1, 16);
    if (0 != rv) {
	fprintf(stderr, "fail: truncate should succeed\n");
    } else if (0 != fop_stat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: stat error on %s\n", TEST_FILE1);
	if (16 != st.st_size) {
	    fprintf(stderr,
		    "fail: size not turncated %lu\n",
		    (unsigned long)st.st_size);
	} else {
	    fprintf(stderr, "succeed\n");
	}
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_ftruncate(void * fopc)
{
    int		fd;
    struct stat	st;
    int		rv;

    fprintf(stderr, "ftruncate: ");

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    fop_write(fopc, fd, ABC, 26);

    rv = fop_ftruncate(fopc, fd, 16);
    fop_close(fopc, fd);

    if (0 != rv) {
	fprintf(stderr, "fail: truncate should succeed\n");
    } else if (0 != fop_stat(fopc, TEST_FILE1, &st)) {
	fprintf(stderr, "fail: stat error on %s\n", TEST_FILE1);
	if (16 != st.st_size) {
	    fprintf(stderr,
		    "fail: size not truncated %lu\n",
		    (unsigned long)st.st_size);
	} else {
	    fprintf(stderr, "succeed\n");
	}
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_opendir(void * fopc)
{
    int			fd;
    DIR *		dirp;
    struct dirent *	de;
    char		path[PATH_MAX];
    int			found1;
    int			found2;

    fprintf(stderr, "opendir: ");

    fop_mkdir(fopc, TEST_DIR1, 0777);
    fd = fop_open(fopc, TEST_DIR_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);
    fd = fop_open(fopc, TEST_DIR_FILE2, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);
    found1 = 0;
    found2 = 0;

    dirp = fop_opendir(fopc, TEST_DIR1);
    while (NULL != (de = fop_readdir(fopc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", TEST_DIR1, de->d_name);
	if (0 == strcmp(path, TEST_DIR_FILE1)) {
	    found1 = 1;
	} else if (0 == strcmp(path, TEST_DIR_FILE2)) {
	    found2 = 1;
	}
    }
    fop_closedir(fopc, dirp);

    if ((1 == found1) && (1 == found2)) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: file not found\n");
    }

    fop_unlink(fopc, TEST_DIR_FILE1);
    fop_unlink(fopc, TEST_DIR_FILE2);
    fop_rmdir(fopc, TEST_DIR1);
}


void
test_readdir(void * fopc)
{
    int			fd;
    DIR *		dirp;
    struct dirent *	de;
    char		path[PATH_MAX];
    int			found1;
    int			found2;

    fprintf(stderr, "readdir: ");

    fop_mkdir(fopc, TEST_DIR1, 0777);
    fd = fop_open(fopc, TEST_DIR_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);
    fd = fop_open(fopc, TEST_DIR_FILE2, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    fop_close(fopc, fd);
    found1 = 0;
    found2 = 0;

    dirp = fop_opendir(fopc, TEST_DIR1);
    while (NULL != (de = fop_readdir(fopc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", TEST_DIR1, de->d_name);
	if (0 == strcmp(path, TEST_DIR_FILE1)) {
	    found1 = 1;
	} else if (0 == strcmp(path, TEST_DIR_FILE2)) {
	    found2 = 1;
	}
    }
    fop_closedir(fopc, dirp);

    if ((1 == found1) && (1 == found2)) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: files not found\n");
    }

    fop_unlink(fopc, TEST_DIR_FILE1);
    fop_unlink(fopc, TEST_DIR_FILE2);
    fop_rmdir(fopc, TEST_DIR1);
}


void
test_closedir(void * fopc)
{
    DIR *		dirp;

    fprintf(stderr, "closedir: ");

    fop_mkdir(fopc, TEST_DIR1, 0777);

    dirp = fop_opendir(fopc, TEST_DIR1);
    if (0 == fop_closedir(fopc, dirp)) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "failed\n");
    }

    fop_rmdir(fopc, TEST_DIR1);
}


void
test_access(void * fopc)
{
    int	rv;
    int	fd;

    fprintf(stderr, "access: ");

    rv = fop_access(fopc, TEST_FILE1, F_OK);
    if (0 == rv) {
	fprintf(stderr, "fail: F_OK should fail on none-existent file\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    if (0 != fop_access(fopc, TEST_FILE1, R_OK)) {
	fprintf(stderr, "fail: R_OK should succeed\n");
    } else if (0 == fop_access(fopc, TEST_FILE1, X_OK)) {
	fprintf(stderr, "fail: X_OK should fail\n");
    } else {
	fprintf(stderr, "succeed\n");
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_chmod(void * fopc)
{
    int		rv;
    int		fd;
    struct stat	st;

    fprintf(stderr, "chmod: ");

    rv = fop_chmod(fopc, TEST_FILE1, 0555);
    if (0 == rv) {
	fprintf(stderr, "fail: should fail on none-existent file\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    if (0 != fop_chmod(fopc, TEST_FILE1, 0555)) {
	fprintf(stderr, "fail: should succeed\n");
    } else {
	fop_stat(fopc, TEST_FILE1, &st);
	if (0555 != (S_IAMB & st.st_mode)) {
	    fprintf(stderr,
		    "fail: incorrect mode: %d\n", (S_IAMB & st.st_mode));
	} else {
	    fprintf(stderr, "succeed\n");
	}
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_fchmod(void * fopc)
{
    int		rv;
    int		fd;
    struct stat	st;

    fprintf(stderr, "fchmod: ");

    rv = fop_fchmod(fopc, 99, 0555);
    if (0 == rv) {
	fprintf(stderr, "fail: should fail on none-existent file\n");
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (0 != fop_fchmod(fopc, fd, 0555)) {
	fprintf(stderr, "fail: should succeed\n");
    } else {
	fop_fstat(fopc, fd, &st);
	if (0555 != (S_IAMB & st.st_mode)) {
	    fprintf(stderr,
		    "fail: incorrect mode: %d\n", (S_IAMB & st.st_mode));
	} else {
	    fprintf(stderr, "succeed\n");
	}
    }

    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);
}


void
test_chown(void * fopc)
{
    int		rv;
    int		fd;
    int		errno_save;

    fprintf(stderr, "chown: ");

    rv = fop_chown(fopc, TEST_FILE1, 99, 99);
    if (0 == rv) {
	fprintf(stderr, "fail: should fail on non-existent file\n");
	return;
    } else if (ENOENT != errno) {
	fprintf(stderr, "fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    rv = fop_chown(fopc, TEST_FILE1, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    fprintf(stderr, "fail: uid = %d: should succeed\n", geteuid());
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    fprintf(stderr, "fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    fprintf(stderr, "invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_lchown(void * fopc)
{
    int		rv;
    int		fd;
    int		errno_save;
    uid_t	uid;

    fprintf(stderr, "lchown: ");

    uid = geteuid();

    rv = fop_lchown(fopc, TEST_FILE1, 99, 99);
    if (0 == rv) {
	fprintf(stderr, "fail: should fail on non-existent file\n");
	return;
    } else if ((0 == uid) && (ENOENT != errno)) {
	fprintf(stderr, "fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    } else if ((0 != uid) && (EPERM != errno)) {
	fprintf(stderr, "fail: invalid errno: %d should be EPERM (%d)\n",
	       errno, EPERM);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    rv = fop_lchown(fopc, TEST_FILE1, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    fprintf(stderr, "fail: uid = %d: should succeed\n", geteuid());
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    fprintf(stderr, "fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    fprintf(stderr, "invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_fchown(void * fopc)
{
    int		rv;
    int		fd;
    int		errno_save;
    uid_t	uid;

    fprintf(stderr, "fchown: ");

    uid = geteuid();

    rv = fop_fchown(fopc, 99, 99, 99);
    if (0 == rv) {
	fprintf(stderr, "fail: should fail on non-existent file\n");
	return;
    } else if (EBADF != errno) {
	fprintf(stderr,
		"fail: invalid errno: %d should be EBADF (%d)\n",
		errno, EBADF);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    rv = fop_fchown(fopc, fd, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    fprintf(stderr, "fail: uid = %d: should succeed\n", geteuid());
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    fprintf(stderr, "fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    fprintf(stderr, "invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    fprintf(stderr, "succeed\n");
	}
	break;
    }

    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);
}


void
test_fpathconf(void * fopc)
{
    long	rv;
    int		fd;

    fprintf(stderr, "fpathconf: ");

    rv = fop_fpathconf(fopc, 99, _PC_PATH_MAX);
    if (-1 != rv) {
	fprintf(stderr, "fail: should fail\n");
	return;
    } else if (EBADF != errno) {
	fprintf(stderr, "fail: invalid errno: %d should be EBADF (%d)\n",
	       errno, EBADF);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    rv = fop_fpathconf(fopc, fd, _PC_PATH_MAX);
    if (-1 != rv) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: %ld\n", rv);
    }

    fop_close(fopc, fd);
    fop_unlink(fopc, TEST_FILE1);
}


void
test_pathconf(void * fopc)
{
    long	rv;
    int		fd;

    fprintf(stderr, "pathconf: ");

    rv = fop_pathconf(fopc, TEST_FILE1, _PC_PATH_MAX);
    if ((-1 == rv) && (ENOENT != errno)) {
	fprintf(stderr, "fail: invalid errno: %d should be ENOENT (%d)\n",
		errno, ENOENT);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    rv = fop_pathconf(fopc, TEST_FILE1, _PC_PATH_MAX);
    if (-1 != rv) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: %lu\n", rv);
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_utime(void * fopc)
{
    int	rv;
    int	fd;

    fprintf(stderr, "utime: ");

    rv = fop_utime(fopc, TEST_FILE1, NULL);
    if (-1 != rv) {
	fprintf(stderr, "fail: should fail");
	return;
    } else if (ENOENT != errno) {
	fprintf(stderr, "fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    rv = fop_utime(fopc, TEST_FILE1, NULL);
    if (-1 != rv) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: %d\n", rv);
    }

    fop_unlink(fopc, TEST_FILE1);
}


void
test_utimes(void * fopc)
{
    int	rv;
    int	fd;

    fprintf(stderr, "utimes: ");

    rv = fop_utimes(fopc, TEST_FILE1, NULL);
    if (-1 != rv) {
	fprintf(stderr, "fail: should fail");
	return;
    } else if (ENOENT != errno) {
	fprintf(stderr, "fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = fop_open(fopc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    fop_close(fopc, fd);

    rv = fop_utimes(fopc, TEST_FILE1, NULL);
    if (-1 != rv) {
	fprintf(stderr, "succeed\n");
    } else {
	fprintf(stderr, "fail: %d\n", rv);
    }

    fop_unlink(fopc, TEST_FILE1);
}


int
fop_test_cases_all(void * ptr, iml_fop_get_function_t fop_get_function)
{
    void *	fopc;

    fop__fopc_create =
	(iml__fopc_create_t)(fop_get_function("_nsc_create"));
    if (NULL == fop__fopc_create) fprintf(stderr, "_nsc_create: fail\n");
    fop__fopc_free = (iml__fopc_free_t)(fop_get_function("_nsc_free"));
    if (NULL == fop__fopc_free) fprintf(stderr, "_nsc_free: fail\n");
    fop_access = (iml_fop_access_t)(fop_get_function("access"));
    if (NULL == fop_access) fprintf(stderr, "access: fail\n");
    fop_chmod = (iml_fop_chmod_t)(fop_get_function("chmod"));
    if (NULL == fop_chmod) fprintf(stderr, "chmod: fail\n");
    fop_fchmod = (iml_fop_fchmod_t)(fop_get_function("fchmod"));
    if (NULL == fop_fchmod) fprintf(stderr, "fchmod: fail\n");
    fop_chown = (iml_fop_chown_t)(fop_get_function("chown"));
    if (NULL == fop_chown) fprintf(stderr, "chown: fail\n");
#if 0
    fop_lchown = (iml_fop_lchown_t)(fop_get_function("lchown"));
    if (NULL == fop_lchown) fprintf(stderr, "lchown: fail\n");
#endif
    fop_fchown = (iml_fop_fchown_t)(fop_get_function("fchown"));
    if (NULL == fop_fchown) fprintf(stderr, "fchown: fail\n");
    fop_close = (iml_fop_close_t)(fop_get_function("close"));
    if (NULL == fop_close) fprintf(stderr, "close: fail\n");
    fop_closedir = (iml_fop_closedir_t)(fop_get_function("closedir"));
    if (NULL == fop_closedir) fprintf(stderr, "closedir: fail\n");
    fop_creat = (iml_fop_creat_t)(fop_get_function("creat"));
    if (NULL == fop_creat) fprintf(stderr, "creat: fail\n");
    fop_fcntl = (iml_fop_fcntl_t)(fop_get_function("fcntl"));
    if (NULL == fop_fcntl) fprintf(stderr, "fcntl: fail\n");
    fop_fpathconf = (iml_fop_fpathconf_t)(fop_get_function("fpathconf"));
    if (NULL == fop_fpathconf) fprintf(stderr, "fpathconf: fail\n");
    fop_fstat = (iml_fop_fstat_t)(fop_get_function("fstat"));
    if (NULL == fop_fstat) fprintf(stderr, "fstat: fail\n");
    fop_ftruncate = (iml_fop_ftruncate_t)(fop_get_function("ftruncate"));
    if (NULL == fop_ftruncate) fprintf(stderr, "ftruncate: fail\n");
    fop_link = (iml_fop_link_t)(fop_get_function("link"));
    if (NULL == fop_link) fprintf(stderr, "link: fail\n");
    fop_lseek = (iml_fop_lseek_t)(fop_get_function("lseek"));
    if (NULL == fop_lseek) fprintf(stderr, "lseek: fail\n");
    fop_lstat = (iml_fop_lstat_t)(fop_get_function("lstat"));
    if (NULL == fop_lstat) fprintf(stderr, "lstat: fail\n");
    fop_mkdir = (iml_fop_mkdir_t)(fop_get_function("mkdir"));
    if (NULL == fop_mkdir) fprintf(stderr, "mkdir: fail\n");
    fop_open = (iml_fop_open_t)(fop_get_function("open"));
    if (NULL == fop_open) fprintf(stderr, "open: fail\n");
    fop_opendir = (iml_fop_opendir_t)(fop_get_function("opendir"));
    if (NULL == fop_opendir) fprintf(stderr, "opendir: fail\n");
    fop_pathconf = (iml_fop_pathconf_t)(fop_get_function("pathconf"));
    if (NULL == fop_pathconf) fprintf(stderr, "pathconf: fail\n");
    fop_read = (iml_fop_read_t)(fop_get_function("read"));
    if (NULL == fop_read) fprintf(stderr, "read: fail\n");
    fop_readdir = (iml_fop_readdir_t)(fop_get_function("readdir"));
    if (NULL == fop_readdir) fprintf(stderr, "readdir: fail\n");
    fop_readv = (iml_fop_readv_t)(fop_get_function("readv"));
    if (NULL == fop_readv) fprintf(stderr, "readv: fail\n");
    fop_rename = (iml_fop_rename_t)(fop_get_function("rename"));
    if (NULL == fop_rename) fprintf(stderr, "rename: fail\n");
    fop_rmdir = (iml_fop_rmdir_t)(fop_get_function("rmdir"));
    if (NULL == fop_rmdir) fprintf(stderr, "rmdir: fail\n");
    fop_stat = (iml_fop_stat_t)(fop_get_function("stat"));
    if (NULL == fop_stat) fprintf(stderr, "stat: fail\n");
    fop_symlink = (iml_fop_symlink_t)(fop_get_function("symlink"));
    if (NULL == fop_symlink) fprintf(stderr, "symlink: fail\n");
    fop_truncate = (iml_fop_truncate_t)(fop_get_function("truncate"));
    if (NULL == fop_truncate) fprintf(stderr, "truncate: fail\n");
    fop_unlink = (iml_fop_unlink_t)(fop_get_function("unlink"));
    if (NULL == fop_unlink) fprintf(stderr, "unlink: fail\n");
    fop_utime = (iml_fop_utime_t)(fop_get_function("utime"));
    if (NULL == fop_utime) fprintf(stderr, "utime: fail\n");
    fop_utimes = (iml_fop_utimes_t)(fop_get_function("utimes"));
    if (NULL == fop_utimes) fprintf(stderr, "utimes: fail\n");
    fop_write = (iml_fop_write_t)(fop_get_function("write"));
    if (NULL == fop_write) fprintf(stderr, "write: fail\n");
    fop_writev = (iml_fop_writev_t)(fop_get_function("writev"));
    if (NULL == fop_writev) fprintf(stderr, "writev: fail\n");

    fopc = fop__fopc_create("fop_test", IML_NSC_TYPE_DESKTOP, ptr);

    test_prep(fopc);
    test_open(fopc);
    test_read(fopc);
    test_readv(fopc);
    test_write(fopc);
    test_writev(fopc);
    test_close(fopc);
    test_creat(fopc);
    test_lseek(fopc);
    test_stat(fopc);
    test_lstat(fopc);
    test_fstat(fopc);
    test_mkkdir(fopc);
    test_rmdir(fopc);
    test_symlink(fopc);
    test_link(fopc);
    test_unlink(fopc);
    test_rename(fopc);
    test_fcntl(fopc);
    test_truncate(fopc);
    test_ftruncate(fopc);
    test_opendir(fopc);
    test_readdir(fopc);
    test_closedir(fopc);
    test_access(fopc);
    test_chmod(fopc);
    test_fchmod(fopc);
    test_chown(fopc);
#if 0
    test_lchown(fopc);
#endif
    test_fchown(fopc);
    test_fpathconf(fopc);
    test_pathconf(fopc);
    test_utime(fopc);
    test_utimes(fopc);

    fop__fopc_free(fopc);

    return 0;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
