summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2hg <devnull@localhost>2001-06-27 02:57:52 +0000
committercvs2hg <devnull@localhost>2001-06-27 02:57:52 +0000
commitb1436512cf9072e3f2e301fee0bbd95c78660f36 (patch)
treee73486417521f562784a101580cc03df1d3169ae
parent44a198477328df3d60378a40033e984c3a6ace66 (diff)
downloadnspr-hg-FASTLOAD_20010703_BASE.tar.gz
fixup commit for branch 'FASTLOAD_20010703_BRANCH'FASTLOAD_20010703_BASE
-rw-r--r--lib/tests/event.c366
-rw-r--r--pr/src/md/mac/prgcleak.c99
-rw-r--r--pr/src/md/unix/os_Linux_ia64.s80
-rw-r--r--pr/src/md/unix/os_SunOS_sparcv9.s201
-rw-r--r--pr/tests/acceptreademu.c299
-rw-r--r--pr/tests/append.c155
-rw-r--r--pr/tests/env.c218
-rw-r--r--pr/tests/errset.c183
-rw-r--r--pr/tests/freeif.c72
-rw-r--r--pr/tests/intrio.c166
-rw-r--r--pr/tests/obsints.c80
-rw-r--r--pr/tests/peek.c389
-rw-r--r--pr/tests/pipeping2.c189
-rw-r--r--pr/tests/pipepong2.c127
-rw-r--r--pr/tests/primblok.c145
-rw-r--r--pr/tests/prpollml.c159
-rw-r--r--pr/tests/rmdir.c124
-rw-r--r--pr/tests/selintr.c78
18 files changed, 2665 insertions, 465 deletions
diff --git a/lib/tests/event.c b/lib/tests/event.c
deleted file mode 100644
index af94538a..00000000
--- a/lib/tests/event.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.1 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
-/*
-** File: event.c
-** Description: Test functions in plevent.c
-**
-** This test creates a number of threads. Each thread sends
-** an event to the next higher numbered (in creation order)
-** thread. On receipt of that event, that thread in turn
-** sends an event to the next thread until the event goes
-** around the circle of threads. The test self terminates
-** after a predetermined number of events have circled the
-** circle of threads.
-**
-**
-** Internal Design
-**
-** TState:
-** TState is the Event Handler State Strucuture. It
-** contains the state for an EventThread. There is one TState
-** structure per thread running in the EventThread()
-** function.
-**
-** TestEvents():
-** The TestEvent() function is the "real main()" function of
-** this test. The function creates 'numThreads' instances of
-** a thread running the EventThread() function. He then waits
-** for these threads to complete.
-**
-** EventThread():
-** The EventThread() function runs in the context of a thread
-** instance created by TestEvents(). The function processes
-** events from threads running the same function. An event is
-** created and sent around the ring
-**
-** EventHandler():
-** The EventHandler() function processes events received by
-** EventThread(). His job is to create and send a new event
-** to the next EventThread() thread in the ring of threads.
-**
-** EventDestructor():
-** The EventDestructor() function disposes of the event.
-** Required by the protocol for PLEvent.
-**
-**
-*/
-
-#include "nspr.h"
-#include "plgetopt.h"
-#include "plevent.h"
-
-/*
-** TState -- Event Handler State Structure
-**
-*/
-typedef struct TState
-{
- PRIntn threadIndex; /* thread number. [0..n] */
- PRIntn quitSwitch; /* when 0, running; when 1, order to quit */
- PLEventQueue *eventQueue; /* event queue for this thread */
-} TState;
-
-/*
-** Thread Event structure
-*/
-typedef struct TEvent
-{
- PLEvent plEvent;
- PRIntn tIndex; /* Thread index of thread receiving event */
- PRIntn quitSwitch; /* when 0, keep going; when 1 set TState[me].quitSwitch = 1 */
-} TEvent;
-
-static void PR_CALLBACK EventHandler( TEvent *ep );
-static void PR_CALLBACK EventDestructor( TEvent *ep );
-PR_EXTERN(PRIntn) TestEvents( void );
-
-/* --- Global data ---------------------------------------*/
-
-static PRIntn failed = 0; /* when 1, indicates test failed */
-static PRLogModuleInfo *lm; /* LogModule "test" */
-
-static PRIntn numThreads = 4; /* Number of threads in the ring */
-static PRIntn iterations = 7; /* Number of iterations per thread */
-
-static PRIntn iterationCount = 0; /* Counting times around the ring */
-
-static PRIntn activeThreads = 0; /* Number of active threads */
-static TState *tsa = NULL; /* array of all TStates */
-static PRMonitor *mon;
-static PRBool useMonitoredQueue = PR_FALSE;
-
-/*
-** SendEvent() -- Send an event to the next thread
-**
-*/
-static void SendEvent(
- PRIntn threadIndex,
- PRIntn quitSwitch
-)
-{
- PLEventQueue *eq = (tsa+threadIndex)->eventQueue;
- TEvent *event = PR_NEWZAP( TEvent );
-
- PR_ASSERT( event != NULL );
-
- PR_LOG( lm, PR_LOG_NOTICE, ("SendEvent: event: %p, threadIndex: %d quitSwitch: %d", event, threadIndex, quitSwitch ));
- PL_ENTER_EVENT_QUEUE_MONITOR( eq );
-
- PL_InitEvent( &event->plEvent, 0,
- (PLHandleEventProc)EventHandler,
- (PLDestroyEventProc)EventDestructor );
- event->quitSwitch = quitSwitch;
- event->tIndex = threadIndex;
-
- PL_PostEvent( eq, &event->plEvent );
- PL_EXIT_EVENT_QUEUE_MONITOR( eq );
- return;
-} /* end SendEvent() */
-
-
-/*
-** EventHandler() -- Handle events posted from EventThread()
-**
-** if message says quit
-** Tell my thread to quit.
-** create an event, if I quit, pass it on.
-** PostEvent( TEvent.threadIndex+1)
-**
-*/
-static void PR_CALLBACK EventHandler( TEvent *ep )
-{
- TState *ts = tsa+(ep->tIndex);
- PRIntn ndx;
-
- PR_LOG( lm, PR_LOG_NOTICE, ("EventHandler: %p, ti: %d", ep, ep->tIndex ));
- if ( ep->quitSwitch == PR_TRUE )
- ts->quitSwitch = PR_TRUE;
-
- if ( ts->threadIndex == 0 )
- {
- if ( iterationCount++ >= iterations )
- ep->quitSwitch = PR_TRUE;
- }
- /*
- ** Calculate thread index of the next thread to get an event,
- ** then send him the event.
- */
- ndx = ep->tIndex +1;
- if ( ndx >= numThreads )
- ndx = 0;
-
- SendEvent( ndx, ep->quitSwitch );
-
- return;
-} /* end EventHandler() */
-
-/*
-** EventDestructor() -- Free the event handled in EventHandler()
-**
-** free(the event)
-**
-*/
-static void PR_CALLBACK EventDestructor( TEvent *ep )
-{
- PR_LOG( lm, PR_LOG_NOTICE, ("EventDestructor: event: %p", ep ));
- PR_Free( ep );
- return;
-} /* end EventDestructor() */
-
-/*
-** EventThread() -- Drive events around the ring of threads
-**
-** do
-** WaitforEvent()
-** HandleEvent()
-** PR_LOG( the event)
-** until told to quit
-**
-*/
-static void EventThread( void *arg )
-{
- TEvent *ep;
- TState *ts = (TState *)arg;
-
-
- while ( ts->eventQueue == 0 )
- PR_Sleep( PR_MillisecondsToInterval(100));
-
- do {
- ep = (TEvent *)PL_WaitForEvent( ts->eventQueue );
- PL_HandleEvent( (PLEvent *)ep );
- PR_LOG( lm, PR_LOG_NOTICE,("EventThread() Handled event: %d", ts->threadIndex ));
- } while( ts->quitSwitch == 0 );
-
- PR_EnterMonitor( mon );
- activeThreads--;
- PR_Notify( mon );
- PR_ExitMonitor( mon );
-
- PR_LOG( lm, PR_LOG_NOTICE,("EventThread() Exit: %d", ts->threadIndex ));
-
- return;
-} /* end EventThread() */
-
-/*
-** TestEvents() --
-**
-** Create array of TEvents
-** CreateThreads of EventThreads
-** PostEvent() to the first EventThread
-** monitor for completion.
-** report results.
-**
-*/
-PR_IMPLEMENT( PRIntn ) TestEvents( void )
-{
- PRIntn i;
-
- lm = PR_NewLogModule( "test" );
- PR_LOG( lm, PR_LOG_NOTICE,("TestEvent(): Starting" ));
- mon = PR_NewMonitor();
-
- /*
- ** Allocate array of all TEvents
- */
- tsa = PR_Calloc( numThreads ,sizeof(TState));
-
- /*
- ** Initialize this event queue and create its thead
- */
- PR_ASSERT( tsa != NULL );
- activeThreads = numThreads;
- for ( i = 0 ; i < numThreads; i++ )
- {
- PRThread *me;
- PLEventQueue *eq;
-
- (tsa +i)->threadIndex = i;
- (tsa +i)->quitSwitch = 0;
- me = PR_CreateThread( PR_USER_THREAD,
- EventThread,
- (void *)(tsa +i),
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0 );
- if ( me == NULL )
- {
- PR_LOG( lm, PR_LOG_ERROR, ("TestEvents: Can't create thread %d", i ));
- exit(1);
- }
-
- if ( useMonitoredQueue == PR_TRUE )
- eq = PL_CreateMonitoredEventQueue( "EventThread", me );
- else
- eq = PL_CreateNativeEventQueue( "EventThread", me );
- PR_ASSERT( eq != NULL );
-
- (tsa+i)->eventQueue = eq;
- }
-
-
- /*
- ** Post and event to the first thread in the ring
- ** to get things started.
- */
- SendEvent( 0, 0 );
- /*
- ** Wait for all threads to exit
- */
- PR_EnterMonitor( mon );
- while ( activeThreads > 0 )
- PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
- PR_ExitMonitor( mon );
-
- /*
- ** Release assets: event queue for each thread, the list of TStates.
- */
- for ( i = 0 ; i < numThreads; i++ )
- {
- PL_DestroyEventQueue( (tsa +i)->eventQueue );
- }
- PR_Free( tsa );
-
- /*
- ** All done! Log completion and return
- */
- PR_LOG( lm, PR_LOG_NOTICE,("TestEvent(): Ending" ));
- return 0;
-} /* end TestEvents() */
-
-
-
-
-static void Help( void )
-{
- printf( "Event: Help\n"
- "syntax: event [-d][-h]\n"
- "where: -h gives this message\n"
- " -d sets debug mode (a no-op here)\n"
- );
-} /* end Help() */
-
-PRIntn main(PRIntn argc, char **argv )
-{
- PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "dhmt:i:");
-
-
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) continue;
- switch (opt->option)
- {
- case 'm': /* use monitored event queue */
- useMonitoredQueue = PR_TRUE;
- break;
- case 'd': /* debug mode (noop) */
- break;
- case 't': /* needs guidance */
- numThreads = atol(opt->value);
- break;
- case 'i': /* needs guidance */
- iterations = atol(opt->value);
- break;
- case 'h': /* needs guidance */
- default:
- Help();
- return 2;
- }
- }
- PL_DestroyOptState(opt);
-
- TestEvents();
- /*
- ** Evaluate results and exit
- */
- if (failed)
- {
- printf("FAILED\n");
- return(1);
- }
- else
- {
- printf("PASSED\n");
- return(0);
- }
-} /* end main() */
-
-/* end event.c */
diff --git a/pr/src/md/mac/prgcleak.c b/pr/src/md/mac/prgcleak.c
deleted file mode 100644
index a27b9b69..00000000
--- a/pr/src/md/mac/prgcleak.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.1 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1999 Netscape Communications Corporation. All Rights
- * Reserved.
- *
- * Contributor(s):
- * Patrick Beard <beard@netscape.com>
- */
-
-/*
- * prgcleak.c
- */
-
-#ifdef GC_LEAK_DETECTOR
-
-/* for FILE */
-#include <stdio.h>
-
-/* NSPR stuff */
-#include "generic_threads.h"
-#include "primpl.h"
-
-extern FILE *GC_stdout, *GC_stderr;
-
-extern void GC_gcollect(void);
-extern void GC_clear_roots(void);
-
-static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr,
- PRUword count, void* closure)
-{
- char* begin = (char*)baseAddr;
- char* end = (char*)(baseAddr + count);
- GC_mark_range_proc marker = (GC_mark_range_proc) closure;
- marker(begin, end);
- return PR_SUCCESS;
-}
-
-static void mark_all_stacks(GC_mark_range_proc marker)
-{
- PR_ScanStackPointers(&scanner, (void *)marker);
-}
-
-static void locker(void* mutex)
-{
- if (_PR_MD_CURRENT_CPU())
- PR_Lock(mutex);
-}
-
-static void unlocker(void* mutex)
-{
- if (_PR_MD_CURRENT_CPU())
- PR_Unlock(mutex);
-}
-
-static void stopper(void* unused)
-{
- if (_PR_MD_CURRENT_CPU())
- PR_SuspendAll();
-}
-
-static void starter(void* unused)
-{
- if (_PR_MD_CURRENT_CPU())
- PR_ResumeAll();
-}
-
-void _PR_InitGarbageCollector()
-{
- void* mutex;
-
- /* redirect GC's stderr to catch startup leaks. */
- GC_stderr = fopen("StartupLeaks", "w");
-
- mutex = PR_NewLock();
- PR_ASSERT(mutex != NULL);
-
- GC_generic_init_threads(&mark_all_stacks, mutex,
- &locker, &unlocker,
- &stopper, &starter);
-}
-
-void _PR_ShutdownGarbageCollector()
-{
- /* do anything you need to shut down the collector. */
-}
-
-#endif /* GC_LEAK_DETECTOR */
diff --git a/pr/src/md/unix/os_Linux_ia64.s b/pr/src/md/unix/os_Linux_ia64.s
new file mode 100644
index 00000000..bf5b03fc
--- /dev/null
+++ b/pr/src/md/unix/os_Linux_ia64.s
@@ -0,0 +1,80 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+//
+// The contents of this file are subject to the Mozilla Public
+// License Version 1.1 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of
+// the License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS
+// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// rights and limitations under the License.
+//
+// The Original Code is the Netscape Portable Runtime (NSPR).
+//
+// The Initial Developer of the Original Code is Netscape
+// Communications Corporation. Portions created by Netscape are
+// Copyright (C) 2000 Netscape Communications Corporation. All
+// Rights Reserved.
+//
+// Contributor(s):
+//
+// Alternatively, the contents of this file may be used under the
+// terms of the GNU General Public License Version 2 or later (the
+// "GPL"), in which case the provisions of the GPL are applicable
+// instead of those above. If you wish to allow use of your
+// version of this file only under the terms of the GPL and not to
+// allow others to use your version of this file under the MPL,
+// indicate your decision by deleting the provisions above and
+// replace them with the notice and other provisions required by
+// the GPL. If you do not delete the provisions above, a recipient
+// may use your version of this file under either the MPL or the
+// GPL.
+//
+
+.text
+ .align 16
+ .global _PR_ia64_AtomicIncrement#
+ .proc _PR_ia64_AtomicIncrement#
+_PR_ia64_AtomicIncrement:
+ fetchadd4.acq r8 = [r32], 1
+ ;;
+ adds r8 = 1, r8
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicIncrement#
+//
+ .align 16
+ .global _PR_ia64_AtomicDecrement#
+ .proc _PR_ia64_AtomicDecrement#
+_PR_ia64_AtomicDecrement:
+ fetchadd4.rel r8 = [r32], -1
+ ;;
+ adds r8 = -1, r8
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicDecrement#
+//
+ .align 16
+ .global _PR_ia64_AtomicAdd#
+ .proc _PR_ia64_AtomicAdd#
+_PR_ia64_AtomicAdd:
+ ld4 r15 = [r32]
+ ;;
+.L3:
+ mov r14 = r15
+ mov ar.ccv = r15
+ add r8 = r15, r33
+ ;;
+ cmpxchg4.acq r15 = [r32], r8, ar.ccv
+ ;;
+ cmp4.ne p6, p7 = r15, r14
+ (p6) br.cond.dptk .L3
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicAdd#
+//
+ .align 16
+ .global _PR_ia64_AtomicSet#
+ .proc _PR_ia64_AtomicSet#
+_PR_ia64_AtomicSet:
+ xchg4 r8 = [r32], r33
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicSet#
diff --git a/pr/src/md/unix/os_SunOS_sparcv9.s b/pr/src/md/unix/os_SunOS_sparcv9.s
new file mode 100644
index 00000000..a4bb3b79
--- /dev/null
+++ b/pr/src/md/unix/os_SunOS_sparcv9.s
@@ -0,0 +1,201 @@
+! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+!
+! The contents of this file are subject to the Mozilla Public
+! License Version 1.1 (the "License"); you may not use this file
+! except in compliance with the License. You may obtain a copy of
+! the License at http://www.mozilla.org/MPL/
+!
+! Software distributed under the License is distributed on an "AS
+! IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+! implied. See the License for the specific language governing
+! rights and limitations under the License.
+!
+! The Original Code is the Netscape Portable Runtime (NSPR).
+!
+! The Initial Developer of the Original Code is Netscape
+! Communications Corporation. Portions created by Netscape are
+! Copyright (C) 1998-2000 Netscape Communications Corporation. All
+! Rights Reserved.
+!
+! Contributor(s):
+!
+! Alternatively, the contents of this file may be used under the
+! terms of the GNU General Public License Version 2 or later (the
+! "GPL"), in which case the provisions of the GPL are applicable
+! instead of those above. If you wish to allow use of your
+! version of this file only under the terms of the GPL and not to
+! allow others to use your version of this file under the MPL,
+! indicate your decision by deleting the provisions above and
+! replace them with the notice and other provisions required by
+! the GPL. If you do not delete the provisions above, a recipient
+! may use your version of this file under either the MPL or the
+! GPL.
+!
+
+!
+! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc)
+! using CAS (compare-and-swap) atomic instructions
+!
+! this MUST be compiled with an ultrasparc-aware assembler
+!
+! standard asm linkage macros; this module must be compiled
+! with the -P option (use C preprocessor)
+
+#include <sys/asm_linkage.h>
+
+! ======================================================================
+!
+! Perform the sequence a = a + 1 atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicIncrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicIncrement) ! standard assembler/ELF prologue
+
+retryAI:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAI ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicIncrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a - 1 atomically with respect to other
+! fetch-and-decs to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicDecrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicDecrement) ! standard assembler/ELF prologue
+
+retryAD:
+ ld [%o0], %o2 ! set o2 to the current value
+ sub %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAD ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicDecrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = b atomically with respect to other
+! fetch-and-stores to location a in a wait-free fashion.
+!
+! usage : old_val = PR_AtomicSet(address, newval)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [input] - the new value to set for [%o0]
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicSet) ! standard assembler/ELF prologue
+
+retryAS:
+ ld [%o0], %o2 ! set o2 to the current value
+ mov %o1, %o3 ! set up the new value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAS ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o3, %o0 ! set the return code to the prev value
+
+ SET_SIZE(_MD_AtomicSet) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a + b atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : newval = PR_AtomicAdd(address, val)
+! return: the value after addition
+!
+ ENTRY(_MD_AtomicAdd) ! standard assembler/ELF prologue
+
+retryAA:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, %o1, %o3 ! calc the new value
+ mov %o3, %o4 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAA ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o4, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicAdd) ! standard assembler/ELF epilogue
+
+!
+! end
+!
diff --git a/pr/tests/acceptreademu.c b/pr/tests/acceptreademu.c
new file mode 100644
index 00000000..140714b5
--- /dev/null
+++ b/pr/tests/acceptreademu.c
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * This test is the same as acceptread.c except that it uses the
+ * emulated acceptread method instead of the regular acceptread.
+ */
+
+#include <prio.h>
+#include <prprf.h>
+#include <prinit.h>
+#include <prnetdb.h>
+#include <prinrval.h>
+#include <prthread.h>
+#include <pprio.h>
+
+#include <plerror.h>
+
+#include <stdlib.h>
+
+#define DEFAULT_PORT 12273
+#define GET "GET / HTTP/1.0\n\n"
+static PRFileDesc *std_out, *err_out;
+static PRIntervalTime write_dally, accept_timeout;
+static PRDescIdentity emu_layer_ident;
+static PRIOMethods emu_layer_methods;
+
+/* the acceptread method in emu_layer_methods */
+static PRInt32 PR_CALLBACK emu_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+ PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ return PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
+}
+
+static PRStatus PrintAddress(const PRNetAddr* address)
+{
+ char buffer[100];
+ PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
+ if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
+ else PR_fprintf(
+ std_out, "Accepted connection from (0x%p)%s:%d\n",
+ address, buffer, address->inet.port);
+ return rv;
+} /* PrintAddress */
+
+static void ConnectingThread(void *arg)
+{
+ PRInt32 nbytes;
+ char buf[1024];
+ PRFileDesc *sock;
+ PRNetAddr peer_addr, *addr;
+
+ addr = (PRNetAddr*)arg;
+
+ sock = PR_NewTCPSocket();
+ if (sock == NULL)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_Connect (client) failed");
+ PR_ProcessExit(1);
+ }
+ if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ /*
+ ** Then wait between the connection coming up and sending the expected
+ ** data. At some point in time, the server should fail due to a timeou
+ ** on the AcceptRead() operation, which according to the document is
+ ** only due to the read() portion.
+ */
+ PR_Sleep(write_dally);
+
+ nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");
+
+ nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
+ else
+ {
+ PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
+ buf[sizeof(buf) - 1] = '\0';
+ PR_fprintf(std_out, "%s\n", buf);
+ }
+
+ if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
+ PL_FPrintError(err_out, "PR_Shutdown (client) failed");
+
+ if (PR_FAILURE == PR_Close(sock))
+ PL_FPrintError(err_out, "PR_Close (client) failed");
+
+ return;
+} /* ConnectingThread */
+
+#define BUF_SIZE 117
+static void AcceptingThread(void *arg)
+{
+ PRStatus rv;
+ PRInt32 bytes;
+ PRSize buf_size = BUF_SIZE;
+ PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
+ PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
+ PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
+ PRFileDesc *layer;
+ PRSocketOptionData sock_opt;
+
+ if (NULL == listen_sock)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
+ PR_ProcessExit(1);
+ }
+ layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods);
+ if (NULL == layer)
+ {
+ PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed");
+ PR_ProcessExit(1);
+ }
+ if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_PushIOLayer (server) failed");
+ PR_ProcessExit(1);
+ }
+ sock_opt.option = PR_SockOpt_Reuseaddr;
+ sock_opt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(listen_sock, &sock_opt);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Bind(listen_sock, listen_addr);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Bind (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Listen(listen_sock, 10);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Listen (server) failed");
+ PR_ProcessExit(1);
+ }
+ bytes = PR_AcceptRead(
+ listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);
+
+ if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
+ else
+ {
+ PrintAddress(accept_addr);
+ PR_fprintf(
+ std_out, "(Server) read [0x%p..0x%p) %s\n",
+ buf, &buf[BUF_SIZE], buf);
+ bytes = PR_Write(accept_sock, buf, bytes);
+ rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Shutdown (server) failed");
+ }
+
+ if (-1 != bytes)
+ {
+ rv = PR_Close(accept_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+ }
+
+ rv = PR_Close(listen_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+} /* AcceptingThread */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRHostEnt he;
+ PRStatus status;
+ PRIntn next_index;
+ PRUint16 port_number;
+ char netdb_buf[PR_NETDB_BUF_SIZE];
+ PRNetAddr client_addr, server_addr;
+ PRThread *client_thread, *server_thread;
+ PRIntervalTime delta = PR_MillisecondsToInterval(500);
+
+ err_out = PR_STDERR;
+ std_out = PR_STDOUT;
+ accept_timeout = PR_SecondsToInterval(2);
+ emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead");
+ emu_layer_methods = *PR_GetDefaultIOMethods();
+ emu_layer_methods.acceptread = emu_AcceptRead;
+
+ if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
+ else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);
+
+ status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ if (argc < 3)
+ {
+ status = PR_InitializeNetAddr(
+ PR_IpAddrLoopback, port_number, &client_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ }
+ else
+ {
+ status = PR_GetHostByName(
+ argv[1], netdb_buf, sizeof(netdb_buf), &he);
+ if (status == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetHostByName failed");
+ PR_ProcessExit(1);
+ }
+ next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
+ if (next_index == -1)
+ {
+ PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
+ PR_ProcessExit(1);
+ }
+ }
+
+ for (
+ write_dally = 0;
+ write_dally < accept_timeout + (2 * delta);
+ write_dally += delta)
+ {
+ PR_fprintf(
+ std_out, "Testing w/ write_dally = %d msec\n",
+ PR_IntervalToMilliseconds(write_dally));
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, AcceptingThread, &server_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (server_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (server) failed");
+ PR_ProcessExit(1);
+ }
+
+ PR_Sleep(delta); /* let the server pot thicken */
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, ConnectingThread, &client_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (client_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_JoinThread(client_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (client) failed");
+
+ if (PR_JoinThread(server_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (server) failed");
+ }
+
+ return 0;
+}
diff --git a/pr/tests/append.c b/pr/tests/append.c
new file mode 100644
index 00000000..40a2d079
--- /dev/null
+++ b/pr/tests/append.c
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** File: append.c
+** Description: Testing File writes where PR_APPEND was used on open
+**
+** append attempts to verify that a file opened with PR_APPEND
+** will always append to the end of file, regardless where the
+** current file pointer is positioned. To do this, PR_Seek() is
+** called before each write with the position set to beginning of
+** file. Subsequent writes should always append.
+** The file is read back, summing the integer data written to the
+** file. If the expected result is equal, the test passes.
+**
+** See BugSplat: 4090
+*/
+#include "plgetopt.h"
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+PRIntn debug = 0;
+PRIntn verbose = 0;
+PRBool failedAlready = PR_FALSE;
+const PRInt32 addedBytes = 1000;
+const PRInt32 buf = 1; /* constant written to fd, addedBytes times */
+PRInt32 inBuf; /* read it back into here */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRStatus rc;
+ PRInt32 rv;
+ PRFileDesc *fd;
+ PRIntn i;
+ PRInt32 sum = 0;
+
+ { /* Get command line options */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "vd");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ break;
+ case 'v': /* verbose */
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } /* end block "Get command line options" */
+/* ---------------------------------------------------------------------- */
+ fd = PR_Open( "/tmp/nsprAppend", (PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY), 0666 );
+ if ( NULL == fd ) {
+ if (debug) printf("PR_Open() failed for writing: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+ for ( i = 0; i < addedBytes ; i++ ) {
+ rv = PR_Write( fd, &buf, sizeof(buf));
+ if ( sizeof(buf) != rv ) {
+ if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ rv = PR_Seek( fd, 0 , PR_SEEK_SET );
+ if ( -1 == rv ) {
+ if (debug) printf("PR_Seek() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ }
+ rc = PR_Close( fd );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf("PR_Close() failed after writing: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+/* ---------------------------------------------------------------------- */
+ fd = PR_Open( "/tmp/nsprAppend", PR_RDONLY, 0 );
+ if ( NULL == fd ) {
+ if (debug) printf("PR_Open() failed for reading: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+ for ( i = 0; i < addedBytes ; i++ ) {
+ rv = PR_Read( fd, &inBuf, sizeof(inBuf));
+ if ( sizeof(inBuf) != rv) {
+ if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ sum += inBuf;
+ }
+
+ rc = PR_Close( fd );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf("PR_Close() failed after reading: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ if ( sum != addedBytes ) {
+ if (debug) printf("Uh Oh! addedBytes: %d. Sum: %d\n", addedBytes, sum);
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+/* ---------------------------------------------------------------------- */
+Finished:
+ if (debug || verbose) printf("%s\n", (failedAlready)? "FAILED" : "PASSED" );
+ return( (failedAlready)? 1 : 0 );
+} /* main() */
+
+/* append.c */
diff --git a/pr/tests/env.c b/pr/tests/env.c
new file mode 100644
index 00000000..bdffe206
--- /dev/null
+++ b/pr/tests/env.c
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** File: env.c
+** Description: Testing environment variable operations
+**
+*/
+#include "prenv.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+PRIntn debug = 0;
+PRIntn verbose = 0;
+PRBool failedAlready = PR_FALSE;
+
+#define ENVNAME "NSPR_ENVIRONMENT_TEST_VARIABLE"
+#define ENVVALUE "The expected result"
+#define ENVBUFSIZE 256
+
+char *envBuf; /* buffer pointer. We leak memory here on purpose! */
+
+static char * NewBuffer( size_t size )
+{
+ char *buf = malloc( size );
+ if ( NULL == buf ) {
+ printf("env: NewBuffer() failed\n");
+ exit(1);
+ }
+ return(buf);
+} /* end NewBuffer() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ char *value;
+ PRStatus rc;
+
+ { /* Get command line options */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "vd");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ break;
+ case 'v': /* verbose */
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } /* end block "Get command line options" */
+
+#if 0
+ {
+ /*
+ ** This uses Windows native environment manipulation
+ ** as an experiment. Note the separation of namespace!
+ */
+ BOOL rv;
+ DWORD size;
+ rv = SetEnvironmentVariable( ENVNAME, ENVVALUE );
+ if ( rv == 0 ) {
+ if (debug) printf("env: Shit! SetEnvironmentVariable() failed\n");
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: SetEnvironmentVariable() worked\n");
+
+ size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE );
+ if ( size == 0 ) {
+ if (debug) printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf );
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf);
+
+ value = PR_GetEnv( ENVNAME );
+ if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
+ if (debug) printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value);
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: PR_GetEnv() worked. Found: %s\n", value);
+ }
+#endif
+
+ /* set an environment variable, read it back */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" ENVVALUE );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed setting\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() worked.\n");
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
+ if (debug) printf( "env: PR_GetEnv() Failed after setting\n" );
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value );
+ }
+
+/* ---------------------------------------------------------------------- */
+ /* un-set the variable, using RAW name... should not work */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (verbose) printf( "env: PR_SetEnv() not un-set using RAW name. Good!\n");
+ } else {
+ if (debug) printf("env: PR_SetEnv() un-set using RAW name. Bad!\n" );
+ failedAlready = PR_TRUE;
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if ( NULL == value ) {
+ if (debug) printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n" );
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf( "env: PR_GetEnv() after RAW un-set found: %s\n", value );
+ }
+
+/* ---------------------------------------------------------------------- */
+ /* set it again ... */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" ENVVALUE );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed setting the second time.\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() worked.\n");
+ }
+
+ /* un-set the variable using the form name= */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if (( NULL == value ) || ( 0x00 == *value )) {
+ if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
+ } else {
+ if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
+ failedAlready = PR_TRUE;
+ }
+/* ---------------------------------------------------------------------- */
+ /* un-set the variable using the form name= */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "999=" );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
+ }
+
+ value = PR_GetEnv( ENVNAME "999" );
+ if (( NULL == value ) || ( 0x00 == *value )) {
+ if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
+ } else {
+ if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
+ failedAlready = PR_TRUE;
+ }
+
+/* ---------------------------------------------------------------------- */
+ if (debug || verbose) printf("\n%s\n", (failedAlready)? "FAILED" : "PASSED" );
+ return( (failedAlready)? 1 : 0 );
+} /* main() */
+
+/* env.c */
diff --git a/pr/tests/errset.c b/pr/tests/errset.c
new file mode 100644
index 00000000..51c7b565
--- /dev/null
+++ b/pr/tests/errset.c
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/***********************************************************************
+**
+** Name: errset.c
+**
+** Description: errset.c exercises the functions in prerror.c.
+** This code is a unit test of the prerror.c capability.
+**
+** Note: There's some fluff in here. The guts of the test
+** were plagerized from another test. So, sue me.
+**
+**
+*/
+#include "prerror.h"
+#include "plgetopt.h"
+#include "prlog.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static int _debug_on = 0;
+
+struct errinfo {
+ PRErrorCode errcode;
+ char *errname;
+};
+
+struct errinfo errcodes[] = {
+{PR_OUT_OF_MEMORY_ERROR, "PR_OUT_OF_MEMORY_ERROR"},
+{PR_UNKNOWN_ERROR, "An intentionally long error message text intended to force a delete of the current errorString buffer and get another one."},
+{PR_BAD_DESCRIPTOR_ERROR, "PR_BAD_DESCRIPTOR_ERROR"},
+{PR_WOULD_BLOCK_ERROR, "PR_WOULD_BLOCK_ERROR"},
+{PR_ACCESS_FAULT_ERROR, "PR_ACCESS_FAULT_ERROR"},
+{PR_INVALID_METHOD_ERROR, "PR_INVALID_METHOD_ERROR"},
+{PR_ILLEGAL_ACCESS_ERROR, "PR_ILLEGAL_ACCESS_ERROR"},
+{PR_UNKNOWN_ERROR, "PR_UNKNOWN_ERROR"},
+{PR_PENDING_INTERRUPT_ERROR, "PR_PENDING_INTERRUPT_ERROR"},
+{PR_NOT_IMPLEMENTED_ERROR, "PR_NOT_IMPLEMENTED_ERROR"},
+{PR_IO_ERROR, "PR_IO_ERROR"},
+{PR_IO_TIMEOUT_ERROR, "PR_IO_TIMEOUT_ERROR"},
+{PR_IO_PENDING_ERROR, "PR_IO_PENDING_ERROR"},
+{PR_DIRECTORY_OPEN_ERROR, "PR_DIRECTORY_OPEN_ERROR"},
+{PR_INVALID_ARGUMENT_ERROR, "PR_INVALID_ARGUMENT_ERROR"},
+{PR_ADDRESS_NOT_AVAILABLE_ERROR, "PR_ADDRESS_NOT_AVAILABLE_ERROR"},
+{PR_ADDRESS_NOT_SUPPORTED_ERROR, "PR_ADDRESS_NOT_SUPPORTED_ERROR"},
+{PR_IS_CONNECTED_ERROR, "PR_IS_CONNECTED_ERROR"},
+{PR_BAD_ADDRESS_ERROR, "PR_BAD_ADDRESS_ERROR"},
+{PR_ADDRESS_IN_USE_ERROR, "PR_ADDRESS_IN_USE_ERROR"},
+{PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR"},
+{PR_NETWORK_UNREACHABLE_ERROR, "PR_NETWORK_UNREACHABLE_ERROR"},
+{PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR"},
+{PR_NOT_CONNECTED_ERROR, "PR_NOT_CONNECTED_ERROR"},
+{PR_LOAD_LIBRARY_ERROR, "PR_LOAD_LIBRARY_ERROR"},
+{PR_UNLOAD_LIBRARY_ERROR, "PR_UNLOAD_LIBRARY_ERROR"},
+{PR_FIND_SYMBOL_ERROR, "PR_FIND_SYMBOL_ERROR"},
+{PR_INSUFFICIENT_RESOURCES_ERROR, "PR_INSUFFICIENT_RESOURCES_ERROR"},
+{PR_DIRECTORY_LOOKUP_ERROR, "PR_DIRECTORY_LOOKUP_ERROR"},
+{PR_TPD_RANGE_ERROR, "PR_TPD_RANGE_ERROR"},
+{PR_PROC_DESC_TABLE_FULL_ERROR, "PR_PROC_DESC_TABLE_FULL_ERROR"},
+{PR_SYS_DESC_TABLE_FULL_ERROR, "PR_SYS_DESC_TABLE_FULL_ERROR"},
+{PR_NOT_SOCKET_ERROR, "PR_NOT_SOCKET_ERROR"},
+{PR_NOT_TCP_SOCKET_ERROR, "PR_NOT_TCP_SOCKET_ERROR"},
+{PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "PR_SOCKET_ADDRESS_IS_BOUND_ERROR"},
+{PR_NO_ACCESS_RIGHTS_ERROR, "PR_NO_ACCESS_RIGHTS_ERROR"},
+{PR_OPERATION_NOT_SUPPORTED_ERROR, "PR_OPERATION_NOT_SUPPORTED_ERROR"},
+{PR_PROTOCOL_NOT_SUPPORTED_ERROR, "PR_PROTOCOL_NOT_SUPPORTED_ERROR"},
+{PR_REMOTE_FILE_ERROR, "PR_REMOTE_FILE_ERROR"},
+{PR_BUFFER_OVERFLOW_ERROR, "PR_BUFFER_OVERFLOW_ERROR"},
+{PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR"},
+{PR_RANGE_ERROR, "PR_RANGE_ERROR"},
+{PR_DEADLOCK_ERROR, "PR_DEADLOCK_ERROR"},
+{PR_FILE_IS_LOCKED_ERROR, "PR_FILE_IS_LOCKED_ERROR"},
+{PR_FILE_TOO_BIG_ERROR, "PR_FILE_TOO_BIG_ERROR"},
+{PR_NO_DEVICE_SPACE_ERROR, "PR_NO_DEVICE_SPACE_ERROR"},
+{PR_PIPE_ERROR, "PR_PIPE_ERROR"},
+{PR_NO_SEEK_DEVICE_ERROR, "PR_NO_SEEK_DEVICE_ERROR"},
+{PR_IS_DIRECTORY_ERROR, "PR_IS_DIRECTORY_ERROR"},
+{PR_LOOP_ERROR, "PR_LOOP_ERROR"},
+{PR_NAME_TOO_LONG_ERROR, "PR_NAME_TOO_LONG_ERROR"},
+{PR_FILE_NOT_FOUND_ERROR, "PR_FILE_NOT_FOUND_ERROR"},
+{PR_NOT_DIRECTORY_ERROR, "PR_NOT_DIRECTORY_ERROR"},
+{PR_READ_ONLY_FILESYSTEM_ERROR, "PR_READ_ONLY_FILESYSTEM_ERROR"},
+{PR_DIRECTORY_NOT_EMPTY_ERROR, "PR_DIRECTORY_NOT_EMPTY_ERROR"},
+{PR_FILESYSTEM_MOUNTED_ERROR, "PR_FILESYSTEM_MOUNTED_ERROR"},
+{PR_NOT_SAME_DEVICE_ERROR, "PR_NOT_SAME_DEVICE_ERROR"},
+{PR_DIRECTORY_CORRUPTED_ERROR, "PR_DIRECTORY_CORRUPTED_ERROR"},
+{PR_FILE_EXISTS_ERROR, "PR_FILE_EXISTS_ERROR"},
+{PR_MAX_DIRECTORY_ENTRIES_ERROR, "PR_MAX_DIRECTORY_ENTRIES_ERROR"},
+{PR_INVALID_DEVICE_STATE_ERROR, "PR_INVALID_DEVICE_STATE_ERROR"},
+{PR_DEVICE_IS_LOCKED_ERROR, "PR_DEVICE_IS_LOCKED_ERROR"},
+{PR_NO_MORE_FILES_ERROR, "PR_NO_MORE_FILES_ERROR"},
+{PR_END_OF_FILE_ERROR, "PR_END_OF_FILE_ERROR"},
+{PR_FILE_SEEK_ERROR, "PR_FILE_SEEK_ERROR"},
+{PR_FILE_IS_BUSY_ERROR, "PR_FILE_IS_BUSY_ERROR"},
+{PR_IN_PROGRESS_ERROR, "PR_IN_PROGRESS_ERROR"},
+{PR_ALREADY_INITIATED_ERROR, "PR_ALREADY_INITIATED_ERROR"},
+{PR_GROUP_EMPTY_ERROR, "PR_GROUP_EMPTY_ERROR"},
+{PR_INVALID_STATE_ERROR, "PR_INVALID_STATE_ERROR"},
+{PR_NETWORK_DOWN_ERROR, "PR_NETWORK_DOWN_ERROR"},
+{PR_SOCKET_SHUTDOWN_ERROR, "PR_SOCKET_SHUTDOWN_ERROR"},
+{PR_CONNECT_ABORTED_ERROR, "PR_CONNECT_ABORTED_ERROR"},
+{PR_HOST_UNREACHABLE_ERROR, "PR_HOST_UNREACHABLE_ERROR"}
+};
+
+int
+main(int argc, char **argv)
+{
+
+ int count, errnum;
+
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ count = sizeof(errcodes)/sizeof(errcodes[0]);
+ printf("\nNumber of error codes = %d\n\n",count);
+ for (errnum = 0; errnum < count; errnum++) {
+ PRInt32 len1, len2, err;
+ char msg[256];
+
+ PR_SetError( errnum, -5 );
+ err = PR_GetError();
+ PR_ASSERT( err == errnum );
+ err = PR_GetOSError();
+ PR_ASSERT( err == -5 );
+ PR_SetErrorText( strlen(errcodes[errnum].errname), errcodes[errnum].errname );
+ len1 = PR_GetErrorTextLength();
+ len2 = PR_GetErrorText( msg );
+ PR_ASSERT( len1 == len2 );
+ printf("%5.5d -- %s\n", errnum, msg );
+ }
+
+ return 0;
+}
diff --git a/pr/tests/freeif.c b/pr/tests/freeif.c
new file mode 100644
index 00000000..cca2f5e6
--- /dev/null
+++ b/pr/tests/freeif.c
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * A test to see if the macros PR_DELETE and PR_FREEIF are
+ * properly defined. (See Bugzilla bug #39110.)
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void Noop(void) { }
+
+static void Fail(void)
+{
+ printf("FAIL\n");
+ exit(1);
+}
+
+int main()
+{
+ int foo = 1;
+ char *ptr = NULL;
+
+ /* this fails to compile with the old definition of PR_DELETE */
+ if (foo)
+ PR_DELETE(ptr);
+ else
+ Noop();
+
+ /* this nests incorrectly with the old definition of PR_FREEIF */
+ if (foo)
+ PR_FREEIF(ptr);
+ else
+ Fail();
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/pr/tests/intrio.c b/pr/tests/intrio.c
new file mode 100644
index 00000000..7c21454e
--- /dev/null
+++ b/pr/tests/intrio.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * File: intrio.c
+ * Purpose: testing i/o interrupts (see Bugzilla bug #31120)
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+/* for synchronization between the main thread and iothread */
+static PRLock *lock;
+static PRCondVar *cvar;
+static PRBool iothread_ready;
+
+static void PR_CALLBACK AbortIO(void *arg)
+{
+ PRStatus rv;
+ PR_Sleep(PR_SecondsToInterval(2));
+ rv = PR_Interrupt((PRThread*)arg);
+ PR_ASSERT(PR_SUCCESS == rv);
+} /* AbortIO */
+
+static void PR_CALLBACK IOThread(void *arg)
+{
+ PRFileDesc *sock, *newsock;
+ PRNetAddr addr;
+
+ sock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+ /* tell the main thread that we are ready */
+ PR_Lock(lock);
+ iothread_ready = PR_TRUE;
+ PR_NotifyCondVar(cvar);
+ PR_Unlock(lock);
+ newsock = PR_Accept(sock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (newsock != NULL) {
+ fprintf(stderr, "PR_Accept shouldn't have succeeded\n");
+ exit(1);
+ }
+ if (PR_GetError() != PR_PENDING_INTERRUPT_ERROR) {
+ fprintf(stderr, "PR_Accept failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("PR_Accept() is interrupted as expected\n");
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+static void Test(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *iothread, *abortio;
+
+ printf("A %s thread will be interrupted by a %s thread\n",
+ (scope1 == PR_LOCAL_THREAD ? "local" : "global"),
+ (scope2 == PR_LOCAL_THREAD ? "local" : "global"));
+ iothread_ready = PR_FALSE;
+ iothread = PR_CreateThread(
+ PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL,
+ scope1, PR_JOINABLE_THREAD, 0);
+ if (iothread == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+ PR_Lock(lock);
+ while (!iothread_ready)
+ PR_WaitCondVar(cvar, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(lock);
+ abortio = PR_CreateThread(
+ PR_USER_THREAD, AbortIO, iothread, PR_PRIORITY_NORMAL,
+ scope2, PR_JOINABLE_THREAD, 0);
+ if (abortio == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+ if (PR_JoinThread(iothread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(abortio) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+}
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PR_STDIO_INIT();
+ lock = PR_NewLock();
+ if (lock == NULL) {
+ fprintf(stderr, "PR_NewLock failed\n");
+ exit(1);
+ }
+ cvar = PR_NewCondVar(lock);
+ if (cvar == NULL) {
+ fprintf(stderr, "PR_NewCondVar failed\n");
+ exit(1);
+ }
+ /* test all four combinations */
+ Test(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+ Test(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+ Test(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+ Test(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+ printf("PASSED\n");
+ return 0;
+} /* main */
diff --git a/pr/tests/obsints.c b/pr/tests/obsints.c
new file mode 100644
index 00000000..abd31492
--- /dev/null
+++ b/pr/tests/obsints.c
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test: obsints.c
+ *
+ * Description: make sure that protypes.h defines the obsolete integer
+ * types intn, uintn, uint, int8, uint8, int16, uint16, int32, uint32,
+ * int64, and uint64.
+ */
+
+#include <stdio.h>
+
+#ifdef NO_NSPR_10_SUPPORT
+
+/* nothing to do */
+int main()
+{
+ printf("PASS\n");
+ return 0;
+}
+
+#else /* NO_NSPR_10_SUPPORT */
+
+#include "prtypes.h" /* which includes protypes.h */
+
+int main()
+{
+ /*
+ * Compilation fails if any of these integer types are not
+ * defined by protypes.h.
+ */
+ intn in;
+ uintn uin;
+ uint ui;
+ int8 i8;
+ uint8 ui8;
+ int16 i16;
+ uint16 ui16;
+ int32 i32;
+ uint32 ui32;
+ int64 i64;
+ uint64 ui64;
+
+ printf("PASS\n");
+ return 0;
+}
+
+#endif /* NO_NSPR_10_SUPPORT */
diff --git a/pr/tests/peek.c b/pr/tests/peek.c
new file mode 100644
index 00000000..23faec11
--- /dev/null
+++ b/pr/tests/peek.c
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1999-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * A test case for the PR_MSG_PEEK flag of PR_Recv().
+ *
+ * Test both blocking and non-blocking sockets.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFFER_SIZE 1024
+
+static int iterations = 10;
+
+/*
+ * In iteration i, recv_amount[i] is the number of bytes we
+ * wish to receive, and send_amount[i] is the number of bytes
+ * we actually send. Therefore, the number of elements in the
+ * recv_amount or send_amount array should equal to 'iterations'.
+ * For this test to pass we need to ensure that
+ * recv_amount[i] <= BUFFER_SIZE,
+ * send_amount[i] <= BUFFER_SIZE,
+ * send_amount[i] <= recv_amount[i].
+ */
+static PRInt32 recv_amount[10] = {
+ 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
+static PRInt32 send_amount[10] = {
+ 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32};
+
+/* Blocking I/O */
+static void ServerB(void *arg)
+{
+ PRFileDesc *listenSock = (PRFileDesc *) arg;
+ PRFileDesc *sock;
+ char buf[BUFFER_SIZE];
+ PRInt32 nbytes;
+ int i;
+ int j;
+
+ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == sock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+
+ for (i = 0; i < iterations; i++) {
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: received expected data\n");
+
+ PR_Sleep(PR_SecondsToInterval(1));
+ memset(buf, 2*i+1, send_amount[i]);
+ nbytes = PR_Send(sock, buf, send_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+/* Non-blocking I/O */
+static void ClientNB(void *arg)
+{
+ PRFileDesc *sock;
+ PRSocketOptionData opt;
+ PRUint16 port = (PRUint16) arg;
+ PRNetAddr addr;
+ char buf[BUFFER_SIZE];
+ PRPollDesc pd;
+ PRInt32 npds;
+ PRInt32 nbytes;
+ int i;
+ int j;
+
+ sock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (NULL == sock) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetSocketOption failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
+ == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetConnectStatus failed\n");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < iterations; i++) {
+ PR_Sleep(PR_SecondsToInterval(1));
+ memset(buf, 2*i, send_amount[i]);
+ while ((nbytes = PR_Send(sock, buf, send_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+
+ memset(buf, 0, sizeof(buf));
+ while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_READ;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: received expected data\n");
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+static void
+RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port)
+{
+ PRThread *server, *client;
+
+ server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock,
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == server) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ client = PR_CreateThread(
+ PR_USER_THREAD, ClientNB, (void *) port,
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == client) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+
+ if (PR_JoinThread(server) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(client) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock;
+ PRNetAddr addr;
+ PRUint16 port;
+
+ listenSock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (NULL == listenSock) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ port = PR_ntohs(addr.ipv6.port);
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ fprintf(stderr, "Running the test with local threads\n");
+ RunTest(PR_LOCAL_THREAD, listenSock, port);
+ fprintf(stderr, "Running the test with global threads\n");
+ RunTest(PR_GLOBAL_THREAD, listenSock, port);
+
+ if (PR_Close(listenSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/pr/tests/pipeping2.c b/pr/tests/pipeping2.c
new file mode 100644
index 00000000..a8d40d5b
--- /dev/null
+++ b/pr/tests/pipeping2.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * File: pipeping2.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipepong2 test.
+ * This test creates two pipes and passes two pipe fd's
+ * to the pipepong2 test. Then this test writes "ping" to
+ * to the pipepong2 test and the pipepong2 test writes "pong"
+ * back. To run this pair of tests, just invoke pipeping2.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+#include "prproces.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+static char *child_argv[] = { "pipepong2", NULL };
+
+int main()
+{
+ PRFileDesc *in_pipe[2];
+ PRFileDesc *out_pipe[2];
+ PRStatus status;
+ PRProcess *process;
+ PRProcessAttr *attr;
+ char buf[1024];
+ PRInt32 nBytes;
+ PRInt32 exitCode;
+ int idx;
+
+ status = PR_CreatePipe(&in_pipe[0], &in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+ status = PR_CreatePipe(&out_pipe[0], &out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+
+ status = PR_SetFDInheritable(in_pipe[0], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(in_pipe[1], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[0], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[1], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ attr = PR_NewProcessAttr();
+ if (attr == NULL) {
+ fprintf(stderr, "PR_NewProcessAttr failed\n");
+ exit(1);
+ }
+
+ status = PR_ProcessAttrSetInheritableFD(attr, out_pipe[0], "PIPE_READ");
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n");
+ exit(1);
+ }
+ status = PR_ProcessAttrSetInheritableFD(attr, in_pipe[1], "PIPE_WRITE");
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n");
+ exit(1);
+ }
+
+ process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr);
+ if (process == NULL) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+ PR_DestroyProcessAttr(attr);
+ status = PR_Close(out_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ strcpy(buf, "ping");
+ printf("ping process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(out_pipe[1], buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(in_pipe[0], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ printf("ping process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "pong") != 0) {
+ fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ }
+
+ status = PR_Close(in_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_WaitProcess(process, &exitCode);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exitCode == 0) {
+ printf("PASS\n");
+ return 0;
+ } else {
+ printf("FAIL\n");
+ return 1;
+ }
+}
diff --git a/pr/tests/pipepong2.c b/pr/tests/pipepong2.c
new file mode 100644
index 00000000..dbe871ea
--- /dev/null
+++ b/pr/tests/pipepong2.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * File: pipepong2.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipeping2 test.
+ * The pipeping2 test creates two pipes and passes two
+ * pipe fd's to this test. Then the pipeping2 test writes
+ * "ping" to this test and this test writes "pong" back.
+ * To run this pair of tests, just invoke pipeping2.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+int main()
+{
+ PRFileDesc *pipe_read, *pipe_write;
+ PRStatus status;
+ char buf[1024];
+ PRInt32 nBytes;
+ int idx;
+
+ pipe_read = PR_GetInheritedFD("PIPE_READ");
+ if (pipe_read == NULL) {
+ fprintf(stderr, "PR_GetInheritedFD failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(pipe_read, PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ pipe_write = PR_GetInheritedFD("PIPE_WRITE");
+ if (pipe_write == NULL) {
+ fprintf(stderr, "PR_GetInheritedFD failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(pipe_write, PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(pipe_read, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("pong process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "ping") != 0) {
+ fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+
+ strcpy(buf, "pong");
+ printf("pong process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(pipe_write, buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed\n");
+ exit(1);
+ }
+ }
+
+ status = PR_Close(pipe_read);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(pipe_write);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/pr/tests/primblok.c b/pr/tests/primblok.c
new file mode 100644
index 00000000..7ebc3bfa
--- /dev/null
+++ b/pr/tests/primblok.c
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * File: primblok.c
+ * Purpose: testing whether the primordial thread can block in a
+ * native blocking function without affecting the correct
+ * functioning of NSPR I/O functions (Bugzilla bug #30746)
+ */
+
+#if !defined(WINNT)
+
+#include <stdio.h>
+
+int main()
+{
+ printf("This test is not relevant on this platform\n");
+ return 0;
+}
+
+#else /* WINNT */
+
+#include "nspr.h"
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TEST_FILE_NAME "primblok.dat"
+
+/* use InterlockedExchange to update this variable */
+static LONG iothread_done;
+
+static void PR_CALLBACK IOThread(void *arg)
+{
+ PRFileDesc *fd;
+ char buf[32];
+ PRInt32 nbytes;
+
+ /* Give the primordial thread one second to block */
+ Sleep(1000);
+
+ /*
+ * See if our PR_Write call will hang when the primordial
+ * thread is blocking in a native blocking function.
+ */
+ fd = PR_Open(TEST_FILE_NAME, PR_WRONLY|PR_CREATE_FILE, 0666);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_Open failed\n");
+ exit(1);
+ }
+ memset(buf, 0xaf, sizeof(buf));
+ fprintf(stderr, "iothread: calling PR_Write\n");
+ nbytes = PR_Write(fd, buf, sizeof(buf));
+ fprintf(stderr, "iothread: PR_Write returned\n");
+ if (nbytes != sizeof(buf)) {
+ fprintf(stderr, "PR_Write returned %d\n", nbytes);
+ exit(1);
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_Delete failed\n");
+ exit(1);
+ }
+
+ /* Tell the main thread that we are done */
+ InterlockedExchange(&iothread_done, 1);
+}
+
+int main()
+{
+ PRThread *iothread;
+
+ /* Must be a global thread */
+ iothread = PR_CreateThread(
+ PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (iothread == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+
+ /*
+ * Block in a native blocking function.
+ * Give iothread 5 seconds to finish its task.
+ */
+ Sleep(5000);
+
+ /*
+ * Is iothread done or is it hung?
+ *
+ * I'm actually only interested in reading the value
+ * of iothread_done. I'm using InterlockedExchange as
+ * a thread-safe way to read iothread_done.
+ */
+ if (InterlockedExchange(&iothread_done, 1) == 0) {
+ fprintf(stderr, "iothread is hung\n");
+ fprintf(stderr, "FAILED\n");
+ exit(1);
+ }
+
+ if (PR_JoinThread(iothread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ printf("PASSED\n");
+ return 0;
+} /* main */
+
+#endif /* WINNT */
diff --git a/pr/tests/prpollml.c b/pr/tests/prpollml.c
new file mode 100644
index 00000000..8c8cbedd
--- /dev/null
+++ b/pr/tests/prpollml.c
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * This test exercises the code that allocates and frees the syspoll_list
+ * array of PRThread in the pthreads version. This test is intended to be
+ * run under Purify to verify that there is no memory leak.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define POLL_DESC_COUNT 256 /* This should be greater than the
+ * STACK_POLL_DESC_COUNT macro in
+ * ptio.c to cause syspoll_list to
+ * be created. */
+
+static PRPollDesc pd[POLL_DESC_COUNT];
+
+static void Test(void)
+{
+ int i;
+ PRInt32 rv;
+ PRIntervalTime timeout;
+
+ timeout = PR_MillisecondsToInterval(10);
+ /* cause syspoll_list to grow */
+ for (i = 1; i <= POLL_DESC_COUNT; i++) {
+ rv = PR_Poll(pd, i, timeout);
+ if (rv != 0) {
+ fprintf(stderr,
+ "PR_Poll should time out but returns %d (%d, %d)\n",
+ rv, PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ }
+ /* syspoll_list should be large enough for all these */
+ for (i = POLL_DESC_COUNT; i >= 1; i--) {
+ rv = PR_Poll(pd, i, timeout);
+ if (rv != 0) {
+ fprintf(stderr, "PR_Poll should time out but returns %d\n", rv);
+ exit(1);
+ }
+ }
+}
+
+static void ThreadFunc(void *arg)
+{
+ Test();
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ PRThread *thread;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons(0);
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ for (i = 0; i < POLL_DESC_COUNT; i++) {
+ sock = PR_NewTCPSocket();
+ if (sock == NULL) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ pd[i].fd = sock;
+ pd[i].in_flags = PR_POLL_READ;
+ }
+
+ /* first run the test on the primordial thread */
+ Test();
+
+ /* then run the test on all three kinds of threads */
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ for (i = 0; i < POLL_DESC_COUNT; i++) {
+ if (PR_Close(pd[i].fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+ PR_Cleanup();
+ printf("PASS\n");
+ return 0;
+}
diff --git a/pr/tests/rmdir.c b/pr/tests/rmdir.c
new file mode 100644
index 00000000..a29b5872
--- /dev/null
+++ b/pr/tests/rmdir.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** File: rmdir.c
+** Description: Demonstrate bugzilla 80884.
+**
+** after fix to unix_errors.c, message should report correct
+** failure of PR_Rmdir().
+**
+**
+**
+*/
+
+#include <prio.h>
+#include <stdio.h>
+#include <prerror.h>
+#include <prlog.h>
+#include "plgetopt.h"
+
+#define DIRNAME "xxxBug80884/"
+#define FILENAME "file80883"
+
+PRBool failed_already = PR_FALSE;
+PRBool debug_mode = PR_FALSE;
+
+PRLogModuleInfo *lm;
+
+/*
+** Help() -- print Usage information
+*/
+static void Help( void ) {
+ fprintf(stderr, "template usage:\n"
+ "\t-d debug mode\n"
+ );
+} /* --- end Help() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dh");
+ PRFileDesc* fd;
+ PRErrorCode err;
+
+ /* parse command line options */
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ lm = PR_NewLogModule( "testcase" );
+
+ (void) PR_MkDir( DIRNAME, 0777);
+ fd = PR_Open( DIRNAME FILENAME, PR_CREATE_FILE|PR_RDWR, 0666);
+ if (fd == 0) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr, "create file fails: %d: %s\n", err,
+ PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ PR_Close(fd);
+
+ if (PR_RmDir( DIRNAME ) == PR_SUCCESS) {
+ fprintf(stderr, "remove directory succeeds\n");
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ err = PR_GetError();
+ fprintf(stderr, "remove directory fails with: %d: %s\n", err,
+ PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+
+ (void) PR_Delete( DIRNAME FILENAME);
+ (void) PR_RmDir( DIRNAME );
+
+ return 0;
+
+Finished:
+ if ( debug_mode ) printf("%s\n", ( failed_already ) ? "FAILED" : "PASS" );
+ return( (failed_already)? 1 : 0 );
+} /* --- end main() */
+/* --- end template.c */
diff --git a/pr/tests/selintr.c b/pr/tests/selintr.c
new file mode 100644
index 00000000..165d273c
--- /dev/null
+++ b/pr/tests/selintr.c
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test whether classic NSPR's select() wrapper properly blocks
+ * the periodic SIGALRM clocks. On some platforms (such as
+ * HP-UX and SINIX) an interrupted select() system call is
+ * restarted with the originally specified timeout, ignoring
+ * the time that has elapsed. If a select() call is interrupted
+ * repeatedly, it will never time out. (See Bugzilla bug #39674.)
+ */
+
+#if !defined(XP_UNIX)
+
+/*
+ * This test is applicable to Unix only.
+ */
+
+int main()
+{
+ return 0;
+}
+
+#else /* XP_UNIX */
+
+#include "nspr.h"
+
+#include <sys/time.h>
+#include <stdio.h>
+
+int main()
+{
+ struct timeval timeout;
+ int rv;
+
+ PR_SetError(0, 0); /* force NSPR to initialize */
+ PR_EnableClockInterrupts();
+
+ /* 2 seconds timeout */
+ timeout.tv_sec = 2;
+ timeout.tv_usec = 0;
+ rv = select(1, NULL, NULL, NULL, &timeout);
+ printf("select returned %d\n", rv);
+ return 0;
+}
+
+#endif /* XP_UNIX */