/*
 * nasd_edrfs_test_functions.c
 *
 * Test the NASD EDRFS mount operation.
 *
 * Author: Mathew Monroe
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#include <nasd/nasd_options.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_error.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_pdrive_client.h>
#include <nasd/nasd_edrfs_client.h>
#include <nasd/nasd_edrfs_types.h>
#include <nasd/nasd_edrfs_types_marshall.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdio.h>
#include <stdlib.h>

#include "nasd_edrfs_test_common.h"
#include "nasd_edrfs_test.h"


/*
 * This looks really ugly, but since a majority of the test functions
 * are identical except for the type declariations, just use this
 * instead of retyping.  Remember ## does token concatination.
 */

#define TYPE(_T_, _U_) nasd_edrfs_ ## _T_ ## _ ## _U_ ## _t

#define DEF_TEST(_T_) nasd_status_t nasd_edrfs_test_ ## _T_ ## _test \
(nasd_edrfs_handle_t handle, void *args, void **res, \
 nasd_rpc_status_t *op_status){ \
				  TYPE(_T_, args) *a = \
				  (TYPE(_T_, args) *) args; \
 TYPE(_T_, res) *r;\
 NASD_Malloc(r, sizeof(TYPE(_T_, res)), (TYPE(_T_, res) *)); \
 *res = (void *) r; \
 nasd_edrfscli_ ## _T_ (handle, a, r, op_status); \
 return r->nasd_status; \
}

/*
 * The cleanup functions also are all almost identical.
 */

#define DEF_CLEANUP(_T_) nasd_status_t \
nasd_edrfs_test_ ## _T_ ## _cleanup \
(void *args, void *res){ \
	       NASD_ASSERT(args && res); \
 NASD_Free(args, sizeof(TYPE(_T_, args))); \
 NASD_Free(res, sizeof(TYPE(_T_, res))); \
 return NASD_SUCCESS; \
}

/*
 * A couple more common functions.
 */

#define SCAN_EDRFS_ID(_F_, _D_) sscanf(_F_, "0x%" NASD_ID_FMT ",%hx,%hx\n",\
	 &(_D_.nasd_identifier), &(_D_.disk_identifier), \
	 &(_D_.partnum));

#define PRINT_EDRFS_ID(_F_) printf("id 0x%" NASD_ID_FMT ",0x%hx,0x%hx\n", \
				 _F_.nasd_identifier, \
				 _F_.disk_identifier, \
				 _F_.partnum);

/*
 *
 * Null functions
 *
 */

nasd_status_t nasd_edrfs_test_null_test(nasd_edrfs_handle_t handle, void *args,
					void **res,
				      nasd_rpc_status_t *op_status){
  nasd_status_t rc;

  nasd_edrfscli_null(handle, &rc, op_status);
  return rc;
}

/*
 *
 * Mount functions
 *
 */

nasd_status_t nasd_edrfs_test_mount_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_mount_args_t *a;

  if (argc != 1)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);
  
  NASD_Malloc(a, sizeof(nasd_edrfs_mount_args_t),(nasd_edrfs_mount_args_t *));
  *args = (void *) a;

  strncpy(a->in_dirpath, argv[0], NASD_EDRFS_MAX_NAME_LEN);
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_mount_printres(void *res){
  nasd_edrfs_mount_res_t *r = (nasd_edrfs_mount_res_t *) res;
  struct in_addr net_addr;

  NASD_ASSERT(r);
  net_addr.s_addr = r->out_drivelist[0].network_address;
  
  printf("Drive is at %s:%d, partition %d\n", inet_ntoa(net_addr),
	 r->out_drivelist[0].port_number, r->out_drivelist[0].partnum);

  PRINT_EDRFS_ID(r->out_identifier)

  return NASD_SUCCESS;
}

DEF_TEST(mount)
DEF_CLEANUP(mount)


/*
 *
 * Fsstat functions
 *
 */

nasd_status_t nasd_edrfs_test_fsstat_marshall(int argc, char *argv[],
					      void **args){
  nasd_edrfs_fsstat_args_t *a;

  if (argc != 1)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_fsstat_args_t),
	      (nasd_edrfs_fsstat_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_identifier)

  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_fsstat_printres(void *res){
  nasd_edrfs_fsstat_res_t *r = (nasd_edrfs_fsstat_res_t *) res;

  NASD_ASSERT(r);
  printf("Bytes: Total %10u Free %10u User Free %10u\n",
	 r->out_stat.total_bytes, r->out_stat.free_bytes,
	 r->out_stat.user_free_bytes);
  printf("Files: Total %10u Free %10u User Free %10u\n",
	 r->out_stat.total_files, r->out_stat.free_files,
	 r->out_stat.user_free_files);
  printf("Invariant Seconds %u\n", r->out_stat.invariant_seconds);
  
  if(r->out_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->out_attribute.attribute);
  
  return NASD_SUCCESS;
}

