/***********************************************************
* odintest.c                                               *
* Created 12-Jul-90 by Peter Oerbaek                       *
* This is supposed to be a complete test-suite of the      *
* functions in odin.library                                *
* Modified 13-Jul-90 for ANSI compatibility                *
* Modified 23-Aug-90 for testing of version 2              *
************************************************************/

#include	"exec/types.h"
#include	"exec/tasks.h"
#include	"exec/semaphores.h"
#include	"exec/execbase.h"
#include	"odin.h"
#include	"stdio.h"

void *OpenLibrary();
struct Task *FindTask();
struct Message *GetMsg();
void WaitPort(),FreeMem(),DeletePort();
struct MsgPort *CreatePort();

struct OdinBase *OdinBase;
struct SignalSemaphore ss;
#define CR(s) ObtainSemaphore(&ss); { s } ReleaseSemaphore(&ss);
#define debug(str) CR(printf(str);)

Envelope e1,e2,e3,e4;

struct MsgPort *mp;
struct EnvMsg *msg;

Envelope *my_copyfunc(src,tar)
Envelope *src,*tar;
{
	int i;
	register char *a,*b;

	a = (char *)src; b = (char *)tar;
	for(i = 0; i < e_sizeof; i++) {
		*a++ = *b++;
	}

	return tar;
}

Envelope *process1(e)
Envelope *e;
{
	struct Task *tsk;
	Envelope *env;

	debug("process1 started\n");
	CR(printf("lenght = %ld\n",e->e_len);)

	tsk = FindTask(NULL);
	
	CR(printf("stacksize = %d\n",(int)(tsk->tc_SPUpper - tsk->tc_SPLower));)
	CR(printf("pri = %d\n",(int)tsk->tc_Node.ln_Pri);)
	CR(printf("taskname=%s\n",tsk->tc_Node.ln_Name);)

	debug("creating envelope\n");
	env = CreateEnvelope("Env2",e_sizeof);
	if(env == NULL) { debug("create returned NULL\n"); return e; }

	debug("envelope created\n");

	Delay(100L);
	debug("copyouting\n");
	CopyOut(env);

	Delay(199L);
	debug("copy outing with copyfunc\n");
	env->e_copyfunc = my_copyfunc;
	CopyOut(env);

	debug("normal out\n");
	Out(env);

	debug("wait for V3\n");
	while(!(env = PollNamedEnvelope("V3"))) { 
		debug("waiting with poll.\n");
	}

	debug("got V3 dispose\n");
	DisposeEnvelope(env);

	debug("wait for V4 and dispose\n");
	DisposeEnvelope(AwaitNamedEnvelope("V4"));

	debug("wait for task1\n");
	DisposeEnvelope(AwaitNamedEnvelope("V5"));
	debug("shake hands\n");
	(void)OutEmptyEnvelope("R1");

	(void)OutEmptyEnvelope("envelope3");

	Delay(200L);
	(void)OutEmptyEnvelope("envelope4");
	debug("2 envelopes outed\n");

	(void)OutEmptyEnvelope("te1");
	Delay(300L);
	(void)OutEmptyEnvelope("te2");

	debug("te1 and te2 outed\n");

	(void)AwaitTimed("never",10L,0L);
	debug("awaittaimed timed out after 10 secs\n");

	return e;
}

void task1()
{
	(void)OutEmptyEnvelope("V5");	/* shake hands with process */
	DisposeEnvelope(AwaitNamedEnvelope("R1"));
}

