Logo Search packages:      
Sourcecode: lfc version File versions  Download package

srm_testJiri.c

/*
 * SRM test suite, written by Jiri Kosina <kosina@fzu.cz>, based on work done 
 * by Jean-Phillipe Baud <Jean-Philippe.Baud@cern.ch>
 * Migrated to gsoap_2.6 by GG
 *
 * TODO (among others):
 * - let user choose between rfio, gsiftp & dcap
 *
 */

// $Id: srm_testJiri.c,v 1.8 2005/11/14 11:30:21 grodid Exp $

#define VERSION "0.3.4_multiple_gsoap_2.6"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "srmv1H.h"
#include "ISRM.nsmap"

#define DEFPOLLINT 10
#define SRM_EP_PATH "/srm/managerv1"

#define PINNED 0
#define UNPINNED 1

#define METHOD_RFIO 1
#define METHOD_GSIFTP 2
#define METHOD_DCAP 3

#ifdef GFAL_SECURE
#include "cgsi_plugin.h"
#endif

#ifdef DMALLOC
#include "dmalloc.h"
#endif

/* debugging output */
#define DEBUG
#ifdef DEBUG
#define PRINTF(format, args...) printf (format, ## args); fflush(stdout)
#else
#define PRINTF(format, args...)
#endif 

/* taken from gfal_api.h */
struct srm_filestatus {
        char    *surl;
        char    *turl;
        int     fileid;
        int     status;
};

/* forward declaration */
struct ns1__FileMetaData **request_get_file_metadata(char **argv, int i);

char testfilename1[1024], testfilename2[1024]; /* ugly */
char current_command[1024]; /* ugly, should be replaced by union */
struct soap soap;

volatile int segfault = 0;
sigjmp_buf env;
int saved_sigs;

int flags;
int reqid;
int nbproto;
int somebug = 0; /* this is global variable which indicates if there was
                any problem during the whoel run of test suite - in other
                words, if everything passed or not */
int transfer_method = 0;
int SURL_was_not_set = 0;

/* SIGSEGV handler used to detect SRM server returning junk */
void segv(int dummy)
{
      segfault = 1;
      siglongjmp(env, 1);     
}

/* check if returned metadata about file corresponds to local file */
int check_metadata_consistency (struct ns1__FileMetaData **p, char *fname, int pin)
{
      struct stat buf;
      int ret;

      printf("stating %s\n", fname);
      ret = stat(fname, &buf);
      if (ret == -1){
            PRINTF("[!] \tstrange, local stat() failed\n");
            perror("stat");
            somebug = 1;
            return 1;
            
      }

      if (buf.st_size != (*p)->size){
            PRINTF("[!]\tsize of localfile (%d) differs from what SRM reports (%d), FAILED\n",
                        buf.st_size, (*p)->size);
            somebug = 1;
      }
      else
            PRINTF("[+]\tsizes of local file and SRM reported size match\n");
      
      if (buf.st_mode != (*p)->permMode){
            PRINTF("[?]\tmode of localfile (%o) differs from what SRM reports (%o)\n", 
                        buf.st_mode, (*p)->permMode);
      }
      else
            PRINTF("[+]\tmode of local file and SRM reported size match (%o)\n", 
                        buf.st_mode);

      if (pin == PINNED && (*p)->isPinned == true_){
            PRINTF("[+]\tfile is correctly pinned\n");
      } else if (pin == PINNED && (*p)->isPinned == false_){
            PRINTF("[?]\tfile is not pinned, but should be\n");
/*          somebug = 1;*/
      }

      if (pin == UNPINNED && (*p)->isPinned == false_) {
            PRINTF("[+]\tfile is correctly unpinned\n");
      } else if (pin == UNPINNED && (*p)->isPinned == true_) {
            PRINTF("[?]\tfile is pinned, but should be unpinned\n");
/*          somebug = 1;*/
      }

      return 0;
}


/* this routine checks if all fields of requestFileStatus are set 
 * with compilance of "standard"
 *
 * More checks could be added (StartTime > SubmitTime, etc)
 *
 * Maybe dumping the whole structure at error would be nice
 */
int check_request_file_status_consistency(struct ns1__RequestStatus *p, 
            char *invoking_method, char **argv)
{
/* FIXME */
#define CHKPRINTF PRINTF
      
  //OLDBADstruct ns1__RequestFileStatus *status;
  struct ns1__RequestFileStatus **status;
      int i;

      /* FIXME FIXME FIXME DEBUG */
      
      if (!p) {
            CHKPRINTF("[!]\t\trequest status is NULL, FAILED\n");
            somebug = 1;
      }
      else CHKPRINTF("[+]\t\trequest status check not-NULL, passed\n");
      
      if (strcasecmp(p->type, invoking_method) != 0){
            CHKPRINTF("[!]\t\trequest %s and returned type %s do not match, FAILED\n",
                        invoking_method, p->type);
            somebug = 1;
      }
      else CHKPRINTF("[+]\t\trequest and returned type match, passed\n");
      
      if (!p->fileStatuses){
            CHKPRINTF("[!]\t\tGot no filestatuses, FAILED\n");
            errno = EPROTONOSUPPORT;
            perror ("put");
            soap_end (&soap);
            somebug = 1;
            return -1;
      }


      if (p->fileStatuses->__size != 2){
            CHKPRINTF("[!]\t\trequest status contains %d file(s), WRONG", 
                  p->fileStatuses->__size);
            somebug = 1;
      } else {
            CHKPRINTF("[+]\t\trequest status contains %d file(s), passed\n",
                  p->fileStatuses->__size);
      }

      
      status = p->fileStatuses->__ptr;
      for (i=0; i < p->fileStatuses->__size; i++){

            signal(SIGSEGV, segv);
            if (sigsetjmp(env, saved_sigs) != 0){
                  CHKPRINTF("\t\tFATAL: SRM server returned junk SURL in second fileStatus.\n");
                  somebug = 1;
                  exit (1);                     
            }

            //OLDBADif (!status[i].SURL) {
            if (!status[i]->SURL) {
                  CHKPRINTF("[!]\t\t%d: surl not set\n", i);
                  somebug = 1;
            } 
            else 
                  if (!strcasecmp(status[i]->SURL, argv[i+2])){ 
                              CHKPRINTF("[+]\t\t%d: surl (%s) check passed\n", i, status[i]->SURL);
                  }
                  else {
                        CHKPRINTF("[!]\t\t%d: surl (%s, %s) check mismatch! FAILED\n", i, status[i]->SURL, argv[i+2]);
                        somebug = 1;
                  }     

            signal(SIGSEGV, SIG_DFL);
            
            if (status[i]->size <  0) {
                  CHKPRINTF("[!]\t\t%dsize < 0, this shouldn't happen, FAILED\n", i); 
                  somebug = 1;
            } 
            else CHKPRINTF("[+]\t\t%d: size (%d) check passed\n", i, status[i]->size);

            if (!status[i]->state || (strcasecmp(status[i]->state, "Pending") && 
                        strcasecmp(status[i]->state, "Running") &&
                        strcasecmp(status[i]->state, "Ready") &&
                        strcasecmp(status[i]->state, "Failed") &&
                        strcasecmp(status[i]->state, "Done"))){
                  CHKPRINTF("[!]\t\t%d: state (%s) check FAILED\n", i, status[i]->state);
                  somebug = 1;
            }
            else CHKPRINTF("[+]\t\t%d: state (%s) check passed\n", i, status[i]->state);

            /*
            if (status[i]->fileId < 0){
                  CHKPRINTF("[!]\t\t%d: fileId < 0, this shouldn't happen, check FAILED\n", i);
                  somebug = 1;
            }
            else CHKPRINTF("[+]\t\t%d: fileId (%d) check passed\n", i, status[i]->fileId);
            */
            CHKPRINTF("[+]\t\t%d: fileId (%d) check disabled\n", i, status[i]->fileId);

            if ((!strcasecmp(status[i]->state, "Ready") || 
                  !strcasecmp(status[i]->state, "Done")) && 
                  !status[i]->TURL){
                  CHKPRINTF("[!]\t\t%d: TURL shouldn't be NULL at this moment, FAILED\n", i);
                  somebug = 1;
            }

      }
      return 0;
}

/* just ping the SRM server */
int request_ping(char **argv)
{
      struct ns5__pingResponse out;
      struct ArrayOfstring surlarray;     
      char *srm_endpoint, *sfn;
      struct ns1__FileMetaData *p;
      
        if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
                perror ("parsesurl");
            somebug = 1;
            return 0;
        }

      surlarray.__ptr = &argv[2]; 
        surlarray.__size = 1; 
        //surlarray.__offset = 0;

        if (soap_call_ns5__ping (&soap, srm_endpoint, "Ping", &out)) {
                soap_print_fault (&soap, stderr);
              soap_print_fault_location (&soap, stderr);
            somebug = 1;
      }
        if (out._Result){
                PRINTF ("[+]\tSRM server is alive\n");
      }
        else {
                PRINTF ("[!]\tSRM server is not responding\n");
            somebug = 1;
            return 1;
      }
      return 0;
}

/* make the file pinned (in use) on SRM server */
int request_pin(char **argv)
{
      struct ns5__pinResponse out;
      struct ArrayOfstring surlarray;     
      char *srm_endpoint, *sfn;
      struct ns1__FileMetaData *p;
      
      // Missing same cross-check for argv[3] ?
        if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
                perror ("parsesurl");
            somebug = 1;
            return 1;
        }

      surlarray.__ptr = (char **)argv+2; 
        surlarray.__size = 2; 
        //surlarray.__offset = 0;   

        if (soap_call_ns5__pin (&soap, srm_endpoint, "Pin", &surlarray, &out)) {
                soap_print_fault (&soap, stderr);
              soap_print_fault_location (&soap, stderr);
            somebug = 1;
      }
      /* here the out._Result->fileStatuses == NULL :/ */   
/*    if (out._Result->fileStatuses == NULL){
            printf("[!]\tfileStatuses pointer is bogus after Pin command. reporting as a bug (is this OK?)\n");
            somebug = 1;
      }
*/
      return 0;
}

/* advisoryDelete both files on the SRM server */

int request_advisoryDelete (char **argv, int i)
{
      int flags;
      struct ns5__advisoryDeleteResponse out;
      char *sfn;
      struct soap soap;
      char *srm_endpoint;
      struct ArrayOfstring surlarray;

      if (parsesurl (argv[2+i], &srm_endpoint, &sfn) < 0) {
            perror ("parsesurl");
            exit (1);
      }

      soap_init (&soap);
#ifdef GFAL_SECURE
      flags = CGSI_OPT_DISABLE_NAME_CHECK;
      soap_register_plugin_arg (&soap, client_cgsi_plugin, &flags);
#endif

      /* issue "advisoryDelete" request */

      surlarray.__ptr = &argv[2+i];
      surlarray.__size = 2;
      surlarray.__size = 1;  //  1st try ...

      if (soap_call_ns5__advisoryDelete (&soap, srm_endpoint,
          "advisoryDelete", &surlarray, &out)) {
            soap_print_fault (&soap, stderr);
            soap_end (&soap);
            return (1);
      }
      soap_end (&soap);
      return (0);
}


/* make the file unpin (not in use) on SRM server */
int request_unpin(char **argv, int reqid)
{
      struct ns5__unPinResponse out;
      struct ArrayOfstring surlarray;     
      char *srm_endpoint, *sfn;
      struct ns1__FileMetaData *p;
      
      // Missing same cross-check for argv[3] ?
        if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
                perror ("parsesurl");
            somebug = 1;
            return 0;
        }

      //Jiri's Bug ?    surlarray.__ptr = (char **)argv; 
      surlarray.__ptr = (char **)argv+2; 
        surlarray.__size = 2; 
        //surlarray.__offset = 0;   

        if (soap_call_ns5__unPin (&soap, srm_endpoint, "UnPin", &surlarray, reqid, 
                        &out)) {
                soap_print_fault (&soap, stderr);
              soap_print_fault_location (&soap, stderr);
            somebug = 1;
      }
      /* here ... se above */
}

/* I made the following macros and not functions because of
 * argument madness :)
 */

/* initialize structures for getFileMetaData and send to SRM server */
#define init_get_file_metadata_request() \
        surlarray.__ptr = (char **)argv+2; \
        surlarray.__size = 2; \
      \
        if (soap_call_ns5__getFileMetaData (&soap, srm_endpoint,  \
            "getFileMetaData", &surlarray, &out)) {   \
                soap_print_fault (&soap, stderr);     \
            somebug = 1; \
        }   


/* initialize structures for GET request and send to SRM server */
#define init_get_request() \
      while (*protocols[nbproto]) nbproto++;    \
      \
      surlarray = (struct ArrayOfstring *) malloc(sizeof(struct ArrayOfstring));\
      surlarray->__ptr = (char **)argv+2; \
      \
      surlarray->__size = 2;        \
      \
      protoarray.__ptr = protocols; \
      protoarray.__size = nbproto;  \
      \
      if (soap_call_ns5__get (&soap, srm_endpoint, "Get", surlarray,    \
          &protoarray, &out)) {     \
            soap_print_fault (&soap, stderr);   \
            soap_print_fault_location (&soap, stderr);      \
            somebug = 1; \
            return -1;  \
      }     \
      \
      reqstatp = out._Result; \
      /* FIXME will be duplicit after writing checks */\
      if (reqstatp->fileStatuses == NULL) {     \
            errno = EPROTONOSUPPORT;      \
            perror ("get");   \
            somebug = 1;      \
            return -1;  \
      }     \
      reqid = reqstatp->requestId;  

/* initialize structures for PUT request and send to SRM server */
#define init_put_request() \
      while (*protocols[nbproto]) nbproto++; \
      \
      surlarray = (struct ArrayOfstring *) malloc(sizeof(struct ArrayOfstring));\
      \
      srcarray = (struct ArrayOfstring *) malloc(sizeof(struct ArrayOfstring));\
      \
      sizearray = (struct ArrayOflong *) malloc(sizeof(struct ArrayOflong));\
      \
      permarray = (struct ArrayOfboolean *) malloc(sizeof(struct ArrayOfboolean));\
      \
      srcarray->__ptr = (char **)argv+2;  \
      srcarray->__size = 2;         \
      \
      surlarray->__size = 2;        \
      surlarray->__ptr = (char **)argv+2; \
      \
        /* dummy */  \
        size_tmp_arr[0] = 1;  \
        size_tmp_arr[1] = 1;  \
      sizearray->__size = 2;        \
      sizearray->__ptr = &size_tmp_arr[0];            \
         \
        /* dummy */     \
        perm_tmp_arr[0] = 1;  \
        perm_tmp_arr[1] = 1;  \
      permarray->__size = 2;        \
      permarray->__ptr = &perm_tmp_arr[0];      \
      \
      protoarray.__ptr = protocols; \
      protoarray.__size = nbproto;  \
      \
                      \
      /* send PUT command to SRM */ \
      PRINTF("[+]\tSending Put to SRM server\n");     \
      if (soap_call_ns5__put (&soap, srm_endpoint, "Put", srcarray,     \
          surlarray, sizearray, permarray, &protoarray, &out)) {  \
            soap_print_fault (&soap, stderr);   \
            soap_print_fault_location (&soap, stderr);      \
            somebug = 1; \
            return 1;   \
            }     \
      \
      reqstatp = out._Result; \
        if (reqstatp->errorMessage) \
                      printf ("errorMessage: %s\n", reqstatp->errorMessage);  \
      \
      fflush (stdout);\
      fflush (stderr);\
      /* FIXME will be duplicit after writing checks */\
      if (reqstatp->fileStatuses == NULL) {     \
            errno = EPROTONOSUPPORT;      \
            perror ("put");   \
            somebug = 1; \
            return 1;   \
      }     \
      reqid = reqstatp->requestId;

/* this macro loops, polling SRM server, while the status of the
 * request is "pending". 
 * TODO add some timeouting, this could loop forever
 */
//                !strcasecmp(reqstatp->state, "active") || 
#if OLD
#define loop_while_pending()  \
        PRINTF ("[GG0]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state); \
        PRINTF ("[GG0]\tsoap_call_ns5__put returned reqstatp->fileStatuses->__ptr->state: %s\n", \
                 reqstatp->fileStatuses->__ptr->state); \
        while ((strcmp(reqstatp->state, "pending") == 0 ||  \
                strcmp(reqstatp->state, "Pending") == 0) || \
               (strcmp(reqstatp->fileStatuses->__ptr->state, "pending") == 0  \
                || strcmp(reqstatp->fileStatuses->__ptr->state,   \
                          "Pending") == 0)) {   \
                sleep((r++ == 0) ? 1 : (reqstatp->retryDeltaTime > 0) ? \
                      reqstatp->retryDeltaTime : DEFPOLLINT);     \
                if (soap_call_ns5__getRequestStatus(&soap, srm_endpoint,      \
                                                    "getRequestStatus", \
                                                    reqid, &outq)) {    \
                        soap_print_fault(&soap, stderr);    \
                        soap_end(&soap);  \
                        exit(1);    \
                } \
                reqstatp = outq._Result;  \
        PRINTF ("[GGw]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state); \
        PRINTF ("[GGw]\tsoap_call_ns5__put returned reqstatp->fileStatuses->__ptr->state: %s\n", \
                 reqstatp->fileStatuses->__ptr->state); \
        }   \
        if (reqstatp->errorMessage) \
                printf("errorMessage: %s\n", reqstatp->errorMessage);   \
        if (strcmp(reqstatp->fileStatuses->__ptr->state, "ready") &&    \
            strcmp(reqstatp->fileStatuses->__ptr->state, "Ready")) {    \
                printf("state = %s\n",    \
                       reqstatp->fileStatuses->__ptr->state);     \
            somebug = 1; \
            return 1; \
        }   \
      \

