/*===========================================================================
  Copyright (C) 1995-2005 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        atestosu
.LANGUAGE    C
.AUTHOR      Carlos Guirao. IPG-ESO Garching
.CATEGORY    Tests of host operating system interfaces. Tape management.
.COMMENTS    Automatic tape test. 
	     This test exercises the functions of the module "osu" which
	     perform basic i/o to magnetic tapes on UNIX/VMS enviroments
             The goal of this test is exercising the funtionality of the
	     set of rutines defined in "osu.c". 
	     On passing this test, we consider the "osu", and the lower
             module "iodev" ready for being included in the "libos" 
	     library.
	     If some error is detected, the test exits inmediatly, and
	     both modules "osu.c" and "iodev.c" will have to be tested 
	     manually with "testosu.exe" and "testtape.exe" respectively.
	     On failing this test, we do not consider the "iodev.c"
	     suitable for utilities like "intape" or "outtape" when
	     accesing data from tape.
	
.ENVIRONment UNIX/VMS

.VERSION 1.0 12-Aug-1988   Implementation     C. Guirao
.VERSION 1.1 04-May-1989   Discarding "osubseek" test C. Guirao
.VERSION 1.2 910909  Checking for environment variable DEVCAPFILE. CG.
051021		last modif

------------------------------------------------------------*/

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <filedef.h>            /* Contains READ, WRITE, etc... */
/*#include <osparms.h> */

static char dev_name[80] = "ns2:/dev/nrst0";
static char normalfile[] = "atestosu";
static char nonexistent[] = "/dev/atestosu";

#define PATTERN0 '0'
#define PATTERN1 'a'
#define PATTERN2 'B'
#define PATTERN3 'C'
static char PATTERN4 = 'c';
#define PERROR { printf("ERROR: %s\n",osmsg()); ospexit(1); }