main()
{
	Envelope *ptr;
	struct Task *tsk;
	char buffer[30];
	int i;

	if(!(OdinBase = (struct OdinBase *)OpenLibrary("RAM:odin.library",0L)))
	{
		printf("couldn't find odin.library.\n");
		exit(20);
	}

	mp = CreatePort("testport",0L);

	InitSemaphore(&ss);

	debug("begin\n");

	debug("test InitEnvelope():\n");
	ptr = InitEnvelope(&e1,"Test",e_sizeof,NoCopyFunc);
	debug("init envelope finished\n");
	if(ptr == &e1) {
		debug("returnvalue ok.\n");
		if(strcmp(ptr->e_name,"Test") == 0) {
			debug("name inited ok\n");
		} else {
			debug("name wrong\n");
		}
		if(ptr->e_len == e_sizeof && ptr->e_copyfunc == NULL) {
			debug("inited ok\n");
		} else {
			debug("wrong init\n");
		}
	} else {
		debug("returned wrong value.\n");
	}


	debug("test Eval():\n");
	e1.e_proc = process1;
	(void)Eval(&e1,(long)0,(ULONG)8000,EVAL_PROCESS);
	debug("eval finished\n");

	debug("test rdp\n");
	(void)InitEnvelope(&e2,"Env2",e_sizeof,NoCopyFunc);
	while(!(ptr = Rdp(&e2))) { debug("waiting in rdp\n"); }
	if(ptr == &e2) {
		debug("rdp returned ok\n");
	} else {
		debug("rdp returned wrong\n");
	}
	CR(printf("name returned by rdp: %s\n",e2.e_name);)

	debug("test rd\n");
	(void)InitEnvelope(&e2,"Env2",e_sizeof,NoCopyFunc);
	ptr = Rd(&e2);
	if(ptr == &e2) {
		debug("rd returned ok\n");
	} else {
		debug("rd returned wrong\n");
	}
	CR(printf("name returned by rd: %s\n",ptr->e_name);)

	debug("test In()\n");
	(void)InitEnvelope(&e2,"Env2",e_sizeof,NoCopyFunc);
	ptr = In(&e2);
	if(ptr != &e2) {
		debug("in returned ok\n");
	} else {
		debug("in returned wrong\n");
	}
	CR(printf("name returned by in: %s\n",ptr->e_name);)
	DisposeEnvelope(ptr);

	debug("test AwaitNamedEnvelope()\n");
	ptr = AwaitNamedEnvelope("Env2");
	CR(printf("name returned by Await..: %s\n",ptr->e_name);)
	DisposeEnvelope(ptr);

	debug("test rdp with copyfunc\n");
	(void)InitEnvelope(&e2,"Env2",e_sizeof,NoCopyFunc);
	while(!(ptr = Rdp(&e2))) { debug("waiting in rdp2\n"); }
	if(ptr == &e2) {
		debug("rdp2 returned ok\n");
	} else {
		debug("rdp2 returned wrong\n");
	}
	CR(printf("name returned by rdp2: %s\n",e2.e_name);)

	debug("rd with copyfunc\n");
	(void)InitEnvelope(&e2,"Env2",e_sizeof,NoCopyFunc);
	ptr = Rd(&e2);
	if(ptr == &e2) {
		debug("rd2 returned ok\n");
	} else {
		debug("rd2 returned wrong\n");
	}
	CR(printf("name returned by rd2: %s\n",e2.e_name);)

	DisposeEnvelope(AwaitNamedEnvelope("Env2"));

	Delay(100L);
	Out(CreateEnvelope("V3",e_sizeof));

	(void)OutEmptyEnvelope("V4");

	tsk = StartTask(task1,"Task1",0L,4000L);
	if(tsk == NULL) { debug("couldn't start task\n"); }
	debug("task started\n");

	/*** version 2 additions ***/

	(void)InitEnvelope(&e3,"envelope3",e_sizeof,NoCopyFunc);

	/* wait max 5 secs */
	ptr = TimedRd(&e3,5L,0L);
	if(ptr == &e3) {
		debug("timedrd returned ok\n");
		CR(printf("name returned by TimedRd: %s\n",ptr->e_name);)
	} else {
		debug("timedrd timed out\n");
	}

	debug("ready for timedin\n");
	ptr = TimedIn(&e3,3L,0L);
	if(ptr != 0L) {
		debug("timedin returned ok\n");
		CR(printf("name returned by TimedIn: %s\n",ptr->e_name);)
		DisposeEnvelope(ptr);
	} else {
		debug("timedin timed out\n");
	}
	
	(void)InitEnvelope(&e4,"envelope4",e_sizeof,NoCopyFunc);
	AsyncIn(&e4,mp);

	debug("returned from asyncin, waiting\n");

	WaitPort(mp);
	msg = (struct EnvMsg *)GetMsg(mp);
	debug("got message\n");
	DisposeEnvelope(msg->em_env);
	debug("disposed of envelope\n");
	FreeMem(msg,(long)sizeof(struct EnvMsg));
	debug("freed message\n");

	ptr = AwaitTimed("te1",1L,0L);
	if(ptr != 0L) {
		debug("te1 arrived\n");
		DisposeEnvelope(ptr);
	} else {
		debug("te1 didn't arrive in time\n");
	}

	AsyncRequest("te2",mp);
	debug("waiting for te2\n");

	WaitPort(mp); msg = (struct EnvMsg *)GetMsg(mp);
	DisposeEnvelope(msg->em_env); FreeMem(msg,(long)sizeof(struct EnvMsg));

	/* generate some unique names */
	for(i = 1; i < 200; i++) {
		(void)strcpy(buffer,"prefix");
		CR(printf("%s\n",UniqueName(buffer));)
	}
	
	debug("wait for process to die\n");
	(void)AwaitNamedEnvelope("Test");	
	debug("exiting\n");

	DeletePort(mp);
	CloseLibrary(OdinBase);
}

