-
Rob Swindell authoredRob Swindell authored
wraptest.c 10.14 KiB
/* wraptest.c */
/* Verification of cross-platform development wrappers */
/* $Id: wraptest.c,v 1.45 2019/07/24 04:15:54 rswindell Exp $ */
#include <time.h> /* ctime */
#include "genwrap.h"
#include "conwrap.h"
#include "dirwrap.h"
#include "filewrap.h"
#include "sockwrap.h"
#include "threadwrap.h"
#include "xpbeep.h"
#include "xpendian.h"
#define LOCK_FNAME "test.fil"
#define LOCK_OFFSET 0
#define LOCK_LEN 4
static void getkey(void);
static void sem_test_thread(void* arg);
static void sem_test_thread_block(void* arg);
static void sleep_test_thread(void* arg);
static void sopen_test_thread(void* arg);
static void sopen_child_thread(void* arg);
static void lock_test_thread(void* arg);
typedef struct {
sem_t parent_sem;
sem_t child_sem;
} thread_data_t;
int main()
{
char str[128];
char compiler[128];
char fpath[MAX_PATH+1];
char* path = ".";
char* glob_pattern = "*wrap*";
int i;
int ch;
uint u;
time_t t;
glob_t g;
DIR* dir;
DIRENT* dirent;
thread_data_t thread_data;
int fd;
int fd2;
int canrelock=0;
clock_t ticks;
/* Show platform details */
DESCRIBE_COMPILER(compiler);
printf("%-15s: %s\n","Platform",PLATFORM_DESC);
printf("%-15s: %s\n","Version",os_version(str));
printf("%-15s: %s\n","Compiler" ,compiler);
printf("%-15s: %ld\n","Random Number",xp_random(1000));
for(i=0;i<3;i++) {
if(_beginthread(
sopen_child_thread /* entry point */
,0 /* stack size (0=auto) */
,(void*)i /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else
SLEEP(1);
}
printf("Waiting for all sopen_child_threads to close...\n");
SLEEP(5000); /* wait for all threads to quit */
/* Exclusive sopen test */
printf("\nsopen() test\n");
if((fd=sopen(LOCK_FNAME,O_RDWR|O_CREAT,SH_DENYRW,S_IREAD|S_IWRITE))==-1) {
perror(LOCK_FNAME);
return(errno);
}
printf("%s is opened with an exclusive (read/write) lock\n",LOCK_FNAME);
getkey();
if(_beginthread(
sopen_test_thread /* entry point */
,0 /* stack size (0=auto) */
,NULL /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else
SLEEP(1000);
close(fd);
/* sopen()/lock test */
printf("\nlock() test\n");
if((fd=sopen(LOCK_FNAME,O_RDWR|O_CREAT,SH_DENYNO,S_IREAD|S_IWRITE))==-1) {
perror(LOCK_FNAME);
return(errno);
}
write(fd,"lock testing\n",LOCK_LEN);
if(lock(fd,LOCK_OFFSET,LOCK_LEN)==0)
printf("lock() succeeds\n");
else
printf("!FAILURE: lock() non-functional (or file already locked)\n");
if(lock(fd,LOCK_OFFSET,LOCK_LEN)==0) {
printf("!FAILURE: Subsequent lock of region was allowed (will skip some tests)\n");
canrelock=1;
}
if(_beginthread(
lock_test_thread /* entry point */
,0 /* stack size (0=auto) */
,NULL /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else
SLEEP(1000);
if(canrelock)
printf("?? Skipping some tests due to inability to detect own locks\n");
else {
if(lock(fd,LOCK_OFFSET,LOCK_LEN))
printf("Locks in first thread survive open()/close() in other thread\n");
else
printf("!FAILURE: lock() in first thread lost by open()/close() in other thread\n");
if(lock(fd,LOCK_OFFSET+LOCK_LEN+1,LOCK_LEN))
printf("!FAILURE: file locking\n");
else
printf("Record locking\n");
}
if((fd2=sopen(LOCK_FNAME,O_RDWR,SH_DENYRW))==-1) {
printf("Cannot reopen SH_DENYRW while lock is held\n");
close(fd2);
}
else {
printf("!FAILURE: can reopen SH_DENYRW while lock is held\n");
}
if(unlock(fd,LOCK_OFFSET,LOCK_LEN))
printf("!FAILURE: unlock() non-functional\n");
if(lock(fd,LOCK_OFFSET+LOCK_LEN+1,LOCK_LEN))
printf("Cannot re-lock after non-overlapping unlock()\n");
else
printf("!FAILURE: can re-lock after non-overlappping unlock()\n");
if(lock(fd,LOCK_OFFSET,LOCK_LEN))
printf("!FAILURE: cannot re-lock unlocked area\n");
close(fd);
/* getch test */
printf("\ngetch() test (ESC to continue)\n");
do {
ch=getch();
printf("getch() returned %d\n",ch);
} while(ch!=ESC);
/* kbhit test */
printf("\nkbhit() test (any key to continue)\n");
while(!kbhit()) {
printf(".");
fflush(stdout);
SLEEP(500);
}
getch(); /* remove character from keyboard buffer */
/* BEEP test */
printf("\nBEEP() test\n");
getkey();
for(i=750;i>250;i-=5)
BEEP(i,15);
for(;i<1000;i+=5)
BEEP(i,15);
/* SLEEP test */
printf("\nSLEEP(5 second) test\n");
getkey();
t=time(NULL);
printf("sleeping... ");
fflush(stdout);
ticks=msclock();
SLEEP(5000);
printf("slept %ld seconds (%ld according to msclock)\n",time(NULL)-t,(msclock()-ticks)/MSCLOCKS_PER_SEC);
/* Thread SLEEP test */
printf("\nThread SLEEP(5 second) test\n");
getkey();
i=0;
if(_beginthread(
sleep_test_thread /* entry point */
,0 /* stack size (0=auto) */
,&i /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else {
SLEEP(1); /* yield to child thread */
while(i==0) {
printf(".");
fflush(stdout);
SLEEP(1000);
}
}
/* glob test */
printf("\nglob(%s) test\n",glob_pattern);
getkey();
i=glob(glob_pattern,GLOB_MARK,NULL,&g);
if(i==0) {
for(u=0;u<g.gl_pathc;u++)
printf("%s\n",g.gl_pathv[u]);
globfree(&g);
} else
printf("glob(%s) returned %d\n",glob_pattern,i);
/* opendir (and other directory functions) test */
printf("\nopendir(%s) test\n",path);
getkey();
printf("\nDirectory of %s\n\n",FULLPATH(fpath,path,sizeof(fpath)));
dir=opendir(path);
while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
t=fdate(dirent->d_name);
printf("%.24s %10lu %06o %s%c\n"
,ctime(&t)
,flength(dirent->d_name)
,getfattr(dirent->d_name)
,dirent->d_name
,isdir(dirent->d_name) ? '/':0
);
}
if(dir!=NULL)
closedir(dir);
printf("\nFree disk space: %lu kbytes\n",getfreediskspace(path,1024));
/* Thread (and inter-process communication) test */
printf("\nSemaphore test\n");
getkey();
if(sem_init(&thread_data.parent_sem
,0 /* shared between processes */
,0 /* initial count */
)) {
printf("sem_init failed\n");
}
if(sem_init(&thread_data.child_sem
,0 /* shared between processes */
,0 /* initial count */
)) {
printf("sem_init failed\n");
}
if(_beginthread(
sem_test_thread /* entry point */
,0 /* stack size (0=auto) */
,&thread_data /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else {
sem_wait(&thread_data.child_sem); /* wait for thread to begin */
for(i=0;i<10;i++) {
printf("<parent>");
sem_post(&thread_data.parent_sem);
sem_wait(&thread_data.child_sem);
}
sem_wait(&thread_data.child_sem); /* wait for thread to end */
}
sem_destroy(&thread_data.parent_sem);
sem_destroy(&thread_data.child_sem);
printf("\nSemaphore blocking test\n");
getkey();
sem_init(&thread_data.parent_sem
,0 /* shared between processes */
,0 /* initial count */
);
sem_init(&thread_data.child_sem
,0 /* shared between processes */
,0 /* initial count */
);
if(_beginthread(
sem_test_thread_block /* entry point */
,0 /* stack size (0=auto) */
,&thread_data /* data */
)==(unsigned long)-1)
printf("_beginthread failed\n");
else {
sem_wait(&thread_data.child_sem); /* wait for thread to begin */
for(i=0;i<10;i++) {
printf("<parent>");
SLEEP(5000);
sem_post(&thread_data.parent_sem);
sem_wait(&thread_data.child_sem);
}
sem_wait(&thread_data.child_sem); /* wait for thread to end */
}
printf("\nsem_trywait_block test...");
t=time(NULL);
sem_trywait_block(&thread_data.parent_sem,5000);
printf("\ntimed-out after %ld seconds (should be 5 seconds)\n",time(NULL)-t);
sem_destroy(&thread_data.parent_sem);
sem_destroy(&thread_data.child_sem);
printf("\nendian check...");
memcpy(&i,"\x01\x02\x03\x04",4);
if(LE_LONG(i)==67305985) {
printf("OK!\n");
}
else {
printf("FAILED!\n");
}
return 0;
}
static void getkey(void)
{
printf("Hit any key to continue...");
fflush(stdout);
getch();
printf("\r%30s\r","");
fflush(stdout);
}
static void sleep_test_thread(void* arg)
{
time_t t=time(NULL);
printf("child sleeping");
fflush(stdout);
SLEEP(5000);
printf("\nchild awake after %ld seconds\n",time(NULL)-t);
*(int*)arg=1; /* signal parent: we're done */
}
static void sem_test_thread(void* arg)
{
ulong i;
thread_data_t* data = (thread_data_t*)arg;
printf("sem_test_thread entry\n");
sem_post(&data->child_sem); /* signal parent: we've started */
for(i=0;i<10;i++) {
sem_wait(&data->parent_sem);
printf(" <child>\n");
sem_post(&data->child_sem);
}
printf("sem_test_thread exit\n");
sem_post(&data->child_sem); /* signal parent: we're done */
}
static void sem_test_thread_block(void* arg)
{
ulong i;
thread_data_t* data = (thread_data_t*)arg;
printf("sem_test_thread_block entry\n");
sem_post(&data->child_sem); /* signal parent: we've started */
for(i=0;i<10;i++) {
if(sem_trywait_block(&data->parent_sem,500)) {
printf(" sem_trywait_block() timed out");
sem_wait(&data->parent_sem);
}
else {
printf(" FAILURE: Didn't block");
}
printf(" <child>\n");
sem_post(&data->child_sem);
}
printf("sem_test_thread_block exit\n");
sem_post(&data->child_sem); /* signal parent: we're done */
}
static void lock_test_thread(void* arg)
{
int fd;
fd=sopen(LOCK_FNAME,O_RDWR,SH_DENYNO);
if(lock(fd,LOCK_OFFSET,LOCK_LEN)==0)
printf("!FAILURE: Lock not effective between threads\n");
else
printf("Locks effective between threads\n");
close(fd);
fd=sopen(LOCK_FNAME,O_RDWR,SH_DENYNO);
if(lock(fd,LOCK_OFFSET,LOCK_LEN))
printf("Locks survive file open()/close() in other thread\n");
else
printf("!FAILURE: Locks do not survive file open()/close() in other thread\n");
close(fd);
}
static void sopen_test_thread(void* arg)
{
int fd;
if((fd=sopen(LOCK_FNAME,O_RDWR,SH_DENYWR))!=-1)
printf("!FAILURE: allowed to reopen with SH_DENYWR\n");
else if((fd=sopen(LOCK_FNAME,O_RDWR,SH_DENYRW))!=-1)
printf("!FAILURE: allowed to reopen with SH_DENYRW\n");
else
printf("reopen disallowed\n");
if(fd!=-1)
close(fd);
}
static void sopen_child_thread(void* arg)
{
int fd;
printf("sopen_child_thread: %d begin\n",(int)arg);
if((fd=sopen(LOCK_FNAME,O_RDWR,SH_DENYRW))!=-1) {
if(arg)
printf("!FAILURE: was able to reopen in child thread\n");
else {
SLEEP(5000);
}
close(fd);
} else if(arg==0)
perror(LOCK_FNAME);
printf("sopen_child_thread: %d end\n",(int)arg);
}
/* End of wraptest.c */