File: [Development] / xfs-cmds / xfstests / dmapi / src / suite2 / src / test_invis.c (download)
Revision 1.12, Thu Jul 26 21:25:32 2007 UTC (10 years, 2 months ago) by lachlan.longdrop.melbourne.sgi.com
Branch: MAIN
CVS Tags: HEAD Changes since 1.11: +2 -1
lines
Fix build failure.
Merge of master-melb:xfs-cmds:29235a by kenmcd.
Fix build failure.
|
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc.
* All Rights Reserved.
*
* 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.
*
* This program is distributed in the hope that it would 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 the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <lib/hsm.h>
#include <lib/errtest.h>
#include <getopt.h>
#include <string.h>
#include <time.h>
/*---------------------------------------------------------------------------
Automated test of the DMAPI functions dm_write_invis() and dm_read_invis()
The command line is:
test_invis [-s sid] [-v] ls_path pathname
where:
sid
is the session ID whose events you you are interested in.
ls_path
is the path to a specific copy of ls, important only for its size
pathname
is the filesystem to use for the test.
DM_WRITE_SYNC is is not supported.
----------------------------------------------------------------------------*/
#define OFF_MAX 50
#define OFF_STEP 5
#define LEN_MAX 50
#define LEN_STEP 5
#ifndef linux
extern char *sys_errlist[];
#endif
extern int optind;
extern char *optarg;
char *Progname;
static void
usage(void)
{
fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path pathname\n",
Progname);
exit(1);
}
int
main(
int argc,
char **argv)
{
dm_sessid_t sid = DM_NO_SESSION;
char *dir_name = NULL;
char *ls_path = NULL;
dm_off_t offset = 0;
dm_size_t length = 1;
dm_size_t curlength = 0;
u_char ch;
void *bufp = NULL;
void *hanp;
size_t hlen;
dm_ssize_t rc;
char *name;
char test_file[128];
char command[128];
int opt;
int i;
int j;
int k;
int Vflag=0;
struct stat statbuf;
struct stat checkbuf;
dm_token_t test_token;
void* test_vp;
int cont;
int error_reported;
if (Progname = strrchr(argv[0], '/')) {
Progname++;
} else {
Progname = argv[0];
}
/* Crack and validate the command line options. */
while ((opt = getopt(argc, argv, "vs:")) != EOF) {
switch (opt) {
case 'v':
Vflag++;
break;
case 's':
sid = atol(optarg);
break;
case '?':
usage();
}
}
if (optind + 2 != argc)
usage();
ls_path = argv[optind];
dir_name = argv[optind+1];
if (dm_init_service(&name) == -1) {
fprintf(stderr, "Can't initialize the DMAPI\n");
exit(1);
}
if (sid == DM_NO_SESSION)
find_test_session(&sid);
/* Get a random character for read/write tests */
srand((unsigned int)time(NULL));
ch = (u_char)rand();
printf("Invisible read/write tests beginning...\n");
/* File creation loop*/
for(i=0; i<LEN_MAX; i+=LEN_STEP) {
for (j=0; j<OFF_MAX; j+=OFF_STEP) {
sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d",
dir_name, i, j);
sprintf(command, "cp %s %s\n", ls_path, test_file);
system(command);
}
}
/* Write to files, then read them to check for correct results.
Do timestamp checking along the way. */
for(i=0; i<LEN_MAX; i+=LEN_STEP) {
for (j=0; j<OFF_MAX; j+=OFF_STEP) {
#define max(a,b) ((a) > (b) ? (a) : (b))
length = max((dm_size_t)(i), length);
offset = (dm_off_t)(j);
sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d",
dir_name, i, j);
if (stat(test_file, &statbuf)){
fprintf(stdout,
"Error: unable to stat test file; %s (before test)\n",
test_file);
continue;
}
if (dm_path_to_handle(test_file, &hanp, &hlen)) {
fprintf(stderr, "can't get handle for %s; bypassing test\n",
test_file);
continue;
}
if (length > curlength) {
if(curlength>0)
free(bufp);
if ((bufp = malloc(length)) == NULL) {
fprintf(stderr, "malloc of %llu bytes failed\n", length);
continue;
}
curlength = length;
memset(bufp, ch, length);
}
rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
0, offset, length, bufp);
cont = 0;
if (rc < 0) {
fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
cont=1;
} else if (rc != length) {
fprintf(stderr, "expected to write %lld bytes, actually "
"wrote %lld\n", length, rc);
cont=1;
}
if(cont)
continue;
/* Timestamp checking, part 1 */
if (stat(test_file, &checkbuf)){
fprintf(stdout,
"Error: unable to stat the test file; %s (after write)\n",
test_file);
}
else {
#ifdef __sgi
if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
(statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
(statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
(statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
(statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
(statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
#else
if ((statbuf.st_atime == checkbuf.st_atime) &&
(statbuf.st_mtime == checkbuf.st_mtime) &&
(statbuf.st_ctime == checkbuf.st_ctime))
#endif
{
if (Vflag) {
printf("Report: time stamp unchanged by write\n");
}
}
else {
printf("Error: time stamp changed by write\n");
}
}
rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
offset, length, bufp);
if (rc < 0) {
fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
continue;
}
else if (rc != length) {
fprintf(stderr, "expected to read %lld bytes, actually "
"wrote %lld\n", length, rc);
continue;
}
else {
/* Be sure the buffer is filled with the test char */
error_reported = 0;
for (k=0; k<i; k++){
if (((u_char *)bufp)[k] == ch) {
if (Vflag) printf(".");
}
else {
if(!error_reported){
printf("Error!(line=%d)\n", __LINE__);
error_reported++;
}
}
}
if (Vflag) printf("\n");
}
/* Timestamp checking, part 2 */
if (stat(test_file, &statbuf)){
fprintf(stdout,
"Error: unable to stat the test file; %s (after write)\n",
test_file);
}
else {
#ifdef __sgi
if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
(statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
(statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
(statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
(statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
(statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
#else
if ((statbuf.st_atime == checkbuf.st_atime) &&
(statbuf.st_mtime == checkbuf.st_mtime) &&
(statbuf.st_ctime == checkbuf.st_ctime))
#endif
{
if (Vflag) {
printf("Report: time stamp unchanged by read\n");
}
}
else {
printf("Error: time stamp changed by read\n");
}
}
} /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
} /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
/* File deletion loop*/
for(i=0; i<LEN_MAX; i+=LEN_STEP) {
for(j=0; j<OFF_MAX; j+=OFF_STEP) {
sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d",
dir_name, i, j);
sprintf(command, "rm %s\n", test_file);
system(command);
}
}
/*************************************\
|* Correct-input testing complete. *|
|* Beginning improper-input testing. *|
\*************************************/
sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO",
dir_name);
sprintf(command, "cp %s %s\n", ls_path, test_file);
system(command);
if (dm_path_to_handle(test_file, &hanp, &hlen)) {
fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
test_file);
}
else {
dm_off_t offset;
/* Try writing a character waaaaaay up in the millions range */
sprintf(bufp, "%c", ch);
if (stat(test_file, &statbuf)){
fprintf(stdout,
"Error: unable to stat the test file; %s \n",
test_file);
}
offset = ((1000000*(dm_off_t)(ch)) > statbuf.st_size) ?
statbuf.st_size : (1000000*(dm_off_t)(ch));
if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0,
offset, 1, bufp)==-1){
printf("Error invis-writing 0x%x at byte 0x%x million: %s\n",
*(u_char *)bufp, (unsigned int)ch, ERR_NAME);
}
else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
offset, 1, bufp)==-1){
printf("Error invis-reading at byte %u million: %s\n",
(unsigned int)ch, ERR_NAME);
}
else if (((u_char *)bufp)[0]!=ch) {
printf("Error: wanted to read %c and instead got %s.\n",
ch, (u_char *)bufp);
}
else if (Vflag) {
printf("Report: \"0x%x\" was written and \"0x%x\" was read "
"at byte %d million.\n", ch, *(u_char *)bufp, ch);
}
#ifdef __sgi
/* Try writing a character in the 2 gigabyte (2^31) range */
sprintf(bufp, "%c", ch);
if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0,
2147840000, 1, bufp)==-1){
printf("Error invis-writing %s at 2 gigabytes: %s\n",
(u_char *)bufp, ERR_NAME);
}
else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
2147840000, 1, bufp)==-1){
printf("Error invis-reading at 2 gigabytes: %s\n",
ERR_NAME);
}
else if (((u_char *)bufp)[0]!=ch) {
printf("Error: wanted to read %c and instead got %s.\n",
ch, (u_char *)bufp);
}
else if (Vflag) {
printf("Report: \"0x%x\" was written and \"0x%x\" was read "
"at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n",
ch, *(u_char *)bufp);
}
#endif
printf("\t(errno subtests beginning...)\n");
/**** WRITE tests ****/
/*---------------------------------------------------------*/
EXCLTEST("write", hanp, hlen, test_token,
dm_write_invis(sid, hanp, hlen, test_token,
0, 0, 13, "write test 1"))
/*---------------------------------------------------------*/
if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
fprintf(stderr,
"Cannot create a test handle (%s); skipping EBADF test\n",
ERR_NAME);
}
else {
((char *) test_vp)[hlen/2]++;
ERRTEST(EBADF,
"write",
dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
0, 0, 0, bufp))
ERRTEST(EBADF,
"read",
dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
0, 0, bufp))
dm_handle_free(test_vp, hlen);
}
/*---------------------------------------------------------*/
ERRTEST(EBADF,
"write",
dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
0, 0, 0, NULL))
/*---------------------------------------------------------*/
ERRTEST(EFAULT,
"write",
dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
0, 0, 0, NULL))
/*---------------------------------------------------------*/
#if 0
PROBLEM: write_invis refuses to produce EINVAL for
lengths that will not fit in a dm_size_t.
ERRTEST(EINVAL,
"(bad length) write",
dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
"write invalid length test"))
#endif
/*---------------------------------------------------------*/
#if 0
PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
Presumably, this signal is needed to comply with...something.
If this is uncommented, the program will abort here, with the
error message "exceeded file size limit".
ERRTEST(EFBIG,
"write",
dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
0, (long long)0xFFFFFFFFFFLL,
(long long)0xFFFFFFFFFFLL,
"foo foo foo"))
#endif
/*---------------------------------------------------------*/
#ifdef VERITAS_21
ERRTEST(EINVAL,
"(bad offset) write",
dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
0, (dm_size_t) ULONG_MAX, 5,
"write invalid offset test"))
#else
#ifndef linux
ERRTEST(EINVAL,
"(bad offset) write",
dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
0, (dm_size_t) ULONGLONG_MAX, 5,
"write invalid offset test"))
#endif
#endif
/*---------------------------------------------------------*/
ERRTEST(EINVAL,
"(bad sid) write",
dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
0, 0, 26, "write invalid offset test"))
/**** READ tests ****/
/*---------------------------------------------------------*/
SHAREDTEST("read", hanp, hlen, test_token,
dm_read_invis(sid, hanp, hlen, test_token,
0, 13, bufp))
/*---------------------------------------------------------*/
ERRTEST(EBADF,
"read",
dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
0, 0, bufp))
/*---------------------------------------------------------*/
ERRTEST(EFAULT,
"read",
dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
0, 0, bufp))
/*---------------------------------------------------------*/
#ifdef VERITAS_21
ERRTEST(EINVAL,
"(bad offset) read",
dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
ULONG_MAX, 5, bufp));
#else
#ifndef linux
ERRTEST(EINVAL,
"(bad offset) read",
dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
ULONGLONG_MAX, 5, bufp));
#endif
#endif
/*---------------------------------------------------------*/
ERRTEST(EINVAL,
"(bad sid) read",
dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
0, 5, bufp))
/*---------------------------------------------------------*/
printf("\t(errno subtests complete!)\n");
}
sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO",
dir_name);
sprintf(command, "rm %s \n", test_file);
system(command);
printf("Invisible read/write tests complete.\n");
dm_handle_free(hanp, hlen);
exit(0);
}