📄 stresstest.cpp
字号:
prog = "stresstest"; } printf("Usage: %s -m <isapi.dll> -d|-l <file> [-t <numthreads>] [-i <numiterations>]\n" " -m path to isapi dll\n" " -d <directory> php directory (to run php test files).\n" " -f <file> file containing list of files to run\n" " -t number of threads to use (default=1)\n" " -i number of iterations per thread (default=1)\n" " -h This help\n", prog);}int main(int argc, char* argv[]){ LPVOID lpMsgBuf; char *filelist=NULL, *environment=NULL, *module=NULL; int c = NULL; while ((c=ap_getopt(argc, argv, OPTSTRING))!=-1) { switch (c) { case 'd': bUseTestFiles = TRUE; filelist = strdup(ap_optarg); break; case 'f': bUseTestFiles = FALSE; filelist = strdup(ap_optarg); break; case 'e': environment = strdup(ap_optarg); break; case 't': numThreads = atoi(ap_optarg); break; case 'i': iterations = atoi(ap_optarg); break; case 'm': module = strdup(ap_optarg); break; case 'h': _usage(argv[0]); exit(0); break; } } if (!module || !filelist) { _usage(argv[0]); exit(0); } GetTempPath(sizeof(temppath), temppath); hDll = LoadLibrary(module); // Load our DLL if (!hDll) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"Error: Dll 'php5isapi.dll' not found -%d\n%s\n", GetLastError(), lpMsgBuf); free (module); free(filelist); LocalFree( lpMsgBuf ); return -1; } // // Find the exported functions IsapiGetExtensionVersion = (VersionProc)GetProcAddress(hDll,"GetExtensionVersion"); if (!IsapiGetExtensionVersion) { fprintf(stderr,"Can't Get Extension Version %d\n", GetLastError()); free (module); free(filelist); return -1; } IsapiHttpExtensionProc = (HttpExtProc)GetProcAddress(hDll,"HttpExtensionProc"); if (!IsapiHttpExtensionProc) { fprintf(stderr,"Can't Get Extension proc %d\n", GetLastError()); free (module); free(filelist); return -1; } TerminateExtensionProc = (TerminateProc) GetProcAddress(hDll, "TerminateExtension"); // This should really check if the version information matches what we // expect. // if (!IsapiGetExtensionVersion(&version_info) ) { fprintf(stderr,"Fatal: GetExtensionVersion failed\n"); free (module); free(filelist); return -1; } if (bUseTestFiles) { char TestPath[MAX_PATH]; if (filelist != NULL) _snprintf(TestPath, sizeof(TestPath)-1, "%s\\tests", filelist); else strcpy(TestPath, "tests"); DoTestFiles(TestPath, environment); } else { DoFileList(filelist, environment); } // cleanup if (TerminateExtensionProc) TerminateExtensionProc(0); // We should really free memory (e.g., from GetEnv), but we'll be dead // soon enough FreeLibrary(hDll); free (module); free(filelist); return 0;}DWORD CALLBACK IsapiThread(void *p){ DWORD filecount = IsapiFileList.GetSize(); for (DWORD j=0; j<iterations; j++) { for (DWORD i=0; i<filecount; i++) { // execute each file CString testname = TestNames.GetAt(i); BOOL ok = FALSE; if (stress_main(IsapiFileList.GetAt(i), IsapiGetData.GetAt(i), IsapiPostData.GetAt(i), IsapiMatchData.GetAt(i))) { InterlockedIncrement(&Results[i].ok); ok = TRUE; } else { InterlockedIncrement(&Results[i].bad); ok = FALSE; } if (testname.IsEmpty()) { printf("Thread %d File %s\n", GetCurrentThreadId(), IsapiFileList.GetAt(i)); } else { printf("tid %d: %s %s\n", GetCurrentThreadId(), testname, ok?"OK":"FAIL"); } Sleep(10); } } printf("Thread ending...\n"); return 0;}/* * ======================================================================= * * In the startup of this program, we look at our executable name and * * replace the ".EXE" with ".DLL" to find the ISAPI DLL we need to load. * * This means that the executable need only be given the same "name" as * * the DLL to load. There is no recompilation required. * * ======================================================================= **/BOOL stress_main(const char *filename, const char *arg, const char *postdata, const char *matchdata) { EXTENSION_CONTROL_BLOCK ECB; DWORD rc; TIsapiContext context; // open output and input files context.tid = GetCurrentThreadId(); CString fname; fname.Format("%08X.out", context.tid); context.out = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); if (context.out==INVALID_HANDLE_VALUE) { printf("failed to open output file %s\n", fname); return 0; } // not using post files context.in = INVALID_HANDLE_VALUE; // // Fill the ECB with the necessary information // if (!FillExtensionControlBlock(&ECB, &context) ) { fprintf(stderr,"Fill Ext Block Failed\n"); return -1; } // check for command line argument, // first arg = filename // this is added for testing php from command line context.env.RemoveAll(); context.env["PATH_TRANSLATED"]= filename; context.env["SCRIPT_MAP"]= filename; context.env["CONTENT_TYPE"]= ""; context.env["CONTENT_LENGTH"]= ""; context.env["QUERY_STRING"]= arg; context.env["METHOD"]="GET"; context.env["PATH_INFO"] = ""; context.waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); char buf[MAX_PATH]; if (postdata && *postdata !=0) { ECB.cbAvailable = strlen(postdata); ECB.cbTotalBytes = ECB.cbAvailable; ECB.lpbData = (unsigned char *)postdata; context.env["METHOD"]="POST"; _snprintf(buf, sizeof(buf)-1, "%d", ECB.cbTotalBytes); context.env["CONTENT_LENGTH"]=buf; context.env["CONTENT_TYPE"]="application/x-www-form-urlencoded"; } ECB.lpszMethod = strdup(context.env["METHOD"]); ECB.lpszPathTranslated = strdup(filename); ECB.lpszQueryString = strdup(arg); ECB.lpszPathInfo = strdup(context.env["PATH_INFO"]); // Call the DLL // rc = IsapiHttpExtensionProc(&ECB); if (rc == HSE_STATUS_PENDING) { // We will exit in ServerSupportFunction WaitForSingleObject(context.waitEvent, INFINITE); } CloseHandle(context.waitEvent); //Sleep(75); free(ECB.lpszPathTranslated); free(ECB.lpszQueryString); free(ECB.lpszMethod); free(ECB.lpszPathInfo); BOOL ok = TRUE; if (context.out != INVALID_HANDLE_VALUE) CloseHandle(context.out); // compare the output with the EXPECT section if (matchdata && *matchdata != 0) { ok = CompareFiles(fname, matchdata); } DeleteFile(fname); return ok; }//// GetServerVariable() is how the DLL calls the main program to figure out// the environment variables it needs. This is a required function.//BOOL WINAPI GetServerVariable(HCONN hConn, LPSTR lpszVariableName, LPVOID lpBuffer, LPDWORD lpdwSize){ DWORD rc; CString value; TIsapiContext *c = (TIsapiContext *)hConn; if (!c) return FALSE; if (IsapiEnvironment.Lookup(lpszVariableName, value)) { rc = value.GetLength(); strncpy((char *)lpBuffer, value, *lpdwSize-1); } else if (c->env.Lookup(lpszVariableName, value)) { rc = value.GetLength(); strncpy((char *)lpBuffer, value, *lpdwSize-1); } else rc = GetEnvironmentVariable(lpszVariableName, (char *)lpBuffer, *lpdwSize) ; if (!rc) { // return of 0 indicates the variable was not found SetLastError(ERROR_NO_DATA); return FALSE; } if (rc > *lpdwSize) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } *lpdwSize =rc + 1 ; // GetEnvironmentVariable does not count the NULL return TRUE;}//// Again, we don't have an HCONN, so we simply wrap ReadClient() to// ReadFile on stdin. The semantics of the two functions are the same//BOOL WINAPI ReadClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize) { TIsapiContext *c = (TIsapiContext *)hConn; if (!c) return FALSE; if (c->in != INVALID_HANDLE_VALUE) return ReadFile(c->in, lpBuffer, (*lpdwSize), lpdwSize, NULL); return FALSE;}//// ditto for WriteClient()//BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize, DWORD dwReserved) { TIsapiContext *c = (TIsapiContext *)hConn; if (!c) return FALSE; if (c->out != INVALID_HANDLE_VALUE) return WriteFile(c->out, lpBuffer, *lpdwSize, lpdwSize, NULL); return FALSE;}//// This is a special callback function used by the DLL for certain extra // functionality. Look at the API help for details.//BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){ TIsapiContext *c = (TIsapiContext *)hConn; char *lpszRespBuf; char * temp = NULL; DWORD dwBytes; BOOL bRet = TRUE; switch(dwHSERequest) { case (HSE_REQ_SEND_RESPONSE_HEADER) : lpszRespBuf = (char *)xmalloc(*lpdwSize);//+ 80);//accomodate our header if (!lpszRespBuf) return FALSE; wsprintf(lpszRespBuf,"%s", //HTTP_VER, /* Default response is 200 Ok */ //lpvBuffer?lpvBuffer:"200 Ok", /* Create a string for the time. */ //temp=MakeDateStr(), //SERVER_VERSION, /* If this exists, it is a pointer to a data buffer to be sent. */ lpdwDataType?(char *)lpdwDataType:NULL); if (temp) xfree(temp); dwBytes = strlen(lpszRespBuf); bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); xfree(lpszRespBuf); break; // // A real server would do cleanup here case (HSE_REQ_DONE_WITH_SESSION): SetEvent(c->waitEvent); //ExitThread(0); break; // // This sends a redirect (temporary) to the client. // The header construction is similar to RESPONSE_HEADER above. // case (HSE_REQ_SEND_URL_REDIRECT_RESP): lpszRespBuf = (char *)xmalloc(*lpdwSize +80) ; if (!lpszRespBuf) return FALSE; wsprintf(lpszRespBuf,"%s %s %s\r\n", HTTP_VER, "302 Moved Temporarily", (lpdwSize > 0)?lpvBuffer:0); xfree(temp); dwBytes = strlen(lpszRespBuf); bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); xfree(lpszRespBuf); break; default: return FALSE; break; } return bRet; }//// Makes a string of the date and time from GetSystemTime().// This is in UTC, as required by the HTTP spec.`//char * MakeDateStr(void){ SYSTEMTIME systime; char *szDate= (char *)xmalloc(64); char * DaysofWeek[] = {"Sun","Mon","Tue","Wed","Thurs","Fri","Sat"}; char * Months[] = {"NULL","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", "Sep","Oct","Nov","Dec"}; GetSystemTime(&systime); wsprintf(szDate,"%s, %d %s %d %d:%d.%d", DaysofWeek[systime.wDayOfWeek], systime.wDay, Months[systime.wMonth], systime.wYear, systime.wHour, systime.wMinute, systime.wSecond ); return szDate;}//// Fill the ECB up //BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *ECB, TIsapiContext *context) { char * temp; ECB->cbSize = sizeof(EXTENSION_CONTROL_BLOCK); ECB->dwVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR); ECB->ConnID = (void *)context; // // Pointers to the functions the DLL will call. // ECB->GetServerVariable = GetServerVariable; ECB->ReadClient = ReadClient; ECB->WriteClient = WriteClient; ECB->ServerSupportFunction = ServerSupportFunction; // // Fill in the standard CGI environment variables // ECB->lpszMethod = GetEnv("REQUEST_METHOD"); if (!ECB->lpszMethod) ECB->lpszMethod = "GET"; ECB->lpszQueryString = GetEnv("QUERY_STRING"); ECB->lpszPathInfo = GetEnv("PATH_INFO"); ECB->lpszPathTranslated = GetEnv("PATH_TRANSLATED"); ECB->cbTotalBytes=( (temp=GetEnv("CONTENT_LENGTH")) ? (atoi(temp)): 0); ECB->cbAvailable = 0; ECB->lpbData = (unsigned char *)""; ECB->lpszContentType = GetEnv("CONTENT_TYPE"); return TRUE;}//// Works like _getenv(), but uses win32 functions instead.//char *GetEnv(LPSTR lpszEnvVar){ char *var, dummy; DWORD dwLen; if (!lpszEnvVar) return ""; dwLen =GetEnvironmentVariable(lpszEnvVar, &dummy, 1); if (dwLen == 0) return ""; var = (char *)xmalloc(dwLen); if (!var) return ""; (void)GetEnvironmentVariable(lpszEnvVar, var, dwLen); return var;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -