sl@0: /*
sl@0: * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description:
sl@0: * Test code for pipes, using dubious WINS extension for multiple processes...
sl@0: * 
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: 
sl@0: #include <stdlib.h>
sl@0: #include <stdio.h>
sl@0: #include <string.h>
sl@0: #include <unistd.h>	/* for MAXPATHLEN */
sl@0: #include <sys/errno.h>
sl@0: #include <sys/ioctl.h>
sl@0: 
sl@0: #include "CTEST.H"
sl@0: 
sl@0: int fids[3];
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1074
sl@0: @SYMTestCaseDesc	    Tests for operations on pipes 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests for command line arguments,directory operations,environment variables.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: int do_main(int argc, char* argv[])
sl@0: 	{
sl@0: 	test_Data;
sl@0: 	int i;
sl@0: 	char* var;
sl@0: 	char* varname;
sl@0: 	char cwd[MAXPATHLEN];
sl@0: 
sl@0: 	test_Title("PIPE");
sl@0: 
sl@0: 	test_Next("Command line arguments");
sl@0: 	test(argc>0);
sl@0: 	test(argv!=0);
sl@0: 	printf("  argc=%d\r\n", argc);
sl@0: 	for (i=0; i<argc; i++)
sl@0: 		{
sl@0: 		test(argv[i]!=0);
sl@0: 		printf("  argv[%d]=\"%s\" length %d\r\n", i, argv[i], strlen(argv[i]));
sl@0: 		}
sl@0: 	printf("\r\n");
sl@0: 
sl@0: 	test_Next("Current working directory");
sl@0: 	var=getcwd(cwd,sizeof(cwd));
sl@0: 	test(var==cwd);
sl@0: 	printf("  %s\r\n\n", cwd);
sl@0: 
sl@0: 	test_Next("Change directory");
sl@0: 	i=chdir("z:/system");
sl@0: 	test(i==0);
sl@0: 	var=getcwd(cwd,sizeof(cwd));
sl@0: 	test(var==cwd);
sl@0: 	printf("  %s\r\n\n", cwd);
sl@0: 
sl@0: 	test_Next("Environment variables");
sl@0: 
sl@0: 	varname="CLASSPATH";
sl@0: 	var=getenv(varname);
sl@0: 	test(var!=0);
sl@0: 	printf("  %s=%s\r\n", varname,var);
sl@0: 
sl@0: 	varname="VARIABLE2";
sl@0: 	var=getenv(varname);
sl@0: 	if (var!=0)
sl@0: 		{
sl@0: 		printf("  %s=%s\r\n", varname,var);
sl@0: 		unsetenv("VARIABLE2");
sl@0: 		}
sl@0: 
sl@0: 	varname="USER";
sl@0: 	var=getenv(varname);
sl@0: 	test(var!=0);
sl@0: 	printf("  %s=%s\r\n\n", varname,var);
sl@0: 
sl@0: 	sleep(5);
sl@0: 
sl@0: 	test_Close();
sl@0: 	return 0;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Bodge up two pretend processes 
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1075
sl@0: @SYMTestCaseDesc	    Tests for operations on pipes 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Excecute the basic test operations
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void do_mainA()
sl@0: 	{
sl@0: 	char* argv[] = { "tpipe.exe", "A" };
sl@0: 
sl@0: 	setenv("CLASSPATH",".;classes;?:/classes;?:/system/java/lib/classes.zip",0);
sl@0: 	setenv("VARIABLE2","value2",0);
sl@0: 	setenv("USER","Tumblin' Duke - Go fer yer guns!",0);
sl@0: 
sl@0: 	do_main(2, argv);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1076
sl@0: @SYMTestCaseDesc	    Tests for operations on pipes 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests for ioctl functions
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void do_mainB()
sl@0: 	{
sl@0: 	test_Data;
sl@0: 	char* argv[] = { "tpipe.exe", "B" };
sl@0: 	int nbytes=1;
sl@0: 	int mask, err;
sl@0: 	int firstread=1;
sl@0: 
sl@0: 	/* Don't use test_* because it involves fflush and will cause deadlock */
sl@0: 	printf("PIPE Child");
sl@0: 
sl@0: 	printf("Child reads from STDIN\n");
sl@0: 	while (nbytes>0)
sl@0: 		{
sl@0: 		char buf[5];
sl@0: 		printf("Child calls read of fid=0\n");
sl@0: 		nbytes=read(0,buf,sizeof(buf));
sl@0: 		printf("Child got %d bytes\n", nbytes);
sl@0: 		if (nbytes>0)
sl@0: 			{
sl@0: 			if (firstread)
sl@0: 				{
sl@0: 				/* We hope that there is still stuff to read */
sl@0: 				printf("Child calls E32IOSELECT(WRITE) on STDIN\n");
sl@0: 				mask=E32SELECT_WRITE;
sl@0: 				err=ioctl(0,E32IOSELECT,(void*)&mask);
sl@0: 				test(err==0);
sl@0: 				test(mask==0);
sl@0: 				printf("Child calls E32IOSELECT(READ) on STDIN\n");
sl@0: 				mask=E32SELECT_READ+E32SELECT_WRITE;
sl@0: 				err=ioctl(0,E32IOSELECT,(void*)&mask);
sl@0: 				test(err==0);
sl@0: 				test(mask==E32SELECT_READ);
sl@0: 				firstread=0;
sl@0: 				}
sl@0: 			printf("  %02d >%.*s<\n", nbytes, nbytes, buf);
sl@0: 			}
sl@0: 		else
sl@0: 		if (nbytes<0)
sl@0: 			printf("  %d (errno=%d)\n", nbytes, errno);
sl@0: 		}
sl@0: 
sl@0: 	printf("Child calls E32IOSELECT on STDOUT");
sl@0: 	mask=E32SELECT_READ+E32SELECT_WRITE;
sl@0: 	err=ioctl(1,E32IOSELECT,(void*)&mask);
sl@0: 	test(err==0);
sl@0: 	test(mask==E32SELECT_WRITE);
sl@0: 
sl@0: 	fflush(stdout);
sl@0: 
sl@0: 	do_main(2, argv);
sl@0: 	fclose(stdout);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1077
sl@0: @SYMTestCaseDesc	    Tests for operations on pipes 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests for file descriptors
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void do_piping()
sl@0: 	{
sl@0: 	test_Data;
sl@0: 	char* s;
sl@0: 	char buf[180];
sl@0: 
sl@0: 	test_Title("PIPE");
sl@0: 
sl@0: 	test_Next("Pipe file descriptors");
sl@0: 	printf("  fids= %d, %d, %d\n", fids[0], fids[1], fids[2]);
sl@0: 
sl@0: 	if (fids[0]>=0)
sl@0: 		{
sl@0: 		int nbytes;
sl@0: 		int remainder;
sl@0: 		int mask, err;
sl@0: 		const char* buf="test data 18 bytes";
sl@0: 
sl@0: 		test_Next("E32IOSELECT(READ) on Child STDIN");
sl@0: 		mask=E32SELECT_READ;
sl@0: 		err=ioctl(fids[0],E32IOSELECT,(void*)&mask);
sl@0: 		test(err==0);
sl@0: 		test(mask==0);
sl@0: 		test_Next("E32IOSELECT(WRITE) on Child STDIN");
sl@0: 		mask=E32SELECT_READ+E32SELECT_WRITE;
sl@0: 		err=ioctl(fids[0],E32IOSELECT,(void*)&mask);
sl@0: 		test(err==0);
sl@0: 		test(mask==E32SELECT_WRITE);
sl@0: 
sl@0: 		test_Next("Child STDIN");
sl@0: 		remainder=strlen(buf);
sl@0: 		while (remainder>0)
sl@0: 			{
sl@0: 			int length=(remainder<7)?remainder:7;
sl@0: 			nbytes=write(fids[0],buf,length);
sl@0: 			printf("  >%.*s<",nbytes,buf);
sl@0: 			buf+=nbytes;
sl@0: 			remainder-=nbytes;
sl@0: 			test(nbytes>0);
sl@0: 			test(nbytes<=length);
sl@0: 			}
sl@0: 		printf("\n");
sl@0: 		close(fids[0]);
sl@0: 		sleep(5);
sl@0: 		}
sl@0: 	if (fids[1]>=0)
sl@0: 		{
sl@0: 		FILE* cout;
sl@0: 		int mask, err;
sl@0: 		int firstread=1;
sl@0: 
sl@0: 		test_Next("Child STDOUT");
sl@0: 		cout=fdopen(fids[1],"r");
sl@0: 		test(cout!=0);
sl@0: 
sl@0: 		do
sl@0: 			{
sl@0: 			s=fgets(buf,sizeof(buf),cout);
sl@0: 			if (s!=0)
sl@0: 				{
sl@0: 				printf("  >%s", s);
sl@0: 				if (firstread)
sl@0: 					{
sl@0: 					test_Next("\nE32IOSELECT(WRITE) on Child STDOUT");
sl@0: 					mask=E32SELECT_WRITE;
sl@0: 					err=ioctl(fids[1],E32IOSELECT,(void*)&mask);
sl@0: 					test(err==0);
sl@0: 					test(mask==0);
sl@0: 					test_Next("E32IOSELECT(READ) on Child STDOUT");
sl@0: 					mask=E32SELECT_READ+E32SELECT_WRITE;
sl@0: 					err=ioctl(fids[1],E32IOSELECT,(void*)&mask);
sl@0: 					test(err==0);
sl@0: 					test(mask==E32SELECT_READ);
sl@0: 					firstread=0;
sl@0: 					}
sl@0: 				}
sl@0: 			}
sl@0: 		while (s!=0);
sl@0: 		fclose(cout);
sl@0: 		}
sl@0: 
sl@0: 	test_Close();
sl@0: 	}
sl@0: 
sl@0: /* Linked with mcrt0.o, so that the exe starts the CPosixServer automatically as per the
sl@0:  * plan all along.
sl@0:  */
sl@0: 
sl@0: int main(int argc, char* argv[])
sl@0: 	{
sl@0: 	void* proc2;
sl@0: 
sl@0: 	start_redirection_server();
sl@0: 
sl@0: 	if (argc==1)
sl@0: 		{
sl@0: 		do_mainA();
sl@0: 		sleep(5);
sl@0: 		proc2 = create_process(do_mainB, "B", "rw", fids);
sl@0: 		if (proc2)
sl@0: 			start_process(proc2);
sl@0: 		else
sl@0: 			perror("Failed to start processB: ");
sl@0: 
sl@0: 		if (proc2)
sl@0: 			{
sl@0: 			int exit;
sl@0: 			do_piping();
sl@0: 			exit=wait_for_process(proc2);
sl@0: 			printf("wait_for_process returned %d\r\n", exit);
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		do_mainB();
sl@0: 		}
sl@0: 
sl@0: 	return 0;
sl@0: 	}