summaryrefslogtreecommitdiff
path: root/pr/tests
diff options
context:
space:
mode:
Diffstat (limited to 'pr/tests')
-rw-r--r--pr/tests/Makefile190
-rw-r--r--pr/tests/accept.c78
-rw-r--r--pr/tests/atomic.c21
-rw-r--r--pr/tests/attach.c17
-rw-r--r--pr/tests/bigfile.c135
-rw-r--r--pr/tests/cltsrv.c170
-rw-r--r--pr/tests/concur.c18
-rw-r--r--pr/tests/cvar2.c5
-rw-r--r--pr/tests/dceemu.c6
-rw-r--r--pr/tests/dll/Makefile4
-rw-r--r--pr/tests/dlltest.c79
-rw-r--r--pr/tests/foreign.c345
-rw-r--r--pr/tests/forktest.c21
-rw-r--r--pr/tests/initclk.c87
-rw-r--r--pr/tests/inrval.c157
-rw-r--r--pr/tests/instrumt.c470
-rw-r--r--pr/tests/ipv6.c65
-rw-r--r--pr/tests/joinkk.c4
-rw-r--r--pr/tests/layer.c6
-rw-r--r--pr/tests/lock.c105
-rw-r--r--pr/tests/many_cv.c2
-rw-r--r--pr/tests/multiwait.c61
-rw-r--r--pr/tests/nbconn.c574
-rw-r--r--pr/tests/nblayer.c91
-rw-r--r--pr/tests/op_filok.c37
-rw-r--r--pr/tests/op_noacc.c4
-rw-r--r--pr/tests/op_nofil.c37
-rw-r--r--pr/tests/parent.c10
-rw-r--r--pr/tests/perf.c24
-rw-r--r--pr/tests/poll_nm.c2
-rw-r--r--pr/tests/pollable.c273
-rw-r--r--pr/tests/prftest2.c2
-rw-r--r--pr/tests/priotest.c4
-rw-r--r--pr/tests/provider.c1356
-rw-r--r--pr/tests/sel_spd.c15
-rw-r--r--pr/tests/socket.c7
-rw-r--r--pr/tests/stack.c266
-rw-r--r--pr/tests/switch.c4
-rw-r--r--pr/tests/testfile.c85
-rw-r--r--pr/tests/tpd.c77
-rw-r--r--pr/tests/udpsrv.c78
-rw-r--r--pr/tests/version.c101
42 files changed, 4377 insertions, 716 deletions
diff --git a/pr/tests/Makefile b/pr/tests/Makefile
index 9db675f9..d1fc8afd 100644
--- a/pr/tests/Makefile
+++ b/pr/tests/Makefile
@@ -37,6 +37,7 @@ OS_CFLAGS = $(OS_EXE_CFLAGS)
endif
CSRCS = \
+ acceptread.c \
accept.c \
alarm.c \
atomic.c \
@@ -52,11 +53,14 @@ CSRCS = \
dtoa.c \
exit.c \
fileio.c \
+ foreign.c \
forktest.c \
fsync.c \
getproto.c \
i2l.c \
+ initclk.c \
inrval.c \
+ instrumt.c \
intrupt.c \
io_timeout.c \
ipv6.c \
@@ -86,9 +90,11 @@ CSRCS = \
poll_er.c \
poll_nm.c \
poll_to.c \
+ pollable.c \
prftest1.c \
prftest2.c \
priotest.c \
+ provider.c \
ranfile.c \
sel_spd.c \
selct_er.c \
@@ -106,6 +112,7 @@ CSRCS = \
sprintf.c \
sproc_ch.c \
sproc_p.c \
+ stack.c \
stdio.c \
strod.c \
suspend.c \
@@ -120,6 +127,7 @@ CSRCS = \
tmoacc.c \
tmocon.c \
tpd.c \
+ version.c \
udpsrv.c \
writev.c \
xnotify.c \
@@ -133,7 +141,7 @@ endif
PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
-TARGETS = $(PROGS) $(OBJS)
+TARGETS = $(PROGS)
INCLUDES = -I$(DIST)/include/obsolete -I$(DIST)/include/private -I$(DIST)/include
@@ -165,96 +173,112 @@ PWD = $(shell pwd)
endif
ifeq ($(OS_ARCH), IRIX)
-LDOPTS += -rpath $(PWD)/$(DIST)/lib -rdata_shared
-
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -rpath $(PWD)/$(DIST)/lib -rdata_shared
# For 6.x machines, include this flag
-ifeq ($(basename $(OS_RELEASE)),6)
-ifeq ($(USE_N32),1)
-LDOPTS += -n32
-else
-LDOPTS += -32
-endif
-endif
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifeq ($(USE_N32),1)
+ LDOPTS += -n32
+ else
+ LDOPTS += -32
+ endif
+ ifeq ($(USE_PTHREADS), 1)
+ ifeq ($(OS_RELEASE), 6.2)
+ LDOPTS += -Wl,-woff,85
+ endif
+ endif
+ endif
endif
ifeq ($(OS_ARCH), OSF1)
+ ifeq ($(USE_CPLUS), 1)
+ CC = cxx
+ endif
# I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so
# we do static linking.
-ifeq ($(OS_RELEASE), V3.2)
- LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
- LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
- EXTRA_LIBS = -lc_r
-else
- LDOPTS += -rpath $(PWD)/$(DIST)/lib
-endif
+ ifeq ($(OS_RELEASE), V3.2)
+ LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
+ LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
+ EXTRA_LIBS = -lc_r
+ else
+ LDOPTS += -rpath $(PWD)/$(DIST)/lib
+ endif
endif
ifeq ($(OS_ARCH), HP-UX)
-LDOPTS += -Wl,+s,+b,$(PWD)/$(DIST)/lib
+ LDOPTS += -z -Wl,+s,+b,$(PWD)/$(DIST)/lib
+ ifeq ($(USE_64),1)
+ LDOPTS += -L/usr/lib/pa20_64 -lpthread +DD64
+ endif
endif
# AIX
ifeq ($(OS_ARCH),AIX)
-ifeq ($(CLASSIC_NSPR),1)
-LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lpp/xlC/lib:/usr/lib:/lib
-else
-LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib
-endif
-ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
-LIBPR = -lnspr$(MOD_VERSION)_shr
-LIBPLC = -lplc$(MOD_VERSION)_shr
-else
-LDOPTS += -brtl
-EXTRA_LIBS = -ldl
-endif
+ ifeq ($(CLASSIC_NSPR),1)
+ LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lpp/xlC/lib:/usr/lib:/lib
+ else
+ LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib
+ endif
+ ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+ LIBPR = -lnspr$(MOD_VERSION)_shr
+ LIBPLC = -lplc$(MOD_VERSION)_shr
+ else
+ LDOPTS += -brtl
+ EXTRA_LIBS = -ldl
+ endif
endif
# Solaris
ifeq ($(OS_ARCH), SunOS)
-ifneq ($(OS_RELEASE), 4.1.3_U1)
-ifdef NS_USE_GCC
-LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(DIST)/lib
-else
-LDOPTS += -R $(PWD)/$(DIST)/lib
-endif
-endif
-
-ifneq ($(LOCAL_THREADS_ONLY),1)
+ ifneq ($(OS_RELEASE), 4.1.3_U1)
+ ifdef NS_USE_GCC
+ LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(DIST)/lib
+ else
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -R $(PWD)/$(DIST)/lib
+ endif
+ endif
+
+ ifneq ($(LOCAL_THREADS_ONLY),1)
# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
# even though we already linked with these system libraries
# when we built libnspr.so.
-ifeq ($(OS_RELEASE), 5.4)
-EXTRA_LIBS = -lthread
-endif
-
-ifeq ($(OS_RELEASE), 5.5)
-ifdef USE_PTHREADS
-EXTRA_LIBS = -lpthread
-else
-EXTRA_LIBS = -lthread
-endif
-endif
-endif # LOCAL_THREADS_ONLY
+ ifeq ($(OS_RELEASE), 5.4)
+ EXTRA_LIBS = -lthread
+ endif
+
+ ifeq ($(OS_RELEASE), 5.5)
+ ifdef USE_PTHREADS
+ EXTRA_LIBS = -lpthread
+ else
+ EXTRA_LIBS = -lthread
+ endif
+ endif
+ endif # LOCAL_THREADS_ONLY
endif # SunOS
ifeq ($(OS_ARCH), NEC)
-EXTRA_LIBS = $(OS_LIBS)
+ EXTRA_LIBS = $(OS_LIBS)
# This hardcodes in the executable programs the directory to find
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
-export LD_RUN_PATH = $(PWD)/$(DIST)/lib
+ export LD_RUN_PATH = $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH), NCR)
# NCR needs to link against -lsocket -lnsl -ldl (and -lc, which is
# linked implicitly by $(CC)). Note that we did not link with these
# system libraries when we built libnspr.so.
-EXTRA_LIBS = -lsocket -lnsl -ldl
+ EXTRA_LIBS = -lsocket -lnsl -ldl
# This hardcodes in the executable programs the directory to find
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
-export LD_RUN_PATH = $(PWD)/$(DIST)/lib
+ export LD_RUN_PATH = $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH), NEWS-OS)
@@ -262,20 +286,20 @@ ifeq ($(OS_ARCH), NEWS-OS)
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
#export LD_RUN_PATH = $(PWD)/$(DIST)/lib
- LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
- LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
- EXTRA_LIBS = -lsocket -lnsl -lgen -lresolv
+ LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
+ LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
+ EXTRA_LIBS = -lsocket -lnsl -lgen -lresolv
endif
ifeq ($(OS_ARCH), Linux)
-ifeq ($(OS_RELEASE), 1.2)
-EXTRA_LIBS = -ldl
-else
-LDOPTS += -Xlinker -rpath $(PWD)/$(DIST)/lib
-ifeq ($(USE_PTHREADS),1)
-EXTRA_LIBS = -lpthread
-endif
-endif
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(PWD)/$(DIST)/lib
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
endif
ifeq ($(OS_ARCH), SCOOS)
@@ -304,12 +328,29 @@ ifeq ($(OS_ARCH),FreeBSD)
ifeq ($(USE_PTHREADS),1)
EXTRA_LIBS = -lc_r
endif
+LDOPTS += -Xlinker -R $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH),BSD_OS)
EXTRA_LIBS = -ldl
endif
+ifeq ($(USE_PTHREADS),1)
+ifeq ($(OS_ARCH),AIX)
+LIBPTHREAD = -lpthreads
+else
+ ifeq ($(OS_ARCH),FreeBSD)
+ LIBPTHREAD = -lc_r
+ else
+ ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10)
+ LIBPTHREAD = -ldce
+ else
+ LIBPTHREAD = -lpthread
+ endif
+ endif
+endif
+endif
+
#####################################################
#
# The rules
@@ -352,15 +393,7 @@ else
ifeq ($(USE_PTHREADS), 1)
$(OBJDIR)/attach: $(OBJDIR)/attach.$(OBJ_SUFFIX)
@$(MAKE_OBJDIR)
-ifeq ($(OS_ARCH), AIX)
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lpthreads -o $@
-else
-ifeq ($(OS_ARCH),FreeBSD)
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lc_r -o $@
-else
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lpthread -o $@
-endif
-endif
+ $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) -o $@
endif
@@ -400,6 +433,13 @@ install:: export
clean::
rm -f $(TARGETS)
+ifeq ($(USE_PTHREADS), 1)
+$(OBJDIR)/foreign: $(OBJDIR)/foreign.o
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) $(LIBPTHREAD) -o $@
+$(OBJDIR)/provider: $(OBJDIR)/provider.o
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) $(LIBPTHREAD) -o $@
+endif
+
#
# Run the test programs with no arguments
#
diff --git a/pr/tests/accept.c b/pr/tests/accept.c
index 79ab811f..5318de74 100644
--- a/pr/tests/accept.c
+++ b/pr/tests/accept.c
@@ -48,12 +48,6 @@
#include "plgetopt.h"
#include "plerror.h"
-#ifdef XP_MAC
-#include "prlog.h"
-#define printf PR_LogPrint
-extern void SetupMacPrintfLog(char *logFile);
-#endif
-
#define BASE_PORT 8001
#define CLIENT_DATA 128
@@ -76,6 +70,7 @@ extern void SetupMacPrintfLog(char *logFile);
PRIntervalTime timeoutTime;
static PRInt32 count = 1;
+static PRFileDesc *output;
static PRNetAddr serverAddr;
static PRThreadScope thread_scope = PR_LOCAL_THREAD;
@@ -86,13 +81,8 @@ void Test_Assert(const char *msg, const char *file, PRIntn line)
{
failed_already=1;
if (debug_mode) {
-#if defined(WIN16)
- printf( "@%s:%d ", file, line);
- printf(msg);
-#else
- PR_fprintf(PR_STDERR, "@%s:%d ", file, line);
- PL_FPrintError(PR_STDERR, msg);
-#endif
+ PR_fprintf(output, "@%s:%d ", file, line);
+ PR_fprintf(output, msg);
}
} /* Test_Assert */
@@ -106,7 +96,7 @@ void timeout_callback(void *magic)
{
TEST_ASSERT(magic == (void *)CALLBACK_MAGIC);
if (debug_mode)
- printf("timeout callback called okay\n");
+ PR_fprintf(output, "timeout callback called okay\n");
}
#endif
@@ -131,7 +121,7 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf("client: unable to create socket\n");
+ PR_fprintf(output, "client: unable to create socket\n");
return;
}
@@ -142,10 +132,9 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf(
+ PR_fprintf(output,
"client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
- iterations, rv, PR_GetError(),
- PR_GetOSError());
+ iterations, rv, PR_GetError(), PR_GetOSError());
goto ErrorExit;
}
@@ -155,25 +144,24 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf("client: unable to send to server (%d, %ld, %ld)\n",
- CLIENT_DATA, rv,
- PR_GetError());
+ PR_fprintf(output,
+ "client: unable to send to server (%d, %ld, %ld)\n",
+ CLIENT_DATA, rv, PR_GetError());
goto ErrorExit;
}
} else {
- PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
- 1));
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
}
} else {
- PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
- 1));
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
}
if (debug_mode)
- printf(".");
+ PR_fprintf(output, ".");
PR_Close(sock);
+ sock = NULL;
}
if (debug_mode)
- printf("\n");
+ PR_fprintf(output, "\n");
ErrorExit:
if (sock != NULL)
@@ -203,7 +191,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (!listenSock) {
failed_already=1;
if (debug_mode)
- printf("unable to create listen socket\n");
+ PR_fprintf(output, "unable to create listen socket\n");
return;
}
listenAddr.inet.family = PR_AF_INET;
@@ -213,7 +201,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (rv == PR_FAILURE) {
failed_already=1;
if (debug_mode)
- printf("unable to bind\n");
+ PR_fprintf(output, "unable to bind\n");
return;
}
@@ -221,7 +209,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (rv == PR_FAILURE) {
failed_already=1;
if (debug_mode)
- printf("unable to listen\n");
+ PR_fprintf(output, "unable to listen\n");
return;
}
@@ -232,7 +220,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (!clientThread) {
failed_already=1;
if (debug_mode)
- printf("error creating client thread\n");
+ PR_fprintf(output, "error creating client thread\n");
return;
}
@@ -288,8 +276,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
case CLIENT_TIMEOUT_ACCEPT:
TEST_ASSERT(clientSock == 0);
if (debug_mode)
- printf("PR_GetError is %ld\n",
- PR_GetError());
+ PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError());
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
break;
case CLIENT_NORMAL:
@@ -342,8 +329,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
break;
case CLIENT_TIMEOUT_SEND:
if (debug_mode)
- printf("clientSock = 0x%8.8lx\n",
- clientSock);
+ PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
TEST_ASSERT(clientSock);
TEST_ASSERT(status == -1);
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
@@ -431,7 +417,7 @@ static void Measure(void (*func)(void), const char *msg)
d = (double)PR_IntervalToMicroseconds(stop - start);
if (debug_mode)
- printf("%40s: %6.2f usec\n", msg, d / count);
+ PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count);
}
@@ -467,6 +453,7 @@ int main(int argc, char **argv)
PL_DestroyOptState(opt);
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ output = PR_STDERR;
PR_STDIO_INIT();
#ifdef XP_MAC
@@ -476,7 +463,7 @@ int main(int argc, char **argv)
timeoutTime = PR_SecondsToInterval(TIMEOUTSECS);
if (debug_mode)
- printf("\nRun accept() sucessful connection tests\n");
+ PR_fprintf(output, "\nRun accept() sucessful connection tests\n");
Measure(AcceptUpdatedTest, "PR_Accept()");
Measure(AcceptReadTest, "PR_AcceptRead()");
@@ -486,28 +473,19 @@ int main(int argc, char **argv)
Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
if (debug_mode)
- printf("\nRun accept() timeout in the accept tests\n");
+ PR_fprintf(output, "\nRun accept() timeout in the accept tests\n");
#ifdef WINNT
Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
Measure(TimeoutReadUpdatedTest, "PR_Accept()");
if (debug_mode)
- printf("\nRun accept() timeout in the read tests\n");
+ PR_fprintf(output, "\nRun accept() timeout in the read tests\n");
Measure(TimeoutReadReadTest, "PR_AcceptRead()");
#ifdef WINNT
Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
- if(failed_already)
- {
- printf("FAIL\n");
- return 1;
- }
- else
- {
- printf("PASS\n");
- return 0;
-
- }
+ PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS");
+ return failed_already;
}
diff --git a/pr/tests/atomic.c b/pr/tests/atomic.c
index d5e334d5..a2ba2044 100644
--- a/pr/tests/atomic.c
+++ b/pr/tests/atomic.c
@@ -22,7 +22,7 @@
PRIntn main(PRIntn argc, char **argv)
{
- PRInt32 rv, test, result = 0;
+ PRInt32 rv, oldval, test, result = 0;
PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);
test = -2;
@@ -42,6 +42,25 @@ PRIntn main(PRIntn argc, char **argv)
output, "PR_AtomicIncrement(%d) == %d: %s\n",
test, rv, (rv > 0) ? "PASSED" : "FAILED");
+ oldval = test = -2;
+ rv = PR_AtomicAdd(&test,1);
+ result = result | ((rv == -1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, 4);
+ result = result | ((rv == 3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, -6);
+ result = result | ((rv == -3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED");
+
test = 2;
rv = PR_AtomicDecrement(&test);
result = result | ((rv > 0) ? 0 : 1);
diff --git a/pr/tests/attach.c b/pr/tests/attach.c
index 3fa38d49..79a5d3d8 100644
--- a/pr/tests/attach.c
+++ b/pr/tests/attach.c
@@ -66,7 +66,7 @@
#include <os2.h>
#endif
-#define DEFAULT_COUNT 10000
+#define DEFAULT_COUNT 1000
PRIntn failed_already=0;
PRIntn debug_mode;
@@ -81,21 +81,17 @@ AttachDetach(void)
PRInt32 index;
for (index=0;index<count; index++) {
-
me = PR_AttachThread(PR_USER_THREAD,
PR_PRIORITY_NORMAL,
NULL);
if (!me) {
- fprintf(stderr, "Error attaching thread %d: "
- "nspr20 error code %d, os error code %d\n",
- count, PR_GetError(), PR_GetOSError());
- failed_already = 1;
- return;
+ fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n",
+ count);
+ failed_already = 1;
+ return;
}
-
PR_DetachThread();
-
}
}
@@ -277,7 +273,7 @@ int main(int argc, char **argv)
}
rv = WaitForSingleObject(hThread, INFINITE);
if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
- else if (rv != WAIT_FAILED) {
+ else if (rv == WAIT_FAILED) {
failed_already=1;
goto exit_now;
}
@@ -296,6 +292,7 @@ int main(int argc, char **argv)
else {
if (debug_mode)
printf ("thread creation succeeded \n");
+ sleep(3);
goto exit_now;
}
rv = waitpid(threadID, NULL, 0);
diff --git a/pr/tests/bigfile.c b/pr/tests/bigfile.c
index 9cb4e7fd..399da8cd 100644
--- a/pr/tests/bigfile.c
+++ b/pr/tests/bigfile.c
@@ -35,10 +35,10 @@ static void Verbose(Verbosity, const char*, const char*, PRIntn);
#define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__)
-static PRIntn filesize = 1;
static PRIntn test_result = 2;
static PRFileDesc *output = NULL;
static PRIntn verbose = v_silent;
+static PRIntn filesize = DEFAULT_FILESIZE;
static PRIntn Usage(void)
{
@@ -46,6 +46,7 @@ static PRIntn Usage(void)
PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s <n>] <filename>\n");
PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n");
PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n");
+ PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n");
PR_fprintf(output, "\ts <n>\tFile size in megabytes\t\t(1 megabyte)\n");
PR_fprintf(output, "\t<filename>\tName of test file\t(none)\n");
return 2; /* nothing happened */
@@ -64,6 +65,7 @@ static PRStatus DeleteIfFound(const char *filename)
}
else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError())
VERBOSE(v_shout, "Cannot access big file");
+ else rv = PR_SUCCESS;
return rv;
} /* DeleteIfFound */
@@ -87,20 +89,43 @@ static void Verbose(
PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg);
} /* Verbose */
+static void PrintInfo(PRFileInfo64 *info, const char *filename)
+{
+ PRExplodedTime tm;
+ char ctime[40], mtime[40];
+ static const char *types[] = {"FILE", "DIRECTORY", "OTHER"};
+ PR_fprintf(
+ output, "[%s : %d]: File info for %s\n",
+ __FILE__, __LINE__, filename);
+ PR_fprintf(
+ output, " type: %s, size: %llu bytes,\n",
+ types[info->type - 1], info->size);
+
+ PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm);
+ PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm);
+
+ PR_fprintf(
+ output, " creation: %s,\n modify: %s\n", ctime, mtime);
+} /* PrintInfo */
+
PRIntn main(PRIntn argc, char **argv)
{
PRStatus rv;
char *buffer;
PLOptStatus os;
PRInt32 loop, bytes;
+ PRFileInfo small_info;
+ PRFileInfo64 big_info;
+ PRBool keep = PR_FALSE;
PRFileDesc *file = NULL;
const char *filename = NULL;
PRIntn count = DEFAULT_COUNT;
- PRFileInfo64 *big_info = NULL;
- PRInt64 big_answer, big_size, one_meg, zero_meg, big_fragment;
- PRInt64 filesize64;
+ PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment;
+ PRInt64 sevenFox = LL_INIT(0,0x7fffffff);
- PLOptState *opt = PL_CreateOptState(argc, argv, "dvhs:");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:");
output = PR_GetSpecialFD(PR_StandardError);
PR_STDIO_INIT();
@@ -116,6 +141,9 @@ PRIntn main(PRIntn argc, char **argv)
case 'd': /* debug mode */
verbose = v_shout;
break;
+ case 'k': /* keep file */
+ keep = PR_TRUE;
+ break;
case 'v': /* verbosity */
if (v_shout > verbose) verbose += 1;
break;
@@ -132,9 +160,13 @@ PRIntn main(PRIntn argc, char **argv)
}
PL_DestroyOptState(opt);
- if (NULL == filename) return Usage();
if (0 == count) count = DEFAULT_COUNT;
if (0 == filesize) filesize = DEFAULT_FILESIZE;
+ if (NULL == filename)
+ {
+ if (DEFAULT_FILESIZE != filesize) return Usage();
+ else filename = "/usr/tmp/bigfile.dat";
+ }
if (PR_FAILURE == DeleteIfFound(filename)) return 1;
@@ -145,7 +177,7 @@ PRIntn main(PRIntn argc, char **argv)
LL_I2L(filesize64, filesize);
buffer = (char*)PR_MALLOC(BUFFER_SIZE);
LL_I2L(big_fragment, BUFFER_SIZE);
- LL_MUL(big_size, filesize64, one_meg);
+ LL_MUL(filesize64, filesize64, one_meg);
for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop;
@@ -157,32 +189,45 @@ PRIntn main(PRIntn argc, char **argv)
big_answer = file->methods->available64(file);
if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename);
-#if 0
- VERBOSE(v_whisper, "Filling big file with data");
- while (LL_CMP(big_answer, <, big_size))
- {
- bytes = file->methods->write(file, buffer, BUFFER_SIZE);
- if (bytes != BUFFER_SIZE) return Error("write", filename);
- LL_ADD(big_answer, big_answer, big_fragment);
- }
-#else
- LL_SUB(big_size, big_size, one_meg);
+ LL_SUB(big_size, filesize64, one_meg);
+ VERBOSE(v_whisper, "Creating sparce big file by seeking to end");
big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
+ if (!LL_EQ(big_answer, big_size)) return Error("seek", filename);
+
+ VERBOSE(v_whisper, "Writing block at end of sparce file");
bytes = file->methods->write(file, buffer, BUFFER_SIZE);
if (bytes != BUFFER_SIZE) return Error("write", filename);
-#endif
- VERBOSE(v_whisper, "Testing available space in filled file");
+ VERBOSE(v_whisper, "Testing available space at end of sparce file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, zero_meg)) return Error("eof available64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename);
+
+ VERBOSE(v_whisper, "Getting big info on sparce big file");
+ rv = file->methods->fileInfo64(file, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
+ VERBOSE(v_whisper, "Getting small info on sparce big file");
+ rv = file->methods->fileInfo(file, &small_info);
+ if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv))
+ {
+ VERBOSE(v_whisper, "Should have failed and didn't");
+ return Error("fileInfo()", filename);
+ }
+ else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv))
+ {
+ VERBOSE(v_whisper, "Should have succeeded and didn't");
+ return Error("fileInfo()", filename);
+ }
VERBOSE(v_whisper, "Rewinding big file");
big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
- if (LL_NE(big_answer, zero_meg)) return Error("rewind seek64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename);
VERBOSE(v_whisper, "Establishing available space in rewound file");
- big_size = file->methods->available64(file);
- if (!LL_GE_ZERO(big_size)) return Error("bof available64()", filename);
+ big_answer = file->methods->available64(file);
+ if (LL_NE(filesize64, big_answer))
+ return Error("bof available64()", filename);
VERBOSE(v_whisper, "Closing big file");
rv = file->methods->close(file);
@@ -190,47 +235,59 @@ PRIntn main(PRIntn argc, char **argv)
VERBOSE(v_whisper, "Reopening big file");
file = PR_Open(filename, PR_RDWR, 0666);
- if (NULL == file) return Error("bof seek64()", filename);
+ if (NULL == file) return Error("open failed", filename);
VERBOSE(v_whisper, "Checking available data in reopened file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_size, big_answer)) return Error("reopened available64()", filename);
+ if (LL_NE(filesize64, big_answer))
+ return Error("reopened available64()", filename);
big_answer = zero_meg;
- VERBOSE(v_whisper, "Rewriting big file data");
- while (LL_CMP(big_answer, <, big_size))
+ VERBOSE(v_whisper, "Rewriting every byte of big file data");
+ do
{
bytes = file->methods->write(file, buffer, BUFFER_SIZE);
- if (bytes != BUFFER_SIZE) return Error("write", filename);
+ if (bytes != BUFFER_SIZE)
+ return Error("write", filename);
LL_ADD(big_answer, big_answer, big_fragment);
- }
+ } while (LL_CMP(big_answer, <, filesize64));
+
+ VERBOSE(v_whisper, "Checking position at eof");
+ big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR);
+ if (LL_NE(big_answer, filesize64))
+ return Error("file size error", filename);
VERBOSE(v_whisper, "Testing available space at eof");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, zero_meg)) return Error("eof available64()", filename);
+ if (!LL_IS_ZERO(big_answer))
+ return Error("eof available64()", filename);
- VERBOSE(v_whisper, "Rewinding full file file");
+ VERBOSE(v_whisper, "Rewinding full file");
big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
- if (LL_NE(big_answer, zero_meg)) return Error("bof seek64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename);
VERBOSE(v_whisper, "Testing available space in rewound file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, big_size)) return Error("bof available64()", filename);
+ if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename);
VERBOSE(v_whisper, "Seeking to end of big file");
- big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
- if (LL_NE(big_answer, big_size)) return Error("eof seek64()", filename);
+ big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET);
+ if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename);
- VERBOSE(v_whisper, "Getting info on big file");
- big_info = PR_NEWZAP(PRFileInfo64);
- rv = file->methods->fileInfo64(file, big_info);
+ VERBOSE(v_whisper, "Getting info on big file while it's open");
+ rv = file->methods->fileInfo64(file, &big_info);
if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
- PR_DELETE(big_info);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
VERBOSE(v_whisper, "Closing big file");
rv = file->methods->close(file);
if (PR_FAILURE == rv) return Error("close()", filename);
+ VERBOSE(v_whisper, "Getting info on big file after it's closed");
+ rv = PR_GetFileInfo64(filename, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
VERBOSE(v_whisper, "Deleting big file");
rv = PR_Delete(filename);
if (PR_FAILURE == rv) return Error("PR_Delete()", filename);
diff --git a/pr/tests/cltsrv.c b/pr/tests/cltsrv.c
index 346ff2f9..f3333be4 100644
--- a/pr/tests/cltsrv.c
+++ b/pr/tests/cltsrv.c
@@ -79,6 +79,8 @@
#define RECV_FLAGS 0
#define SEND_FLAGS 0
+#define DEFAULT_LOW 0
+#define DEFAULT_HIGH 0
#define BUFFER_SIZE 1024
#define DEFAULT_BACKLOG 5
#define DEFAULT_PORT 12848
@@ -204,22 +206,6 @@ static PRBool Aborted(PRStatus rv)
PR_TRUE : PR_FALSE;
}
-static void Assert(const char *s, const char *file, PRIntn ln)
-{
- PRIntn error = PR_GetError(), syserrno = PR_GetOSError();
- TEST_LOG(
- cltsrv_log_file, TEST_LOG_ALWAYS,
- ("Assertion failed(0x%lx): '%s' in %s[%d]\n",
- PR_CurrentThread(), s, file, ln));
- TEST_LOG(
- cltsrv_log_file, TEST_LOG_ALWAYS,
- ("**Error information: Error = %d, OSError = %d\n",
- error, syserrno));
- PR_LogFlush();
-
- PR_Abort();
-} /* Assert */
-
static void TimeOfDayMessage(const char *msg, PRThread* me)
{
char buffer[100];
@@ -229,7 +215,7 @@ static void TimeOfDayMessage(const char *msg, PRThread* me)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("%s(0x%lx): %s\n", msg, me, buffer));
+ ("%s(0x%p): %s\n", msg, me, buffer));
} /* TimeOfDayMessage */
@@ -264,7 +250,7 @@ static void PR_CALLBACK Client(void *arg)
(void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
- ("\tClient(0x%lx): connecting to server at %s\n", me, buffer));
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
fd = PR_Socket(domain, SOCK_STREAM, protocol);
TEST_ASSERT(NULL != fd);
@@ -273,7 +259,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): conection failed\n", me));
+ ("\tClient(0x%p): conection failed\n", me));
goto aborted;
}
@@ -281,10 +267,10 @@ static void PR_CALLBACK Client(void *arg)
descriptor->size = PR_htonl(descbytes = rand() % clipping);
PR_snprintf(
descriptor->filename, sizeof(descriptor->filename),
- "CS%lx%lx-%lx.dat", client->started, me, client->operations);
+ "CS%p%p-%p.dat", client->started, me, client->operations);
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): sending descriptor for %ld bytes\n", me, descbytes));
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
bytes = PR_Send(
fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
if (sizeof(CSDescriptor_t) != bytes)
@@ -294,7 +280,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): send descriptor timeout\n", me));
+ ("\tClient(0x%p): send descriptor timeout\n", me));
goto retry;
}
}
@@ -308,7 +294,7 @@ static void PR_CALLBACK Client(void *arg)
filebytes = descbytes - netbytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): sending %d bytes\n", me, filebytes));
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
if (filebytes != bytes)
{
@@ -317,7 +303,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): send data timeout\n", me));
+ ("\tClient(0x%p): send data timeout\n", me));
goto retry;
}
}
@@ -332,7 +318,7 @@ static void PR_CALLBACK Client(void *arg)
netbytes = descbytes - filebytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): receiving %d bytes\n", me, netbytes));
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
if (-1 == bytes)
{
@@ -340,17 +326,17 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive data aborted\n", me));
+ ("\tClient(0x%p): receive data aborted\n", me));
goto aborted;
}
else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive data timeout\n", me));
+ ("\tClient(0x%p): receive data timeout\n", me));
else
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive error (%ld, %ld)\n",
+ ("\tClient(0x%p): receive error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto retry;
}
@@ -358,7 +344,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tClient(0x%lx): unexpected end of stream\n",
+ ("\t\tClient(0x%p): unexpected end of stream\n",
PR_CurrentThread()));
break;
}
@@ -372,7 +358,7 @@ retry:
(void)PR_Close(fd); fd = NULL;
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("\tClient(0x%lx): disconnected from server\n", me));
+ ("\tClient(0x%p): disconnected from server\n", me));
PR_Lock(client->ml);
client->operations += 1;
@@ -395,7 +381,7 @@ aborted:
PR_DELETE(descriptor);
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("\tClient(0x%lx): stopped after %lu operations and %lu bytes\n",
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
PR_CurrentThread(), client->operations, client->bytesTransferred));
} /* Client */
@@ -412,7 +398,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): receiving desciptor\n", me));
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
bytes = PR_Recv(
fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
if (-1 == bytes)
@@ -423,7 +409,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): receive timeout\n", me));
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
}
goto exit;
}
@@ -432,7 +418,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
rv = PR_FAILURE;
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): unexpected end of file\n", me));
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
goto exit;
}
descbytes = PR_ntohl(descriptor->size);
@@ -440,7 +426,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): read descriptor {%ld, %s}\n",
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
me, descbytes, descriptor->filename));
file = PR_Open(
@@ -453,7 +439,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): open file timeout\n", me));
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
goto aborted;
}
}
@@ -467,7 +453,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
netbytes = descbytes - filebytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): receive %d bytes\n", me, netbytes));
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
if (-1 == bytes)
{
@@ -477,7 +463,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): receive data timeout\n", me));
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
goto aborted;
}
/*
@@ -487,7 +473,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
*/
TEST_LOG(
cltsrv_log_file, TEST_LOG_WARNING,
- ("\t\tProcessRequest(0x%lx): unexpected error (%d, %d)\n",
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -495,7 +481,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_WARNING,
- ("\t\tProcessRequest(0x%lx): unexpected end of stream\n", me));
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
rv = PR_FAILURE;
goto aborted;
}
@@ -505,7 +491,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
MY_ASSERT(netbytes > 0);
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): write %d bytes to file\n", me, netbytes));
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
bytes = PR_Write(file, buffer, netbytes);
if (netbytes != bytes)
{
@@ -515,7 +501,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): write file timeout\n", me));
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
goto aborted;
}
}
@@ -533,7 +519,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): opening %s\n", me, descriptor->filename));
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
file = PR_Open(descriptor->filename, PR_RDONLY, 0);
if (NULL == file)
{
@@ -543,13 +529,13 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): open file timeout\n",
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
PR_CurrentThread()));
goto aborted;
}
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): other file open error (%u, %u)\n",
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -563,7 +549,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
filebytes = descbytes - netbytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): read %d bytes from file\n", me, filebytes));
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
bytes = PR_Read(file, buffer, filebytes);
if (filebytes != bytes)
{
@@ -572,11 +558,11 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
if (PR_IO_TIMEOUT_ERROR == PR_GetError())
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): read file timeout\n", me));
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
else
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): other file error (%d, %d)\n",
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -585,7 +571,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
filebytes = bytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): sending %d bytes\n", me, filebytes));
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
if (filebytes != bytes)
{
@@ -595,7 +581,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): send data timeout\n", me));
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
goto aborted;
}
break;
@@ -622,7 +608,7 @@ aborted:
exit:
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): Finished\n", me));
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
PR_DELETE(descriptor);
@@ -648,7 +634,7 @@ static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
}
TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
- ("\tCreateWorker(0x%lx): create new worker (0x%lx)\n",
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
PR_CurrentThread(), worker->thread));
return PR_SUCCESS;
@@ -666,7 +652,7 @@ static void PR_CALLBACK Worker(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\t\tWorker(0x%lx): started [%lu]\n", me, pool->workers + 1));
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
PR_Lock(server->ml);
PR_APPEND_LINK(&worker->element, &server->list);
@@ -678,14 +664,14 @@ static void PR_CALLBACK Worker(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tWorker(0x%lx): waiting for accept slot[%d]\n",
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
me, pool->accepting));
rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
if (Aborted(rv) || (cs_run != server->state))
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\tWorker(0x%lx): has been %s\n",
+ ("\tWorker(0x%p): has been %s\n",
me, (Aborted(rv) ? "interrupted" : "stopped")));
goto exit;
}
@@ -695,7 +681,7 @@ static void PR_CALLBACK Worker(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tWorker(0x%lx): calling accept\n", me));
+ ("\t\tWorker(0x%p): calling accept\n", me));
fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
PR_Lock(server->ml);
@@ -736,7 +722,7 @@ static void PR_CALLBACK Worker(void *arg)
if (PR_SUCCESS != rv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tWorker(0x%lx): server process ended abnormally\n", me));
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
(void)PR_Close(fd); fd = NULL;
PR_Lock(server->ml);
@@ -756,7 +742,7 @@ exit:
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\t\tWorker(0x%lx): exiting [%lu]\n", PR_CurrentThread(), pool->workers));
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
PR_Lock(server->ml);
pool->workers -= 1; /* undefine our existance */
@@ -809,7 +795,7 @@ static void PR_CALLBACK Server(void *arg)
*/
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tServer(0x%lx): waiting for state change\n", me));
+ ("\tServer(0x%p): waiting for state change\n", me));
PR_Lock(server->ml);
while ((cs_run == server->state) && !Aborted(rv))
@@ -821,7 +807,7 @@ static void PR_CALLBACK Server(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("\tServer(0x%lx): shutting down workers\n", me));
+ ("\tServer(0x%p): shutting down workers\n", me));
/*
** Get all the worker threads to exit. They know how to
@@ -838,7 +824,7 @@ static void PR_CALLBACK Server(void *arg)
CSWorker_t *worker = (CSWorker_t*)head;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tServer(0x%lx): interrupting worker(0x%lx)\n", me, worker));
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
rv = PR_Interrupt(worker->thread);
TEST_ASSERT(PR_SUCCESS == rv);
PR_REMOVE_AND_INIT_LINK(head);
@@ -848,7 +834,7 @@ static void PR_CALLBACK Server(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\tServer(0x%lx): waiting for %lu workers to exit\n",
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
me, server->pool.workers));
(void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
}
@@ -859,7 +845,7 @@ static void PR_CALLBACK Server(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("\tServer(0x%lx): stopped after %lu operations and %lu bytes\n",
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
me, server->operations, server->bytesTransferred));
if (NULL != server->listener) PR_Close(server->listener);
@@ -867,26 +853,15 @@ static void PR_CALLBACK Server(void *arg)
} /* Server */
-#if defined(DEBUG) && defined(_PR_PTHREADS)
-static void PrintPthreadStats(void)
-{
- PT_FPrintStats(debug_out, "\nPThread Statistics\n");
-} /* PrintPthreadStats */
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
-
static void WaitForCompletion(PRIntn execution)
{
-#if defined(DEBUG) && defined(_PR_PTHREADS)
while (execution > 0)
{
PRIntn dally = (execution > 30) ? 30 : execution;
PR_Sleep(PR_SecondsToInterval(dally));
- if (pthread_stats) PrintPthreadStats();
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
execution -= dally;
}
-#else
- PR_Sleep(PR_SecondsToInterval(execution));
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
} /* WaitForCompletion */
static void Help(void)
@@ -895,6 +870,8 @@ static void Help(void)
PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-f <low> low water mark for fd caching (0)\n");
+ PR_fprintf(debug_out, "\t-F <high> high water mark for fd caching (0)\n");
PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
@@ -932,12 +909,15 @@ PRIntn main(PRIntn argc, char** argv)
PRUintn workersMin = DEFAULT_WORKERS_MIN;
PRUintn workersMax = DEFAULT_WORKERS_MAX;
PRIntn execution = DEFAULT_EXECUTION_TIME;
+ PRIntn low = DEFAULT_LOW, high = DEFAULT_HIGH;
/*
* -G use global threads
* -a <n> threads allowed in accept
* -b <n> backlock for listen
* -c <threads> number of clients to create
+ * -f <low> low water mark for caching FDs
+ * -F <high> high water mark for caching FDs
* -w <threads> minimal number of server threads
* -W <threads> maximum number of server threads
* -e <seconds> duration of the test in seconds
@@ -946,7 +926,7 @@ PRIntn main(PRIntn argc, char** argv)
*/
PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:vdhp");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:f:F:w:W:e:s:vdhp");
debug_out = PR_GetSpecialFD(PR_StandardError);
@@ -976,6 +956,12 @@ PRIntn main(PRIntn argc, char** argv)
case 'c': /* number of client threads */
clients = atoi(opt->value);
break;
+ case 'f': /* low water fd cache */
+ low = atoi(opt->value);
+ break;
+ case 'F': /* low water fd cache */
+ high = atoi(opt->value);
+ break;
case 'w': /* minimum server worker threads */
workersMin = atoi(opt->value);
break;
@@ -1026,12 +1012,15 @@ PRIntn main(PRIntn argc, char** argv)
debug_mode = PR_TRUE;
#endif
+ rv = PR_SetFDCacheSize(low, high);
+ PR_ASSERT(PR_SUCCESS == rv);
+
if (serverIsLocal)
{
/* Establish the server */
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("main(0x%lx): starting server\n", PR_CurrentThread()));
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
server = PR_NEWZAP(CSServer_t);
PR_INIT_CLIST(&server->list);
@@ -1048,7 +1037,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): creating server thread\n", PR_CurrentThread()));
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
server->thread = PR_CreateThread(
PR_USER_THREAD, Server, server, PR_PRIORITY_HIGH,
@@ -1057,7 +1046,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): waiting for server init\n", PR_CurrentThread()));
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
PR_Lock(server->ml);
while (server->state == cs_init)
@@ -1066,7 +1055,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): server init complete (port #%d)\n",
+ ("main(0x%p): server init complete (port #%d)\n",
PR_CurrentThread(), server->port));
}
@@ -1079,7 +1068,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): creating %d client threads\n",
+ ("main(0x%p): creating %d client threads\n",
PR_CurrentThread(), clients));
if (!serverIsLocal)
@@ -1110,7 +1099,7 @@ PRIntn main(PRIntn argc, char** argv)
client[index].stateChange = PR_NewCondVar(client[index].ml);
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("main(0x%lx): creating client threads\n", PR_CurrentThread()));
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
client[index].thread = PR_CreateThread(
PR_USER_THREAD, Client, &client[index], PR_PRIORITY_NORMAL,
thread_scope, PR_JOINABLE_THREAD, 0);
@@ -1125,7 +1114,7 @@ PRIntn main(PRIntn argc, char** argv)
/* Then just let them go at it for a bit */
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("main(0x%lx): waiting for execution interval (%d seconds)\n",
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
PR_CurrentThread(), execution));
WaitForCompletion(execution);
@@ -1137,7 +1126,7 @@ PRIntn main(PRIntn argc, char** argv)
for (index = 0; index < clients; ++index)
{
TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
- ("main(0x%lx): notifying client(0x%lx) to stop\n",
+ ("main(0x%p): notifying client(0x%p) to stop\n",
PR_CurrentThread(), client[index].thread));
PR_Lock(client[index].ml);
@@ -1152,7 +1141,7 @@ PRIntn main(PRIntn argc, char** argv)
PR_Unlock(client[index].ml);
TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): joining client(0x%lx)\n",
+ ("main(0x%p): joining client(0x%p)\n",
PR_CurrentThread(), client[index].thread));
joinStatus = PR_JoinThread(client[index].thread);
@@ -1168,7 +1157,7 @@ PRIntn main(PRIntn argc, char** argv)
/* All clients joined - retrieve the server */
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): notifying server(0x%lx) to stop\n",
+ ("main(0x%p): notifying server(0x%p) to stop\n",
PR_CurrentThread(), server->thread));
PR_Lock(server->ml);
@@ -1180,7 +1169,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): joining server(0x%lx)\n",
+ ("main(0x%p): joining server(0x%p)\n",
PR_CurrentThread(), server->thread));
joinStatus = PR_JoinThread(server->thread);
TEST_ASSERT(PR_SUCCESS == joinStatus);
@@ -1194,13 +1183,12 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("main(0x%lx): test complete\n", PR_CurrentThread()));
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
-#if defined(DEBUG) && defined(_PR_PTHREADS)
- PrintPthreadStats();
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
+ PT_FPrintStats(debug_out, "\nPThread Statistics\n");
TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ PR_Cleanup();
return 0;
} /* main */
diff --git a/pr/tests/concur.c b/pr/tests/concur.c
index 88575dd5..fa2bfa1f 100644
--- a/pr/tests/concur.c
+++ b/pr/tests/concur.c
@@ -26,6 +26,8 @@
#include "prinrval.h"
#include "prlock.h"
#include "prprf.h"
+#include "prmem.h"
+#include "prlog.h"
#include "plgetopt.h"
@@ -37,7 +39,7 @@
#include <stdlib.h>
-#define DEFAULT_RANGE 20
+#define DEFAULT_RANGE 10
#define DEFAULT_LOOPS 100
static PRThreadScope thread_scope = PR_LOCAL_THREAD;
@@ -71,8 +73,11 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
{
PRUintn cpus;
PLOptStatus os;
+ PRThread **threads;
PRBool debug = PR_FALSE;
PRUintn range = DEFAULT_RANGE;
+ PRStatus rc;
+ PRUintn cnt;
PRUintn loops = DEFAULT_LOOPS;
PRIntervalTime hundredMills = PR_MillisecondsToInterval(100);
PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:");
@@ -109,16 +114,17 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
PR_fprintf(
PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops);
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range);
while (--loops > 0)
{
- for (cpus = 1; cpus < range; ++cpus)
+ for (cpus = 1; cpus <= range; ++cpus)
{
PR_SetConcurrency(cpus);
context.want = cpus;
- (void)PR_CreateThread(
+ threads[cpus - 1] = PR_CreateThread(
PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL,
- thread_scope, PR_UNJOINABLE_THREAD, 0);
+ thread_scope, PR_JOINABLE_THREAD, 0);
}
PR_Sleep(hundredMills);
@@ -132,6 +138,10 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
PR_NotifyCondVar(context.cv);
PR_Unlock(context.ml);
}
+ for(cnt = 0; cnt < range; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
}
diff --git a/pr/tests/cvar2.c b/pr/tests/cvar2.c
index f6b34268..f2508a7b 100644
--- a/pr/tests/cvar2.c
+++ b/pr/tests/cvar2.c
@@ -35,6 +35,7 @@
***********************************************************************/
#include "nspr.h"
+#include "plerror.h"
#include "plgetopt.h"
#include <stdio.h>
@@ -167,8 +168,8 @@ CreateTestThread(threadinfo *info,
scope,
PR_JOINABLE_THREAD,
0);
- if (!info->thread)
- printf("error creating thread\n");
+ if (!info->thread)
+ PL_PrintError("error creating thread\n");
}
diff --git a/pr/tests/dceemu.c b/pr/tests/dceemu.c
index 7935eae8..cb04cbd6 100644
--- a/pr/tests/dceemu.c
+++ b/pr/tests/dceemu.c
@@ -36,7 +36,7 @@
***********************************************************************/
-#if defined(XP_UNIX)
+#if defined(_PR_DCETHREADS)
#include "prlog.h"
#include "prinit.h"
@@ -93,12 +93,12 @@ static PRIntn prmain(PRIntn argc, char **argv)
} /* prmain */
-#endif /* #if defined(XP_UNIX) */
+#endif /* #if defined(_PR_DCETHREADS) */
int main(int argc, char **argv)
{
-#if defined(XP_UNIX)
+#if defined(_PR_DCETHREADS)
PR_Initialize(prmain, argc, argv, 0);
if(failed_already)
return 1;
diff --git a/pr/tests/dll/Makefile b/pr/tests/dll/Makefile
index 7afc7300..c2f72d71 100644
--- a/pr/tests/dll/Makefile
+++ b/pr/tests/dll/Makefile
@@ -58,7 +58,9 @@ else
TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
endif
else
+ifdef MKSHLIB
SHARED_LIBRARY = $(OBJDIR)/libmy.$(DLL_SUFFIX)
+endif
TARGETS = $(SHARED_LIBRARY)
endif
@@ -81,6 +83,7 @@ OS_DLL_OPTION = NOCASEEXACT
OS_LIB_FLAGS = -irn
endif
+ifdef SHARED_LIBRARY
export:: $(TARGETS)
$(NSINSTALL) $(TARGETS) ../$(OBJDIR)/dll
@@ -88,3 +91,4 @@ install:: export
clean::
rm -rf $(TARGETS)
+endif
diff --git a/pr/tests/dlltest.c b/pr/tests/dlltest.c
index bd8f7c49..bc817a05 100644
--- a/pr/tests/dlltest.c
+++ b/pr/tests/dlltest.c
@@ -84,15 +84,15 @@ int main(int argc, char** argv)
fprintf(
stderr, "PR_LoadLibrary failed (%d, %d, %s)\n",
PR_GetError(), PR_GetOSError(), text);
- if (!debug_mode) failed_already=1;
+ if (!debug_mode) failed_already=1;
}
getFcn = (GetFcnType) PR_FindSymbol(lib, "My_GetValue");
setFcn = (SetFcnType) PR_FindSymbol(lib, "My_SetValue");
(*setFcn)(888);
value = (*getFcn)();
if (value != 888) {
- fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value);
- if (!debug_mode) failed_already=1;
+ fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
}
if (debug_mode) printf("Test 1 passed\n");
@@ -103,26 +103,24 @@ int main(int argc, char** argv)
*/
getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2);
- if (lib != lib2) {
- fprintf(stderr, "Test 2 failed: handles for the same library are not "
- "equal: handle 1: %p, handle 2: %p\n", lib, lib2);
- if (!debug_mode) failed_already=1;
-
+ if (NULL == getFcn || lib != lib2) {
+ fprintf(stderr, "Test 2 failed: handles for the same library are not "
+ "equal: handle 1: %p, handle 2: %p\n", lib, lib2);
+ if (!debug_mode) failed_already=1;
}
setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
value = (*getFcn)();
if (value != 888) {
- fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n",
- value);
- if (!debug_mode) failed_already=1;
-
+ fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n",
+ value);
+ if (!debug_mode) failed_already=1;
}
(*setFcn)(777);
value = (*getFcn)();
if (value != 777) {
- fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value);
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) printf("Test 2 passed\n");
@@ -133,19 +131,19 @@ int main(int argc, char** argv)
status = PR_UnloadLibrary(lib);
if (PR_FAILURE == status) {
- fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n",
- PR_GetError(), PR_GetOSError());
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
getFcn = (GetFcnType) PR_FindSymbol(lib2, "My_GetValue");
setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
(*setFcn)(666);
value = (*getFcn)();
if (value != 666) {
- fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value);
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) printf("Test 3 passed\n");
@@ -155,21 +153,21 @@ int main(int argc, char** argv)
status = PR_UnloadLibrary(lib2);
if (PR_FAILURE == status) {
- fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n",
- PR_GetError(), PR_GetOSError());
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
- status = PR_UnloadLibrary(lib2);
- if (PR_FAILURE != status || PR_GetError() != PR_INVALID_ARGUMENT_ERROR) {
- fprintf(stderr, "Test 4 failed: how can an already unloaded library "
- "be unloaded again?\n");
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2);
+ if (NULL != getFcn) {
+ fprintf(stderr, "Test 4 failed: how can we find a symbol "
+ "in an already unloaded library?\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) {
- printf("Test 4 passed\n");
- }
+ printf("Test 4 passed\n");
+ }
/*
** Test 5: LoadStaticLibrary()
@@ -181,21 +179,24 @@ int main(int argc, char** argv)
lib = PR_LoadStaticLibrary( "my.dll", slt );
if ( lib == NULL )
{
- printf("dlltest: Test 5: LoadStatiLibrary() failed\n" );
+ fprintf(stderr, "Test 5: LoadStatiLibrary() failed\n" );
goto exit_now;
}
- printf("Test 5 passed\n");
+ if (debug_mode)
+ {
+ printf("Test 5 passed\n");
+ }
}
- goto exit_now;
+ goto exit_now;
exit_now:
PR_Cleanup();
if (failed_already) {
printf("FAILED\n");
- return 1;
+ return 1;
} else {
printf("PASSED\n");
- return 0;
+ return 0;
}
}
diff --git a/pr/tests/foreign.c b/pr/tests/foreign.c
new file mode 100644
index 00000000..dcf88250
--- /dev/null
+++ b/pr/tests/foreign.c
@@ -0,0 +1,345 @@
+/* -*- 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.0 (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: foreign.c
+** Description: Testing various functions w/ foreign threads
+**
+** We create a thread and get it to call exactly one runtime function.
+** The thread is allowed to be created by some other environment that
+** NSPR, but it does not announce itself to the runtime prior to calling
+** in.
+**
+** The goal: try to survive.
+**
+*/
+
+#include "prcvar.h"
+#include "prenv.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prthread.h"
+#include "prtypes.h"
+#include "prprf.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static enum {
+ thread_nspr, thread_pthread, thread_sproc, thread_win32
+} thread_provider;
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+static PRFileDesc *output;
+
+static int _debug_on = 0;
+
+#define DEFAULT_THREAD_COUNT 10
+
+#define DPRINTF(arg) if (_debug_on) PR_fprintf arg
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include "md/_pth.h"
+#include <pthread.h>
+static void *pthread_start(void *arg)
+{
+ StartFn start = ((StartObject*)arg)->start;
+ void *data = ((StartObject*)arg)->arg;
+ PR_Free(arg);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus CreateThread(StartFn start, void *arg)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* CreateThread */
+
+static void PR_CALLBACK lazyEntry(void *arg)
+{
+ PR_ASSERT(NULL == arg);
+} /* lazyEntry */
+
+
+static void OneShot(void *arg)
+{
+ PRUintn pdkey;
+ PRFileDesc *pair[2];
+ PRIntn test = (PRIntn)arg;
+
+ for (test = 0; test < 11; ++test) {
+
+ switch (test)
+ {
+ case 0:
+ (void)PR_NewLock();
+ DPRINTF((output,"Thread[0x%x] called PR_NewLock\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 1:
+ (void)PR_SecondsToInterval(1);
+ DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 2: (void)PR_CreateThread(
+ PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 3:
+ (void)PR_Open("/usr/tmp/", PR_RDONLY, 0);
+ DPRINTF((output,"Thread[0x%x] called PR_Open\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 4:
+ (void)PR_NewUDPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 5:
+ (void)PR_NewTCPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 6:
+ (void)PR_OpenDir("/usr/tmp/");
+ DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 7:
+ (void)PR_NewThreadPrivateIndex(&pdkey, NULL);
+ DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 8:
+ (void)PR_GetEnv("PATH");
+ DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 9:
+ (void)PR_NewTCPSocketPair(pair);
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 10:
+ PR_SetConcurrency(2);
+ DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n",
+ PR_GetCurrentThread()));
+ break;
+
+ default:
+ break;
+ } /* switch() */
+ }
+} /* OneShot */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRIntn test_number;
+ PRInt32 thread_cnt = DEFAULT_THREAD_COUNT;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
+
+#if defined(WIN32)
+ thread_provider = thread_win32;
+#elif defined(_PR_PTHREADS)
+ thread_provider = thread_pthread;
+#elif defined(IRIX)
+ thread_provider = thread_sproc;
+#else
+ thread_provider = thread_nspr;
+#endif
+
+
+ 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;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(2);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+
+ while (thread_cnt-- > 0)
+ {
+ rv = CreateThread(OneShot, (void*)thread_cnt);
+ PR_ASSERT(PR_SUCCESS == rv);
+ PR_Sleep(PR_MillisecondsToInterval(5));
+ }
+ PR_Sleep(PR_SecondsToInterval(3));
+ return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1;
+} /* main */
+
+/* foreign.c */
diff --git a/pr/tests/forktest.c b/pr/tests/forktest.c
index b52499d5..ecb09c5b 100644
--- a/pr/tests/forktest.c
+++ b/pr/tests/forktest.c
@@ -40,6 +40,7 @@
#include "plgetopt.h"
#include "nspr.h"
+#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -259,6 +260,7 @@ char *argv[]
)
{
pid_t pid;
+ int rv;
/* main test program */
@@ -275,9 +277,18 @@ char *argv[]
printf("Fork succeeded. Parent process continues.\n");
DoIO();
- if (waitpid(pid, &childStatus, 0) != pid) {
- fprintf(stderr, "waitpid failed: %d\n", errno);
- failed_already = 1;
+ if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ /*
+ * nspr may handle SIGCLD signal
+ */
+ if ((rv < 0) && (errno == ECHILD)) {
+ } else
+#endif
+ {
+ fprintf(stderr, "waitpid failed: %d\n", errno);
+ failed_already = 1;
+ }
} else if (!WIFEXITED(childStatus)
|| WEXITSTATUS(childStatus) != 0) {
failed_already = 1;
@@ -290,6 +301,10 @@ char *argv[]
}
return failed_already;
} else {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ extern void _PR_IRIX_CHILD_PROCESS(void);
+ _PR_IRIX_CHILD_PROCESS();
+#endif
printf("Fork succeeded. Child process continues.\n");
DoIO();
printf("Child process exits.\n");
diff --git a/pr/tests/initclk.c b/pr/tests/initclk.c
new file mode 100644
index 00000000..a815997f
--- /dev/null
+++ b/pr/tests/initclk.c
@@ -0,0 +1,87 @@
+/* -*- 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.0 (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.
+ */
+
+/*
+ * This is a regression test for the bug that the interval timer
+ * is not initialized when _PR_CreateCPU calls PR_IntervalNow.
+ * The bug would make this test program finish prematurely,
+ * when the SHORT_TIMEOUT period expires. The correct behavior
+ * is for the test to finish when the LONG_TIMEOUT period expires.
+ */
+
+#include "prlock.h"
+#include "prcvar.h"
+#include "prthread.h"
+#include "prinrval.h"
+#include "prlog.h"
+#include <stdio.h>
+
+/* The timeouts, in milliseconds */
+#define SHORT_TIMEOUT 1000
+#define LONG_TIMEOUT 3000
+
+PRLock *lock1, *lock2;
+PRCondVar *cv1, *cv2;
+
+void ThreadFunc(void *arg)
+{
+ PR_Lock(lock1);
+ PR_WaitCondVar(cv1, PR_MillisecondsToInterval(SHORT_TIMEOUT));
+ PR_Unlock(lock1);
+}
+
+int main()
+{
+ PRThread *thread;
+ PRIntervalTime start, end;
+ PRUint32 elapsed_ms;
+
+ lock1 = PR_NewLock();
+ PR_ASSERT(NULL != lock1);
+ cv1 = PR_NewCondVar(lock1);
+ PR_ASSERT(NULL != cv1);
+ lock2 = PR_NewLock();
+ PR_ASSERT(NULL != lock2);
+ cv2 = PR_NewCondVar(lock2);
+ PR_ASSERT(NULL != cv2);
+ start = PR_IntervalNow();
+ thread = PR_CreateThread(
+ PR_USER_THREAD,
+ ThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ PR_ASSERT(NULL != thread);
+ PR_Lock(lock2);
+ PR_WaitCondVar(cv2, PR_MillisecondsToInterval(LONG_TIMEOUT));
+ PR_Unlock(lock2);
+ PR_JoinThread(thread);
+ end = PR_IntervalNow();
+ elapsed_ms = PR_IntervalToMilliseconds((PRIntervalTime)(end - start));
+ /* Allow 100ms imprecision */
+ if (elapsed_ms < LONG_TIMEOUT - 100 || elapsed_ms > LONG_TIMEOUT + 100) {
+ printf("Elapsed time should be %u ms but is %u ms\n",
+ LONG_TIMEOUT, elapsed_ms);
+ printf("FAIL\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/pr/tests/inrval.c b/pr/tests/inrval.c
index b963da48..ce1df9cc 100644
--- a/pr/tests/inrval.c
+++ b/pr/tests/inrval.c
@@ -40,6 +40,9 @@
#else
#include "obsolete/pralarm.h"
#endif
+
+#include "prio.h"
+#include "prprf.h"
#include "prlock.h"
#include "prlong.h"
#include "prcvar.h"
@@ -51,14 +54,8 @@
#include <stdio.h>
#include <stdlib.h>
-#ifdef XP_MAC
-#include "prlog.h"
-#define printf PR_LogPrint
-extern void SetupMacPrintfLog(char *logFile);
-#endif
-
-PRIntn failed_already=0;
-PRIntn debug_mode;
+static PRIntn debug_mode;
+static PRFileDesc *output;
static void TestConversions(void)
@@ -66,26 +63,62 @@ static void TestConversions(void)
PRIntervalTime ticks = PR_TicksPerSecond();
if (debug_mode) {
- printf("PR_TicksPerSecond: %ld\n\n", ticks);
- printf("PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1));
- printf("PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000));
- printf("PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000));
+ PR_fprintf(output, "PR_TicksPerSecond: %ld\n\n", ticks);
+ PR_fprintf(output, "PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1));
+ PR_fprintf(output, "PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000));
- printf("PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3));
- printf("PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000));
- printf("PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000));
+ PR_fprintf(output, "PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3));
+ PR_fprintf(output, "PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000));
- printf("PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
- printf("PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
- printf("PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
ticks *= 3;
- printf("PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
- printf("PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
- printf("PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
} /*end debug mode */
} /* TestConversions */
+static void TestIntervalOverhead(void)
+{
+ /* Hopefully the optimizer won't delete this function */
+ PRUint32 elapsed, per_call, loops = 1000000;
+
+ PRIntervalTime timeout, timein = PR_IntervalNow();
+ while (--loops > 0)
+ timeout = PR_IntervalNow();
+
+ elapsed = 1000U * PR_IntervalToMicroseconds(timeout - timein);
+ per_call = elapsed / 1000000U;
+ PR_fprintf(
+ output, "Overhead of 'PR_IntervalNow()' is %u nsecs\n\n", per_call);
+} /* TestIntervalOverhead */
+
+static void TestNowOverhead(void)
+{
+ PRTime timeout, timein;
+ PRInt32 overhead, loops = 1000000;
+ PRInt64 elapsed, per_call, ten23rd, ten26th;
+
+ LL_I2L(ten23rd, 1000);
+ LL_I2L(ten26th, 1000000);
+
+ timein = PR_Now();
+ while (--loops > 0)
+ timeout = PR_Now();
+
+ LL_SUB(elapsed, timeout, timein);
+ LL_MUL(elapsed, elapsed, ten23rd);
+ LL_DIV(per_call, elapsed, ten26th);
+ LL_L2I(overhead, per_call);
+ PR_fprintf(
+ output, "Overhead of 'PR_Now()' is %u nsecs\n\n", overhead);
+} /* TestNowOverhead */
+
static void TestIntervals(void)
{
PRStatus rv;
@@ -107,58 +140,18 @@ static void TestIntervals(void)
LL_I2L(thousand, 1000);
LL_DIV(elapsed, elapsed, thousand);
LL_L2UI(delta, elapsed);
- if (debug_mode) printf(
+ if (debug_mode) PR_fprintf(output,
"TestIntervals: %swaiting %ld seconds took %ld msecs\n",
((rv == PR_SUCCESS) ? "" : "FAILED "), seconds, delta);
}
PR_DestroyCondVar(cv);
PR_DestroyLock(ml);
- if (debug_mode) printf("\n");
+ if (debug_mode) PR_fprintf(output, "\n");
} /* TestIntervals */
-static PRUint32 GetInterval(PRUint32 loops)
-{
- PRIntervalTime interval = 0;
- while (loops-- > 0) interval += PR_IntervalNow();
- return 0;
-} /* GetInterval */
-
-static PRUint32 TimeThis(
- const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops)
-{
- PRUint32 overhead, usecs32;
- PRTime timein, timeout, usecs;
-
- timein = PR_Now();
- overhead = func(loops);
- timeout = PR_Now();
-
- LL_SUB(usecs, timeout, timein);
- LL_L2I(usecs32, usecs);
-
- if(usecs32 < overhead)
- {
- if (debug_mode) {
- printf("%s ran in negative time\n", msg);
- printf(" predicted overhead was %ld usecs\n", overhead);
- printf(" test completed in %ld usecs\n\n", usecs);
- }
- }
- else
- {
- if (debug_mode)
- printf(
- "%s [\n\ttotal: %ld usecs\n\toverhead: %ld usecs\n\tcost: %6.3f usecs]\n\n",
- msg, usecs, overhead,
- ((double)(usecs32 - overhead) / (double)loops));
- }
-
- return overhead;
-} /* TimeThis */
-
static PRIntn PR_CALLBACK RealMain(int argc, char** argv)
{
- PRUint32 cpu, cpus = 2, loops = 1000;
+ PRUint32 vcpu, cpus = 0, loops = 1000;
/* The command line argument: -d is used to determine if the test is being run
in debug mode. The regress tool requires only one line output:PASS or FAIL.
@@ -191,42 +184,28 @@ static PRIntn PR_CALLBACK RealMain(int argc, char** argv)
}
PL_DestroyOptState(opt);
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ PR_fprintf(output, "inrval: Examine stdout to determine results.\n");
- printf("inrval: Examine stdout to determine results.\n");
-
- if (cpus == 0) cpus = 2;
+ if (cpus == 0) cpus = 8;
if (loops == 0) loops = 1000;
- if (debug_mode) printf("Inrval: Using %d loops\n", loops);
-
-
- cpus = (argc < 3) ? 2 : atoi(argv[2]);
- if (cpus == 0) cpus = 2;
- if (debug_mode) printf("Inrval: Using %d cpu(s)\n", cpus);
if (debug_mode > 0)
{
- printf("Inrval: Using %d loops\n", loops);
- printf("Inrval: Using %d cpu(s)\n", cpus);
+ PR_fprintf(output, "Inrval: Using %d loops\n", loops);
+ PR_fprintf(output, "Inrval: Using 1 and %d cpu(s)\n", cpus);
}
-#ifdef XP_MAC
- SetupMacPrintfLog("inrval.log");
- debug_mode = 1;
-#endif
-
- for (cpu = 1; cpu <= cpus; ++cpu)
+ for (vcpu = 1; vcpu <= cpus; vcpu += cpus - 1)
{
+ if (debug_mode)
+ PR_fprintf(output, "\nInrval: Using %d CPU(s)\n\n", vcpu);
+ PR_SetConcurrency(vcpu);
- if (debug_mode) printf("\nInrval: Using %d CPU(s)\n", cpu);
- if (debug_mode > 0)
- printf("\nInrval: Using %d CPU(s)\n", cpu);
-
- PR_SetConcurrency(cpu);
-
+ TestNowOverhead();
+ TestIntervalOverhead();
TestConversions();
TestIntervals();
-
- (void)TimeThis("GetInterval", GetInterval, loops);
}
return 0;
diff --git a/pr/tests/instrumt.c b/pr/tests/instrumt.c
new file mode 100644
index 00000000..5a51a9f3
--- /dev/null
+++ b/pr/tests/instrumt.c
@@ -0,0 +1,470 @@
+/* -*- 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.0 (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: instrumt.c
+** Description: This test is for the NSPR debug aids defined in
+** prcountr.h, prtrace.h, prolock.h
+**
+** The test case tests the three debug aids in NSPR:
+**
+** Diagnostic messages can be enabled using "instrumt -v 6"
+** This sets the msgLevel to something that PR_LOG() likes.
+** Also define in the environment "NSPR_LOG_MODULES=Test:6"
+**
+** CounterTest() tests the counter facility. This test
+** creates 4 threads. Each thread either increments, decrements,
+** adds to or subtracts from a counter, depending on an argument
+** passed to the thread at thread-create time. Each of these threads
+** does COUNT_LIMIT iterations doing its thing. When all 4 threads
+** are done, the result of the counter is evaluated. If all was atomic,
+** the the value of the counter should be zero.
+**
+** TraceTest():
+** This test mingles with the counter test. Counters trace.
+** A thread to extract trace entries on the fly is started.
+** A thread to dump trace entries to a file is started.
+**
+** OrderedLockTest():
+**
+**
+**
+**
+**
+*/
+
+#include <stdio.h>
+#include <plstr.h>
+#include <prclist.h>
+#include <prmem.h>
+#include <plgetopt.h>
+#include <prlog.h>
+#include <prmon.h>
+#include <pratom.h>
+#include <prtrace.h>
+#include <prcountr.h>
+#include <prolock.h>
+
+#define COUNT_LIMIT (10 * ( 1024))
+
+#define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
+
+typedef enum
+{
+ CountLoop = 1,
+ TraceLoop = 2,
+ TraceFlow = 3
+} TraceTypes;
+
+
+PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
+
+PRBool help = PR_FALSE;
+PRBool failed = PR_FALSE;
+
+
+PRLogModuleInfo *lm;
+PRMonitor *mon;
+PRInt32 activeThreads = 0;
+PR_DEFINE_COUNTER( hCounter );
+PR_DEFINE_TRACE( hTrace );
+
+static void Help(void)
+{
+ printf("Help? ... Ha!\n");
+}
+
+static void ListCounters(void)
+{
+ PR_DEFINE_COUNTER( qh );
+ PR_DEFINE_COUNTER( rh );
+ char *qn, *rn, *dn;
+ char **qname = &qn, **rname = &rn, **desc = &dn;
+ PRUint32 tCtr;
+
+ PR_INIT_COUNTER_HANDLE( qh, NULL );
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_COUNTER_HANDLE( rh, NULL );
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ tCtr = PR_GET_COUNTER(tCtr, rh);
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s Value: %ld\n",
+ qn, rn, dn, tCtr ));
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+static void ListTraces(void)
+{
+ PR_DEFINE_TRACE( qh );
+ PR_DEFINE_TRACE( rh );
+ char *qn, *rn, *dn;
+ char **qname = &qn, **rname = &rn, **desc = &dn;
+
+ PR_INIT_TRACE_HANDLE( qh, NULL );
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_TRACE_HANDLE( rh, NULL );
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s",
+ qn, rn, dn ));
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+
+static PRInt32 one = 1;
+static PRInt32 two = 2;
+static PRInt32 three = 3;
+static PRInt32 four = 4;
+
+/*
+** Thread to iteratively count something.
+*/
+static void PR_CALLBACK CountSomething( void *arg )
+{
+ PRInt32 switchVar = *((PRInt32 *)arg);
+ PRInt32 i;
+
+ PR_LOG( lm, msgLevel,
+ ("CountSomething: begin thread %ld", switchVar ));
+
+ for ( i = 0; i < COUNT_LIMIT ; i++)
+ {
+ switch ( switchVar )
+ {
+ case 1 :
+ PR_INCREMENT_COUNTER( hCounter );
+ break;
+ case 2 :
+ PR_DECREMENT_COUNTER( hCounter );
+ break;
+ case 3 :
+ PR_ADD_TO_COUNTER( hCounter, 1 );
+ break;
+ case 4 :
+ PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
+ break;
+ default :
+ PR_ASSERT( 0 );
+ break;
+ }
+ PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
+ } /* end for() */
+
+ PR_LOG( lm, msgLevel,
+ ("CounterSomething: end thread %ld", switchVar ));
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end CountSomething() */
+
+/*
+** Create the counter threads.
+*/
+static void CounterTest( void )
+{
+ PRThread *t1, *t2, *t3, *t4;
+ PR_DEFINE_COUNTER( tc );
+
+ PR_LOG( lm, msgLevel,
+ ("Begin CounterTest"));
+
+ activeThreads += 4;
+ PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
+
+ PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
+ PR_ASSERT( tc == hCounter );
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &one,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &two,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ t3 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &three,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t3);
+
+ t4 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &four,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t4);
+
+ PR_LOG( lm, msgLevel,
+ ("Counter Threads started"));
+
+ ListCounters();
+ return;
+} /* end CounterTest() */
+
+/*
+** Thread to dump trace buffer to a file.
+*/
+static void PR_CALLBACK RecordTrace(void *arg )
+{
+ PR_RECORD_TRACE_ENTRIES();
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end RecordTrace() */
+
+
+
+#define NUM_TRACE_RECORDS ( 10000 )
+/*
+** Thread to extract and print trace entries from the buffer.
+*/
+static void PR_CALLBACK SampleTrace( void *arg )
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRInt32 found, rc;
+ PRTraceEntry *foundEntries;
+ PRInt32 i;
+
+ foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
+ PR_ASSERT(foundEntries != NULL );
+
+ do
+ {
+ rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
+
+ if ( found != 0)
+ {
+ for ( i = 0 ; i < found; i++ )
+ {
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
+ (foundEntries +i)->thread,
+ (foundEntries +i)->time,
+ (foundEntries +i)->userData[0],
+ (foundEntries +i)->userData[1],
+ (foundEntries +i)->userData[2] ));
+ }
+ }
+ PR_Sleep(PR_MillisecondsToInterval(50));
+ }
+ while( found != 0 && activeThreads >= 1 );
+
+ PR_Free( foundEntries );
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace(): exiting"));
+
+#endif
+ return;
+} /* end RecordTrace() */
+
+/*
+** Basic trace test.
+*/
+static void TraceTest( void )
+{
+ PRInt32 i;
+ PRInt32 size;
+ PR_DEFINE_TRACE( th );
+ PRThread *t1, *t2;
+
+ PR_LOG( lm, msgLevel,
+ ("Begin TraceTest"));
+
+ size = SMALL_TRACE_BUFSIZE;
+ PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
+ PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
+ PR_ASSERT( i == size );
+
+ PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
+
+ PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
+
+
+
+ activeThreads += 2;
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ RecordTrace, NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ SampleTrace, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ ListTraces();
+
+ PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
+ PR_ASSERT( th == hTrace );
+
+ PR_LOG( lm, msgLevel,
+ ("End TraceTest"));
+ return;
+} /* end TraceTest() */
+
+
+/*
+** Ordered lock test.
+*/
+static void OrderedLockTest( void )
+{
+ PR_LOG( lm, msgLevel,
+ ("Begin OrderedLockTest"));
+
+
+} /* end OrderedLockTest() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRUint32 counter;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
+ lm = PR_NewLogModule("Test");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* verbose mode */
+ msgLevel = (PRLogModuleLevel)atol( opt->value);
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
+ mon = PR_NewMonitor();
+ PR_EnterMonitor( mon );
+
+ TraceTest();
+ CounterTest();
+ OrderedLockTest();
+
+ /* Wait for all threads to exit */
+ while ( activeThreads > 0 ) {
+ if ( activeThreads == 1 )
+ PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ PR_GET_COUNTER( counter, hCounter );
+ }
+ PR_ExitMonitor( mon );
+
+ /*
+ ** Evaluate results
+ */
+ PR_GET_COUNTER( counter, hCounter );
+ if ( counter != 0 )
+ {
+ failed = PR_TRUE;
+ PR_LOG( lm, msgLevel,
+ ("Expected counter == 0, found: %ld", counter));
+ printf("FAIL\n");
+ }
+ else
+ {
+ printf("PASS\n");
+ }
+
+ PR_DestroyMonitor( mon );
+
+ PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
+ PR_DESTROY_TRACE( hTrace );
+#else
+ printf("Test not defined\n");
+#endif
+ return 0;
+} /* main() */
+/* end instrumt.c */
+
diff --git a/pr/tests/ipv6.c b/pr/tests/ipv6.c
index 63ddfbf6..15303430 100644
--- a/pr/tests/ipv6.c
+++ b/pr/tests/ipv6.c
@@ -17,10 +17,13 @@
*/
#include "prio.h"
+#include "prenv.h"
#include "prmem.h"
+#include "prlink.h"
#include "prsystem.h"
#include "prnetdb.h"
#include "prprf.h"
+#include "prvrsion.h"
#include "plerror.h"
#include "plgetopt.h"
@@ -37,8 +40,9 @@ static PRFileDesc *err = NULL;
static void Help(void)
{
- PR_fprintf(err, "Usage: [-t s] [-s] [-h]\n");
+ PR_fprintf(err, "Usage: [-V] [-6] [-h]\n");
PR_fprintf(err, "\t<nul> Name of host to lookup (default: self)\n");
+ PR_fprintf(err, "\t-V Display runtime version info (default: FALSE)\n");
PR_fprintf(err, "\t-6 First turn on IPv6 capability (default: FALSE)\n");
PR_fprintf(err, "\t-h This message and nothing else\n");
} /* Help */
@@ -91,8 +95,8 @@ PRIntn main(PRIntn argc, char **argv)
PRProtoEnt proto;
PRBool ipv6 = PR_FALSE;
const char *name = NULL;
- PRBool failed = PR_FALSE;
- PLOptState *opt = PL_CreateOptState(argc, argv, "h6");
+ PRBool failed = PR_FALSE, version = PR_FALSE;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Vh6");
err = PR_GetSpecialFD(PR_StandardError);
@@ -107,6 +111,9 @@ PRIntn main(PRIntn argc, char **argv)
case '6': /* Turn on IPv6 mode */
ipv6 = PR_TRUE;
break;
+ case 'V': /* Do version discovery */
+ version = PR_TRUE;
+ break;
case 'h': /* user wants some guidance */
default:
Help(); /* so give him an earful */
@@ -115,6 +122,58 @@ PRIntn main(PRIntn argc, char **argv)
}
PL_DestroyOptState(opt);
+ if (version)
+ {
+#if defined(XP_UNIX)
+#define NSPR_LIB "nspr21"
+#elif defined(WIN32)
+#define NSPR_LIB "libnspr21"
+#else
+#error "Architecture not supported"
+#endif
+ const PRVersionDescription *version_info;
+ char *nspr_path = PR_GetEnv("LD_LIBRARY_PATH");
+ char *nspr_name = PR_GetLibraryName(nspr_path, NSPR_LIB);
+ PRLibrary *runtime = PR_LoadLibrary(nspr_name);
+ if (NULL == runtime)
+ PL_FPrintError(err, "PR_LoadLibrary");
+ else
+ {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint)
+ PL_FPrintError(err, "PR_FindSymbol");
+ else
+ {
+ char buffer[100];
+ PRExplodedTime exploded;
+ version_info = versionPoint();
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ }
+ }
+ if (NULL != nspr_name) PR_FreeLibraryName(nspr_name);
+ }
+
if (ipv6)
{
rv = PR_SetIPv6Enable(ipv6);
diff --git a/pr/tests/joinkk.c b/pr/tests/joinkk.c
index f3b5396d..5c2e4e9c 100644
--- a/pr/tests/joinkk.c
+++ b/pr/tests/joinkk.c
@@ -154,12 +154,12 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
if(failed_already)
{
printf("FAIL\n");
- return 0;
+ return 1;
}
else
{
printf("PASS\n");
- return 1;
+ return 0;
}
}
diff --git a/pr/tests/layer.c b/pr/tests/layer.c
index e6be944f..0c93e4b6 100644
--- a/pr/tests/layer.c
+++ b/pr/tests/layer.c
@@ -64,6 +64,7 @@ static PRFileDesc *PushLayer(PRFileDesc *stack)
return stack;
} /* PushLayer */
+#if 0
static PRFileDesc *PopLayer(PRFileDesc *stack)
{
PRFileDesc *popped = PR_PopIOLayer(stack, identity);
@@ -73,6 +74,7 @@ static PRFileDesc *PopLayer(PRFileDesc *stack)
return stack;
} /* PopLayer */
+#endif
static void PR_CALLBACK Client(void *arg)
{
@@ -355,8 +357,8 @@ PRIntn main(PRIntn argc, char **argv)
rv = PR_JoinThread(server_thread);
PR_ASSERT(PR_SUCCESS == rv);
- rv = PR_Close(PopLayer(client)); PR_ASSERT(PR_SUCCESS == rv);
- rv = PR_Close(PopLayer(service)); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
if (verbosity > silent)
PR_fprintf(logFile, "Ending layered test\n");
}
diff --git a/pr/tests/lock.c b/pr/tests/lock.c
index e5683171..6f4616dc 100644
--- a/pr/tests/lock.c
+++ b/pr/tests/lock.c
@@ -48,9 +48,11 @@
/* Used to get the command line option */
#include "plgetopt.h"
+#include "prio.h"
#include "prcmon.h"
#include "prinit.h"
#include "prinrval.h"
+#include "prprf.h"
#include "prlock.h"
#include "prlog.h"
#include "prmon.h"
@@ -60,7 +62,6 @@
#include "plstr.h"
-#include <stdio.h>
#include <stdlib.h>
#if defined(XP_UNIX)
@@ -72,21 +73,28 @@
#define printf PR_LogPrint
extern void SetupMacPrintfLog(char *logFile);
#endif
-PRIntn failed_already=0;
-PRIntn debug_mode;
+
+static PRIntn failed_already=0;
+static PRFileDesc *std_err = NULL;
+static PRBool verbosity = PR_FALSE;
+static PRBool debug_mode = PR_FALSE;
const static PRIntervalTime contention_interval = 50;
typedef struct LockContentious_s {
PRLock *ml;
- PRUint32 loops;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
PRIntervalTime overhead;
PRIntervalTime interval;
} LockContentious_t;
typedef struct MonitorContentious_s {
PRMonitor *ml;
- PRUint32 loops;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
PRIntervalTime overhead;
PRIntervalTime interval;
} MonitorContentious_t;
@@ -137,6 +145,7 @@ static void PR_CALLBACK LockContender(void *arg)
while (contention->loops-- > 0)
{
PR_Lock(contention->ml);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_Unlock(contention->ml);
@@ -150,7 +159,7 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
LockContentious_t * contention;
PRIntervalTime rv, overhead, timein = PR_IntervalNow();
- contention = (LockContentious_t *) PR_Calloc( 1, sizeof(LockContentious_t));
+ contention = PR_NEWZAP(LockContentious_t);
contention->loops = loops;
contention->overhead = 0;
contention->ml = PR_NewLock();
@@ -162,9 +171,10 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_Lock(contention->ml);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_Unlock(contention->ml);
@@ -175,6 +185,10 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
PR_DestroyLock(contention->ml);
overhead += (PR_IntervalNow() - timein);
rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
PR_Free(contention);
return rv;
} /* ContentiousLock */
@@ -210,23 +224,23 @@ static PRIntervalTime NonContentiousMonitor(PRUint32 loops)
static void PR_CALLBACK TryEntry(void *arg)
{
PRMonitor *ml = (PRMonitor*)arg;
- if (debug_mode) printf("Reentrant thread created\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread created\n");
PR_EnterMonitor(ml);
- if (debug_mode) printf("Reentrant thread acquired monitor\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread acquired monitor\n");
PR_ExitMonitor(ml);
- if (debug_mode) printf("Reentrant thread released monitor\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread released monitor\n");
} /* TryEntry */
static PRIntervalTime ReentrantMonitor(PRUint32 loops)
{
- PRStatus status;
+ PRStatus status;
PRThread *thread;
PRMonitor *ml = PR_NewMonitor();
- if (debug_mode) printf("\nMonitor created for reentrant test\n");
+ if (debug_mode) PR_fprintf(std_err, "\nMonitor created for reentrant test\n");
PR_EnterMonitor(ml);
PR_EnterMonitor(ml);
- if (debug_mode) printf("Monitor acquired twice\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor acquired twice\n");
thread = PR_CreateThread(
PR_USER_THREAD, TryEntry, ml,
@@ -235,13 +249,13 @@ static PRIntervalTime ReentrantMonitor(PRUint32 loops)
PR_Sleep(PR_SecondsToInterval(1));
PR_ExitMonitor(ml);
- if (debug_mode) printf("Monitor released first time\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor released first time\n");
PR_ExitMonitor(ml);
- if (debug_mode) printf("Monitor released second time\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor released second time\n");
status = PR_JoinThread(thread);
- if (debug_mode) printf(
+ if (debug_mode) PR_fprintf(std_err,
"Reentrant thread joined %s\n",
(status == PR_SUCCESS) ? "successfully" : "in error");
@@ -255,6 +269,7 @@ static void PR_CALLBACK MonitorContender(void *arg)
while (contention->loops-- > 0)
{
PR_EnterMonitor(contention->ml);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_ExitMonitor(contention->ml);
@@ -268,7 +283,7 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
MonitorContentious_t * contention;
PRIntervalTime rv, overhead, timein = PR_IntervalNow();
- contention = (MonitorContentious_t *) PR_Calloc(1, sizeof(MonitorContentious_t));
+ contention = PR_NEWZAP(MonitorContentious_t);
contention->loops = loops;
contention->overhead = 0;
contention->ml = PR_NewMonitor();
@@ -280,9 +295,10 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_EnterMonitor(contention->ml);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_ExitMonitor(contention->ml);
@@ -293,6 +309,10 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
PR_DestroyMonitor(contention->ml);
overhead += (PR_IntervalNow() - timein);
rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
PR_Free(contention);
return rv;
} /* ContentiousMonitor */
@@ -317,6 +337,7 @@ static void PR_CALLBACK Contender(void *arg)
while (contention->loops-- > 0)
{
PR_CEnterMonitor(contention);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_CExitMonitor(contention);
@@ -330,9 +351,8 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
MonitorContentious_t * contention;
PRIntervalTime overhead, timein = PR_IntervalNow();
- contention = (MonitorContentious_t *) PR_Calloc(1, sizeof(MonitorContentious_t));
+ contention = PR_NEWZAP(MonitorContentious_t);
contention->ml = NULL;
- contention->overhead = 0;
contention->loops = loops;
contention->interval = contention_interval;
thread = PR_CreateThread(
@@ -342,9 +362,10 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_CEnterMonitor(contention);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_CExitMonitor(contention);
@@ -353,7 +374,13 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
timein = PR_IntervalNow();
status = PR_JoinThread(thread);
overhead += (PR_IntervalNow() - timein);
- return overhead + contention->overhead;
+ overhead += overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
+ PR_Free(contention);
+ return overhead;
} /* ContentiousCMonitor */
static PRIntervalTime Test(
@@ -381,12 +408,12 @@ static PRIntervalTime Test(
accountable = duration - predicted;
accountable -= overhead;
elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
- printf("%s:", msg);
- while (spaces++ < 50) printf(" ");
+ PR_fprintf(PR_STDOUT, "%s:", msg);
+ while (spaces++ < 50) PR_fprintf(PR_STDOUT, " ");
if ((PRInt32)accountable < 0)
- printf("*****.** usecs/iteration\n");
+ PR_fprintf(PR_STDOUT, "*****.** usecs/iteration\n");
else
- printf("%8.2f usecs/iteration\n", elapsed/loops);
+ PR_fprintf(PR_STDOUT, "%8.2f usecs/iteration\n", elapsed/loops);
}
return duration;
} /* Test */
@@ -410,14 +437,17 @@ int main(int argc, char **argv)
Usage: lock [-d] [-l <num>] [-c <num>]
*/
PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "dl:c:");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dvl:c:");
while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
{
if (PL_OPT_BAD == os) continue;
switch (opt->option)
{
case 'd': /* debug mode */
- debug_mode = 1;
+ debug_mode = PR_TRUE;
+ break;
+ case 'v': /* debug mode */
+ verbosity = PR_TRUE;
break;
case 'l': /* number of loops */
loops = atoi(opt->value);
@@ -441,16 +471,20 @@ int main(int argc, char **argv)
#endif
if (loops == 0) loops = 100;
- if (debug_mode) printf("Lock: Using %d loops\n", loops);
+ if (debug_mode)
+ {
+ std_err = PR_STDERR;
+ PR_fprintf(std_err, "Lock: Using %d loops\n", loops);
+ }
if (cpus == 0) cpus = 2;
- if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus);
+ if (debug_mode) PR_fprintf(std_err, "Lock: Using %d cpu(s)\n", cpus);
(void)Sleeper(10); /* try filling in the caches */
for (cpu = 1; cpu <= cpus; ++cpu)
{
- if (debug_mode) printf("\nLock: Using %d CPU(s)\n", cpu);
+ if (debug_mode) PR_fprintf(std_err, "\nLock: Using %d CPU(s)\n", cpu);
PR_SetConcurrency(cpu);
duration = Test("Overhead of PR_Sleep", Sleeper, loops, 0);
@@ -469,7 +503,10 @@ int main(int argc, char **argv)
(void)ReentrantMonitor(loops);
}
- if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((rv) ? "passed" : "failed"));
+ if (debug_mode)
+ PR_fprintf(
+ std_err, "%s: test %s\n", "Lock(mutex) test",
+ ((rv) ? "passed" : "failed"));
else {
if (!rv)
failed_already=1;
@@ -477,12 +514,12 @@ int main(int argc, char **argv)
if(failed_already)
{
- printf("FAIL\n");
+ PR_fprintf(PR_STDOUT, "FAIL\n");
return 1;
}
else
{
- printf("PASS\n");
+ PR_fprintf(PR_STDOUT, "PASS\n");
return 0;
}
diff --git a/pr/tests/many_cv.c b/pr/tests/many_cv.c
index ae973655..1f964458 100644
--- a/pr/tests/many_cv.c
+++ b/pr/tests/many_cv.c
@@ -114,9 +114,7 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
printf("PASS\n");
-#if defined(DEBUG) && defined(_PR_PTHREADS)
PT_FPrintStats(err, "\nPThread Statistics\n");
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
return 0;
}
diff --git a/pr/tests/multiwait.c b/pr/tests/multiwait.c
index be4ed6bb..4358b350 100644
--- a/pr/tests/multiwait.c
+++ b/pr/tests/multiwait.c
@@ -43,7 +43,6 @@ typedef struct Shared
typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
-static PRUint32 identity = 0;
static PRFileDesc *debug = NULL;
static PRInt32 desc_allocated = 0;
static PRUint16 default_port = 12273;
@@ -113,7 +112,7 @@ static PRRecvWait *CreateRecvWait(PRFileDesc *fd, PRIntervalTime timeout)
return desc_out;
} /* CreateRecvWait */
-static void DestroyRecvWait(Shared *shared, PRRecvWait *desc_out)
+static void DestroyRecvWait(PRRecvWait *desc_out)
{
if (verbosity > chatty)
PrintRecvDesc(desc_out, "Destroying");
@@ -134,7 +133,7 @@ static void CancelGroup(Shared *shared)
do
{
desc_out = PR_CancelWaitGroup(shared->group);
- if (NULL != desc_out) DestroyRecvWait(shared, desc_out);
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
} while (NULL != desc_out);
MW_ASSERT(0 == desc_allocated);
@@ -298,7 +297,7 @@ static void PR_CALLBACK SomeOpsThread(void *arg)
if (NULL == desc_out)
{
MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
- if (verbosity > quiet) PrintRecvDesc(desc_out, "Aborted");
+ if (verbosity > quiet) PR_fprintf(debug, "Aborted\n");
break;
}
MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome);
@@ -422,9 +421,6 @@ static void PR_CALLBACK ServiceThread(void *arg)
case PR_MW_SUCCESS:
{
PR_AtomicIncrement(&ops_done);
- if (verbosity > quiet)
- PR_fprintf(
- debug, "%s: Servicing %u\n", shared->title, ops_done);
if (verbosity > chatty)
PrintRecvDesc(desc_out, "Service ready");
rv = ServiceRequest(shared, desc_out);
@@ -445,10 +441,40 @@ static void PR_CALLBACK ServiceThread(void *arg)
}
} while (PR_SUCCESS == rv);
- if (NULL != desc_out) DestroyRecvWait(shared, desc_out);
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
} /* ServiceThread */
+static void PR_CALLBACK EnumerationThread(void *arg)
+{
+ PRStatus rv;
+ PRIntn count;
+ PRRecvWait *desc;
+ Shared *shared = (Shared*)arg;
+ PRIntervalTime five_seconds = PR_SecondsToInterval(5);
+ PRMWaitEnumerator *enumerator = PR_CreateMWaitEnumerator(shared->group);
+ MW_ASSERT(NULL != enumerator);
+
+ while (PR_SUCCESS == PR_Sleep(five_seconds))
+ {
+ count = 0;
+ desc = NULL;
+ while (NULL != (desc = PR_EnumerateWaitGroup(enumerator, desc)))
+ {
+ if (verbosity > chatty) PrintRecvDesc(desc, shared->title);
+ count += 1;
+ }
+ if (verbosity > silent)
+ PR_fprintf(debug,
+ "%s Enumerated %d objects\n", shared->title, count);
+ }
+
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+
+
+ rv = PR_DestroyMWaitEnumerator(enumerator);
+ MW_ASSERT(PR_SUCCESS == rv);
+} /* EnumerationThread */
static void PR_CALLBACK ServerThread(void *arg)
{
@@ -534,7 +560,7 @@ static void RealOneGroupIO(Shared *shared)
*/
PRStatus rv;
PRIntn index;
- PRThread *server_thread, **client_thread;
+ PRThread *server_thread, *enumeration_thread, **client_thread;
if (verbosity > quiet)
PR_fprintf(debug, "%s: creating server_thread\n", shared->title);
@@ -545,6 +571,14 @@ static void RealOneGroupIO(Shared *shared)
PR_JOINABLE_THREAD, 16 * 1024);
if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating enumeration_thread\n", shared->title);
+
+ enumeration_thread = PR_CreateThread(
+ PR_USER_THREAD, EnumerationThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+
+ if (verbosity > quiet)
PR_fprintf(debug, "%s: snoozing before creating clients\n", shared->title);
PR_Sleep(5 * shared->timeout);
@@ -572,6 +606,13 @@ static void RealOneGroupIO(Shared *shared)
}
if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining enumeration_thread\n", shared->title);
+ rv = PR_Interrupt(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > quiet)
PR_fprintf(debug, "%s: interrupting/joining server_thread\n", shared->title);
rv = PR_Interrupt(server_thread);
MW_ASSERT(PR_SUCCESS == rv);
@@ -598,7 +639,7 @@ static void RunThisOne(
static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
{
PRIntn verbage = (PRIntn)verbosity;
- return (Verbosity)(verbage += 1);
+ return (Verbosity)(verbage += delta);
} /* ChangeVerbosity */
PRIntn main(PRIntn argc, char **argv)
diff --git a/pr/tests/nbconn.c b/pr/tests/nbconn.c
index 372a8e78..b206f991 100644
--- a/pr/tests/nbconn.c
+++ b/pr/tests/nbconn.c
@@ -38,6 +38,7 @@
*/
#include "nspr.h"
+#include "plgetopt.h"
#include <stdio.h>
#ifdef XP_MAC
@@ -46,21 +47,61 @@ extern void SetupMacPrintfLog(char *logFile);
static char *hosts[4] = {"cynic", "warp", "gandalf", "neon"};
#endif
+#define SERVER_MAX_BIND_COUNT 100
+#define DATA_BUF_SIZE 256
+#define TCP_SERVER_PORT 10000
+
+typedef struct Server_Param {
+ PRFileDesc *sp_fd; /* server port */
+} Server_Param;
+static void PR_CALLBACK TCP_Server(void *arg);
+
+int _debug_on;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+static PRIntn connection_success_test();
+static PRIntn connection_failure_test();
int main(int argc, char **argv)
{
PRHostEnt he;
char buf[1024];
PRNetAddr addr;
- PRFileDesc *sock;
PRPollDesc pd;
PRStatus rv;
PRSocketOptionData optData;
- PRIntn n;
-
+ const char *hostname;
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRInt32 failed_already = 0;
#ifdef XP_MAC
int index;
PRIntervalTime timeout;
+#endif
+
+ /*
+ * -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 0: /* debug mode */
+ hostname = opt->value;
+ break;
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#ifdef XP_MAC
SetupMacPrintfLog("nbconn.log");
for (index=0; index<4; index++) {
argv[1] = hosts[index];
@@ -69,90 +110,473 @@ int main(int argc, char **argv)
timeout = PR_SecondsToInterval(10UL);
#endif
+
PR_STDIO_INIT();
#ifndef XP_MAC
- if (argc != 2) {
- fprintf(stderr, "Usage: nbconn <hostname>\n");
- exit(1);
- }
+ if (hostname)
+ default_case = 0;
+ else
+ default_case = 1;
#endif
- if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
- printf( "Unknown host: %s\n", buf);
- exit(1);
- } else {
- printf( "host: %s\n", buf);
- }
- PR_EnumerateHostEnt(0, &he, 80, &addr);
-
- sock = PR_NewTCPSocket();
- optData.option = PR_SockOpt_Nonblocking;
- optData.value.non_blocking = PR_TRUE;
- PR_SetSocketOption(sock, &optData);
- rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
- if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
- printf( "Connect in progress\n");
- }
+ if (default_case) {
+
+ /*
+ * In the default case the following tests are executed:
+ * 1. successful connection: a server thread accepts a connection
+ * from the main thread
+ * 2. unsuccessful connection: the main thread tries to connect to a
+ * non-existent port and expects to get an error
+ */
+ rv = connection_success_test();
+ if (rv == 0)
+ rv = connection_failure_test();
+ return rv;
+ } else {
+ PRFileDesc *sock;
- pd.fd = sock;
- pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
+ printf( "Unknown host: %s\n", argv[1]);
+ exit(1);
+ } else {
+ printf( "host: %s\n", buf);
+ }
+ PR_EnumerateHostEnt(0, &he, 80, &addr);
+
+ sock = PR_NewTCPSocket();
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(sock, &optData);
+ rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "Connect in progress\n");
+ }
+
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
#ifndef XP_MAC
- n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
#else
- n = PR_Poll(&pd, 1, timeout);
+ n = PR_Poll(&pd, 1, timeout);
#endif
- if (n == -1) {
- printf( "PR_Poll failed\n");
- exit(1);
- }
- printf( "PR_Poll returns %d\n", n);
- if (pd.out_flags & PR_POLL_READ) {
- printf( "PR_POLL_READ\n");
- }
- if (pd.out_flags & PR_POLL_WRITE) {
- printf( "PR_POLL_WRITE\n");
- }
- if (pd.out_flags & PR_POLL_EXCEPT) {
- printf( "PR_POLL_EXCEPT\n");
- }
- if (pd.out_flags & PR_POLL_ERR) {
- printf( "PR_POLL_ERR\n");
- }
- if (pd.out_flags & PR_POLL_NVAL) {
- printf( "PR_POLL_NVAL\n");
- }
+ if (n == -1) {
+ printf( "PR_Poll failed\n");
+ exit(1);
+ }
+ printf( "PR_Poll returns %d\n", n);
+ if (pd.out_flags & PR_POLL_READ) {
+ printf( "PR_POLL_READ\n");
+ }
+ if (pd.out_flags & PR_POLL_WRITE) {
+ printf( "PR_POLL_WRITE\n");
+ }
+ if (pd.out_flags & PR_POLL_EXCEPT) {
+ printf( "PR_POLL_EXCEPT\n");
+ }
+ if (pd.out_flags & PR_POLL_ERR) {
+ printf( "PR_POLL_ERR\n");
+ }
+ if (pd.out_flags & PR_POLL_NVAL) {
+ printf( "PR_POLL_NVAL\n");
+ }
- if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
- printf("PR_GetConnectStatus: connect succeeded\n");
- /* Mac and Win16 have trouble printing to the console. */
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ printf("PR_GetConnectStatus: connect succeeded\n");
+ /* Mac and Win16 have trouble printing to the console. */
#if !defined(XP_MAC) && !defined(WIN16)
- PR_Write(sock, "GET /\r\n\r\n", 9);
- PR_Shutdown(sock, PR_SHUTDOWN_SEND);
- pd.in_flags = PR_POLL_READ;
- while (1) {
- n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
- printf( "poll returns %d\n", n);
- n = PR_Read(sock, buf, sizeof(buf));
- printf( "read returns %d\n", n);
- if (n <= 0) {
- break;
- }
- PR_Write(PR_STDOUT, buf, n);
- }
+ PR_Write(sock, "GET /\r\n\r\n", 9);
+ PR_Shutdown(sock, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ while (1) {
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ printf( "poll returns %d\n", n);
+ n = PR_Read(sock, buf, sizeof(buf));
+ printf( "read returns %d\n", n);
+ if (n <= 0) {
+ break;
+ }
+ PR_Write(PR_STDOUT, buf, n);
+ }
#endif
- } else {
- if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
- printf( "PR_GetConnectStatus: connect still in progress\n");
- exit(1);
- }
- printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
- PR_GetError(), PR_GetOSError());
- }
- PR_Close(sock);
+ } else {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "PR_GetConnectStatus: connect still in progress\n");
+ exit(1);
+ }
+ printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ PR_Close(sock);
#ifdef XP_MAC
- } /* end of for loop */
+ } /* end of for loop */
+#endif
+ printf( "PASS\n");
+ return 0;
+
+ }
+}
+
+
+/*
+ * TCP Server
+ * Server Thread
+ * Accept a connection from the client and write some data
+ */
+static void PR_CALLBACK
+TCP_Server(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRFileDesc *sockfd, *newsockfd;
+ char data_buf[DATA_BUF_SIZE];
+ PRIntn rv, bytes_read;
+
+ sockfd = sp->sp_fd;
+ if ((newsockfd = PR_Accept(sockfd, NULL,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,"ERROR - PR_Accept failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ return;
+ }
+ bytes_read = 0;
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Read(newsockfd, data_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from client - %d\n",bytes_read));
+ rv = PR_Write(newsockfd, data_buf,DATA_BUF_SIZE);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv == DATA_BUF_SIZE);
+ DPRINTF(("Bytes written to client - %d\n",rv));
+ PR_Close(newsockfd);
+}
+
+
+/*
+ * test for successful connection using a non-blocking socket
+ */
+static PRIntn
+connection_success_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRThread *thr = NULL;
+ Server_Param sp;
+ char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRIntn failed_already;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"ERROR - PR_Listen failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ DPRINTF(("Connect in progress\n"));
+ } else {
+ fprintf(stderr,"Error - PR_Connect failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ } else {
+ PR_ASSERT(rv == PR_SUCCESS);
+ fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ /*
+ * Now create a thread to accept a connection
+ */
+ sp.sp_fd = sockfd;
+ thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)&sp,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (thr == NULL) {
+ fprintf(stderr,"Error - PR_CreateThread failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Created TCP_Server thread [0x%x]\n",thr));
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
+#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (pd.out_flags != PR_POLL_WRITE) {
+ fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
+ pd.out_flags);
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+
+ DPRINTF(("Connection successful\n"));
+
+ /*
+ * Write some data, read it back and check data integrity to
+ * make sure the connection is good
+ */
+ pd.in_flags = PR_POLL_WRITE;
+ bytes_sent = 0;
+ memset(send_buf, 'a', DATA_BUF_SIZE);
+ while (bytes_sent != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE));
+ rv = PR_Write(conn_fd, send_buf + bytes_sent,
+ DATA_BUF_SIZE - bytes_sent);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv > 0);
+ bytes_sent += rv;
+ }
+ DPRINTF(("Bytes written to server - %d\n",bytes_sent));
+ PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ bytes_read = 0;
+ memset(recv_buf, 0, DATA_BUF_SIZE);
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ));
+ rv = PR_Read(conn_fd, recv_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from server - %d\n",bytes_read));
+ /*
+ * verify the data read
+ */
+ if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) {
+ fprintf(stderr,"ERROR - data corruption\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Data integrity verified\n"));
+ } else {
+ fprintf(stderr,"PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already = 1;
+ goto def_exit;
+ }
+def_exit:
+ if (thr) {
+ PR_JoinThread(thr);
+ thr = NULL;
+ }
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+
+}
+
+/*
+ * test for connection to a non-existent port using a non-blocking socket
+ */
+static PRIntn
+connection_failure_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRIntn n, failed_already = 0;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError()));
+ } else {
+ PR_ASSERT(rv == PR_SUCCESS);
+ fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (pd.out_flags != PR_POLL_WRITE) {
+ fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
+ pd.out_flags);
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+ fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n");
+ failed_already = 1;
+ goto def_exit;
+ }
+ rv = PR_GetError();
+ DPRINTF(("Connection failed, successfully with PR_Error %d\n",rv));
+def_exit:
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
- printf( "PASS\n");
- return 0;
}
diff --git a/pr/tests/nblayer.c b/pr/tests/nblayer.c
index 2c0ffd67..b14073a1 100644
--- a/pr/tests/nblayer.c
+++ b/pr/tests/nblayer.c
@@ -103,20 +103,24 @@ static void PR_CALLBACK Client(void *arg)
rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError()))
{
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client connect 'in progress'\n");
do
{
- {
- polldesc.fd = stack;
- polldesc.out_flags = 0;
- polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
- ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
- rv = PR_GetConnectStatus(&polldesc);
- if (PR_FAILURE == rv)
- {
- if (PR_IN_PROGRESS_ERROR != PR_GetError()) break;
- }
- }
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ if (verbosity > quiet)
+ PR_fprintf(
+ logFile, "Client connect 'in progress' [0x%x]\n",
+ polldesc.out_flags);
+ rv = PR_GetConnectStatus(&polldesc);
+ if ((PR_FAILURE == rv)
+ && (PR_IN_PROGRESS_ERROR != PR_GetError())) break;
} while (PR_FAILURE == rv);
}
PR_ASSERT(PR_SUCCESS == rv);
@@ -126,24 +130,29 @@ static void PR_CALLBACK Client(void *arg)
for (mits = 0; mits < minor_iterations; ++mits)
{
bytes_sent = 0;
- if (verbosity > chatty)
+ if (verbosity > quiet)
PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer));
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client sending %d bytes\n",
+ sizeof(buffer) - bytes_sent);
ready = PR_Send(
stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_sent += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client send status [%d]\n", ready);
+ if (0 < ready) bytes_sent += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_WRITE;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_sent < sizeof(buffer));
@@ -152,20 +161,26 @@ static void PR_CALLBACK Client(void *arg)
bytes_read = 0;
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receiving %d bytes\n",
+ bytes_sent - bytes_read);
ready = PR_Recv(
stack, buffer + bytes_read, bytes_sent - bytes_read,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_read += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_READ;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_read < bytes_sent);
@@ -200,14 +215,20 @@ static void PR_CALLBACK Server(void *arg)
do
{
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accepting connection\n");
service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accept status [0x%p]\n", service);
if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
- polldesc.in_flags = PR_POLL_READ;
+ polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
} while (NULL == service);
PR_ASSERT(NULL != service);
@@ -220,20 +241,25 @@ static void PR_CALLBACK Server(void *arg)
bytes_read = 0;
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Server receiving %d bytes\n",
+ sizeof(buffer) - bytes_read);
ready = PR_Recv(
service, buffer + bytes_read, sizeof(buffer) - bytes_read,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_read += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = service;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_READ;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_read < sizeof(buffer));
@@ -260,7 +286,9 @@ static void PR_CALLBACK Server(void *arg)
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_WRITE;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_sent < bytes_read);
@@ -331,7 +359,6 @@ static PRInt32 PR_CALLBACK MyRecv(
{
char *b;
PRInt32 rv;
- PRPollDesc polldesc;
PRFileDesc *lo = fd->lower;
PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
diff --git a/pr/tests/op_filok.c b/pr/tests/op_filok.c
index dc17efea..ae540ac7 100644
--- a/pr/tests/op_filok.c
+++ b/pr/tests/op_filok.c
@@ -42,31 +42,42 @@
#else
#endif
-static PRFileDesc *t1;
+/*
+ * The name of a file that is guaranteed to exist
+ * on every machine of a particular OS.
+ */
+#ifdef XP_UNIX
+#define EXISTING_FILENAME "/bin/sh"
+#elif defined(WIN32)
+#define EXISTING_FILENAME "c:/boot.ini"
+#else
+#error "Unknown OS"
+#endif
-PRIntn error_code;
+static PRFileDesc *t1;
int main(int argc, char **argv)
{
-
#ifdef XP_MAC
SetupMacPrintfLog("pr_open_re.log");
#endif
-
-
PR_STDIO_INIT();
- t1 = PR_Open("/usr/tmp/ttools/nspr20/err03.tmp", PR_TRUNCATE | PR_RDWR, 0666);
+ t1 = PR_Open(EXISTING_FILENAME, PR_RDONLY, 0666);
if (t1 == NULL) {
- if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
- printf ("error code is %d \n", PR_GetError());
- printf ("File should be found\n");
+ printf ("error code is %d \n", PR_GetError());
+ printf ("File %s should be found\n",
+ EXISTING_FILENAME);
+ return 1;
+ } else {
+ if (PR_Close(t1) == PR_SUCCESS) {
+ printf ("Test passed \n");
+ return 0;
+ } else {
+ printf ("cannot close file\n");
+ printf ("error code is %d\n", PR_GetError());
return 1;
}
}
- else {
- printf ("Test passed \n");
- return 0;
- }
}
diff --git a/pr/tests/op_noacc.c b/pr/tests/op_noacc.c
index c528dc75..b45fce2e 100644
--- a/pr/tests/op_noacc.c
+++ b/pr/tests/op_noacc.c
@@ -54,6 +54,10 @@ int main(int argc, char **argv)
SetupMacPrintfLog("pr_open_re.log");
#endif
+#ifdef XP_PC
+ printf("op_noacc: Test not valid on MS-Windows.\n\tNo concept of 'mode' on Open() call\n");
+ return(0);
+#endif
PR_STDIO_INIT();
diff --git a/pr/tests/op_nofil.c b/pr/tests/op_nofil.c
index c38063ff..3cb3adef 100644
--- a/pr/tests/op_nofil.c
+++ b/pr/tests/op_nofil.c
@@ -43,31 +43,38 @@
#else
#endif
+/*
+ * A file name that cannot exist
+ */
+#define NO_SUCH_FILE "/no/such/file.tmp"
+
static PRFileDesc *t1;
-PRIntn error_code;
int main(int argc, char **argv)
{
-
#ifdef XP_MAC
SetupMacPrintfLog("pr_open_re.log");
#endif
-
-
PR_STDIO_INIT();
- t1 = PR_Open("/usr/tmp/err02.tmp", PR_RDWR, 0666);
- if (t1 == NULL)
+ t1 = PR_Open(NO_SUCH_FILE, PR_RDONLY, 0666);
+ if (t1 == NULL) {
if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
-
- printf ("error code is %d \n", PR_GetError());
- printf ("PASS\n");
- return 0;
- }
- else {
- printf ("error code is %d \n", PR_GetError());
- printf ("FAIL\n");
- return 1;
+ printf ("error code is PR_FILE_NOT_FOUND_ERROR, as expected\n");
+ printf ("PASS\n");
+ return 0;
+ } else {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("FAIL\n");
+ return 1;
}
+ }
+ printf ("File %s exists on this machine!?\n", NO_SUCH_FILE);
+ if (PR_Close(t1) == PR_FAILURE) {
+ printf ("cannot close file\n");
+ printf ("error code is %d \n", PR_GetError());
+ }
+ printf ("FAIL\n");
+ return 1;
}
diff --git a/pr/tests/parent.c b/pr/tests/parent.c
index 4e82b8b0..d5fef9ec 100644
--- a/pr/tests/parent.c
+++ b/pr/tests/parent.c
@@ -26,6 +26,7 @@
#include "prprf.h"
#include "prinit.h"
#include "prproces.h"
+#include "prinrval.h"
typedef struct Child
{
@@ -44,6 +45,7 @@ PRIntn main (PRIntn argc, char **argv)
{
PRStatus rv;
PRInt32 test_status = 1;
+ PRIntervalTime t_start, t_elapsed;
PRFileDesc *debug = NULL;
Child *child = PR_NEWZAP(Child);
@@ -83,14 +85,22 @@ PRIntn main (PRIntn argc, char **argv)
child->attr, PR_StandardError,
PR_GetSpecialFD(PR_StandardError));
+ t_start = PR_IntervalNow();
child->process = PR_CreateProcess(
child->name, argv, NULL, child->attr);
+ t_elapsed = (PRIntervalTime) (PR_IntervalNow() - t_start);
test_status = (NULL == child->process) ? 1 : 0;
if (NULL != debug)
+ {
PR_fprintf(
debug, "Child was %sforked\n",
(0 == test_status) ? "" : "NOT ");
+ if (0 == test_status)
+ PR_fprintf(
+ debug, "PR_CreateProcess took %lu microseconds\n",
+ PR_IntervalToMicroseconds(t_elapsed));
+ }
if (0 == test_status)
{
diff --git a/pr/tests/perf.c b/pr/tests/perf.c
index 5928052f..b6785d75 100644
--- a/pr/tests/perf.c
+++ b/pr/tests/perf.c
@@ -67,6 +67,26 @@ static void DLLProcedureCall(void)
}
}
+static void Now(void)
+{
+ PRInt32 i;
+ PRTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_Now();
+ }
+}
+
+static void Interval(void)
+{
+ PRInt32 i;
+ PRIntervalTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_IntervalNow();
+ }
+}
+
static void IdleLock(void)
{
PRInt32 i;
@@ -399,6 +419,8 @@ int main(int argc, char **argv)
Measure(LocalProcedureCall, "local procedure call overhead");
Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
Measure(IdleLock, "idle lock lock/unlock pair");
Measure(IdleMonitor, "idle monitor entry/exit pair");
Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
@@ -420,6 +442,8 @@ int main(int argc, char **argv)
Measure(LocalProcedureCall, "local procedure call overhead");
Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
Measure(IdleLock, "idle lock lock/unlock pair");
Measure(IdleMonitor, "idle monitor entry/exit pair");
Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
diff --git a/pr/tests/poll_nm.c b/pr/tests/poll_nm.c
index a8995b3b..ab5c5286 100644
--- a/pr/tests/poll_nm.c
+++ b/pr/tests/poll_nm.c
@@ -89,7 +89,7 @@ clientThreadFunc(void *arg)
addr.inet.port = PR_htons((PRUint16)port);
addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
memset(buf, 0, sizeof(buf));
- PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip);
+ PR_snprintf(buf, sizeof(buf), "%hu", port);
for (i = 0; i < NUM_ITERATIONS; i++) {
sock = PR_NewTCPSocket();
diff --git a/pr/tests/pollable.c b/pr/tests/pollable.c
new file mode 100644
index 00000000..f31d8a93
--- /dev/null
+++ b/pr/tests/pollable.c
@@ -0,0 +1,273 @@
+/* -*- 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.0 (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.
+ */
+
+/*
+ * A test for the pollable events.
+ *
+ * A number of threads are in a ring configuration, each waiting on
+ * a pollable event that is set by its upstream neighbor.
+ */
+
+#include "prinit.h"
+#include "prio.h"
+#include "prthread.h"
+#include "prerror.h"
+#include "prmem.h"
+#include "prlog.h"
+#include "prprf.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+#define DEFAULT_THREADS 10
+#define DEFAULT_LOOPS 100
+
+PRIntn numThreads = DEFAULT_THREADS;
+PRIntn numIterations = DEFAULT_LOOPS;
+PRIntervalTime dally = PR_INTERVAL_NO_WAIT;
+PRFileDesc *debug_out = NULL;
+PRBool debug_mode = PR_FALSE;
+PRBool verbosity = PR_FALSE;
+
+typedef struct ThreadData {
+ PRFileDesc *event;
+ int index;
+ struct ThreadData *next;
+} ThreadData;
+
+void ThreadRoutine(void *arg)
+{
+ ThreadData *data = (ThreadData *) arg;
+ PRIntn i;
+ PRPollDesc pd;
+ PRInt32 rv;
+
+ pd.fd = data->event;
+ pd.in_flags = PR_POLL_READ;
+
+ for (i = 0; i < numIterations; i++) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d awakened\n", data->index);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d posting event\n", data->index);
+ }
+ if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "post event failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void Help(void)
+{
+ debug_out = PR_STDOUT;
+
+ PR_fprintf(
+ debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n");
+ PR_fprintf(
+ debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
+ PR_fprintf(
+ debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
+ PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
+ PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ ThreadData selfData;
+ ThreadData *data;
+ PRThread **thread;
+ void *block;
+ PRIntn i;
+ PRIntervalTime timeStart, timeEnd;
+ PRPollDesc pd;
+ PRInt32 rv;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRBool help = PR_FALSE;
+ PRUintn concurrency = 1;
+ PRUintn average;
+ PLOptStatus os;
+ PLOptState *opt;
+
+ PR_STDIO_INIT();
+
+ opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) {
+ continue;
+ }
+ switch (opt->option) {
+ case 'v': /* verbose mode */
+ verbosity = PR_TRUE;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ numIterations = atoi(opt->value);
+ break;
+ case 't': /* thread limit */
+ numThreads = atoi(opt->value);
+ break;
+ case 'C': /* Concurrency limit */
+ concurrency = atoi(opt->value);
+ break;
+ case 'G': /* global threads only */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'D': /* dally */
+ dally = PR_MillisecondsToInterval(atoi(opt->value));
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (help) {
+ return 1;
+ }
+
+ if (concurrency > 1) {
+ PR_SetConcurrency(concurrency);
+ }
+
+ if (PR_TRUE == debug_mode) {
+ debug_out = PR_STDOUT;
+ PR_fprintf(debug_out, "Test parameters\n");
+ PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads);
+ PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations);
+ PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(debug_out, "\tThread type: %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+ }
+
+ /*
+ * Malloc a block of memory and divide it into data and thread.
+ */
+ block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *)));
+ if (block == NULL) {
+ PR_fprintf(PR_STDERR, "cannot malloc, failed\n");
+ exit(1);
+ }
+ data = (ThreadData *) block;
+ thread = (PRThread **) &data[numThreads];
+
+ /* Pollable event */
+ selfData.event = PR_NewPollableEvent();
+ if (selfData.event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ selfData.next = &data[0];
+ for (i = 0; i < numThreads; i++) {
+ data[i].event = PR_NewPollableEvent();
+ if (data[i].event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ data[i].index = i;
+ if (i != numThreads - 1) {
+ data[i].next = &data[i + 1];
+ } else {
+ data[i].next = &selfData;
+ }
+
+ thread[i] = PR_CreateThread(PR_USER_THREAD,
+ ThreadRoutine, &data[i], PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (thread[i] == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create thread\n");
+ exit(1);
+ }
+ }
+
+ timeStart = PR_IntervalNow();
+ pd.fd = selfData.event;
+ pd.in_flags = PR_POLL_READ;
+ for (i = 0; i < numIterations; i++) {
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread posting event\n");
+ }
+ if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "set event failed\n");
+ exit(1);
+ }
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "wait failed\n");
+ exit(1);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread awakened\n");
+ }
+ if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ }
+ timeEnd = PR_IntervalNow();
+
+ if (debug_mode) {
+ average = PR_IntervalToMicroseconds(timeEnd - timeStart)
+ / (numIterations * numThreads);
+ PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n",
+ average, numThreads);
+ }
+
+ for (i = 0; i < numThreads; i++) {
+ if (PR_JoinThread(thread[i]) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "join thread failed\n");
+ exit(1);
+ }
+ PR_DestroyPollableEvent(data[i].event);
+ }
+ PR_DELETE(block);
+
+ PR_fprintf(PR_STDOUT, "PASSED\n");
+ return 0;
+}
diff --git a/pr/tests/prftest2.c b/pr/tests/prftest2.c
index b5322888..c3239905 100644
--- a/pr/tests/prftest2.c
+++ b/pr/tests/prftest2.c
@@ -105,6 +105,6 @@ int main( int argc, char *argv[])
else
{
printf("PASSED\n");
- return 1;
+ return 0;
}
}
diff --git a/pr/tests/priotest.c b/pr/tests/priotest.c
index cdc76953..f9df1528 100644
--- a/pr/tests/priotest.c
+++ b/pr/tests/priotest.c
@@ -42,7 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
-#define DEFAULT_DURATION 20
+#define DEFAULT_DURATION 5
static PRBool failed = PR_FALSE;
static PRIntervalTime oneSecond;
@@ -131,7 +131,7 @@ static void RudimentaryTests(void)
} /* RudimentataryTests */
-static void CreateThreads(PRInt32 *lowCount, PRInt32 *highCount)
+static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount)
{
(void)PR_CreateThread(
PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW,
diff --git a/pr/tests/provider.c b/pr/tests/provider.c
new file mode 100644
index 00000000..49428b3a
--- /dev/null
+++ b/pr/tests/provider.c
@@ -0,0 +1,1356 @@
+/* -*- 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.0 (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.
+ */
+
+/*
+ *
+ * Notes:
+ * [1] lth. The call to Sleep() is a hack to get the test case to run
+ * on Windows 95. Without it, the test case fails with an error
+ * WSAECONNRESET following a recv() call. The error is caused by the
+ * server side thread termination without a shutdown() or closesocket()
+ * call. Windows docmunentation suggests that this is predicted
+ * behavior; that other platforms get away with it is ... serindipity.
+ * The test case should shutdown() or closesocket() before
+ * thread termination. I didn't have time to figure out where or how
+ * to do it. The Sleep() call inserts enough delay to allow the
+ * client side to recv() all his data before the server side thread
+ * terminates. Whew! ...
+ *
+ ** Modification History:
+ * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+ * The debug mode will print all of the printfs associated with this test.
+ * The regress mode will be the default mode. Since the regress tool limits
+ * the output to a one line status:PASS or FAIL,all of the printf statements
+ * have been handled with an if (debug_mode) statement.
+ */
+
+#include "prclist.h"
+#include "prcvar.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prtime.h"
+#include "prmem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prthread.h"
+
+#include "pprio.h"
+#include "primpl.h"
+
+#include "plstr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#if defined(XP_UNIX)
+#include <math.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+/*
+** This is the beginning of the test
+*/
+
+#define RECV_FLAGS 0
+#define SEND_FLAGS 0
+#define BUFFER_SIZE 1024
+#define DEFAULT_BACKLOG 5
+#define DEFAULT_PORT 12848
+#define DEFAULT_CLIENTS 1
+#define ALLOWED_IN_ACCEPT 1
+#define DEFAULT_CLIPPING 1000
+#define DEFAULT_WORKERS_MIN 1
+#define DEFAULT_WORKERS_MAX 1
+#define DEFAULT_SERVER "localhost"
+#define DEFAULT_EXECUTION_TIME 10
+#define DEFAULT_CLIENT_TIMEOUT 4000
+#define DEFAULT_SERVER_TIMEOUT 4000
+#define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH
+
+typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t;
+
+static void PR_CALLBACK Worker(void *arg);
+typedef struct CSPool_s CSPool_t;
+typedef struct CSWorker_s CSWorker_t;
+typedef struct CSServer_s CSServer_t;
+typedef enum Verbosity
+{
+ TEST_LOG_ALWAYS,
+ TEST_LOG_ERROR,
+ TEST_LOG_WARNING,
+ TEST_LOG_NOTICE,
+ TEST_LOG_INFO,
+ TEST_LOG_STATUS,
+ TEST_LOG_VERBOSE
+} Verbosity;
+
+static enum {
+ thread_nspr, thread_pthread, thread_sproc, thread_win32
+} thread_provider;
+
+static PRInt32 domain = AF_INET;
+static PRInt32 protocol = 6; /* TCP */
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE;
+static PRBool pthread_stats = PR_FALSE;
+static Verbosity verbosity = TEST_LOG_ALWAYS;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+struct CSWorker_s
+{
+ PRCList element; /* list of the server's workers */
+
+ PRThread *thread; /* this worker objects thread */
+ CSServer_t *server; /* back pointer to server structure */
+};
+
+struct CSPool_s
+{
+ PRCondVar *exiting;
+ PRCondVar *acceptComplete;
+ PRUint32 accepting, active, workers;
+};
+
+struct CSServer_s
+{
+ PRCList list; /* head of worker list */
+
+ PRLock *ml;
+ PRThread *thread; /* the main server thread */
+ PRCondVar *stateChange;
+
+ PRUint16 port; /* port we're listening on */
+ PRUint32 backlog; /* size of our listener backlog */
+ PRFileDesc *listener; /* the fd accepting connections */
+
+ CSPool_t pool; /* statistics on worker threads */
+ CSState_t state; /* the server's state */
+ struct /* controlling worker counts */
+ {
+ PRUint32 minimum, maximum, accepting;
+ } workers;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+};
+
+typedef struct CSDescriptor_s
+{
+ PRInt32 size; /* size of transfer */
+ char filename[60]; /* filename, null padded */
+} CSDescriptor_t;
+
+typedef struct CSClient_s
+{
+ PRLock *ml;
+ PRThread *thread;
+ PRCondVar *stateChange;
+ PRNetAddr serverAddress;
+
+ CSState_t state;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+} CSClient_t;
+
+#define TEST_LOG(l, p, a) \
+ do { \
+ if (debug_mode || (p <= verbosity)) printf a; \
+ } while (0)
+
+PRLogModuleInfo *cltsrv_log_file = NULL;
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+#define TEST_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+static void _MY_Assert(const char *s, const char *file, PRIntn ln)
+{
+ PL_PrintError(NULL);
+#if DEBUG
+ PR_Assert(s, file, ln);
+#endif
+} /* _MW_Assert */
+
+static PRBool Aborted(PRStatus rv)
+{
+ return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ?
+ PR_TRUE : PR_FALSE;
+}
+
+static void TimeOfDayMessage(const char *msg, PRThread* me)
+{
+ char buffer[100];
+ PRExplodedTime tod;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("%s(0x%p): %s\n", msg, me, buffer));
+} /* TimeOfDayMessage */
+
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRIntn index;
+ char buffer[1024];
+ PRFileDesc *fd = NULL;
+ PRUintn clipping = DEFAULT_CLIPPING;
+ CSClient_t *client = (CSClient_t*)arg;
+ PRThread *me = client->thread = PR_CurrentThread();
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT);
+
+
+ for (index = 0; index < sizeof(buffer); ++index)
+ buffer[index] = (char)index;
+
+ client->started = PR_IntervalNow();
+
+ PR_Lock(client->ml);
+ client->state = cs_run;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+
+ TimeOfDayMessage("Client started at", me);
+
+ while (cs_run == client->state)
+ {
+ PRInt32 bytes, descbytes, filebytes, netbytes;
+
+ (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
+ TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
+
+ fd = PR_Socket(domain, SOCK_STREAM, protocol);
+ TEST_ASSERT(NULL != fd);
+ rv = PR_Connect(fd, &client->serverAddress, timeout);
+ if (PR_FAILURE == rv)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): conection failed\n", me));
+ goto aborted;
+ }
+
+ memset(descriptor, 0, sizeof(*descriptor));
+ descriptor->size = PR_htonl(descbytes = rand() % clipping);
+ PR_snprintf(
+ descriptor->filename, sizeof(descriptor->filename),
+ "CS%p%p-%p.dat", client->started, me, client->operations);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
+ bytes = PR_Send(
+ fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
+ if (sizeof(CSDescriptor_t) != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send descriptor timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send data timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(bytes == filebytes);
+ netbytes += bytes;
+ }
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ if (Aborted(PR_FAILURE))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data aborted\n", me));
+ goto aborted;
+ }
+ else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto retry;
+ }
+ if (0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tClient(0x%p): unexpected end of stream\n",
+ PR_CurrentThread()));
+ break;
+ }
+ filebytes += bytes;
+ }
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+retry:
+ (void)PR_Close(fd); fd = NULL;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): disconnected from server\n", me));
+
+ PR_Lock(client->ml);
+ client->operations += 1;
+ client->bytesTransferred += 2 * descbytes;
+ rv = PR_WaitCondVar(client->stateChange, rand() % clipping);
+ PR_Unlock(client->ml);
+ if (Aborted(rv)) break;
+ }
+
+aborted:
+ client->stopped = PR_IntervalNow();
+
+ PR_ClearInterrupt();
+ if (NULL != fd) rv = PR_Close(fd);
+
+ PR_Lock(client->ml);
+ client->state = cs_exit;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+ PR_DELETE(descriptor);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
+ PR_CurrentThread(), client->operations, client->bytesTransferred));
+
+} /* Client */
+
+static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
+{
+ PRStatus drv, rv;
+ char buffer[1024];
+ PRFileDesc *file = NULL;
+ PRThread * me = PR_CurrentThread();
+ PRInt32 bytes, descbytes, netbytes, filebytes = 0;
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
+ bytes = PR_Recv(
+ fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto exit;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
+ }
+ goto exit;
+ }
+ if (0 == bytes)
+ {
+ rv = PR_FAILURE;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
+ goto exit;
+ }
+ descbytes = PR_ntohl(descriptor->size);
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
+ me, descbytes, descriptor->filename));
+
+ file = PR_Open(
+ descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(NULL != file);
+
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
+ goto aborted;
+ }
+ /*
+ * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED)
+ * on NT here. This is equivalent to ECONNRESET on Unix.
+ * -wtc
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ if(0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
+ rv = PR_FAILURE;
+ goto aborted;
+ }
+ filebytes += bytes;
+ netbytes = bytes;
+ /* The byte count for PR_Write should be positive */
+ MY_ASSERT(netbytes > 0);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
+ bytes = PR_Write(file, buffer, netbytes);
+ if (netbytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->operations += 1;
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
+ file = PR_Open(descriptor->filename, PR_RDONLY, 0);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
+ PR_CurrentThread()));
+ goto aborted;
+ }
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(NULL != file);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
+ bytes = PR_Read(file, buffer, filebytes);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(bytes > 0);
+ netbytes += bytes;
+ filebytes = bytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
+ goto aborted;
+ }
+ break;
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+aborted:
+ PR_ClearInterrupt();
+ if (NULL != file) PR_Close(file);
+ drv = PR_Delete(descriptor->filename);
+ TEST_ASSERT(PR_SUCCESS == drv);
+exit:
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
+
+ PR_DELETE(descriptor);
+
+#if defined(WIN95)
+ PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */
+#endif
+ return rv;
+} /* ProcessRequest */
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include "md/_pth.h"
+#include <pthread.h>
+
+static void *pthread_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus JoinThread(PRThread *thread)
+{
+ PRStatus rv;
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ rv = PR_JoinThread(thread);
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ rv = PR_SUCCESS;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ case thread_win32:
+#if defined(WIN32)
+ rv = PR_SUCCESS;
+ break;
+#endif
+ default:
+ rv = PR_FAILURE;
+ break;
+ }
+ return rv;
+} /* JoinThread */
+
+static PRStatus NewThread(
+ StartFn start, void *arg, PRThreadPriority prio, PRThreadState state)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ break;
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* NewThread */
+
+static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
+{
+ PRStatus rv;
+ CSWorker_t *worker = PR_NEWZAP(CSWorker_t);
+ worker->server = server;
+ PR_INIT_CLIST(&worker->element);
+ rv = NewThread(
+ Worker, worker, DEFAULT_SERVER_PRIORITY, PR_UNJOINABLE_THREAD);
+ if (PR_FAILURE == rv) PR_DELETE(worker);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
+ PR_CurrentThread(), worker->thread));
+
+ return rv;
+} /* CreateWorker */
+
+static void PR_CALLBACK Worker(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr from;
+ PRFileDesc *fd = NULL;
+ CSWorker_t *worker = (CSWorker_t*)arg;
+ CSServer_t *server = worker->server;
+ CSPool_t *pool = &server->pool;
+
+ PRThread *me = worker->thread = PR_CurrentThread();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
+
+ PR_Lock(server->ml);
+ PR_APPEND_LINK(&worker->element, &server->list);
+ pool->workers += 1; /* define our existance */
+
+ while (cs_run == server->state)
+ {
+ while (pool->accepting >= server->workers.accepting)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
+ me, pool->accepting));
+ rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
+ if (Aborted(rv) || (cs_run != server->state))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tWorker(0x%p): has been %s\n",
+ me, (Aborted(rv) ? "interrupted" : "stopped")));
+ goto exit;
+ }
+ }
+ pool->accepting += 1; /* how many are really in accept */
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): calling accept\n", me));
+ fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Lock(server->ml);
+ pool->accepting -= 1;
+ PR_NotifyCondVar(pool->acceptComplete);
+
+ if ((NULL == fd) && Aborted(PR_FAILURE))
+ {
+ if (NULL != server->listener)
+ {
+ PR_Close(server->listener);
+ server->listener = NULL;
+ }
+ goto exit;
+ }
+
+ if (NULL != fd)
+ {
+ /*
+ ** Create another worker of the total number of workers is
+ ** less than the minimum specified or we have none left in
+ ** accept() AND we're not over the maximum.
+ ** This sort of presumes that the number allowed in accept
+ ** is at least as many as the minimum. Otherwise we'll keep
+ ** creating new threads and deleting them soon after.
+ */
+ PRBool another =
+ ((pool->workers < server->workers.minimum) ||
+ ((0 == pool->accepting)
+ && (pool->workers < server->workers.maximum))) ?
+ PR_TRUE : PR_FALSE;
+ pool->active += 1;
+ PR_Unlock(server->ml);
+
+ if (another) (void)CreateWorker(server, pool);
+
+ rv = ProcessRequest(fd, server);
+ if (PR_SUCCESS != rv)
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
+ (void)PR_Close(fd); fd = NULL;
+
+ PR_Lock(server->ml);
+ pool->active -= 1;
+ }
+ }
+
+exit:
+ PR_ClearInterrupt();
+ PR_Unlock(server->ml);
+
+ if (NULL != fd)
+ {
+ (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ (void)PR_Close(fd);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
+
+ PR_Lock(server->ml);
+ pool->workers -= 1; /* undefine our existance */
+ PR_REMOVE_AND_INIT_LINK(&worker->element);
+ PR_NotifyCondVar(pool->exiting);
+ PR_Unlock(server->ml);
+
+ PR_DELETE(worker); /* destruction of the "worker" object */
+
+} /* Worker */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr serverAddress;
+ CSServer_t *server = (CSServer_t*)arg;
+ PRThread *me = server->thread = PR_CurrentThread();
+
+ server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
+
+ rv = PR_Bind(server->listener, &serverAddress);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Listen(server->listener, server->backlog);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ server->started = PR_IntervalNow();
+ TimeOfDayMessage("Server started at", me);
+
+ PR_Lock(server->ml);
+ server->state = cs_run;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ /*
+ ** Create the first worker (actually, a thread that accepts
+ ** connections and then processes the work load as needed).
+ ** From this point on, additional worker threads are created
+ ** as they are needed by existing worker threads.
+ */
+ rv = CreateWorker(server, &server->pool);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ /*
+ ** From here on this thread is merely hanging around as the contact
+ ** point for the main test driver. It's just waiting for the driver
+ ** to declare the test complete.
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): waiting for state change\n", me));
+
+ PR_Lock(server->ml);
+ while ((cs_run == server->state) && !Aborted(rv))
+ {
+ rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(server->ml);
+ PR_ClearInterrupt();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tServer(0x%p): shutting down workers\n", me));
+
+ /*
+ ** Get all the worker threads to exit. They know how to
+ ** clean up after themselves, so this is just a matter of
+ ** waiting for clorine in the pool to take effect. During
+ ** this stage we're ignoring interrupts.
+ */
+ server->workers.minimum = server->workers.maximum = 0;
+
+ PR_Lock(server->ml);
+ while (!PR_CLIST_IS_EMPTY(&server->list))
+ {
+ PRCList *head = PR_LIST_HEAD(&server->list);
+ CSWorker_t *worker = (CSWorker_t*)head;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
+ rv = PR_Interrupt(worker->thread);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_REMOVE_AND_INIT_LINK(head);
+ }
+
+ while (server->pool.workers > 0)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
+ me, server->pool.workers));
+ (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ server->state = cs_exit;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
+ me, server->operations, server->bytesTransferred));
+
+ if (NULL != server->listener) PR_Close(server->listener);
+ server->stopped = PR_IntervalNow();
+
+} /* Server */
+
+static void WaitForCompletion(PRIntn execution)
+{
+ while (execution > 0)
+ {
+ PRIntn dally = (execution > 30) ? 30 : execution;
+ PR_Sleep(PR_SecondsToInterval(dally));
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+ execution -= dally;
+ }
+} /* WaitForCompletion */
+
+static void Help(void)
+{
+ PR_fprintf(debug_out, "cltsrv test program usage:\n");
+ PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
+ PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
+ PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
+ PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n");
+ PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n");
+ PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'w')(n)\n");
+ PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n");
+#ifdef _PR_INET6
+ PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n");
+#endif /* _PR_INET6 */
+ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n");
+ PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n");
+ PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n");
+ PR_fprintf(debug_out, "\t-h this message\n");
+} /* Help */
+
+static Verbosity IncrementVerbosity(void)
+{
+ PRIntn verboge = (PRIntn)verbosity + 1;
+ return (Verbosity)verboge;
+} /* IncrementVerbosity */
+
+PRIntn main(PRIntn argc, char** argv)
+{
+ PRUintn index;
+ PRBool boolean;
+ CSClient_t *client;
+ PRStatus rv, joinStatus;
+ CSServer_t *server = NULL;
+
+ PRUintn backlog = DEFAULT_BACKLOG;
+ PRUintn clients = DEFAULT_CLIENTS;
+ const char *serverName = DEFAULT_SERVER;
+ PRBool serverIsLocal = PR_TRUE;
+ PRUintn accepting = ALLOWED_IN_ACCEPT;
+ PRUintn workersMin = DEFAULT_WORKERS_MIN;
+ PRUintn workersMax = DEFAULT_WORKERS_MAX;
+ PRIntn execution = DEFAULT_EXECUTION_TIME;
+
+ /*
+ * -G use global threads
+ * -a <n> threads allowed in accept
+ * -b <n> backlock for listen
+ * -c <threads> number of clients to create
+ * -w <threads> minimal number of server threads
+ * -W <threads> maximum number of server threads
+ * -e <seconds> duration of the test in seconds
+ * -s <string> dsn name of server (implies no server here)
+ * -v verbosity
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:T:vdhp");
+
+ debug_out = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'X': /* use XTP as transport */
+ protocol = 36;
+ break;
+#ifdef _PR_INET6
+ case '6': /* Use IPv6 */
+ domain = AF_INET6;
+ PR_SetIPv6Enable(PR_TRUE);
+ break;
+#endif /* _PR_INET6 */
+ case 'a': /* the value for accepting */
+ accepting = atoi(opt->value);
+ break;
+ case 'b': /* the value for backlock */
+ backlog = atoi(opt->value);
+ break;
+ case 'T': /* the thread provider */
+ if ('n' == *opt->value) thread_provider = thread_nspr;
+ else if ('p' == *opt->value) thread_provider = thread_pthread;
+ else if ('w' == *opt->value) thread_provider = thread_win32;
+ else {Help(); return 2; }
+ break;
+ case 'c': /* number of client threads */
+ clients = atoi(opt->value);
+ break;
+ case 'w': /* minimum server worker threads */
+ workersMin = atoi(opt->value);
+ break;
+ case 'W': /* maximum server worker threads */
+ workersMax = atoi(opt->value);
+ break;
+ case 'e': /* program execution time in seconds */
+ execution = atoi(opt->value);
+ break;
+ case 's': /* server's address */
+ serverName = opt->value;
+ break;
+ case 'v': /* verbosity */
+ verbosity = IncrementVerbosity();
+ break;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'p': /* pthread mode */
+ pthread_stats = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE;
+ if (0 == execution) execution = DEFAULT_EXECUTION_TIME;
+ if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX;
+ if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN;
+ if (0 == accepting) accepting = ALLOWED_IN_ACCEPT;
+ if (0 == backlog) backlog = DEFAULT_BACKLOG;
+
+ if (workersMin > accepting) accepting = workersMin;
+
+ PR_STDIO_INIT();
+ TimeOfDayMessage("Client/Server started at", PR_CurrentThread());
+
+ cltsrv_log_file = PR_NewLogModule("cltsrv_log");
+ MY_ASSERT(NULL != cltsrv_log_file);
+ boolean = PR_SetLogFile("cltsrv.log");
+ MY_ASSERT(boolean);
+
+#ifdef XP_MAC
+ debug_mode = PR_TRUE;
+#endif
+
+ if (serverIsLocal)
+ {
+ /* Establish the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
+
+ server = PR_NEWZAP(CSServer_t);
+ PR_INIT_CLIST(&server->list);
+ server->state = cs_init;
+ server->ml = PR_NewLock();
+ server->backlog = backlog;
+ server->port = DEFAULT_PORT;
+ server->workers.minimum = workersMin;
+ server->workers.maximum = workersMax;
+ server->workers.accepting = accepting;
+ server->stateChange = PR_NewCondVar(server->ml);
+ server->pool.exiting = PR_NewCondVar(server->ml);
+ server->pool.acceptComplete = PR_NewCondVar(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
+
+ rv = NewThread(
+ Server, server, PR_PRIORITY_HIGH, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
+
+ PR_Lock(server->ml);
+ while (server->state == cs_init)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): server init complete (port #%d)\n",
+ PR_CurrentThread(), server->port));
+ }
+
+ if (clients != 0)
+ {
+ /* Create all of the clients */
+ PRHostEnt host;
+ char buffer[BUFFER_SIZE];
+ client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t));
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): creating %d client threads\n",
+ PR_CurrentThread(), clients));
+
+ if (!serverIsLocal)
+ {
+ rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(PR_STDERR, "PR_GetHostByName");
+ return 2;
+ }
+ }
+
+ for (index = 0; index < clients; ++index)
+ {
+ client[index].state = cs_init;
+ client[index].ml = PR_NewLock();
+ if (serverIsLocal)
+ {
+ (void)PR_InitializeNetAddr(
+ PR_IpAddrLoopback, DEFAULT_PORT,
+ &client[index].serverAddress);
+ }
+ else
+ {
+ (void)PR_EnumerateHostEnt(
+ 0, &host, DEFAULT_PORT, &client[index].serverAddress);
+ }
+ client[index].stateChange = PR_NewCondVar(client[index].ml);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
+ rv = NewThread(
+ Client, &client[index], PR_PRIORITY_NORMAL, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_Lock(client[index].ml);
+ while (cs_init == client[index].state)
+ PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(client[index].ml);
+ }
+ }
+
+ /* Then just let them go at it for a bit */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
+ PR_CurrentThread(), execution));
+
+ WaitForCompletion(execution);
+
+ TimeOfDayMessage("Shutting down", PR_CurrentThread());
+
+ if (clients != 0)
+ {
+ for (index = 0; index < clients; ++index)
+ {
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("main(0x%p): notifying client(0x%p) to stop\n",
+ PR_CurrentThread(), client[index].thread));
+
+ PR_Lock(client[index].ml);
+ if (cs_run == client[index].state)
+ {
+ client[index].state = cs_stop;
+ PR_Interrupt(client[index].thread);
+ while (cs_stop == client[index].state)
+ PR_WaitCondVar(
+ client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(client[index].ml);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): joining client(0x%p)\n",
+ PR_CurrentThread(), client[index].thread));
+
+ joinStatus = JoinThread(client[index].thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+ PR_DestroyCondVar(client[index].stateChange);
+ PR_DestroyLock(client[index].ml);
+ }
+ PR_DELETE(client);
+ }
+
+ if (NULL != server)
+ {
+ /* All clients joined - retrieve the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): notifying server(0x%p) to stop\n",
+ PR_CurrentThread(), server->thread));
+
+ PR_Lock(server->ml);
+ server->state = cs_stop;
+ PR_Interrupt(server->thread);
+ while (cs_exit != server->state)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): joining server(0x%p)\n",
+ PR_CurrentThread(), server->thread));
+ joinStatus = JoinThread(server->thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+
+ PR_DestroyCondVar(server->stateChange);
+ PR_DestroyCondVar(server->pool.exiting);
+ PR_DestroyCondVar(server->pool.acceptComplete);
+ PR_DestroyLock(server->ml);
+ PR_DELETE(server);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
+
+ PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+
+ TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ return 0;
+} /* main */
+
+/* cltsrv.c */
diff --git a/pr/tests/sel_spd.c b/pr/tests/sel_spd.c
index f4ce1483..b0033567 100644
--- a/pr/tests/sel_spd.c
+++ b/pr/tests/sel_spd.c
@@ -51,6 +51,9 @@ typedef struct timer_slot_t {
unsigned long requests;
} timer_slot_t;
+static long _iterations = 5;
+static long _client_data = 8192;
+
#if defined(XP_MAC)
/*
* Mac does not scale well specially the requirement for thread stack
@@ -58,22 +61,18 @@ typedef struct timer_slot_t {
* memory and not be able to allocate thread stack or client/server data
* buffer.
*/
+static long _server_data = (8*1024);
static long _threads_max = 10, _threads = 10;
-static long _iterations = 50;
-static long _client_data = 8192;
-static long _server_data = 8192;
#else
-static long _threads_max = 100, _threads = 100;
-static long _iterations = 1000;
-static long _client_data = 8192;
static long _server_data = (128*1024);
+static long _threads_max = 100, _threads = 100;
#endif
-static long _thread_exit_count;
+static int verbose=0;
static PRMonitor *exit_cv;
+static long _thread_exit_count;
static timer_slot_t *timer_data;
static PRThreadScope scope1, scope2;
-static int verbose=0;
void tally_results(int);
diff --git a/pr/tests/socket.c b/pr/tests/socket.c
index 33ce32bb..770d5f71 100644
--- a/pr/tests/socket.c
+++ b/pr/tests/socket.c
@@ -373,7 +373,7 @@ UDP_Server(void *arg)
PRFileDesc *sockfd;
buffer *in_buf;
PRNetAddr netaddr;
- PRInt32 bytes, i, rv;
+ PRInt32 bytes, i, rv = 0;
bytes = sp->datalen;
@@ -1046,7 +1046,6 @@ TransmitFile_Client(void *arg)
fprintf(stderr,
"prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
failed_already=1;
- return;
}
#endif
PR_DELETE(small_buf);
@@ -1518,8 +1517,8 @@ done:
PR_DELETE(buf);
}
#ifdef XP_UNIX
- munmap(small_file_addr, SMALL_FILE_SIZE);
- munmap(large_file_addr, LARGE_FILE_SIZE);
+ munmap((char*)small_file_addr, SMALL_FILE_SIZE);
+ munmap((char*)large_file_addr, LARGE_FILE_SIZE);
#endif
PR_Close(small_file_fd);
PR_Close(large_file_fd);
diff --git a/pr/tests/stack.c b/pr/tests/stack.c
new file mode 100644
index 00000000..d48e3ddb
--- /dev/null
+++ b/pr/tests/stack.c
@@ -0,0 +1,266 @@
+/* -*- 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.0 (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.
+ */
+
+
+/*
+ *
+ * Test atomic stack operations
+ *
+ * Two stacks are created and threads add data items (each containing
+ * one of the first n integers) to the first stack, remove data items
+ * from the first stack and add them to the second stack. The primordial
+ * thread compares the sum of the first n integers to the sum of the
+ * integers in the data items in the second stack. The test succeeds if
+ * they are equal.
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+typedef struct _DataRecord {
+ PRInt32 data;
+ PRStackElem link;
+} DataRecord;
+
+#define RECORD_LINK_PTR(lp) ((DataRecord*) ((char*) (lp) - offsetof(DataRecord,link)))
+
+#define MAX_THREAD_CNT 100
+#define DEFAULT_THREAD_CNT 4
+#define DEFAULT_DATA_CNT 4
+/*
+ * sum of the first n numbers using the formula n*(n+1)/2
+ */
+#define SUM_OF_NUMBERS(n) ((n & 1) ? (((n + 1)/2) * n) : ((n/2) * (n+1)))
+
+typedef struct stack_data {
+ PRStack *list1;
+ PRStack *list2;
+ PRInt32 initial_data_value;
+ PRInt32 data_cnt;
+} stack_data;
+
+static void stackop(void *arg);
+
+static int _debug_on;
+
+PRFileDesc *output;
+PRFileDesc *errhandle;
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRInt32 rv, cnt, sum;
+ DataRecord *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ PRStatus rc;
+
+ PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
+ PRInt32 data_cnt = DEFAULT_DATA_CNT;
+ PRThread **threads;
+ stack_data *thread_args;
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
+
+ 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;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ case 'c': /* data count */
+ data_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(4);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ errhandle = PR_GetSpecialFD(PR_StandardError);
+ list1 = PR_CreateStack("Stack_1");
+ if (list1 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+ list2 = PR_CreateStack("Stack_2");
+ if (list2 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
+ thread_args = (stack_data *) PR_CALLOC(sizeof(stack_data) * thread_cnt);
+
+ if (_debug_on)
+ PR_fprintf(output,"%s: thread_cnt = %d data_cnt = %d\n", argv[0],
+ thread_cnt, data_cnt);
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ PRThreadScope scope;
+
+ thread_args[cnt].list1 = list1;
+ thread_args[cnt].list2 = list2;
+ thread_args[cnt].data_cnt = data_cnt;
+ thread_args[cnt].initial_data_value = 1 + cnt * data_cnt;
+
+ if (cnt & 1)
+ scope = PR_GLOBAL_THREAD;
+ else
+ scope = PR_LOCAL_THREAD;
+
+
+ threads[cnt] = PR_CreateThread(PR_USER_THREAD,
+ stackop, &thread_args[cnt],
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (threads[cnt] == NULL) {
+ PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
+ PR_GetError());
+ PR_ProcessExit(2);
+ }
+ if (_debug_on)
+ PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
+ threads[cnt]);
+ }
+
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
+
+ node = PR_StackPop(list1);
+ /*
+ * list1 should be empty
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 1 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+
+ cnt = data_cnt * thread_cnt;
+ sum = 0;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list2);
+ /*
+ * There should be at least 'cnt' number of records
+ */
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ProcessExit(3);
+ }
+ Item = RECORD_LINK_PTR(node);
+ sum += Item->data;
+ }
+ node = PR_StackPop(list2);
+ /*
+ * there should be exactly 'cnt' number of records
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 2 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+ PR_DELETE(threads);
+ PR_DELETE(thread_args);
+
+ PR_DestroyStack(list1);
+ PR_DestroyStack(list2);
+
+ if (sum == SUM_OF_NUMBERS(data_cnt * thread_cnt)) {
+ PR_fprintf(output, "%s successful\n", argv[0]);
+ PR_fprintf(output, "\t\tsum = 0x%x, expected = 0x%x\n", sum,
+ SUM_OF_NUMBERS(thread_cnt * data_cnt));
+ return 0;
+ } else {
+ PR_fprintf(output, "%s failed: sum = 0x%x, expected = 0x%x\n",
+ argv[0], sum,
+ SUM_OF_NUMBERS(data_cnt * thread_cnt));
+ return 2;
+ }
+}
+
+static void stackop(void *thread_arg)
+{
+ PRInt32 val, cnt, index;
+ DataRecord *Items, *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ stack_data *arg = (stack_data *) thread_arg;
+
+ val = arg->initial_data_value;
+ cnt = arg->data_cnt;
+ list1 = arg->list1;
+ list2 = arg->list2;
+
+ /*
+ * allocate memory for the data records
+ */
+ Items = (DataRecord *) PR_CALLOC(sizeof(DataRecord) * cnt);
+ PR_ASSERT(Items != NULL);
+ index = 0;
+
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d data1 = 0x%x datan = 0x%x\n",
+ PR_GetCurrentThread(), val, cnt, &Items[0], &Items[cnt-1]);
+
+
+ /*
+ * add the data records to list1
+ */
+ while (cnt-- > 0) {
+ Items[index].data = val++;
+ PR_StackPush(list1, &Items[index].link);
+ index++;
+ }
+
+ /*
+ * remove the data records from list1 and add them to list2
+ */
+ cnt = arg->data_cnt;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list1);
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ASSERT(node != NULL);
+ PR_ProcessExit(3);
+ }
+ PR_StackPush(list2, node);
+ }
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d exiting\n",
+ PR_GetCurrentThread(), val, cnt);
+
+}
+
diff --git a/pr/tests/switch.c b/pr/tests/switch.c
index 131260fc..878d7d15 100644
--- a/pr/tests/switch.c
+++ b/pr/tests/switch.c
@@ -63,14 +63,14 @@ static void Help(void)
debug_out = PR_STDOUT;
PR_fprintf(
- debug_out, "Usage: >./switch [-d] [-c n] [-t n] [-T n] [-G]\n");
+ debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
PR_fprintf(
debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
PR_fprintf(
debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
- PR_fprintf(debug_out, "-G n\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
} /* Help */
diff --git a/pr/tests/testfile.c b/pr/tests/testfile.c
index d492a0ff..2f5129d4 100644
--- a/pr/tests/testfile.c
+++ b/pr/tests/testfile.c
@@ -44,7 +44,6 @@ extern void SetupMacPrintfLog(char *logFile);
PRLock *lock;
PRMonitor *mon;
-PRMonitor *mon2;
PRInt32 count;
int thread_count;
@@ -108,11 +107,12 @@ int offset, len;
}
DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf))));
PR_Close(fd_file);
+ PR_DELETE(fp);
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
--thread_count;
- PR_Notify(mon2);
- PR_ExitMonitor(mon2);
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
}
static void PR_CALLBACK File_Read(void *arg)
@@ -143,11 +143,12 @@ int offset, len;
}
DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf))));
PR_Close(fd_file);
+ PR_DELETE(fp);
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
--thread_count;
- PR_Notify(mon2);
- PR_ExitMonitor(mon2);
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
}
@@ -295,6 +296,7 @@ static PRInt32 PR_CALLBACK FileTest(void)
PRDir *fd_dir;
int i, offset, len;
PRThread *t;
+PRThreadScope scope;
File_Rdwr_Param *fparamp;
/*
@@ -334,12 +336,7 @@ File_Rdwr_Param *fparamp;
*/
offset = 0;
len = CHUNK_SIZE;
- mon2 = PR_NewMonitor();
- if (mon2 == NULL) {
- printf("testfile: PR_NewMonitor failed\n");
- return -1;
- }
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
for (i = 0; i < NUM_RDWR_THREADS; i++) {
fparamp = PR_NEW(File_Rdwr_Param);
if (fparamp == NULL) {
@@ -356,27 +353,24 @@ File_Rdwr_Param *fparamp;
* Create LOCAL and GLOBAL Threads, alternately
*/
if (i % 1)
- t = PR_CreateThread(PR_USER_THREAD,
- File_Write, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_GLOBAL_THREAD;
else
- t = PR_CreateThread(PR_USER_THREAD,
- File_Write, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_LOCAL_THREAD;
+
+ t = PR_CreateThread(PR_USER_THREAD,
+ File_Write, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
offset += len;
}
thread_count = i;
/* Wait for writer threads to exit */
while (thread_count) {
- PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
}
- PR_ExitMonitor(mon2);
+ PR_ExitMonitor(mon);
/*
@@ -384,7 +378,7 @@ File_Rdwr_Param *fparamp;
*/
offset = 0;
len = CHUNK_SIZE;
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
for (i = 0; i < NUM_RDWR_THREADS; i++) {
fparamp = PR_NEW(File_Rdwr_Param);
if (fparamp == NULL) {
@@ -400,19 +394,16 @@ File_Rdwr_Param *fparamp;
* Create LOCAL and GLOBAL Threads, alternately
*/
if (i % 1)
- t = PR_CreateThread(PR_USER_THREAD,
- File_Read, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_LOCAL_THREAD;
else
- t = PR_CreateThread(PR_USER_THREAD,
- File_Read, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_GLOBAL_THREAD;
+
+ t = PR_CreateThread(PR_USER_THREAD,
+ File_Read, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
offset += len;
if ((offset + len) > BUF_DATA_SIZE)
break;
@@ -421,9 +412,9 @@ File_Rdwr_Param *fparamp;
/* Wait for reader threads to exit */
while (thread_count) {
- PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
}
- PR_ExitMonitor(mon2);
+ PR_ExitMonitor(mon);
if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
printf("File Test failed: file data corrupted\n");
@@ -759,7 +750,7 @@ HANDLE hfile;
* Test file and directory NSPR APIs
*/
-void main(int argc, char **argv)
+int main(int argc, char **argv)
{
#ifdef XP_UNIX
int opt;
@@ -784,7 +775,11 @@ void main(int argc, char **argv)
SetupMacPrintfLog("testfile.log");
#endif
- mon2 = PR_NewMonitor();
+ mon = PR_NewMonitor();
+ if (mon == NULL) {
+ printf("testfile: PR_NewMonitor failed\n");
+ exit(2);
+ }
if (FileTest() < 0) {
printf("File Test failed\n");
@@ -798,5 +793,7 @@ void main(int argc, char **argv)
}
printf("Dir Test passed\n");
+ PR_DestroyMonitor(mon);
PR_Cleanup();
+ return 0;
}
diff --git a/pr/tests/tpd.c b/pr/tests/tpd.c
index 9afce87c..786948e4 100644
--- a/pr/tests/tpd.c
+++ b/pr/tests/tpd.c
@@ -21,6 +21,7 @@
** Description: Exercising the thread private data bailywick.
*/
+#include "prmem.h"
#include "prinit.h"
#include "prlog.h"
#include "prprf.h"
@@ -42,18 +43,20 @@ static PRBool should = PR_TRUE;
static PRBool did = PR_TRUE;
static PRFileDesc *fout = NULL;
-static void PrintProgress(void)
+static void PrintProgress(PRIntn line)
{
+ failed = failed || (should && !did);
+ failed = failed || (!should && did);
if (debug > 0)
{
#if defined(WIN16)
printf(
- "Destructor should %s have been called and was%s\n",
- ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+ "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
#else
PR_fprintf(
- fout, "Destructor should %s have been called and was%s\n",
- ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+ fout, "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
#endif
}
} /* PrintProgress */
@@ -70,10 +73,15 @@ static void MyAssert(const char *expr, const char *file, PRIntn line)
static void PR_CALLBACK Destructor(void *data)
{
+ MY_ASSERT(NULL != data);
if (should) did = PR_TRUE;
else failed = PR_TRUE;
- MY_ASSERT(NULL != data);
- if (debug > 0) MyAssert((const char*)data, __FILE__, __LINE__);
+ /*
+ * We don't actually free the storage since it's actually allocated
+ * on the stack. Normally, this would not be the case and this is
+ * the opportunity to free whatever.
+ PR_Free(data);
+ */
} /* Destructor */
static void PR_CALLBACK Thread(void *null)
@@ -91,24 +99,24 @@ static void PR_CALLBACK Thread(void *null)
pd = PR_GetThreadPrivate(key[keys]);
MY_ASSERT(NULL == pd);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#if !defined(DEBUG)
did = should = PR_FALSE;
for (keys = 4; keys < 8; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_FAILURE == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#endif
did = PR_FALSE; should = PR_TRUE;
@@ -117,7 +125,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 0; keys < 4; ++keys)
@@ -125,7 +133,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
@@ -133,7 +141,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -141,7 +149,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 8; keys < 127; ++keys)
@@ -149,7 +157,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -157,6 +165,17 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
+
+ /* put in keys and leave them there for thread exit */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+ did = PR_FALSE; should = PR_TRUE;
+
} /* Thread */
static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
@@ -177,7 +196,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 8; ++keys)
@@ -185,24 +204,24 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
pd = PR_GetThreadPrivate(key[keys]);
MY_ASSERT(NULL == pd);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#if !defined(DEBUG)
did = should = PR_FALSE;
for (keys = 4; keys < 8; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_FAILURE == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#endif
did = PR_FALSE; should = PR_TRUE;
@@ -211,7 +230,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 0; keys < 4; ++keys)
@@ -219,7 +238,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
@@ -227,7 +246,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -237,7 +256,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 8; keys < 127; ++keys)
@@ -245,7 +264,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -260,6 +279,8 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
(void)PR_JoinThread(thread);
+ PrintProgress(__LINE__);
+
#if defined(WIN16)
printf(
"%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
diff --git a/pr/tests/udpsrv.c b/pr/tests/udpsrv.c
index 4e9292d1..d45421d4 100644
--- a/pr/tests/udpsrv.c
+++ b/pr/tests/udpsrv.c
@@ -64,13 +64,6 @@
#include <string.h>
#include <errno.h>
-/* --- manifest constants --- */
-#ifdef XP_MAC
-#define fprintf(a,b) printf(b)
-#include "prlog.h"
-#define printf PR_LogPrint
-#endif
-
#ifdef XP_PC
#define mode_t int
#endif
@@ -93,12 +86,13 @@ static PRIntn _debug_on = 0;
static PRBool passed = PR_TRUE;
static PRUint32 cltBytesRead = 0;
static PRUint32 srvBytesRead = 0;
+static PRFileDesc *output = NULL;
/* --- static function declarations --- */
-#define DPRINTF(arg) if (_debug_on) printf(arg)
+#define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
+
-
/*******************************************************************
** ListNetAddr() -- Display the Net Address on stdout
**
@@ -122,7 +116,7 @@ void ListNetAddr( char *msg, PRNetAddr *na )
DPRINTF( mbuf );
#endif
} /* --- end ListNetAddr() --- */
-
+
/********************************************************************
** UDP_Server() -- Test a UDP server application
**
@@ -155,7 +149,9 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( svrSock == NULL )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
return;
}
@@ -174,7 +170,7 @@ static void PR_CALLBACK UDP_Server( void *arg )
{
if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
{
- if (debug_mode) printf("udpsrv: UDP_Server(): \
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
PR_Sleep( PR_MillisecondsToInterval( 2000 ));
continue;
@@ -182,7 +178,7 @@ static void PR_CALLBACK UDP_Server( void *arg )
else
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): \
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
PR_Bind(): failed: %ld with error: %ld\n",
rv, PR_GetError() );
PR_Close( svrSock );
@@ -202,8 +198,10 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
- PR_GetError() );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
+ PR_GetError() );
PR_Close( svrSock );
return;
}
@@ -223,8 +221,10 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
- PR_GetError() );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
+ PR_GetError() );
PR_Close( svrSock );
return;
}
@@ -237,14 +237,16 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv != PR_SUCCESS )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
return;
}
DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
} /* --- end UDP_Server() --- */
-
+
static char cltBuf[UDP_BUF_SIZE];
static char cltBufin[UDP_BUF_SIZE];
/********************************************************************
@@ -284,7 +286,9 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( cltSock == NULL )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
return;
}
@@ -307,14 +311,18 @@ static void PR_CALLBACK UDP_Client( void *arg )
{
if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
{
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
PR_Sleep( PR_MillisecondsToInterval( 2000 ));
continue;
}
else
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
rv, PR_GetError() );
PR_Close( cltSock );
return;
@@ -352,7 +360,7 @@ static void PR_CALLBACK UDP_Client( void *arg )
writeThisMany -= numBytes;
{
char mbuf[256];
- sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %ld, numbytes: %ld\n",
+ sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n",
writeThisMany, numBytes );
DPRINTF( mbuf );
}
@@ -362,7 +370,9 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
PR_GetError() );
PR_Close( cltSock );
return;
@@ -376,7 +386,8 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
PR_GetError() );
PR_Close( cltSock );
return;
@@ -393,12 +404,13 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
continue;
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): return data mismatch\n" );
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): return data mismatch\n" );
PR_Close( cltSock );
return;
}
}
- if (debug_mode) printf(".");
+ if (debug_mode) PR_fprintf(output, ".");
}
/* --- Close the socket --- */
@@ -407,12 +419,13 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv != PR_SUCCESS )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
return;
}
DPRINTF("udpsrv: UDP_Client(): ending\n" );
} /* --- end UDP_Client() --- */
-
+
/********************************************************************
** main() -- udpsrv
**
@@ -461,6 +474,7 @@ int main(int argc, char **argv)
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
PR_STDIO_INIT();
+ output = PR_STDERR;
#ifdef XP_MAC
SetupMacPrintfLog("udpsrv.log");
@@ -481,7 +495,7 @@ int main(int argc, char **argv)
0 );
if ( srv == NULL )
{
- if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
passed = PR_FALSE;
}
@@ -504,7 +518,7 @@ int main(int argc, char **argv)
0 );
if ( clt == NULL )
{
- if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
passed = PR_FALSE;
}
@@ -518,7 +532,7 @@ int main(int argc, char **argv)
/*
** Evaluate test results
*/
- if (debug_mode) printf( "\n\nudpsrv: main(): cltBytesRead(%ld), \
+ if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
srvBytesRead(%ld), expected(%ld)\n",
cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
diff --git a/pr/tests/version.c b/pr/tests/version.c
new file mode 100644
index 00000000..c5c3013d
--- /dev/null
+++ b/pr/tests/version.c
@@ -0,0 +1,101 @@
+/* -*- 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.0 (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.
+ */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlink.h"
+#include "prvrsion.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv = 1;
+ PLOptStatus os;
+ PRIntn verbosity = 0;
+ PRLibrary *runtime = NULL;
+ const char *library_name = NULL;
+ const PRVersionDescription *version_info;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* fully qualified library name */
+ library_name = opt->value;
+ break;
+ case 'd': /* verbodity */
+ verbosity += 1;
+ break;
+ default:
+ PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n");
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (NULL == library_name)
+ PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n");
+ else
+ {
+ runtime = PR_LoadLibrary(library_name);
+ if (NULL == runtime) PL_FPrintError(err, "PR_LoadLibrary");
+ else
+ {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint) PL_FPrintError(err, "PR_FindSymbol");
+ else
+ {
+ char buffer[100];
+ PRExplodedTime exploded;
+ version_info = versionPoint();
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ rv = 0;
+ }
+ }
+ }
+ return rv;
+}
+
+/* version.c */