DEF_TEST(fsstat)
DEF_CLEANUP(fsstat)


/*
 *
 * Fsinfo functions
 *
 */

nasd_status_t nasd_edrfs_test_fsinfo_marshall(int argc, char *argv[],
					      void **args){
  nasd_edrfs_fsinfo_args_t *a;

  if (argc != 1)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_fsinfo_args_t),
	      (nasd_edrfs_fsinfo_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_identifier)

  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_fsinfo_printres(void *res){
  nasd_edrfs_fsinfo_res_t *r = (nasd_edrfs_fsinfo_res_t *) res;

  NASD_ASSERT(r);
  printf("Read : Max %10u PrefSize %10u PrefMulti %10u\n",
	 r->out_info.max_read_size, r->out_info.preferred_read_size,
	 r->out_info.preferred_read_multiple);
  printf("Write: Max %10u PrefSize %10u PrefMulti %10u\n",
	 r->out_info.max_write_size, r->out_info.preferred_write_size,
	 r->out_info.preferred_write_multiple);
  printf("Misc : Pref ReadDir Size %10u Max File Size %10u\n",
	 r->out_info.preferred_readdir_size, r->out_info.max_file_size);
  printf("Misc : Properties %08X Time Delta %d:%09d\n",
	 r->out_info.fs_properties, r->out_info.time_delta.ts_sec,
	 r->out_info.time_delta.ts_nsec);

  if(r->out_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->out_attribute.attribute);

  return NASD_SUCCESS;
}

DEF_TEST(fsinfo)
DEF_CLEANUP(fsinfo)


/*
 *
 * Lookup functions
 *
 */

nasd_status_t nasd_edrfs_test_lookup_marshall(int argc, char *argv[],
					      void **args){
  nasd_edrfs_lookup_args_t *a;

  if (argc != 2)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_lookup_args_t),
	      (nasd_edrfs_lookup_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID (argv[0], a->in_identifier);

  strncpy(a->in_dirpath, argv[1], 512);
  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_lookup_printres(void *res){
  nasd_edrfs_lookup_res_t *r = (nasd_edrfs_lookup_res_t *) res;

  NASD_ASSERT(r);
  PRINT_EDRFS_ID(r->out_identifier)
    
  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);

  if(r->out_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->out_attribute.attribute);

  return NASD_SUCCESS;
}

DEF_TEST(lookup)
DEF_CLEANUP(lookup)


/*
 *
 * Readdir functions
 *
 */

nasd_status_t nasd_edrfs_test_readdir_marshall(int argc, char *argv[],
					       void **args){
  nasd_edrfs_readdir_args_t *a;

  if (argc != 4)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_readdir_args_t),
	      (nasd_edrfs_readdir_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID (argv[0], a->in_identifier);

  if (sscanf(argv[1], "%" NASD_64u_FMT, &(a->in_marker)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[2], "%" NASD_64u_FMT, &(a->in_markerv)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[3], "%d" , &(a->in_count)) != 1)
    return NASD_FAIL;
  
  return NASD_SUCCESS;
}

/*
 * Need to keep a bit of extra information around for this one.
 */

typedef struct nasd_edrfs_readdir_test_res_s {
  nasd_edrfs_readdir_res_t res;
  nasd_edrfs_dirent_t *ent;
} nasd_edrfs_readdir_test_res_t;

