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

                        
                 





                                                          
                                        









                      
                    





                         
                              
 

                                                 


                   

                    








                 

              





                    








                                                           
                                                 










                                                           
                                           


































                                                           
                          

































                                                                



                                 




                                 
                           


            


                                                       



















































                                                           





























                                                           










                                                               


                            



                                     
           



                           
                                                 







                                                 
                                                    








                                                             
                                            





                                                             
                                  


                                               







                                             
                              





                               



                                




                                          
          





























                                  





                             





                             
                                             

 

                                           
           













                                                              
                                                      

                           

 
                                                                    



                                           

  






                                                             






                                                                      
                                              
                      


                                        



                              





                                          
                                                            
 
            



                                     





                                          
                           

                                      
                                                            
 
            
                                               





                                          
                                 

                                     











                                                            










                                                            



                                         
               



                                       
             



                                                
                                                         


                                                  

                                 

                                                                 




                                        
/*
 * Copyright (c) 2012-2014 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Dornierstr. 4
 *  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_0,
  TEST_FSTAT_OPEN_1,
  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_1);
  *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,
  ioctl_command_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_0;
      break;
    case TEST_FSTAT_OPEN_0:
      *state = TEST_FSTAT_OPEN_1;
      break;
    case TEST_CLOSED:
      *state = TEST_FSTAT_UNLINK;
      break;
    default:
      rtems_test_assert(0);
      break;
  }

  buf->st_mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;

  return 0;
}

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,
  void *arg
)
{
  test_state *state = NULL;

  node = IMFS_node_initialize_generic(node, arg);
  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 void 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;

  IMFS_node_destroy_default(node);
}

static const IMFS_node_control node_control = {
  .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,
  void *arg
)
{
  errno = EIO;

  return NULL;
}

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

  return node;
}

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

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

static const rtems_filesystem_operations_table *imfs_ops;

static int other_clone(rtems_filesystem_location_info_t *loc)
{
  return (*imfs_ops->clonenod_h)(loc);
}

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);
  rtems_filesystem_operations_table other_ops;
  void *opaque = NULL;
  rtems_resource_snapshot before;

  rtems_resource_snapshot_take(&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;
  imfs_ops = mt_entry->ops;
  other_ops = *imfs_ops;
  other_ops.clonenod_h = other_clone;
  mt_entry->ops = &other_ops;
  rv = IMFS_make_generic_node(
    path,
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    NULL
  );
  mt_entry->ops = imfs_ops;
  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));

  errno = 0;
  rv = IMFS_make_generic_node(
    "/nil/nada",
    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
    &node_control,
    NULL
  );
  rtems_test_assert(rv == -1);
  rtems_test_assert(errno == ENOENT);
  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_SIMPLE_CONSOLE_DRIVER

#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4

#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>