#endif
//        while ( ! strcasecmp(reqstatp->state, "pending") ) {    

#if GG 
                ( strcasecmp(reqstatp->state, "Done") && \
                  strcasecmp(reqstatp->state, "Failed") ) ) {     \

#endif

#define loop_while_pending()  \
        PRINTF ("[GG0]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state); \
        while ( ! reqstatp->state || \
\
                ( strcasecmp(reqstatp->state, "pending" ) == 0 ) && \
              (strcasecmp(reqstatp->fileStatuses->__ptr[0]->state, "pending") == 0  \
                || strcasecmp(reqstatp->fileStatuses->__ptr[1]->state, "pending") == 0 ) ) {    \
\
                sleep((r++ == 0) ? 1 : (reqstatp->retryDeltaTime > 0) ? \
                      reqstatp->retryDeltaTime : DEFPOLLINT);     \
                if (soap_call_ns5__getRequestStatus(&soap, srm_endpoint,      \
                                                    "getRequestStatus", \
                                                    reqid, &outq)) {    \
                        soap_print_fault(&soap, stderr);    \
                        soap_end(&soap);  \
                        exit(1);    \
                } \
                reqstatp = outq._Result;  \
        PRINTF ("[GGw]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state); \
        }   \
        if (reqstatp->errorMessage) \
                printf("errorMessage: %s\n", reqstatp->errorMessage);   \
        if ( ( strcasecmp(reqstatp->fileStatuses->__ptr[0]->state, "ready") ||      \
               strcasecmp(reqstatp->fileStatuses->__ptr[1]->state, "ready") ) ) {   \
                printf("[?]\tstates = %s %s\n", \
                       reqstatp->fileStatuses->__ptr[0]->state,   \
                       reqstatp->fileStatuses->__ptr[1]->state);  \
            somebug = 1; \
            return 1; \
        }   \
      \
        /* now the request status is ready, let's proceed */      \
        n = reqstatp->fileStatuses->__size;     \
        filestatuses = malloc (n * sizeof(struct srm_filestatus));      \
        //f = reqstatp->fileStatuses->__ptr;    \
        f = (*reqstatp->fileStatuses->__ptr);   \
        fs = filestatuses;    \
        for (i = 0; i < n; i++) {   \
                if ((f+i)->SURL && (fs->surl = strdup ((f+i)->SURL)) == NULL) \
                        somebug = 1;      \
                if ((f+i)->state) { \
                        if (strcmp ((f+i)->state, "Pending") == 0 ||    \
                            strcmp ((f+i)->state, "pending") == 0)      \
                                fs->status = 0; \
                        else if (strcmp ((f+i)->state, "Failed") == 0 ||      \
                            strcmp ((f+i)->state, "failed") == 0) \
                                fs->status = -1;      \
                        else  \
                                fs->status = 1; \
                } \
                fs->fileid = (f+i)->fileId;     \
                if ((f+i)->TURL && (fs->turl = strdup ((f+i)->TURL)) == NULL) \
                        somebug = 1;      \
                fs++;   \
        }   \
      \
      PRINTF("[+]\tCalling check_request_file_status_consistency()\n"); \
      check_request_file_status_consistency(reqstatp, current_command, argv);

/* macros used to set file status */ /* GG on SRM server ? */
#define set_file_status(status)     \
      PRINTF("[+]\t\tCalled set_file_status() with %s (fileId %d)\n", status, p->__ptr[i]->fileId); \
      if (soap_call_ns5__setFileStatus (&soap, srm_endpoint, "setFileStatus", \
                        reqid, p->__ptr[i]->fileId, \
                        status, &outs)){  \
            soap_print_fault (&soap, stderr);   \
            somebug = 1;      \
            return 1;   \
      \
      }\
      \
      memset (&outq, 0, sizeof(struct ns5__getRequestStatusResponse));\
        if (soap_call_ns5__getRequestStatus (&soap, srm_endpoint, \
                            "getRequestStatus", reqid, &outq)) { \
            soap_print_fault (&soap, stderr); \
            somebug = 1; \
                return 1; \
      } \
        reqstatp = outq._Result; \
      PRINTF("[+]\tCalling check_request_file_status_consistency()\n");\
        check_request_file_status_consistency(reqstatp, current_command, argv);\
      if (strcasecmp(reqstatp->fileStatuses->__ptr[i]->state, status)){\
            PRINTF("[!]\t\tReturned state %s differs from %s (which was set)\n", \
                  reqstatp->fileStatuses->__ptr[i]->state, status);\
            somebug = 1;\
      }

int parsesurl (const char *surl, char **endpoint, char **sfn)
{
      int len;
      int lenp;
      char *p;
      static char srm_ep[1024];

      if (strncmp (surl, "srm://", 6)) {
            errno = EINVAL;
            return (-1);
      }
      if (p = strstr (surl + 6, "?SFN=")) {
            *sfn = p + 5;
      } else if (p = strchr (surl + 6, '/')) {
            *sfn = p;
      } else {
            errno = EINVAL;
            somebug = 1;
            return (-1);
      }
#ifdef GFAL_SECURE
      strcpy (srm_ep, "https://");
      lenp = 8;
#else
      strcpy (srm_ep, "http://");
      lenp = 7;
#endif
      len = p - surl - 6;
      if (lenp + len >= sizeof(srm_ep)) {
            errno = EINVAL;
            return (-1);
      }
      strncpy (srm_ep + lenp, surl + 6, len);
      *(srm_ep + lenp + len) = '\0';
      if (strchr (srm_ep + lenp, '/') == NULL) {
            if (strlen (SRM_EP_PATH) + lenp + len >= sizeof(srm_ep)) {
                  errno = EINVAL;
                  somebug = 1;
                  return (-1);
            }
            strcat (srm_ep, SRM_EP_PATH);
      }
      
      *endpoint = srm_ep;
      return (0);
}
int gsiftp_copy_out(char *src, char *dest)
{
      char command[1024];
      int ret;
      
      //sprintf(command, "./my_gsiftp_out.sh %s %s\n", src,
      sprintf(command, "my_gsiftp_out.sh %s %s\n", src,
            dest);
      PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
      if (ret != 0){
            PRINTF("[!]\tgsiftp copy failed!!");
            somebug = 1;
            return 1;
      }
      return 0;
}

int gsiftp_copy_in(char *src, char *dest)
{
      char command[1024];
      int ret;
      
      //sprintf(command, "./my_gsiftp_in.sh %s %s\n", src,
      sprintf(command, "my_gsiftp_in.sh %s %s\n", src,
            dest);
      PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
      if (ret != 0){
            PRINTF("[!]\tgsiftp copy failed!!");
            somebug = 1;
            return 1;
      }
      return 0;
}

int rfio_copy_out(char *src, char *dest)
{
        char command[512];
        int ret;

        //sprintf(command, "./my_rfcp_out.sh %s %s\n", src,
        sprintf(command, "my_rfcp_out.sh %s %s\n", src,
                dest);
        PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
        if (ret != 0){
                PRINTF("[!]\trfio copy failed!!");
                somebug = 1;
                return 1;
        }
        return 0;
}

int rfio_copy_in(char *src, char *dest)
{
        char command[512];
        int ret;

        //sprintf(command, "./my_rfcp_in.sh %s %s\n", src,
        sprintf(command, "my_rfcp_in.sh %s %s\n", src,
                dest);
        PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
        if (ret != 0){
                PRINTF("[!]\trfio copy failed!!");
                somebug = 1;
                return 1;
        }
        return 0;
}

int dcap_copy_out(char *src, char *dest)
{
        char command[512];
        int ret;

        //sprintf(command, "./my_dccp_out.sh %s %s\n", src,
        sprintf(command, "my_dccp_out.sh %s %s\n", src,
                dest);
        PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
        if (ret != 0){
                PRINTF("[!]\tdcap copy failed!!");
                somebug = 1;
                return 1;
        }
        return 0;
}

int dcap_copy_in(char *src, char *dest)
{
        char command[512];
        int ret;

        //sprintf(command, "./my_dccp_in.sh %s %s\n", src,
        sprintf(command, "my_dccp_in.sh %s %s\n", src,
                dest);
        PRINTF("%s\n", command);
      ret = system(command);
      ret = WEXITSTATUS(ret);
        if (ret != 0){
                PRINTF("[!]\tdcap copy failed!!");
                somebug = 1;
                return 1;
        }
        return 0;
}


/* this handles communication with SRM server in case of 
 * getFileMetaData request
 *
 * the second parameter indicates which file (in case of multiple files
 * per request) is caller interested into
 */
 /* returns pointer to received structure, caller should check
 * the values against uploaded file
 */
struct ns1__FileMetaData **request_get_file_metadata(char **argv, int i)
{
      /* we need the structure static, because caller wants to access it */
        static struct ns5__getFileMetaDataResponse out;
      struct ArrayOfstring surlarray;
      char *srm_endpoint, *sfn;
      struct ns1__FileMetaData **p;
      
      // Missing same cross-check for argv[3] ?
        if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
                perror ("parsesurl");
            somebug = 1;
            return NULL;
        }
      
      init_get_file_metadata_request();

      p = out._Result->__ptr;
      
      /* FIXME specification doesn't say which fields are mandatory and
       * which are not :/
       */
      PRINTF("\t======== metadata dump begin =========\n");
//    for (i=0; i < out._Result->__size; i++){
            if (p[i]->SURL){
                  PRINTF("\tSURL: %s\n", p[i]->SURL);
                  if (strcasecmp(p[i]->SURL, argv[i+2])){
                        PRINTF("\t[!] returned SURL and requested SURL don't match!\n");
                        somebug = 1;
                  }
            }
            else {
                  PRINTF("\t[?] SURL was not set\n");
                  SURL_was_not_set++;
            }

            if (p[i]->permMode >= 0){
                  PRINTF("\t[+] permMode: %o\n", p[i]->permMode);
            }
            else
                  PRINTF("\t[?] permMode was not set\n");

            if (p[i]->checksumType){
                  PRINTF("\t[+] checksumType: %s\n", p[i]->checksumType);
            }
            else
                  PRINTF("\t[?] checksumType was not set\n");
            
            if (p[i]->owner){
                  PRINTF ("\t[+] owner = %s\n", p[i]->owner);
            }
            else
                  PRINTF ("\t[?] owner was not set\n");     

            if (p[i]->group) {
                  printf ("\t[+] group = %s\n", p[i]->group);
            }
            else
                  PRINTF ("\t[?] group was not set\n");

            if (p[i]->size >= 0) {
                  PRINTF ("\t[+] size = %lld\n", p[i]->size);
            }
            else
                  PRINTF ("\t[?] size was negative\n");
            if (p[i]->isPinned == true_) {
                  PRINTF("\t[+] the file is pinned\n");
            }
            else
                  PRINTF("\t[+] the file is not pinned\n");
            if (p[i]->isPermanent == true_) {
                  PRINTF("\t[+] the file is permanent\n");
            }
            else
                  PRINTF("\t[+] the file is not permanent\n");
            if (p[i]->isCached == true_) {
                  PRINTF("\t[+] the file is cached\n");
            }
            else
                  PRINTF("\t[+] the file is not cached\n");

//    }
      PRINTF("\t======== metadata dump end =========\n");               
      return p+i;
}




/* this handles communication with SRM server in case of PUT request
 * and also copies file to TURL received from server
 * 
 */
int request_push(char **argv)
{
      int flags;
      int nbproto = 0;
      int ret;
      struct ns5__setFileStatusResponse outs;
      struct ns5__putResponse out;
      struct ns5__getRequestStatusResponse outq;
      char command[1024]; /* ugly */
      char rfcp_file[1024]; /* ugly */
      char *rfcp_file_p;
/*
      static char *protocols[] = {
#if GFAL_ENABLE_RFIO
            "rfio",
#endif
#if GFAL_ENABLE_DCAP
            "dcap",
#endif
#if GFAL_ENABLE_GSIFTP
            "gsiftp"
#endif
            ""
      };
*/
      char *protocols[2];
      int r = 0, i;
      struct ns1__RequestStatus *reqstatp;
      struct ArrayOfRequestFileStatus *p;
      char *sfn;
      struct ArrayOflong *sizearray;
      struct ArrayOfstring *srcarray;
      struct ArrayOfstring *surlarray;
      struct ArrayOfboolean *permarray;   
      struct ArrayOfstring protoarray;
      char ** ptr;
      char *srm_endpoint;
        //struct ns1__RequestFileStatus **f;
        struct ns1__RequestFileStatus *f;
        struct srm_filestatus *filestatuses;
        struct srm_filestatus *fs;
      int n;      
        enum xsd__boolean perm_tmp_arr[2];
        LONG64 size_tmp_arr[2];
        //enum xsd__boolean size_tmp_arr[2];

      strcpy(current_command, "put");
      if (transfer_method == METHOD_RFIO)
            protocols[0] = "rfio";
      if (transfer_method == METHOD_GSIFTP)
            protocols[0] = "gsiftp";
      if (transfer_method == METHOD_DCAP)
            protocols[0] = "gsidcap";

      protocols[1] = "";
      if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
            perror ("parsesurl");
            somebug = 1;
            return 1;
      }
      if (parsesurl (argv[3], &srm_endpoint, &sfn) < 0) {
            perror ("parsesurl");
            somebug = 1;
            return 1;
      }

      //PRINTF ("[GG0]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state);
      init_put_request();

      PRINTF ("[+]\tsoap_call_ns5__put returned reqid: %d %x\n", reqid, reqid);
      PRINTF ("[GG1]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state);

      /* loop while the file is pending */

      loop_while_pending();
      PRINTF ("[GG2]\tsoap_call_ns5__put returned reqstatp->state: %s\n", reqstatp->state);
      
      /* let's roll */
      p = reqstatp->fileStatuses;
      for (i = 0; i< p->__size; i++){
            PRINTF ("[+]\tfileid %d, request state %s\n[+]\tTURL = %s\n", 
                  p->__ptr[i]->fileId,
                  p->__ptr[i]->state,
                  p->__ptr[i]->TURL);

            /* update the status to running */
            PRINTF ("[+]\tUpdating status to Running\n");
            set_file_status("Running");
      
      
            if (i == 0){
                  if (transfer_method == METHOD_GSIFTP) {
                        PRINTF("[+]\tPerforming gsiftp copy from %s to %s\n", 
                              testfilename1, p->__ptr[i]->TURL);
                              ret = gsiftp_copy_out(testfilename1, p->__ptr[i]->TURL);
                  }
                  if (transfer_method == METHOD_RFIO) {
                        PRINTF("[+]\tPerforming rfio copy from %s to %s\n", 
                              testfilename1, p->__ptr[i]->TURL);
                              ret = rfio_copy_out(testfilename1, p->__ptr[i]->TURL);
                  }
                  if (transfer_method == METHOD_DCAP) {
                        PRINTF("[+]\tPerforming dcap copy from %s to %s\n", 
                              testfilename1, p->__ptr[i]->TURL);
                              ret = dcap_copy_out(testfilename1, p->__ptr[i]->TURL);
                  }

            }
            else {
                  if (transfer_method == METHOD_GSIFTP) {
                        PRINTF("[+]\tPerforming gsiftp copy from %s to %s\n",
                              testfilename2, p->__ptr[i]->TURL);
                        ret = gsiftp_copy_out(testfilename2, p->__ptr[i]->TURL);
                  }
                  if (transfer_method == METHOD_RFIO) {
                        PRINTF("[+]\tPerforming rfio copy from %s to %s\n",
                              testfilename2, p->__ptr[i]->TURL);
                              ret = rfio_copy_out(testfilename2, p->__ptr[i]->TURL);
                  }
                  if (transfer_method == METHOD_DCAP) {
                        PRINTF("[+]\tPerforming dcap copy from %s to %s\n", 
                              testfilename2, p->__ptr[i]->TURL);
                              ret = dcap_copy_out(testfilename2, p->__ptr[i]->TURL);
                  }

            }
            
            if (ret != 0){
                  PRINTF("[+]\tUpdating status to Failed\n");
                  set_file_status("Failed");
                  somebug = 1;
                  ret = 1;
            }
            else {
                  PRINTF("[+]\tFile copied successfully to %s\n", 
                              p->__ptr[i]->TURL);
                  PRINTF("[+]\tUpdating status to Done ...\n");
                  set_file_status("Done");
            }
      }
      fflush(stdout);
      
      return 0;
}



