michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: ** File: anonfm.c michael@0: ** Description: Test anonymous file map michael@0: ** michael@0: ** Synopsis: anonfm [options] [dirName] michael@0: ** michael@0: ** Options: michael@0: ** -d enable debug mode michael@0: ** -h display a help message michael@0: ** -s size of the anonymous memory map, in KBytes. default: 100KBytes. michael@0: ** -C 1 Operate this process as ClientOne() michael@0: ** -C 2 Operate this process as ClientTwo() michael@0: ** michael@0: ** anonfn.c contains two tests, corresponding to the two protocols for michael@0: ** passing an anonymous file map to a child process. michael@0: ** michael@0: ** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses michael@0: ** PR_CreateProcess() [for portability of the test case] to create the michael@0: ** child process, but does not use the PRProcessAttr structure for michael@0: ** passing the file map data. michael@0: ** michael@0: ** ServerTwo()/ClientTwo() tests the passing of the file map using the michael@0: ** PRProcessAttr structure. michael@0: ** michael@0: */ michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: /* michael@0: ** Test harness infrastructure michael@0: */ michael@0: PRLogModuleInfo *lm; michael@0: PRLogModuleLevel msgLevel = PR_LOG_NONE; michael@0: PRUint32 failed_already = 0; michael@0: michael@0: PRIntn debug = 0; michael@0: PRIntn client = 0; /* invoke client, style */ michael@0: char dirName[512] = "."; /* directory name to contain anon mapped file */ michael@0: PRSize fmSize = (100 * 1024 ); michael@0: PRUint32 fmMode = 0600; michael@0: PRFileMapProtect fmProt = PR_PROT_READWRITE; michael@0: const char *fmEnvName = "nsprFileMapEnvVariable"; michael@0: michael@0: /* michael@0: ** Emit help text for this test michael@0: */ michael@0: static void Help( void ) michael@0: { michael@0: printf("anonfm [options] [dirName]\n"); michael@0: printf("-d -- enable debug mode\n"); michael@0: printf("dirName is alternate directory name. Default: . (current directory)\n"); michael@0: exit(1); michael@0: } /* end Help() */ michael@0: michael@0: michael@0: /* michael@0: ** ClientOne() -- michael@0: */ michael@0: static void ClientOne( void ) michael@0: { michael@0: PRFileMap *fm; michael@0: char *fmString; michael@0: char *addr; michael@0: PRStatus rc; michael@0: michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne() starting")); michael@0: michael@0: fmString = PR_GetEnv( fmEnvName ); michael@0: if ( NULL == fmString ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_Getenv() failed")); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_Getenv(): found: %s", fmString)); michael@0: michael@0: fm = PR_ImportFileMapFromString( fmString ); michael@0: if ( NULL == fm ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_ImportFileMapFromString() failed")); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm )); michael@0: michael@0: addr = PR_MemMap( fm, LL_ZERO, fmSize ); michael@0: if ( NULL == addr ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError() )); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_MemMap(): addr: %p", addr )); michael@0: michael@0: /* write to memory map to release server */ michael@0: *addr = 1; michael@0: michael@0: rc = PR_MemUnmap( addr, fmSize ); michael@0: PR_ASSERT( rc == PR_SUCCESS ); michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_MemUnap(): success" )); michael@0: michael@0: rc = PR_CloseFileMap( fm ); michael@0: if ( PR_FAILURE == rc ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError() )); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ClientOne(): PR_CloseFileMap(): success" )); michael@0: michael@0: return; michael@0: } /* end ClientOne() */ michael@0: michael@0: /* michael@0: ** ClientTwo() -- michael@0: */ michael@0: static void ClientTwo( void ) michael@0: { michael@0: failed_already = 1; michael@0: } /* end ClientTwo() */ michael@0: michael@0: /* michael@0: ** ServerOne() -- michael@0: */ michael@0: static void ServerOne( void ) michael@0: { michael@0: PRFileMap *fm; michael@0: PRStatus rc; michael@0: PRIntn i; michael@0: char *addr; michael@0: char fmString[256]; michael@0: char envBuf[256]; michael@0: char *child_argv[8]; michael@0: PRProcess *proc; michael@0: PRInt32 exit_status; michael@0: michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne() starting")); michael@0: michael@0: fm = PR_OpenAnonFileMap( dirName, fmSize, fmProt ); michael@0: if ( NULL == fm ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("PR_OpenAnonFileMap() failed")); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): FileMap: %p", fm )); michael@0: michael@0: rc = PR_ExportFileMapAsString( fm, sizeof(fmString), fmString ); michael@0: if ( PR_FAILURE == rc ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("PR_ExportFileMap() failed")); michael@0: return; michael@0: } michael@0: michael@0: /* michael@0: ** put the string into the environment michael@0: */ michael@0: PR_snprintf( envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString); michael@0: putenv( envBuf ); michael@0: michael@0: addr = PR_MemMap( fm, LL_ZERO, fmSize ); michael@0: if ( NULL == addr ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("PR_MemMap() failed")); michael@0: return; michael@0: } michael@0: michael@0: /* set initial value for client */ michael@0: for (i = 0; i < (PRIntn)fmSize ; i++ ) michael@0: *(addr+i) = 0x00; michael@0: michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): PR_MemMap(): addr: %p", addr )); michael@0: michael@0: /* michael@0: ** set arguments for child process michael@0: */ michael@0: child_argv[0] = "anonfm"; michael@0: child_argv[1] = "-C"; michael@0: child_argv[2] = "1"; michael@0: child_argv[3] = NULL; michael@0: michael@0: proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); michael@0: PR_ASSERT( proc ); michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): PR_CreateProcess(): proc: %x", proc )); michael@0: michael@0: /* michael@0: ** ClientOne() will set the memory to 1 michael@0: */ michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): waiting on Client, *addr: %x", *addr )); michael@0: while( *addr == 0x00 ) { michael@0: if ( debug ) michael@0: fprintf(stderr, "."); michael@0: PR_Sleep(PR_MillisecondsToInterval(300)); michael@0: } michael@0: if ( debug ) michael@0: fprintf(stderr, "\n"); michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): Client responded" )); michael@0: michael@0: rc = PR_WaitProcess( proc, &exit_status ); michael@0: PR_ASSERT( PR_FAILURE != rc ); michael@0: michael@0: rc = PR_MemUnmap( addr, fmSize); michael@0: if ( PR_FAILURE == rc ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("PR_MemUnmap() failed")); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): PR_MemUnmap(): success" )); michael@0: michael@0: rc = PR_CloseFileMap(fm); michael@0: if ( PR_FAILURE == rc ) { michael@0: failed_already = 1; michael@0: PR_LOG(lm, msgLevel, michael@0: ("PR_CloseFileMap() failed")); michael@0: return; michael@0: } michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerOne(): PR_CloseFileMap() success" )); michael@0: michael@0: return; michael@0: } /* end ServerOne() */ michael@0: michael@0: /* michael@0: ** ServerTwo() -- michael@0: */ michael@0: static void ServerTwo( void ) michael@0: { michael@0: PR_LOG(lm, msgLevel, michael@0: ("ServerTwo(): Not implemented yet" )); michael@0: } /* end ServerTwo() */ michael@0: michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: { michael@0: /* michael@0: ** Get command line options michael@0: */ michael@0: PLOptStatus os; michael@0: PLOptState *opt = PL_CreateOptState(argc, argv, "hdC:"); michael@0: michael@0: while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) michael@0: { michael@0: if (PL_OPT_BAD == os) continue; michael@0: switch (opt->option) michael@0: { michael@0: case 'C': /* Client style */ michael@0: client = atol(opt->value); michael@0: break; michael@0: case 's': /* file size */ michael@0: fmSize = atol( opt->value ) * 1024; michael@0: break; michael@0: case 'd': /* debug */ michael@0: debug = 1; michael@0: msgLevel = PR_LOG_DEBUG; michael@0: break; michael@0: case 'h': /* help message */ michael@0: Help(); michael@0: break; michael@0: default: michael@0: strcpy(dirName, opt->value); michael@0: break; michael@0: } michael@0: } michael@0: PL_DestroyOptState(opt); michael@0: } michael@0: michael@0: lm = PR_NewLogModule("Test"); /* Initialize logging */ michael@0: michael@0: if ( client == 1 ) { michael@0: ClientOne(); michael@0: } else if ( client == 2 ) { michael@0: ClientTwo(); michael@0: } else { michael@0: ServerOne(); michael@0: if ( failed_already ) goto Finished; michael@0: ServerTwo(); michael@0: } michael@0: michael@0: Finished: michael@0: if ( debug ) michael@0: printf("%s\n", (failed_already)? "FAIL" : "PASS"); michael@0: return( (failed_already == PR_TRUE )? 1 : 0 ); michael@0: } /* main() */ michael@0: /* end anonfm.c */ michael@0: