Skip to content

Commit 3b81b97

Browse files
author
Shane Caraveo
committed
an update to stresstest
1 parent cb2124b commit 3b81b97

File tree

2 files changed

+128
-37
lines changed

2 files changed

+128
-37
lines changed

sapi/isapi/stresstest/stresstest.cpp

Lines changed: 118 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <httpext.h>
1515
#include <stdio.h>
1616
#include <stdlib.h>
17+
#include "getopt.h"
1718

1819
// These are things that go out in the Response Header
1920
//
@@ -29,8 +30,9 @@
2930
//
3031
// The mandatory exports from the ISAPI DLL
3132
//
32-
#define NUM_THREADS 10
33-
#define ITERATIONS 1
33+
DWORD numThreads = 1;
34+
DWORD iterations = 1;
35+
3436
HANDLE StartNow;
3537
// quick and dirty environment
3638
typedef CMapStringToString TEnvironment;
@@ -53,6 +55,7 @@ typedef struct _TIsapiContext {
5355
HANDLE out;
5456
DWORD tid;
5557
TEnvironment env;
58+
HANDLE waitEvent;
5659
} TIsapiContext;
5760

5861
//
@@ -62,13 +65,15 @@ extern "C" {
6265
HINSTANCE hDll;
6366
typedef BOOL (WINAPI *VersionProc)(HSE_VERSION_INFO *) ;
6467
typedef DWORD (WINAPI *HttpExtProc)(EXTENSION_CONTROL_BLOCK *);
68+
typedef BOOL (WINAPI *TerminateProc) (DWORD);
6569
BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *, TIsapiContext *) ;
6670
BOOL WINAPI GetServerVariable(HCONN, LPSTR, LPVOID, LPDWORD );
6771
BOOL WINAPI ReadClient(HCONN, LPVOID, LPDWORD);
6872
BOOL WINAPI WriteClient(HCONN, LPVOID, LPDWORD, DWORD);
6973
BOOL WINAPI ServerSupportFunction(HCONN, DWORD, LPVOID, LPDWORD, LPDWORD);
7074
VersionProc IsapiGetExtensionVersion;
7175
HttpExtProc IsapiHttpExtensionProc;
76+
TerminateProc TerminateExtensionProc;
7277
HSE_VERSION_INFO version_info;
7378
}
7479

@@ -153,8 +158,9 @@ BOOL CompareStringWithFile(const char *filename, const char *str, unsigned int s
153158
bool retval;
154159
char buf[COMPARE_BUF_SIZE];
155160
unsigned int offset=0, readbytes;
156-
157-
if ((fp=fopen(filename, "r"))==NULL) {
161+
fprintf(stderr, "test %s\n",filename);
162+
if ((fp=fopen(filename, "rb"))==NULL) {
163+
fprintf(stderr, "Error opening %s\n",filename);
158164
return FALSE;
159165
}
160166

@@ -163,15 +169,17 @@ BOOL CompareStringWithFile(const char *filename, const char *str, unsigned int s
163169
readbytes = fread(buf, 1, sizeof(buf), fp);
164170

165171
// check for end of file
166-
if (feof(fp)) {
167-
break;
168-
}
169172

170173
if (offset+readbytes > str_length
171174
|| memcmp(buf, str+offset, readbytes)!=NULL) {
175+
fprintf(stderr, "File missmatch %s\n",filename);
172176
retval = FALSE;
173177
break;
174178
}
179+
if (feof(fp)) {
180+
if (!retval) fprintf(stderr, "File zero length %s\n",filename);
181+
break;
182+
}
175183
}
176184
fclose(fp);
177185

@@ -250,15 +258,20 @@ void DoThreads() {
250258
printf("Starting Threads...\n");
251259
// loop creating threads
252260
DWORD tid;
253-
HANDLE threads[NUM_THREADS];
254-
for (DWORD i=0; i< NUM_THREADS; i++) {
261+
HANDLE *threads = new HANDLE[numThreads];
262+
DWORD i;
263+
for (i=0; i< numThreads; i++) {
255264
threads[i]=CreateThread(NULL, 0, IsapiThread, NULL, CREATE_SUSPENDED, &tid);
256265
}
257-
for (i=0; i< NUM_THREADS; i++) {
266+
for (i=0; i< numThreads; i++) {
258267
if (threads[i]) ResumeThread(threads[i]);
259268
}
260269
// wait for threads to finish
261-
WaitForMultipleObjects(NUM_THREADS, threads, TRUE, INFINITE);
270+
WaitForMultipleObjects(numThreads, threads, TRUE, INFINITE);
271+
for (i=0; i< numThreads; i++) {
272+
CloseHandle(threads[i]);
273+
}
274+
delete threads;
262275
}
263276

264277
void DoFileList(const char *filelist, const char *environment)
@@ -292,11 +305,11 @@ BOOL ParseTestFile(const char *path, const char *fn)
292305

293306
enum state {none, test, skipif, post, get, file, expect} parsestate = none;
294307

295-
FILE *fp = fopen(filename, "r");
308+
FILE *fp = fopen(filename, "rb");
296309
char *tn = _tempnam(temppath,"pht.");
297310
char *en = _tempnam(temppath,"exp.");
298-
FILE *ft = fopen(tn, "w+");
299-
FILE *fe = fopen(en, "w+");
311+
FILE *ft = fopen(tn, "wb+");
312+
FILE *fe = fopen(en, "wb+");
300313
if (fp && ft && fe) {
301314
while (fgets(line, sizeof(line)-1, fp)) {
302315
if (line[0]=='-') {
@@ -353,9 +366,13 @@ BOOL ParseTestFile(const char *path, const char *fn)
353366
IsapiGetData.Add(cGet);
354367
IsapiPostData.Add(cPost);
355368
IsapiMatchData.Add(en);
369+
free(tn);
370+
free(en);
356371
return TRUE;
357372
}
358373
}
374+
free(tn);
375+
free(en);
359376
return FALSE;
360377
}
361378

@@ -441,23 +458,66 @@ void DoTestFiles(const char *filelist, const char *environment)
441458
printf("Done\r\n");
442459
}
443460

444-
int main(int argc, char* argv[])
461+
#define OPTSTRING "m:f:d:h:t:i:"
462+
static void _usage(char *argv0)
445463
{
446-
LPVOID lpMsgBuf;
447-
char *filelist=NULL, *environment=NULL;
464+
char *prog;
448465

449-
if (argc < 3) {
450-
// look for phpt files in tests
451-
printf("USAGE: stresstest [L|T] filelist [environment]\r\n");
452-
return 0;
466+
prog = strrchr(argv0, '/');
467+
if (prog) {
468+
prog++;
453469
} else {
454-
if (argv[1][0]=='T') bUseTestFiles = TRUE;
455-
if (argc > 1) filelist = argv[2];
456-
if (argc > 2) environment = argv[3];
470+
prog = "stresstest";
471+
}
472+
473+
printf("Usage: %s -m <isapi.dll> -d|-l <file> [-t <numthreads>] [-i <numiterations>]\n"
474+
" -m path to isapi dll\n"
475+
" -d <directory> php directory (to run php test files).\n"
476+
" -f <file> file containing list of files to run\n"
477+
" -t number of threads to use (default=1)\n"
478+
" -i number of iterations per thread (default=1)\n"
479+
" -h This help\n", prog);
480+
}
481+
int main(int argc, char* argv[])
482+
{
483+
LPVOID lpMsgBuf;
484+
char *filelist=NULL, *environment=NULL, *module=NULL;
485+
int c = NULL;
486+
while ((c=ap_getopt(argc, argv, OPTSTRING))!=-1) {
487+
switch (c) {
488+
case 'd':
489+
bUseTestFiles = TRUE;
490+
filelist = strdup(ap_optarg);
491+
break;
492+
case 'f':
493+
bUseTestFiles = FALSE;
494+
filelist = strdup(ap_optarg);
495+
break;
496+
case 'e':
497+
environment = strdup(ap_optarg);
498+
break;
499+
case 't':
500+
numThreads = atoi(ap_optarg);
501+
break;
502+
case 'i':
503+
iterations = atoi(ap_optarg);
504+
break;
505+
case 'm':
506+
module = strdup(ap_optarg);
507+
break;
508+
case 'h':
509+
_usage(argv[0]);
510+
exit(0);
511+
break;
512+
}
513+
}
514+
if (!module || !filelist) {
515+
_usage(argv[0]);
516+
exit(0);
457517
}
458518

459519
GetTempPath(sizeof(temppath), temppath);
460-
hDll = LoadLibrary("php4isapi.dll"); // Load our DLL
520+
hDll = LoadLibrary(module); // Load our DLL
461521

462522
if (!hDll) {
463523
FormatMessage(
@@ -470,6 +530,8 @@ int main(int argc, char* argv[])
470530
NULL
471531
);
472532
fprintf(stderr,"Error: Dll 'php4isapi.dll' not found -%d\n%s\n", GetLastError(), lpMsgBuf);
533+
free (module);
534+
free(filelist);
473535
LocalFree( lpMsgBuf );
474536
return -1;
475537
}
@@ -480,19 +542,27 @@ int main(int argc, char* argv[])
480542
IsapiGetExtensionVersion = (VersionProc)GetProcAddress(hDll,"GetExtensionVersion");
481543
if (!IsapiGetExtensionVersion) {
482544
fprintf(stderr,"Can't Get Extension Version %d\n", GetLastError());
545+
free (module);
546+
free(filelist);
483547
return -1;
484548
}
485549
IsapiHttpExtensionProc = (HttpExtProc)GetProcAddress(hDll,"HttpExtensionProc");
486550
if (!IsapiHttpExtensionProc) {
487551
fprintf(stderr,"Can't Get Extension proc %d\n", GetLastError());
552+
free (module);
553+
free(filelist);
488554
return -1;
489555
}
556+
TerminateExtensionProc = (TerminateProc) GetProcAddress(hDll,
557+
"TerminateExtension");
490558

491559
// This should really check if the version information matches what we
492560
// expect.
493561
//
494562
if (!IsapiGetExtensionVersion(&version_info) ) {
495563
fprintf(stderr,"Fatal: GetExtensionVersion failed\n");
564+
free (module);
565+
free(filelist);
496566
return -1;
497567
}
498568

@@ -507,12 +577,14 @@ int main(int argc, char* argv[])
507577
}
508578

509579
// cleanup
510-
580+
if (TerminateExtensionProc) TerminateExtensionProc(0);
511581

512582
// We should really free memory (e.g., from GetEnv), but we'll be dead
513583
// soon enough
514584

515585
FreeLibrary(hDll);
586+
free (module);
587+
free(filelist);
516588
return 0;
517589
}
518590

@@ -521,7 +593,7 @@ DWORD CALLBACK IsapiThread(void *p)
521593
{
522594
DWORD filecount = IsapiFileList.GetSize();
523595

524-
for (DWORD j=0; j<ITERATIONS; j++) {
596+
for (DWORD j=0; j<iterations; j++) {
525597
for (DWORD i=0; i<filecount; i++) {
526598
// execute each file
527599
CString testname = TestNames.GetAt(i);
@@ -572,7 +644,7 @@ BOOL stress_main(const char *filename,
572644
CString fname;
573645
fname.Format("%08X.out", context.tid);
574646

575-
context.out = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
647+
context.out = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
576648
if (context.out==INVALID_HANDLE_VALUE) {
577649
printf("failed to open output file %s\n", fname);
578650
return 0;
@@ -600,7 +672,8 @@ BOOL stress_main(const char *filename,
600672
context.env["CONTENT_LENGTH"]= "";
601673
context.env["QUERY_STRING"]= arg;
602674
context.env["METHOD"]="GET";
603-
675+
context.env["PATH_INFO"] = "";
676+
context.waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
604677
char buf[MAX_PATH];
605678
if (postdata && *postdata !=0) {
606679
ECB.cbAvailable = strlen(postdata);
@@ -613,28 +686,36 @@ BOOL stress_main(const char *filename,
613686

614687
context.env["CONTENT_TYPE"]="application/x-www-form-urlencoded";
615688
}
689+
ECB.lpszMethod = strdup(context.env["METHOD"]);
616690
ECB.lpszPathTranslated = strdup(filename);
617691
ECB.lpszQueryString = strdup(arg);
692+
ECB.lpszPathInfo = strdup(context.env["PATH_INFO"]);
693+
618694

619695
// Call the DLL
620696
//
621697
rc = IsapiHttpExtensionProc(&ECB);
622-
698+
if (rc == HSE_STATUS_PENDING) {
699+
// We will exit in ServerSupportFunction
700+
WaitForSingleObject(context.waitEvent, INFINITE);
701+
}
702+
CloseHandle(context.waitEvent);
703+
//Sleep(75);
623704
free(ECB.lpszPathTranslated);
624705
free(ECB.lpszQueryString);
706+
free(ECB.lpszMethod);
707+
free(ECB.lpszPathInfo);
625708

626709
BOOL ok = TRUE;
627710

628711
if (context.out != INVALID_HANDLE_VALUE) CloseHandle(context.out);
629712

630713
// compare the output with the EXPECT section
631714
if (matchdata && *matchdata != 0) {
632-
ok = CompareStringWithFile(fname, matchdata, strlen(matchdata));
715+
ok = CompareFiles(fname, matchdata);
633716
}
634717

635718
DeleteFile(fname);
636-
//if (rc == HSE_STATUS_PENDING) // We will exit in ServerSupportFunction
637-
// Sleep(INFINITE);
638719

639720
return ok;
640721

@@ -696,9 +777,8 @@ BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize,
696777
TIsapiContext *c = (TIsapiContext *)hConn;
697778
if (!c) return FALSE;
698779

699-
if (c->out != INVALID_HANDLE_VALUE)
780+
if (c->out != INVALID_HANDLE_VALUE)
700781
return WriteFile(c->out, lpBuffer, *lpdwSize, lpdwSize, NULL);
701-
702782
return FALSE;
703783
}
704784
//
@@ -708,10 +788,11 @@ BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize,
708788
BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest,
709789
LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){
710790

791+
TIsapiContext *c = (TIsapiContext *)hConn;
711792
char *lpszRespBuf;
712793
char * temp = NULL;
713794
DWORD dwBytes;
714-
BOOL bRet;
795+
BOOL bRet = TRUE;
715796

716797
switch(dwHSERequest) {
717798
case (HSE_REQ_SEND_RESPONSE_HEADER) :
@@ -744,6 +825,7 @@ BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest,
744825
//
745826
// A real server would do cleanup here
746827
case (HSE_REQ_DONE_WITH_SESSION):
828+
SetEvent(c->waitEvent);
747829
//ExitThread(0);
748830
break;
749831

sapi/isapi/stresstest/stresstest.dsp

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)