int request_pull(char **argv)
{
      char command[512]; /* ugly */
      int ret, i;
      struct ns5__getResponse out;
      struct ns5__getRequestStatusResponse outq;
      struct ns5__setFileStatusResponse outs;
      struct ArrayOfRequestFileStatus *p;
        //struct ns1__RequestFileStatus **f;
        struct ns1__RequestFileStatus *f;
        struct srm_filestatus *filestatuses;
        struct srm_filestatus *fs;
/*    static char *protocols[] = {
#if GFAL_ENABLE_RFIO
            "rfio",
#endif
#if GFAL_ENABLE_DCAP
            "dcap",
#endif
#if GFAL_ENABLE_GSIFTP
            "gsiftp",
#endif
            ""
      };
*/
      char *protocols[2];
      int r = 0;
      int n;
      struct ns1__RequestStatus *reqstatp;
      char *sfn;
      char *srm_endpoint;
      struct ArrayOfstring *surlarray;
      struct ArrayOfstring protoarray;

      strcpy(current_command, "get");     

      if (transfer_method == METHOD_RFIO)
            protocols[0] = "rfio";
      if (transfer_method == METHOD_GSIFTP)
            protocols[0] = "gsiftp";
      if (transfer_method == METHOD_DCAP)
            protocols[0] = "gsidcap";

      protocols[1] = "";

      if (parsesurl (argv[2], &srm_endpoint, &sfn) < 0) {
            perror ("parsesurl");
            somebug = 1;
            return 1;
      }
      if (parsesurl (argv[3], &srm_endpoint, &sfn) < 0) {
            perror ("parsesurl");
            somebug = 1;
            return 1;
      }

      init_get_request();

      PRINTF ("[+]\tsoap_call_ns5__get returned reqid: %x\n", reqid);
      PRINTF ("[GG1]\tsoap_call_ns5__get returned reqstatp->state: %s\n", reqstatp->state);

      /* now wait for change from pending state */

      loop_while_pending();
      PRINTF ("[GG2]\tsoap_call_ns5__get returned reqstatp->state: %s\n", reqstatp->state);

      /* let's roll */
      p = reqstatp->fileStatuses;
      for (i = 0; i< p->__size; i++){
            PRINTF ("[+]\tfileid %d, request state %s\n[+]\tTURL = %s\n", 
                  p->__ptr[i]->fileId,
                  p->__ptr[i]->state,
                  p->__ptr[i]->TURL);

            /* update the status to running */
            PRINTF ("[+]\tUpdating status to Running\n");
            set_file_status("Running");
      

            if (i == 0){
                  if (transfer_method == METHOD_GSIFTP) {
                        PRINTF("[+]\tPerforming gsiftp copy from %s to %s\n", 
                              p->__ptr[i]->TURL, testfilename1);
                              ret = gsiftp_copy_in(p->__ptr[i]->TURL, testfilename1);
                  }
                  if (transfer_method == METHOD_RFIO) {
                        PRINTF("[+]\tPerforming rfio copy from %s to %s\n", 
                              p->__ptr[i]->TURL, testfilename1);
                              ret = rfio_copy_in(p->__ptr[i]->TURL, testfilename1);
                  }
                  if (transfer_method == METHOD_DCAP) {
                        PRINTF("[+]\tPerforming dcap copy from %s to %s\n", 
                              p->__ptr[i]->TURL, testfilename1);
                              ret = dcap_copy_in(p->__ptr[i]->TURL, testfilename1);
                  }

            }
            else {
                  if (transfer_method == METHOD_GSIFTP) {
                        PRINTF("[+]\tPerforming gsiftp copy from %s to %s\n",
                              p->__ptr[i]->TURL, testfilename2);
                        ret = gsiftp_copy_in(p->__ptr[i]->TURL, testfilename2);

                  }
                  if (transfer_method == METHOD_RFIO) {
                        PRINTF("[+]\tPerforming rfio copy from %s to %s\n",
                              p->__ptr[i]->TURL, testfilename2);
                              ret = rfio_copy_in(p->__ptr[i]->TURL, testfilename2);
                  }
                  if (transfer_method == METHOD_DCAP) {
                        PRINTF("[+]\tPerforming dcap copy from %s to %s\n", 
                              p->__ptr[i]->TURL, testfilename2);
                              ret = dcap_copy_in(p->__ptr[i]->TURL, testfilename2);
                  }

            }
            
            
            
            if (ret != 0){
                  PRINTF("[+]\tUpdating status to Failed\n");
                  set_file_status("Failed");
                  somebug = 1;
                  ret = 1;
            }
            else {
                  PRINTF("[+]\tFile copied successfully\n");
                  PRINTF("[+]\tUpdating status to Done ...\n");
                  set_file_status("Done");
            }
      }

      
      fflush(stdout);
      return 0;
      
}


int main(int argc, char **argv)
{

      char command[1024];
      struct ns1__FileMetaData **metadata;
      int ret = 0;
            
#ifdef DEBUG
      printf("[+] srm_testsuite %s starting, compiled in verbose mode\n", VERSION);
#else
      printf("[+] srm_testsuite %s starting, compiled in quiet mode\n", VERSION);
#endif
      fflush(stdout);
      
      if (argc != 4) {
            fprintf (stderr, "[!] usage: %s [rfio|gsiftp|dcap] SURL SURL\n", argv[0]);
            return 1;
      }

      if ((strcmp(argv[1],"rfio") != 0) && (strcmp(argv[1], "gsiftp") != 0) && (strcmp(argv[1], "dcap") != 0)) {
            fprintf (stderr, "[!] usage: %s [rfio|gsiftp|dcap] SURL SURL\n", argv[0]);
            return 1;
      }

      if (!strcmp(argv[1], "rfio")) 
            transfer_method = METHOD_RFIO;
      if (!strcmp(argv[1], "gsiftp"))
            transfer_method = METHOD_GSIFTP;
      if (!strcmp(argv[1], "dcap"))
            transfer_method = METHOD_DCAP;
      
      soap_init(&soap);
#ifdef GFAL_SECURE
      flags = CGSI_OPT_DISABLE_NAME_CHECK;
      soap_register_plugin_arg (&soap, client_cgsi_plugin, &flags);
#endif

      /* first, ping the server 
       * FIXME this is not in specification (?)
       */

      PRINTF("[+] Calling request_ping()\n");
      ret = request_ping(argv);
      if (ret == 1){
            PRINTF("[+] request_ping() failed, no use to try more\n");
            somebug = 1;
            goto out;
      }
      
      /* ugly */
      strcpy(testfilename1,"TESTFILE");
      strcpy(testfilename2,"TESTFILE2");

/* 
 * 1) create file (done by wrapper)
 * 2) upload
 * 3) get it back to file.x
 * 4) modify it and cp to file.x.y
 * 5) overwrite through SRM on server
 * 6) get it back as file.x.y.y
 */

      /* the file management GET/PUT tests */
      
      /* pin and upload the file */
      /* Jiri's version, does not work
      PRINTF("[+] Calling request_pin()\n");
      ret = request_pin(argv);
      if (ret == 1){
            PRINTF("[!] request_pin() failed, but this is not too critical, going on\n");
            
      }
      */
      

      PRINTF("[+] Calling request_push()\n");
      ret = request_push(argv);
      if (ret == 1) {
            PRINTF("[!] request_push() failed, no use to try more\n");
            somebug = 1;
            goto out;
      }

      /* moved by GG, but not successfully */
#ifdef RPIN 
      PRINTF("[+] Calling request_pin()\n");
      ret = request_pin(argv);
      if (ret == 1){
            PRINTF("[!] request_pin() failed, but this is not too critical, going on\n");
            
      }
#endif
      

      /* now check through getFileMetaData if it is OK */ 
      PRINTF("[+] Calling request_getFileMetaData(0)\n");
      metadata = request_get_file_metadata(argv, 0);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename1, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData(0) failed\n");
            somebug = 1;
      }

      PRINTF("[+] Calling request_getFileMetaData(1)\n");
      metadata = request_get_file_metadata(argv, 1);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename2, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData(1) failed\n");
            somebug = 1;
      }
      
      /* get it back to .x */
      strcat(testfilename1, ".x");
      strcat(testfilename2, ".x");
      PRINTF("[+] Calling request_pull()\n");
      ret = request_pull(argv);
      if (ret == 1){
            PRINTF("[!] request_pull() failed, no use to try more\n");
            somebug = 1;
            goto out;
      }
      
      /* 2nd try by GG */
