summaryrefslogblamecommitdiffstats
path: root/testsuites/fstests/fsimfsgeneric01/init.c
blob: 09e7ed67f8fc5fc7ff6f079ff370d431a7e26ff1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                 
                                        









                      
                    





                         
                              
 

                                                 












                   

              





                    




















                                                           
                                           




































































































































                                                                





























                                                           










                                                               


                            

















                                                  
                                                    




























                                                             
                              





                               



                                




                                          
          





























                                  





                             





                             
                                             

 























                                                               


                                                       










                                                                    










                                                                      


                                        









                                          
                                                            









                                          
                                                            
 
            
                         





                                          
                        

                                      
                                                            
 
            
                                               





                                          
                                 

                                     











                                                            



                                         
               



                                       
             











                                                  

                                                                 




                                        
/*
 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Obere Lagerstr. 30
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#ifdef HAVE_CONFIG_H
  #include "config.h"
#endif

#include "tmacros.h"

#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include <rtems/imfs.h>
#include <rtems/malloc.h>
#include <rtems/libcsupport.h>

const char rtems_test_name[] = "FSIMFSGENERIC 1";

typedef enum {
  TEST_NEW,
  TEST_INITIALIZED,
  TEST_FSTAT_OPEN,
  TEST_OPEN,
  TEST_READ,
  TEST_WRITE,
  TEST_IOCTL,
  TEST_LSEEK,
  TEST_FTRUNCATE,
  TEST_FSYNC,
  TEST_FDATASYNC,
  TEST_FCNTL,
  TEST_READV,
  TEST_WRITEV,
  TEST_CLOSED,
  TEST_FSTAT_UNLINK,
  TEST_REMOVED,
  TEST_DESTROYED
} test_state;

static int handler_open(
  rtems_libio_t *iop,
  const char *path,
  int oflag,
  mode_t mode
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_FSTAT_OPEN);
  *state = TEST_OPEN;

  return 0;
}

static int handler_close(
  rtems_libio_t *iop
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_WRITEV);
  *state = TEST_CLOSED;

  return 0;
}

static ssize_t handler_read(
  rtems_libio_t *iop,
  void *buffer,
  size_t count
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_OPEN);
  *state = TEST_READ;

  return 0;
}

static ssize_t handler_write(
  rtems_libio_t *iop,
  const void *buffer,
  size_t count
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_READ);
  *state = TEST_WRITE;

  return 0;
}

static int handler_ioctl(
  rtems_libio_t *iop,
  uint32_t request,
  void *buffer
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_WRITE);
  *state = TEST_IOCTL;

  return 0;
}

static off_t handler_lseek(
  rtems_libio_t *iop,
  off_t length,
  int whence
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_IOCTL);
  *state = TEST_LSEEK;

  return 0;
}

static int handler_fstat(
  const rtems_filesystem_location_info_t *loc,
  struct stat *buf
)
{
  test_state *state = IMFS_generic_get_context_by_location(loc);

  switch (*state) {
    case TEST_INITIALIZED:
      *state = TEST_FSTAT_OPEN;
      break;
    case TEST_CLOSED:
      *state = TEST_FSTAT_UNLINK;
      break;
    default:
      rtems_test_assert(0);
      break;
  }

  return rtems_filesystem_default_fstat(loc, buf);
}

static int handler_ftruncate(
  rtems_libio_t *iop,
  off_t length
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_LSEEK);
  *state = TEST_FTRUNCATE;

  return 0;
}

static int handler_fsync(
  rtems_libio_t *iop
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_FTRUNCATE);
  *state = TEST_FSYNC;

  return 0;
}

static int handler_fdatasync(
  rtems_libio_t *iop
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_FSYNC);
  *state = TEST_FDATASYNC;

  return 0;
}

static int handler_fcntl(
  rtems_libio_t *iop,
  int cmd
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_FDATASYNC);
  *state = TEST_FCNTL;

  return 0;
}

static ssize_t handler_readv(
  rtems_libio_t *iop,
  const struct iovec *iov,
  int iovcnt,
  ssize_t total
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_FCNTL);
  *state = TEST_READV;

  return 0;
}

static ssize_t handler_writev(
  rtems_libio_t *iop,
  const struct iovec *iov,
  int iovcnt,
  ssize_t total
)
{
  test_state *state = IMFS_generic_get_context_by_iop(iop);

  rtems_test_assert(*state == TEST_READV);
  *state = TEST_WRITEV;

  return 0;
}

static const rtems_filesystem_file_handlers_r node_handlers = {
  .open_h = handler_open,
  .close_h = handler_close,
  .read_h = handler_read,
  .write_h = handler_write,
  .ioctl_h = handler_ioctl,
  .lseek_h = handler_lseek,
  .fstat_h = handler_fstat,
  .ftruncate_h = handler_ftruncate,
  .fsync_h = handler_fsync,
  .fdatasync_h = handler_fdatasync,
  .fcntl_h = handler_fcntl,
  .readv_h = handler_readv,
  .writev_h = handler_writev
};

static IMFS_jnode_t *node_initialize(
  IMFS_jnode_t *node,
  const IMFS_types_union *info
)
{
  test_state *state = NULL;

  node = IMFS_node_initialize_generic(node, info);
  state = IMFS_generic_get_context_by_node(node);

  rtems_test_assert(*state == TEST_NEW);
  *state = TEST_INITIALIZED;

  return node;
}

static IMFS_jnode_t *node_remove(IMFS_jnode_t *node)
{
  test_state *state = IMFS_generic_get_context_by_node(node);

  rtems_test_assert(*state == TEST_FSTAT_UNLINK);
  *state = TEST_REMOVED;

  return node;
}

static IMFS_jnode_t *node_destroy(IMFS_jnode_t *node)
{
  test_state *state = IMFS_generic_get_context_by_node(node);

  rtems_test_assert(*state == TEST_REMOVED);
  *state = TEST_DESTROYED;

  return node;
}

static const IMFS_node_control node_control = {
  .imfs_type = IMFS_GENERIC,
  .handlers = &node_handlers,
  .node_initialize = node_initialize,
  .node_remove = node_remove,
  .node_destroy = node_destroy
};

static void test_imfs_make_generic_node(void)
{
  test_state state = TEST_NEW;
  int rv = 0;
  int fd = 0;
  const char *path = "generic";
  char buf [1];
  ssize_t n = 0;
  off_t off = 0;
  struct iovec iov = {
    .iov_base = &buf [0],
    .iov_len = (int) sizeof(buf)
  };

  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    &state
  );
  rtems_test_assert(rv == 0);

  fd = open(path, O_RDWR);
  rtems_test_assert(fd >= 0);

  n = read(fd, buf, sizeof(buf));
  rtems_test_assert(n == 0);

  n = write(fd, buf, sizeof(buf));
  rtems_test_assert(n == 0);

  rv = ioctl(fd, 0);
  rtems_test_assert(rv == 0);

  off = lseek(fd, off, SEEK_SET);
  rtems_test_assert(off == 0);

  rv = ftruncate(fd, 0);
  rtems_test_assert(rv == 0);

  rv = fsync(fd);
  rtems_test_assert(rv == 0);

  rv = fdatasync(fd);
  rtems_test_assert(rv == 0);

  rv = fcntl(fd, F_GETFD);
  rtems_test_assert(rv >= 0);

  rv = readv(fd, &iov, 1);
  rtems_test_assert(rv == 0);

  rv = writev(fd, &iov, 1);
  rtems_test_assert(rv == 0);

  rv = close(fd);
  rtems_test_assert(rv == 0);

  rv = unlink(path);
  rtems_test_assert(rv == 0);

  rtems_test_assert(state == TEST_DESTROYED);
}

static IMFS_jnode_t *node_initialize_error(
  IMFS_jnode_t *node,
  const IMFS_types_union *info
)
{
  errno = EIO;

  return NULL;
}

static IMFS_jnode_t *node_remove_inhibited(IMFS_jnode_t *node)
{
  rtems_test_assert(false);

  return node;
}

static IMFS_jnode_t *node_destroy_inhibited(IMFS_jnode_t *node)
{
  rtems_test_assert(false);

  return node;
}

static const IMFS_node_control node_invalid_control = {
  .imfs_type = IMFS_DIRECTORY,
  .handlers = &node_handlers,
  .node_initialize = node_initialize_error,
  .node_remove = node_remove_inhibited,
  .node_destroy = node_destroy_inhibited
};

static const IMFS_node_control node_initialization_error_control = {
  .imfs_type = IMFS_GENERIC,
  .handlers = &node_handlers,
  .node_initialize = node_initialize_error,
  .node_remove = node_remove_inhibited,
  .node_destroy = node_destroy_inhibited
};

static void test_imfs_make_generic_node_errors(void)
{
  int rv = 0;
  const char *path = "generic";
  rtems_chain_control *chain = &rtems_filesystem_mount_table;
  rtems_filesystem_mount_table_entry_t *mt_entry =
    (rtems_filesystem_mount_table_entry_t *) rtems_chain_first(chain);
  const char *type = mt_entry->type;
  void *opaque = NULL;
  rtems_resource_snapshot before;

  rtems_resource_snapshot_take(&before);

  errno = 0;
  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_invalid_control,
    NULL
  );
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == EINVAL);
  rtems_test_assert(rtems_resource_snapshot_check(&before));

  errno = 0;
  rv = IMFS_make_generic_node(
    path,
    S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    NULL
  );
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == EINVAL);
  rtems_test_assert(rtems_resource_snapshot_check(&before));

  errno = 0;
  mt_entry->type = "XXX";
  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    NULL
  );
  mt_entry->type = type;
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == ENOTSUP);
  rtems_test_assert(rtems_resource_snapshot_check(&before));

  errno = 0;
  opaque = rtems_heap_greedy_allocate(NULL, 0);
  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    NULL
  );
  rtems_heap_greedy_free(opaque);
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == ENOMEM);
  rtems_test_assert(rtems_resource_snapshot_check(&before));

  errno = 0;
  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_initialization_error_control,
    NULL
  );
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == EIO);
  rtems_test_assert(rtems_resource_snapshot_check(&before));
}

static void Init(rtems_task_argument arg)
{
  TEST_BEGIN();

  test_imfs_make_generic_node();
  test_imfs_make_generic_node_errors();

  TEST_END();
  rtems_test_exit(0);
}

#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER

#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4

#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM

#define CONFIGURE_MAXIMUM_TASKS 1

#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_INIT

#include <rtems/confdefs.h>