nasd_status_t nasd_edrfs_test_readdir_printres(void *res){
  nasd_edrfs_readdir_test_res_t *r = (nasd_edrfs_readdir_test_res_t *) res;
  int i,j;

  NASD_ASSERT(r);
  printf("Mark %" NASD_64u_FMT " MarkVerf %" NASD_64u_FMT
	 " Count %d EOF %d\n", r->res.out_marker, r->res.out_markerv,
	 r->res.out_count, (int) r->res.out_eof);

  for(i=0;i < r->res.out_count; i++){
    printf("DIRENT: Ino %" NASD_64u_FMT " Name \"", r->ent[i].nd_ino);
    for(j = 0; j  < r->ent[i].nd_namlen; j++)
      putchar(r->ent[i].nd_name[j]);
    printf("\"\n");
  }

  if(r->res.post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->res.post_attribute.attribute);

  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_readdir_test(nasd_edrfs_handle_t handle,
					 void *args, void **res,
					 nasd_rpc_status_t *op_status){
  TYPE(readdir, args) *a = (TYPE(readdir, args) *) args;
  nasd_edrfs_readdir_test_res_t *r;

  NASD_Malloc(r, sizeof(nasd_edrfs_readdir_test_res_t),
	      (nasd_edrfs_readdir_test_res_t *));
  NASD_Malloc(r->ent, sizeof(nasd_edrfs_dirent_t) * a->in_count,
	      (nasd_edrfs_dirent_t *));
  *res = (void *) r;

  nasd_edrfscli_readdir(handle, a, r->ent, &(r->res), op_status);
  return r->res.nasd_status;
}

nasd_status_t nasd_edrfs_test_readdir_cleanup(void *args, void *res){
  NASD_ASSERT(args && res);
  NASD_Free(args, sizeof(nasd_edrfs_readdir_args_t));
  NASD_Free(res, sizeof(nasd_edrfs_readdir_test_res_t));
  return NASD_SUCCESS;
}


/*
 *
 * Access functions
 *
 */

nasd_status_t nasd_edrfs_test_access_marshall(int argc, char *argv[],
					   void **args){
  nasd_edrfs_access_args_t *a;

  if (argc != 2)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_access_args_t),
	      (nasd_edrfs_access_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_identifier);

  if (sscanf(argv[1], "%d" , &(a->in_access)) != 1)
    return NASD_FAIL;
  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_access_printres(void *res){
  nasd_edrfs_access_res_t *r = (nasd_edrfs_access_res_t *) res;

  NASD_ASSERT(r);

  printf("Access %08X\n", r->out_access);

  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);

  return NASD_SUCCESS;
}

DEF_TEST(access)
DEF_CLEANUP(access)


/*
 *
 * Create functions
 *
 */

nasd_status_t nasd_edrfs_test_create_marshall(int argc, char *argv[],
					   void **args){
  nasd_edrfs_create_args_t *a;

  if (argc != 3)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_create_args_t),
	      (nasd_edrfs_create_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_directory);

  strncpy(a->in_dirpath, argv[1], 512);

  if (sscanf(argv[2], "%d" , &(a->in_fieldmask)) != 1)
    return NASD_FAIL;
  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_create_printres(void *res){
  nasd_edrfs_create_res_t *r = (nasd_edrfs_create_res_t *) res;

  NASD_ASSERT(r);
  PRINT_EDRFS_ID(r->out_identifier);

  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);
  
  nasd_edrfs_test_print_attribute(r->out_attribute);
  
  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);

  return NASD_SUCCESS;
}

DEF_TEST(create)
DEF_CLEANUP(create)


/*
 *
 * Setattr functions
 *
 */

nasd_status_t nasd_edrfs_test_setattr_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_setattr_args_t *a;
  nasd_edrfs_attributes_t edrfsattr;

  if (argc != 6)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_setattr_args_t),
	      (nasd_edrfs_setattr_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_identifier)

  if (sscanf(argv[1], "%d" , &(a->in_fieldmask)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[2], "%d" , &(edrfsattr.uid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[3], "%d" , &(edrfsattr.gid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[4], "%d" , &(edrfsattr.mode)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[5], "%" NASD_64u_FMT, &(a->in_attribute.object_len)) != 1)
    return NASD_FAIL;

  nasd_edrfs_attributes_t_marshall(&edrfsattr, (nasd_otw_base_t *)
				   a->in_attribute.fs_specific);
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_setattr_printres(void *res){
  nasd_edrfs_setattr_res_t *r = (nasd_edrfs_setattr_res_t *) res;

  NASD_ASSERT(r);

  nasd_edrfs_test_print_attribute(r->out_attribute);
  
  return NASD_SUCCESS;
}

DEF_TEST(setattr)
DEF_CLEANUP(setattr)


/*
 *
 * Symlink functions
 *
 */

nasd_status_t nasd_edrfs_test_symlink_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_symlink_args_t *a;
  nasd_edrfs_attributes_t edrfsattr;

  if (argc != 6)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_symlink_args_t),
	      (nasd_edrfs_symlink_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_directory)

  strncpy(a->in_dirpath, argv[1], sizeof(nasd_edrfs_name_t));
  strncpy(a->in_symlink, argv[1], sizeof(nasd_edrfs_name_t));

  if (sscanf(argv[3], "%d" , &(edrfsattr.uid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[4], "%d" , &(edrfsattr.gid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[5], "%d" , &(edrfsattr.mode)) != 1)
    return NASD_FAIL;

  nasd_edrfs_attributes_t_marshall(&edrfsattr, (nasd_otw_base_t *)
				   a->in_attribute.fs_specific);  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_symlink_printres(void *res){
  nasd_edrfs_symlink_res_t *r = (nasd_edrfs_symlink_res_t *) res;

  NASD_ASSERT(r);
  PRINT_EDRFS_ID(r->out_identifier)

  nasd_edrfs_test_print_attribute(r->out_attribute);

  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);
  
  return NASD_SUCCESS;
}

DEF_TEST(symlink)
DEF_CLEANUP(symlink)


/*
 *
 * Rename functions
 *
 */

nasd_status_t nasd_edrfs_test_rename_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_rename_args_t *a;

  if (argc != 4)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_rename_args_t),
	      (nasd_edrfs_rename_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_from_directory)

  SCAN_EDRFS_ID(argv[1], a->in_to_directory)

  strncpy(a->in_from_path, argv[2], sizeof(nasd_edrfs_name_t));
  strncpy(a->in_to_path, argv[3], sizeof(nasd_edrfs_name_t));
  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_rename_printres(void *res){
  nasd_edrfs_rename_res_t *r = (nasd_edrfs_rename_res_t *) res;

  NASD_ASSERT(r);

  if(r->post_from_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_from_attribute.attribute);
  
  if(r->post_to_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_to_attribute.attribute);
  
  return NASD_SUCCESS;
}

DEF_TEST(rename)
DEF_CLEANUP(rename)


/*
 *
 * Remove functions
 *
 */

nasd_status_t nasd_edrfs_test_remove_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_remove_args_t *a;

  if (argc != 2)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_remove_args_t),
	      (nasd_edrfs_remove_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_directory)

  strncpy(a->in_dirpath, argv[1], sizeof(nasd_edrfs_name_t));
  
  return NASD_SUCCESS;
}