#ifdef RPIN 
      PRINTF("[+] Calling GG request_pin() for both files.x, after request_pull\n");
      ret = request_pin(argv);
      if (ret == 1){
            PRINTF("[!] request_pin() failed, but this is not too critical, going on\n");
            
      }
#endif

      /* now check through getFileMetaData if it is OK */ 
      PRINTF("[+] Calling request_getFileMetaData()\n");
      metadata = request_get_file_metadata(argv, 0);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename1, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }

      PRINTF("[+] Calling request_getFileMetaData()\n");
      metadata = request_get_file_metadata(argv, 1);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename2, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }

      sprintf(command, "cp -p %s %s.y", testfilename1, testfilename1);
      system(command);
      sprintf(command, "cp -p %s %s.y", testfilename2, testfilename2);
      system(command);
      strcat(testfilename1, ".y");
      strcat(testfilename2, ".y");
      sprintf(command, "echo 'ADDED' >> %s", testfilename1);
      /* FIXME this can also fail */
      system(command);
      sprintf(command, "echo 'ADDED' >> %s", testfilename2);
      /* FIXME this can also fail */
      system(command);

      /* now the file will be uploaded back. We'll modify the SURL in
       * last byte, since SRM implementation doesn't allow overwriting
       * (while castor SRM handles it, dCache SRM does not)
       * This is nasty, but works, as far as we have control over the
       * SURL format.
       */
      argv[2][strlen(argv[2])-1] = 'X';
      argv[3][strlen(argv[3])-1] = 'X';
      PRINTF("[+] Calling request_push()\n");
      ret = request_push(argv);
      if (ret == 1){
            PRINTF("[!] request_push() failed, no use to try more\n");
            somebug = 1;
            goto out;
      }

      /* again check through getFileMetaData if it is OK */ 
      PRINTF("[+] Calling request_getFileMetaData()\n");
      metadata = request_get_file_metadata(argv, 0);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename1, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }
      metadata = request_get_file_metadata(argv, 1);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename2, PINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }

      
      /* get it back to .x.y.y and unpin it */
      strcat(testfilename1, ".y");
      strcat(testfilename2, ".y");
      PRINTF("[+] Calling request_pull()\n");
      ret = request_pull(argv);
      if (ret == 1){
            PRINTF("[!] request_pull() failed, no use to try more\n");
            somebug = 1;
            goto out;
      }

#ifdef RPIN 
      PRINTF("[+] Calling request_unpin()\n");
      ret = request_unpin(argv, reqid);
      if (ret == 1){
            PRINTF("[!] request_unpin() failed, but this is not too critical, going on\n");
            
      }
#endif

      
      /* now check through getFileMetaData if it is OK
       * especially if the file is unpinned */ 

      PRINTF("[+] Calling request_getFileMetaData()\n");
      metadata = request_get_file_metadata(argv, 0);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename1, UNPINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }
      metadata = request_get_file_metadata(argv, 1);
      if (metadata) {
            check_metadata_consistency(metadata, testfilename2, UNPINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }

      /* request_advisoryDelete Test */

      ret = request_advisoryDelete(argv, 0);
      if (ret == 1){
            PRINTF("[!] request_advisoryDelete(0) failed, but this is not too critical, going on\n");
            
      }

      /*
      ret = request_advisoryDelete(argv, 1);
      if (ret == 1){
            PRINTF("[!] request_advisoryDelete(1) failed, but this is not too critical, going on\n");
            
      }
      */
      
      SURL_was_not_set = 0;
      PRINTF("[+] Calling request_getFileMetaData() after request_advisoryDelete for %s \n", argv[2]);
      metadata = request_get_file_metadata(argv, 0);
      /*
      if (metadata) {
            check_metadata_consistency(metadata, testfilename1, UNPINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }
      */
      PRINTF("[+] Calling request_getFileMetaData() after request_advisoryDelete for %s \n", argv[3]);
      metadata = request_get_file_metadata(argv, 1);
      /*
      if (metadata) {
            check_metadata_consistency(metadata, testfilename2, UNPINNED);
      }
      else {
            PRINTF("[!] request_getFileMetaData() failed\n");
            somebug = 1;
      }
      */
      if ( SURL_was_not_set != 1 )
        {
          PRINTF("[!] request_advisoryDelete() failed: %d\n", SURL_was_not_set);
          somebug = 1;
        }
        

      /* now it is up to the wrapping script above us to test
       * if original and .x are the same, and .x and .x.y.y differ
       */

      /* the remaining methods are advisoryDelete and mkPermanent. As
       * both of these methods are not required to be supported by SRM,
       * it's not worth testing them, because noone can know if it failed
       * because 'not supported' or because 'bug'. 
       */

      soap_end(&soap);
      /* this is the only exit point. we return the global flag
       * to wrapping scipt, to indicate him if everything went flawlessly
       * or not
       */
      printf("[%s] srm_testsuite finished, bug(s) %sencountered\n", 
                  somebug == 1 ? "!" : "+",
                  somebug == 1 ? "" : "not ");
out:
      return somebug;
}


Generated by  Doxygen 1.6.0   Back to index