#define SIZEBUF 1024
char *buf;
int sizebuf;

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

	char input[80], name[80], *pname;
	int den, mode;
	int fd, fd1;
	char in;
	int i, j, l; 
	long t0,t1, oshtime();
	char answ;

	/*
	 * I check now for DEVCAPFILE otherwise it will fail later in the
	 * osuopen. 
	 * A default place for DEVCAPFILE used to be:
	 *  $MIDASHOME/$MIDVERS/incl/devcap.dat
	 */
	if ( ! oshenv("DEVCAPFILE", (char *)0) ) {
		printf("Warning: Environment variable DEVCAPFILE undefined\n");
	    }

	pname=dev_name;
	printf("Enter name of device to be tested (%s): ",dev_name); 
	gets(name); 
	if (strlen(name) != 0)
		strcpy(dev_name,name);

	printf("Enter size of record to be tested (%d): ",SIZEBUF);
	gets(name);
	if (strlen(name) == 0)
		sizebuf=SIZEBUF;
	else
		sizebuf=atoi(name);

	printf("Allocating memory for buffer...");
	if ( (buf = (char *)malloc((size_t)(sizebuf+1))) == (char *)0)  PERROR
	else 	printf("OK\n");

	/* First step: open & close Read mode*/
	printf("\n************** Testing open & close\n");

	t0 = oshtime();
	printf("Opening a normal file....");
	if ( (fd = osuopen(normalfile,READ_WRITE,0)) != -1) {	
		printf("ERROR: it succeded\n");
		osuclose(fd);
		}
	else	printf("OK\n");

	printf("Opening a nonexistent device ....");
	if ( (fd = osuopen(nonexistent,READ,0)) != -1) {	
		printf("ERROR: it succeded\n");
		osuclose(fd);
		}
	else	printf("OK\n");

	printf("Opening the selected device ...."); fflush(stdout);
	if ( (fd = osuopen(pname,READ,0)) == -1) PERROR
	else	printf("OK\n");

	/*
	printf("Opening the selected device twice...."); fflush(stdout);
	if ( (fd1 = osuopen(pname,READ,0)) != -1) {
		printf("ERROR: it succeded\n");
		osuclose(fd1);
		}
	else	printf("OK\n");
	*/

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	/*
	printf("Closing the selected device twice ...."); fflush(stdout);
	if (osuclose(fd) != -1) PERROR	
	else	printf("OK\n");
	*/

	printf("Opening in READ_WRITE mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR
	else	printf("OK\n");

	printf("Skipping to beginning of tape ..."); fflush(stdout);
	if (osufseek(fd,0,FILE_START) != 0 ) PERROR
	else 	printf("OK\n");

	for(i=0; i<sizebuf; i++) buf[i] = PATTERN0;
	printf("Writting a buffer in device ...."); fflush(stdout);
	if ( osuwrite(fd,buf,sizebuf) == -1) {	
		printf("ERROR writing a buffer\n");
		PERROR;
		}
	else	printf("OK\n");

	printf("Closing a file ...."); fflush(stdout);
	if ( osufclose(fd) == -1) {
		printf("ERROR closing file\n");
		ospexit(1);
		}
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	printf("Opening in WRITE mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,WRITE,0)) == -1) PERROR
	else	printf("OK\n");

	printf("Trying to read a buffer ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) > 0) {	
		printf("ERROR: it succeded reading a buffer\n");
		}
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR
	else	printf("OK\n");


	/* Third step: Writting files on tape */
	printf("\n************** Writting files on tape\n");

	printf("Opening in READ_WRITE mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR
	else	printf("OK\n");

	printf("Skipping to beginning of tape ..."); fflush(stdout);
	l = osufseek(fd,0,FILE_START);
	if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Writting 3 records on file 0 "); 
	if ( testwrite(fd,3,PATTERN0) == -1) ospexit(1);

	printf("Closing file 0 ....");
	if ( osufclose(fd) == -1) PERROR
	else	printf("OK\n");

	printf("Writting 3 records on file 1 "); 
	if ( testwrite(fd,3,PATTERN1) == -1) ospexit(1);

	printf("Closing file 1 ....");
	if ( osufclose(fd) == -1) PERROR
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	printf("Opening in APPEND mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,APPEND,0)) == -1) PERROR
	else	printf("OK\n");

	printf("Writting 3 records on file 2 ");
	if ( testwrite(fd,3,PATTERN2) == -1) PERROR; 

	printf("Closing file 2 ...."); fflush(stdout);
	if ( osufclose(fd) == -1) PERROR
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	printf("Opening in READ_WRITE mode ...."); fflush(stdout);
        if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR
        else    printf("OK\n");

        printf("Skipping to beginning of tape ..."); fflush(stdout);
        l = osufseek(fd,0,FILE_START);
        if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

        printf("Skipping to End Of Media ..."); fflush(stdout);
        l = osufseek(fd,0,FILE_END);
        if (l != 3 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

	printf("Writting 3 records on file 3 ");
	if ( testwrite(fd,3,PATTERN3) == -1) PERROR; 

	printf("Closing file 3 ...."); fflush(stdout);
	if ( osufclose(fd) == -1) PERROR
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	/* Fourth step: Reading files from tape */
	printf("\n************** Reading files from tape\n");

	printf("Opening in READ_WRITE mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR	
	else	printf("OK\n");

	printf("Skipping to beginning of tape ..."); fflush(stdout);
	l = osufseek(fd,0,FILE_START);
	if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else	printf("OK\n");

	printf("Reading 3 records from file 0 "); 
	if ( testread(fd,3,PATTERN0) == -1) PERROR

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) != 0) PERROR	
	else	printf("OK\n");

	printf("Reading 3 records from file 1 "); 
	if ( testread(fd,3,PATTERN1) == -1) PERROR

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) != 0) PERROR	
	else	printf("OK\n");

	printf("Reading 3 records from file 2 ");
	if ( testread(fd,3,PATTERN2) == -1) ospexit(1);

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) != 0) PERROR	
	else	printf("OK\n");

	printf("Reading 3 records from file 3 ");
	if ( testread(fd,3,PATTERN3) == -1) ospexit(1);

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) != 0) PERROR	
	else	printf("OK\n");

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) > 0) PERROR
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	/* Skipping files */
	/* Finth step: Skipping over files */
	printf("\n************** Skipping over files\n");

        printf("Opening in READ mode ...."); fflush(stdout);
        if ( (fd = osuopen(pname,READ,0)) == -1) PERROR
        else    printf("OK\n");

        printf("Rewinding tape ..."); fflush(stdout);
        l = osufseek(fd,0,FILE_START);
        if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

        printf("Skipping to the current file +1 file ..."); fflush(stdout);
        l = osufseek(fd,1,FILE_CURRENT);
        if (l != 1 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

        printf("Reading 3 records from file 1 ");
        if ( testread(fd,3,PATTERN1) == -1) ospexit(1);

        printf("Skipping to beginning of tape +2 files ..."); fflush(stdout);
        l = osufseek(fd,2,FILE_START);
        if (l != 2 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

        printf("Reading 3 records from file 2 ");
        if ( testread(fd,3,PATTERN2) == -1) ospexit(1);

        printf("Trying to skip beyond EOM (End_Of_Media)..."); fflush(stdout);
        l = osufseek(fd,7,FILE_START);
        if (l != 4 && l != -1 )  { printf("(file: %d)", l); PERROR }
        else {
            l = osuftell(fd);
            if (l != 4 && l != 0) { printf("(file: %d)", l); PERROR}
            printf("(file: %d) OK\n",l);
            }

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	t1 = oshtime();
	printf("\nEND OF OSU TESTS FOR MIDAS PROCEDURES\n");
	printf("Do you want to continue with more (not required) tests (n)?: ");
	answ=getchar();
	if (answ != 'y' && answ != 'Y') {
	    printf("END OF ATESTOSU TEST.=== %d seconds ===\n", t1-t0);
	    ospexit(0);
	    }

	/* Overwriting data */
	printf("\n************** Trying to overwrite data\n");
        printf("Opening in READ_WRITE mode ...."); fflush(stdout);
        if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR
        else    printf("OK\n");

        printf("Rewinding tape ..."); fflush(stdout);
        l = osufseek(fd,0,FILE_START);
        if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
        else    printf("OK\n");

        printf("Skipping to begining of tape +3 files ..."); fflush(stdout);
        l = osufseek(fd,3,FILE_START);
        if (l  != 3 ) { printf("Position=%d ", l); PERROR}
        else    printf("OK\n");

        printf("Writting 3 records on file 3 ");
        if ( testwrite(fd,3,PATTERN4) == -1) {
            printf("\n\07\07ERROR: %s\n",osmsg());
            printf("++++ Rewriting is NOT allowed ... Continuing\n\n");
            PATTERN4 = PATTERN3;

            printf("Closing the selected device ...."); fflush(stdout);
            if (osuclose(fd) == -1) PERROR
            else    printf("OK\n");
        }
	else {

            printf("Closing file 3 ....");
            if ( osufclose(fd) == -1) PERROR
            else    printf("OK\n");

            printf("Rewinding tape ..."); fflush(stdout);
            l = osufseek(fd,0,FILE_START);
            if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
            else    printf("OK\n");

            printf("Skipping to begining of tape +3 files ..."); fflush(stdout);
            l = osufseek(fd,3,FILE_START);
            if (l  != 3 ) { printf("Position=%d ", l); PERROR}
            else    printf("OK\n");

            printf("Reading 3 records from file 3 ");
            if ( testread(fd,3,PATTERN4) == -1) ospexit(1);

            printf("Closing the selected device ...."); fflush(stdout);
            if (osuclose(fd) == -1) PERROR
            else    printf("OK\n");
    	    }


	/* Skipping files */
	/* Sixth step: Skipping over files */
	printf("\n************** Skipping over files (backward movements)\n");

	printf("Opening in READ_WRITE mode ...."); fflush(stdout);
	if ( (fd = osuopen(pname,READ_WRITE,0)) == -1) PERROR	
	else	printf("OK\n");

	printf("Rewinding tape ..."); fflush(stdout);
	l = osufseek(fd,0,FILE_START);
	if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Skipping to the last file -2 files ..."); fflush(stdout);
	l = osufseek(fd,-2,FILE_END);
	if (l != 2 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Reading 3 records from file 2 ");
	if ( testread(fd,3,PATTERN2) == -1) ospexit(1);

	printf("Skipping to the current file -3 files ..."); fflush(stdout);
	l = osufseek(fd,-2,FILE_CURRENT);
	if (l != 0 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Reading 3 records from file 0 ");
	if ( testread(fd,3,PATTERN0) == -1) ospexit(1);

	printf("Skipping to the current file +3 files ..."); fflush(stdout);
	l = osufseek(fd,3,FILE_CURRENT);
	if (l != 3 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Reading 3 records from file 3 ");
	if ( testread(fd,3,PATTERN4) == -1) ospexit(1);

	printf("Skipping to the end of tape ..."); fflush(stdout);
	l = osufseek(fd,0,FILE_END);
	if (l != 4 ) { printf("Returned from fseek=%d ", l); PERROR ; }
	else 	printf("OK\n");

	printf("Reading a File Mark ...."); fflush(stdout);
	if ( osuread(fd,buf,sizebuf) > 0) PERROR
	else	printf("OK\n");

	printf("Closing the selected device ...."); fflush(stdout);
	if (osuclose(fd) == -1) PERROR	
	else	printf("OK\n");

	t1 = oshtime();
	printf("END OF ATESTOSU TEST.=== %d seconds ===\n", t1-t0);
	ospexit(0);
}

testread(fd,count,pattern)
int fd;
int count;
char pattern;
{
	int i, j;
	int size;
	for (j=0; j<count; j++) {
		if ( (size=osuread(fd,buf,sizebuf)) != sizebuf) {
		   if (size == -1) printf("\nERROR: reading a sector\n");
		   else  printf("\nERROR: %d bytes read\n",size);
		   return(-1);
		   }
		else	{
			for(i=0; i<sizebuf; i++) 
				if ( buf[i] != pattern ) {
					printf("PATTERN mistmatch: read[%d]='%c'; expected '%c'\n",
					i, buf[i], pattern);
					return(-1);
					}
			printf("...OK");
			}
		}
	printf("\n");
}

testwrite(fd,count,pattern)
int fd;
int count;
char pattern;
{
	int i, j;
	for(i=0; i<sizebuf; i++) buf[i] = pattern;
	for (j=0; j<count; j++) {
		if ( osuwrite(fd,buf,sizebuf) == -1) {	
			printf("\nERROR writing a buffer: %s\n",osmsg());
			return(-1);
			}
		else	printf("...OK");
		}
	printf("\n");
}