DEF_TEST(remove)

nasd_status_t nasd_edrfs_test_remove_cleanup(void *args, void *res){
  NASD_ASSERT(args);
  NASD_Free(args, sizeof(nasd_edrfs_remove_args_t));
  return NASD_SUCCESS;
}


/*
 *
 * Mkdir functions
 *
 */

nasd_status_t nasd_edrfs_test_mkdir_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_mkdir_args_t *a;
  nasd_edrfs_attributes_t edrfsattr;

  if (argc != 6)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_mkdir_args_t),(nasd_edrfs_mkdir_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_directory);

  strncpy(a->in_dirpath, argv[1], sizeof(nasd_edrfs_name_t));

  if (sscanf(argv[2], "%d" , &(a->in_fieldmask)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[3], "%d" , &(edrfsattr.uid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[4], "%d" , &(edrfsattr.gid)) != 1)
    return NASD_FAIL;
  if (sscanf(argv[5], "%d" , &(edrfsattr.mode)) != 1)
    return NASD_FAIL;

  nasd_edrfs_attributes_t_marshall(&edrfsattr, (nasd_otw_base_t *)
				   a->in_attribute.fs_specific);  
  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_mkdir_printres(void *res){
  nasd_edrfs_mkdir_res_t *r = (nasd_edrfs_mkdir_res_t *) res;

  NASD_ASSERT(r);
  PRINT_EDRFS_ID(r->out_identifier)

  nasd_edrfs_test_print_attribute(r->out_attribute);

  if(r->post_attribute.valid == NASD_EDRFS_ATTRIBUTE_VALID)
    nasd_edrfs_test_print_attribute(r->post_attribute.attribute);
    
  return NASD_SUCCESS;
}

DEF_TEST(mkdir)
DEF_CLEANUP(mkdir)


/*
 *
 * Rmdir functions
 *
 */

nasd_status_t nasd_edrfs_test_rmdir_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_rmdir_args_t *a;

  if (argc != 2)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_rmdir_args_t),(nasd_edrfs_rmdir_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_directory)

  strncpy(a->in_dirpath, argv[1], sizeof(nasd_edrfs_name_t));
  
  return NASD_SUCCESS;
}

DEF_TEST(rmdir)

nasd_status_t nasd_edrfs_test_rmdir_cleanup(void *args, void *res){
  NASD_ASSERT(args);
  NASD_Free(args, sizeof(nasd_edrfs_rmdir_args_t));
  return NASD_SUCCESS;
}


/*
 *
 * Newcookie functions
 *
 */

nasd_status_t nasd_edrfs_test_newcookie_marshall(int argc, char *argv[],
					     void **args){
  nasd_edrfs_newcookie_args_t *a;

  if (argc != 1)
    return NASD_FAIL;
  NASD_ASSERT(argv[0]);

  NASD_Malloc(a, sizeof(nasd_edrfs_newcookie_args_t),
	      (nasd_edrfs_newcookie_args_t *));
  *args = (void *) a;

  SCAN_EDRFS_ID(argv[0], a->in_identifier)

  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_newcookie_printres(void *res){
  nasd_edrfs_newcookie_res_t *r = (nasd_edrfs_newcookie_res_t *) res;
  char *cookie_str;

  NASD_ASSERT(r);
  nasd_edrfs_test_encode(&cookie_str, (nasd_byte *) &r->out_cookie,
		       sizeof(nasd_cookie_t));
  printf("COOKIE: %s\n", cookie_str);
    
  NASD_Free(cookie_str, nasd_edrfs_test_encode_len(sizeof(nasd_cookie_t)));
  
  return NASD_SUCCESS;
}

DEF_TEST(newcookie)
DEF_CLEANUP(newcookie)


/*
 *
 * Getstats functions
 *
 */

#define PRINT_OP(_D_) printf("%-16s%10" NASD_64u_FMT "\t%10" \
			     NASD_64u_FMT "\t%10" NASD_64u_FMT "\t%10" \
			     NASD_64u_FMT "\n", \
			     NASD_STRING(_D_), \
			     op->_D_.num_ops, \
			     op->_D_.op_nsecs, \
			     op->_D_.invalid, \
			     op->_D_.in_flight);

#define PRINT_CACHE(_A_, _B_, _C_) printf("%-22s%3" NASD_64u_FMT \
					  " %-22s%3" NASD_64u_FMT \
					  " %-22s%3" NASD_64u_FMT "\n", \
					  NASD_STRING(_A_), cache->_A_, \
					  NASD_STRING(_B_), cache->_B_, \
					  NASD_STRING(_C_), cache->_C_); 

nasd_status_t nasd_edrfs_test_getstats_printres(void *res){
  nasd_edrfs_getstats_res_t *r = (nasd_edrfs_getstats_res_t *) res;
  nasd_edrfs_opstats_t *op;
  nasd_edrfs_cachestats_t *cache;

  NASD_ASSERT(r);
  op = &(r->out_opstats);
  cache = &(r->out_cachestats);

  printf("Function\t    Number\t      Nsec\t   Invalid\t In Flight\n");  
  PRINT_OP(null)
  PRINT_OP(mount)
  PRINT_OP(fsstat)
  PRINT_OP(fsinfo)
  PRINT_OP(lookup)
  PRINT_OP(readdir)
  PRINT_OP(access)
  PRINT_OP(setattr)
  PRINT_OP(create)
  PRINT_OP(remove)
  PRINT_OP(mkdir)
  PRINT_OP(rmdir)
  PRINT_OP(newcookie)
  PRINT_OP(rename)
  PRINT_OP(symlink)
  PRINT_OP(readlink)
  PRINT_OP(getstats)
  
  printf("\nCACHE COUNTS\n");
  PRINT_CACHE(dir_lookup, dir_force, dirc_load_attr)
  PRINT_CACHE(dirc_not_dir, dirc_load_dir, dirc_dirty)
  PRINT_CACHE(dirc_new_dirty, dirc_mkfree_loop, dirc_mkfree_wait)
  PRINT_CACHE(dir_load, dir_get, dir_reget)
  PRINT_CACHE(dir_replace, dir_writer_fls, dir_writer_pages)
  PRINT_CACHE(dir_load_attr, do_getattr, do_setattr)
  PRINT_CACHE(post_attribute, post_attribute_valid, post_attribute_invalid)
  PRINT_CACHE(lookup_post_attribute, access_lookup_fail, access_not_dir)
  PRINT_CACHE(access_fault_attr, access_get_attr, lookup_get_attr)
  printf("%-22s%3" NASD_64u_FMT "\n",
	 "setattr_get_attr", cache->setattr_get_attr);

  printf("\nDrive Time %d:%09d\n", cache->drive_time.ts_sec,
	 cache->drive_time.ts_nsec);

  return NASD_SUCCESS;
}

nasd_status_t nasd_edrfs_test_getstats_test(nasd_edrfs_handle_t handle,
					  void *args, void **res,
					  nasd_rpc_status_t *op_status){
  TYPE(getstats, res) *r;
  NASD_Malloc(r, sizeof(TYPE(getstats, res)), (TYPE(getstats, res) *));
  *res = (void *) r;
  nasd_edrfscli_getstats(handle, r, op_status);
  return r->nasd_status;
}

nasd_status_t nasd_edrfs_test_getstats_cleanup(void *args, void *res){
  NASD_ASSERT(res);
  NASD_Free(res, sizeof(nasd_edrfs_rmdir_res_t));
  return NASD_SUCCESS;
}

