diff --git a/.hgignore b/.hgignore index d0f7a0069..9474de352 100644 --- a/.hgignore +++ b/.hgignore @@ -8,9 +8,8 @@ glob:*.patch glob:*.hg glob:build glob:*.sln.cache -glob:src/Orchard.Web/Modules/Orchard.DevTools/Module.txt -glob:src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt glob:src/Orchard.Web/Media/* glob:desktop.ini glob:src/Orchard.Azure.suo glob:src/Orchard.5.0.ReSharper +glob:log.xml diff --git a/Orchard.proj b/Orchard.proj index fa32d8375..a39d9401b 100644 --- a/Orchard.proj +++ b/Orchard.proj @@ -11,6 +11,7 @@ $(BuildFolder)\Compile $(CompileFolder)\_PublishedWebsites $(BuildFolder)\Stage + $(BuildFolder)\Profiling x64 x86 @@ -32,6 +33,14 @@ + + + + + + + + @@ -141,4 +150,20 @@ + + + + + + + + + + + + + + + + diff --git a/lib/wcat/doc/readme.txt b/lib/wcat/doc/readme.txt new file mode 100644 index 000000000..f23569562 --- /dev/null +++ b/lib/wcat/doc/readme.txt @@ -0,0 +1,37 @@ +Getting Started with WCAT +====================================== + +Documentation + It is suggested that you read the documentation for WCAT in order to understand + the environment and configuration needed. Documentation can be found under the + doc folder in the directory that you installed WCAT to. + +Installing WCAT + Prerequisite: all machines that will run WCAT must have the administrator account + enabled and must all share a common password. + + 1. Log into the WCAT Controller as administrator. + 2. Install wcat.msi on the machine to be used as a WCAT Controller. + 3. If any WCAT extension DLLs will be used, copy them to the WCAT installation + directory. (typically c:\Program Files\WCAT) + 4. Open a command prompt; navigate to the WCAT installation directory. + 5. Run ‘cscript //H:Cscript’ + 6. Run ‘wcat.wsf –terminate –update –clients {comma separated list of WCAT client + machines}’ where the “clients” parameter accepts a comma separated list (no + spaces) of the machines you plan on using as WCAT Client machines. Note: If + the WCAT Controller machine will also be used as a WCAT Client, include + ‘localhost’ OR the name of the WCAT Controller machine in the list of clients. + + NOTE: If WCAT has never been installed on the WCAT Client machines before, + this will cause the machines to reboot. + +Running WCAT + 1. Log into the WCAT Controller as administrator. + 2. Install wcat.msi on the machine to be used as a WCAT Controller. + 3. Open a command prompt, navigate to the WCAT installation directory (typically + c:\Program Files\WCAT) + 4. Run ‘wcat.wsf –terminate –run –clients {comma separated client list} –t + {scenario file} –f {settings file} –s {name of the Web Server} –singleip -x + 5. Output will be generated in the current directory, ‘log.xml’. To change this, + use the ‘-o’ flag. For more help on options to pass to wcat.wsf type + ‘wcctl.exe -?’ diff --git a/lib/wcat/doc/wcat.doc b/lib/wcat/doc/wcat.doc new file mode 100644 index 000000000..45485051b Binary files /dev/null and b/lib/wcat/doc/wcat.doc differ diff --git a/lib/wcat/report.xsl b/lib/wcat/report.xsl new file mode 100644 index 000000000..2045aafbe --- /dev/null +++ b/lib/wcat/report.xsl @@ -0,0 +1,1786 @@ + + + + + + + + + + + + + + + topValue ){ + topIndex = i; + topValue = test; + } + } + } + + return (topIndex+1) * 1; + + }catch(e){ + return 0; + } +} + +function tag(){ + return ++g_tag; +} + +]]> + + + + Contents + Summary + Top: + of + Warnings + Type + Item + Warning + Help + Total + Average + Transactions: + Total Records: + + + + + + + + + + + + + 10 + + + + + + + + 1 + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +

+ + + + + + + +
+ + + : + + + + +
+
+
+
+ + + + + + + + + + + + +
+ + + + + + + +
+ + + + + +
+
+ +
+
+ + + + + + + + + + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ bold + + + + # + + + + + + + +
+ b3 + + + + + + + 40% + + + + + + + + + + b3 + + + + 0.00 + + + + + b3 + + + + 0.00 + + + + + + + + + + b3 + + 40% + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + +
+ b3 + + + + + +
+ + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+
+ + + + + +
+ +
+ + + + + + + +
+ +
+ + +
+ + + + + + + +table_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + top_ + show() + pressTop() + + + + + + + + + + + + + + +
+ + + + + + +
+
+ +
+
+ +
+ + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + +
+ +

+ + +
+ + + + + + + + + + + + + + + + + all + + + + + + + + + + + + + + + all + + + + + + + + + + + + 0 + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + + + + + table_ + + + + + + + ascending + + + + + + number + + + + + + ascending + + + + + + number + + + + + + + + + + + + + + + + + + + + + + + + + b3 + b1 + + + + + + + display:'' + display:'none' + + + + + + + + + + + - + + + + + + + + + + + + + c_ + + + + display:'none'; + + + + + + + + + + + + + + + + + + + + + +
+ + + + true + +
+ + folder( c_ ) + + e_c_ + + + + + + + + + + + +
+ + + + +
+ + + + child + +
+
+ + + + + + border-top: 1px solid black; + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + : + + + + info b3 + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + 8% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + string + + + span + + + number + + + + + sort(); + cursor:hand; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ +
+ + + + + + + + + + w__ + + popup() + .style.display='none' + + + + + + + + + + + + + + + + + + + + + + popup_ + + popup() + .style.display='none' + + + + + +
+
+ +
+
+
+
+
+ +
+ + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + +
+
+ + + + + + + + + + + + + + + b3 + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +
Information
+
+ +
Warning
+
+ +
Error
+
+
+
+ + + # + + + + + + + + + + + + + + + + + + + + help('') + + + +
+
+
+
+
+ + +
+ +
+ +
+
+ i +
+
+
+ + +
+ +
+ ! +
+
+ +
+
+ ! +
+
+
+ + +
+ +
+ +
+
+ +
+
+
+ + +
+ +
+ +
+
+
+ + + + + + +
+
+ + +
+
+
+
+
+
+ + +
diff --git a/lib/wcat/samples/scripts/home.ubr b/lib/wcat/samples/scripts/home.ubr new file mode 100644 index 000000000..2b0ccc56d --- /dev/null +++ b/lib/wcat/samples/scripts/home.ubr @@ -0,0 +1,66 @@ +scenario +{ + name = "IIS Home Page"; + + warmup = 30; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + // + // This script is made for IIS7 + // + transaction + { + id = "Default Web Site Homepage"; + weight = 1; + + request + { + url = "/"; + statuscode = 200; + } + + request + { + url = "/welcome.png"; + statuscode = 200; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = reset; + } + } +} diff --git a/lib/wcat/samples/scripts/settings.ubr b/lib/wcat/samples/scripts/settings.ubr new file mode 100644 index 000000000..9f1607ad4 --- /dev/null +++ b/lib/wcat/samples/scripts/settings.ubr @@ -0,0 +1,102 @@ +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // + // clientfile = "ubr\lcw2.light.ubr"; + // server = "webserver"; + // clients = 10; + // virtualclients = 100; + // + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} diff --git a/lib/wcat/samples/src/precomp.h b/lib/wcat/samples/src/precomp.h new file mode 100644 index 000000000..c63ddad18 --- /dev/null +++ b/lib/wcat/samples/src/precomp.h @@ -0,0 +1,14 @@ +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +#endif // _PRECOMP_H diff --git a/lib/wcat/samples/src/viewstate.c b/lib/wcat/samples/src/viewstate.c new file mode 100644 index 000000000..c0499f42a --- /dev/null +++ b/lib/wcat/samples/src/viewstate.c @@ -0,0 +1,186 @@ +#include +#include +#include "precomp.h" + +#define MAX_VIEWSTATE (1024) +#define VIEWSTATE "__VIEWSTATE" +#define VIEWSTATE_LEN (10) +#define MAX_TAG_NAME (128) + +#define WCATRESULT_ERROR (-1) +#define WCATRESULT_SUCCESS (0) +#define WCATRESULT_MORE_DATA_NEEDED (1) +#define WCATRESULT_NEXT_PACKET (2) + +typedef enum _USER_STATE +{ + UserStateFindViewState, + UserStateFindValue, + UserStateFindEqual, + UserStateFindFirstQuote, + UserStateGetValue, + UserStateFinished +} USER_STATE; + +typedef struct _USER_DATA +{ + USER_STATE state; + char viewstate[MAX_VIEWSTATE]; +} USER_DATA, *PUSER_DATA; + +BOOL WINAPI DllMain( + IN HINSTANCE hinstDll, + IN DWORD dwReason, + IN LPVOID lpvContext + ) +{ + switch( dwReason ) { + + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + + default: + return FALSE; + } + + return TRUE; +} + +DWORD GetViewstate(PVOID *context, DWORD argc, PCHAR argv[], PCHAR *result) +{ + PUSER_DATA user; + + if (*context == NULL) + { + *result = NULL; + return 0; + } + + user = *context; + + *result = user->viewstate; + + return 0; +} + +DWORD ResponseFilter(PVOID *context, DWORD argc, PCHAR argv[], PCHAR packet, ULONG_PTR len, ULONG_PTR sequence) +{ + PCHAR buffer = packet; + DWORD i = 0; + PUSER_DATA user = NULL; + + if (*context == NULL) + { + *context = calloc(1, sizeof(USER_DATA)); + + if (NULL == *context) + { + return -1; + } + } + + user = *context; + + if (sequence == 0) + { + user->state = UserStateFindViewState; + user->viewstate[0] = '\0'; + } + + // + // fastpath for when we don't have any work to do + // + if (user->state == UserStateFinished) + { + return WCATRESULT_SUCCESS; + } + + while (len && *buffer) + { + switch (user->state) + { + case UserStateFindViewState: + if (*buffer == '_') + { + if (len < VIEWSTATE_LEN) + { + return WCATRESULT_MORE_DATA_NEEDED; + } + + if (_strnicmp(buffer, VIEWSTATE, VIEWSTATE_LEN) == 0) + { + len -= VIEWSTATE_LEN-1; + buffer += VIEWSTATE_LEN-1; + + user->state = UserStateFindValue; + } + } + + break; + case UserStateFindValue: + if (*buffer == 'v' || *buffer == 'V') + { + if (len < 5) + { + return WCATRESULT_MORE_DATA_NEEDED; + } + + if (_strnicmp(buffer, "value", 5) == 0) + { + len -= 4; + buffer += 4; + + user->state = UserStateFindEqual; + } + } + break; + case UserStateFindEqual: + if (*buffer == '=') + { + user->state = UserStateFindFirstQuote; + } + + break; + case UserStateFindFirstQuote: + if (*buffer == '"') + { + user->state = UserStateGetValue; + } + + break; + case UserStateGetValue: + i = 0; + + for (i=0; len && *buffer && *buffer != '"'; i++, len--, buffer++) + { + if (i > MAX_VIEWSTATE) + { + return WCATRESULT_ERROR; + } + + user->viewstate[i] = *buffer; + } + + if (len == 0 || *buffer != '"') + { + return WCATRESULT_MORE_DATA_NEEDED; + } + + user->viewstate[i] = '\0'; + + user->state = UserStateFinished; + break; + case UserStateFinished: + break; + default: + break; + } + + len--; buffer++; + } + + return WCATRESULT_SUCCESS; +} diff --git a/lib/wcat/samples/src/viewstate.def b/lib/wcat/samples/src/viewstate.def new file mode 100644 index 000000000..77a7c5829 --- /dev/null +++ b/lib/wcat/samples/src/viewstate.def @@ -0,0 +1,7 @@ +; MYTESTSERVICE.def : declares the module parameters for the DLL. + +LIBRARY "Viewstate" + +EXPORTS + GetViewstate + ResponseFilter diff --git a/lib/wcat/samples/src/wcat.h b/lib/wcat/samples/src/wcat.h new file mode 100644 index 000000000..8f88906db --- /dev/null +++ b/lib/wcat/samples/src/wcat.h @@ -0,0 +1,9 @@ +#ifndef _WCAT_H +#define _WCAT_H + +#define WCATRESULT_ERROR (-1) +#define WCATRESULT_SUCCESS (0) +#define WCATRESULT_MORE_DATA_NEEDED (1) +#define WCATRESULT_NEXT_PACKET (2) + +#endif // define _WCAT_H diff --git a/lib/wcat/wcat.wsf b/lib/wcat/wcat.wsf new file mode 100644 index 000000000..74f0702e3 --- /dev/null +++ b/lib/wcat/wcat.wsf @@ -0,0 +1,1134 @@ + + + + diff --git a/lib/wcat/wcclient.exe b/lib/wcat/wcclient.exe new file mode 100644 index 000000000..301d728bf Binary files /dev/null and b/lib/wcat/wcclient.exe differ diff --git a/lib/wcat/wcctl.exe b/lib/wcat/wcctl.exe new file mode 100644 index 000000000..b1ae2ca3b Binary files /dev/null and b/lib/wcat/wcctl.exe differ diff --git a/lib/wcat/wcutil.exe b/lib/wcat/wcutil.exe new file mode 100644 index 000000000..5ac021bfe Binary files /dev/null and b/lib/wcat/wcutil.exe differ diff --git a/src/Orchard.Profile/Go.cmd b/src/Orchard.Profile/Go.cmd new file mode 100644 index 000000000..05fe49c11 --- /dev/null +++ b/src/Orchard.Profile/Go.cmd @@ -0,0 +1,3 @@ +@echo off +call "%~dp0\_environment" +"%wcatfiles%\wcat.wsf" -terminate -run -clients localhost -t "%~dp0\Scripts\%1.txt" -f "%~dp0\settings.txt" -s localhost -singleip -x diff --git a/src/Orchard.Profile/Initialize.cmd b/src/Orchard.Profile/Initialize.cmd new file mode 100644 index 000000000..ed9183461 --- /dev/null +++ b/src/Orchard.Profile/Initialize.cmd @@ -0,0 +1,4 @@ +@echo off +call "%~dp0\_environment" +"%wcatfiles%\wcat.wsf" -terminate -update -clients localhost + diff --git a/src/Orchard.Profile/Orchard.Profile.csproj b/src/Orchard.Profile/Orchard.Profile.csproj new file mode 100644 index 000000000..7ae306298 --- /dev/null +++ b/src/Orchard.Profile/Orchard.Profile.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {94E694A2-D140-468D-A277-C5FCE1D13E9B} + Library + Properties + Orchard.Profile + Orchard.Profile + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\lib\nunit\nunit.framework.dll + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + False + ..\..\lib\specflow\TechTalk.SpecFlow.dll + + + + + + + + True + True + Profiling.feature + + + + + SpecFlowSingleFileGenerator + Profiling.feature.cs + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.Profile/Properties/AssemblyInfo.cs b/src/Orchard.Profile/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5e65c9f07 --- /dev/null +++ b/src/Orchard.Profile/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.Profile")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Orchard.Profile")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("669564db-5b8e-4378-b40a-03d3b9bec4c9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Orchard.Profile/Scripts/dashboard.txt b/src/Orchard.Profile/Scripts/dashboard.txt new file mode 100644 index 000000000..361125240 --- /dev/null +++ b/src/Orchard.Profile/Scripts/dashboard.txt @@ -0,0 +1,70 @@ +scenario +{ + name = "Orchard Dashboard"; + + warmup = 10; + duration = 30; + cooldown = 1; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + // + // This script is made for IIS7 + // + transaction + { + id = "Login and view admin"; + weight = 1; + + request + { + url = "/Users/Account/LogOn"; + verb = POST; + postdata = "username=admin&password=profiling-secret"; + redirect = true; + redirverb = GET; + statuscode = 200; + } + + request + { + url = "/admin"; + statuscode = 200; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = reset; + } + } +} diff --git a/src/Orchard.Profile/Scripts/scenario.txt b/src/Orchard.Profile/Scripts/scenario.txt new file mode 100644 index 000000000..47e2149ff --- /dev/null +++ b/src/Orchard.Profile/Scripts/scenario.txt @@ -0,0 +1,66 @@ +scenario +{ + name = "IIS Home Page"; + + warmup = 10; + duration = 30; + cooldown = 1; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + // + // This script is made for IIS7 + // + transaction + { + id = "Default Web Site Homepage"; + weight = 1; + + request + { + url = "/"; + statuscode = 200; + } + + request + { + url = "/welcome.png"; + statuscode = 200; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = reset; + } + } +} diff --git a/src/Orchard.Profile/Tests/HttpClient.cs b/src/Orchard.Profile/Tests/HttpClient.cs new file mode 100644 index 000000000..98e6b65f9 --- /dev/null +++ b/src/Orchard.Profile/Tests/HttpClient.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Web; +using TechTalk.SpecFlow; + +namespace Orchard.Profile.Tests { + [Binding] + public class HttpClient { + private readonly CookieContainer _cookieContainer = new CookieContainer(); + private HttpWebRequest _request; + private HttpWebResponse _response; + private string _text; + + [Given(@"I am logged in")] + public void GivenIAmLoggedIn() { + DoRequest("/Users/Account/LogOn", "userNameOrEmail=admin&password=profiling-secret&rememberMe=false"); + } + + [When(@"I go to ""(.*)""")] + public void WhenIGoTo(string url) { + DoRequest(url); + } + + [When(@"I go to ""(.*)"" (.*) times")] + public void WhenIGoTo(string url, int times) { + for (int i = 0; i != times; ++i) + DoRequest(url); + } + + private void DoRequest(string url) { + DoRequest(url, null); + } + + private void DoRequest(string url, string postData) { + _request = (HttpWebRequest)WebRequest.Create("http://localhost" + url); + _request.CookieContainer = _cookieContainer; + if (postData != null) { + _request.Method = "POST"; + _request.ContentType = "application/x-www-form-urlencoded"; + using (var stream = _request.GetRequestStream()) { + using (var writer = new StreamWriter(stream)) { + writer.Write(postData); + } + } + } + try { + _response = (HttpWebResponse)_request.GetResponse(); + } + catch (WebException ex) { + _response = (HttpWebResponse)ex.Response; + } + + using (var stream = _response.GetResponseStream()) { + using (var reader = new StreamReader(stream)) { + _text = reader.ReadToEnd(); + } + } + } + } +} diff --git a/src/Orchard.Profile/Tests/Profiling.feature b/src/Orchard.Profile/Tests/Profiling.feature new file mode 100644 index 000000000..692963c20 --- /dev/null +++ b/src/Orchard.Profile/Tests/Profiling.feature @@ -0,0 +1,8 @@ +Feature: Profiling + In order to profile the site + As a developer + I want to generate a fixed number of repeatable requests + +Scenario: Dashboard + Given I am logged in + When I go to "/admin" 40 times diff --git a/src/Orchard.Profile/Tests/Profiling.feature.cs b/src/Orchard.Profile/Tests/Profiling.feature.cs new file mode 100644 index 000000000..b84190450 --- /dev/null +++ b/src/Orchard.Profile/Tests/Profiling.feature.cs @@ -0,0 +1,68 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (http://www.specflow.org/). +// SpecFlow Version:1.2.0.0 +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Orchard.Profile.Tests +{ + using TechTalk.SpecFlow; + + + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Profiling")] + public partial class ProfilingFeature + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + +#line 1 "Profiling.feature" +#line hidden + + [NUnit.Framework.TestFixtureSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Profiling", "In order to profile the site\r\nAs a developer\r\nI want to generate a fixed number o" + + "f repeatable requests", ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.TestFixtureTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioStart(scenarioInfo); + } + + [NUnit.Framework.TearDownAttribute()] + public virtual void ScenarioTearDown() + { + testRunner.OnScenarioEnd(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Dashboard")] + public virtual void Dashboard() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Dashboard", ((string[])(null))); +#line 6 +this.ScenarioSetup(scenarioInfo); +#line 7 + testRunner.Given("I am logged in"); +#line 8 + testRunner.When("I go to \"/admin\" 40 times"); +#line hidden + testRunner.CollectScenarioErrors(); + } + } +} diff --git a/src/Orchard.Profile/_environment.cmd b/src/Orchard.Profile/_environment.cmd new file mode 100644 index 000000000..a3af1cc38 --- /dev/null +++ b/src/Orchard.Profile/_environment.cmd @@ -0,0 +1,5 @@ +CScript //H:CScript + +set wcatfiles=%programfiles%\wcat +if not "%programfiles(x86)%"=="" set wcatfiles=%programfiles(x86)%\wcat +if not exist "%wcatfiles%" set wcatfiles="%~dp0\..\..\lib\wcat" diff --git a/src/Orchard.Profile/profiling-setup-commands.txt b/src/Orchard.Profile/profiling-setup-commands.txt new file mode 100644 index 000000000..15f7607eb --- /dev/null +++ b/src/Orchard.Profile/profiling-setup-commands.txt @@ -0,0 +1,6 @@ +help commands +setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLite /EnabledFeatures:Orchard.Framework,Common,Dashboard,Feeds,HomePage,Navigation,Scheduling,Settings,XmlRpc,Orchard.Users,Orchard.Roles,TinyMce,Orchard.Modules,Orchard.Themes,Orchard.MultiTenancy,Orchard.Pages,Orchard.Blogs,Orchard.Comments,Futures.Widgets,Orchard.Media,Orchard.Tags,Orchard.DevTools +help commands +tenant list +feature list +add profiling data diff --git a/src/Orchard.Profile/report.xsl b/src/Orchard.Profile/report.xsl new file mode 100644 index 000000000..2045aafbe --- /dev/null +++ b/src/Orchard.Profile/report.xsl @@ -0,0 +1,1786 @@ + + + + + + + + + + + + + + + topValue ){ + topIndex = i; + topValue = test; + } + } + } + + return (topIndex+1) * 1; + + }catch(e){ + return 0; + } +} + +function tag(){ + return ++g_tag; +} + +]]> + + + + Contents + Summary + Top: + of + Warnings + Type + Item + Warning + Help + Total + Average + Transactions: + Total Records: + + + + + + + + + + + + + 10 + + + + + + + + 1 + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +

+ + + + + + + +
+ + + : + + + + +
+
+
+
+ + + + + + + + + + + + +
+ + + + + + + +
+ + + + + +
+
+ +
+
+ + + + + + + + + + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ bold + + + + # + + + + + + + +
+ b3 + + + + + + + 40% + + + + + + + + + + b3 + + + + 0.00 + + + + + b3 + + + + 0.00 + + + + + + + + + + b3 + + 40% + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + +
+ b3 + + + + + +
+ + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+
+ + + + + +
+ +
+ + + + + + + +
+ +
+ + +
+ + + + + + + +table_ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + top_ + show() + pressTop() + + + + + + + + + + + + + + +
+ + + + + + +
+
+ +
+
+ +
+ + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + +
+ +

+ + + + + + + + + + + + + + + + + + + + all + + + + + + + + + + + + + + + all + + + + + + + + + + + + 0 + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + + + + + table_ + + + + + + + ascending + + + + + + number + + + + + + ascending + + + + + + number + + + + + + + + + + + + + + + + + + + + + + + + + b3 + b1 + + + + + + + display:'' + display:'none' + + + + + + + + + + + - + + + + + + + + + + + + + c_ + + + + display:'none'; + + + + + + + + + + + + + + + + + + + + + +
+ + + + true + +
+ + folder( c_ ) + + e_c_ + + + + + + + + + + + +
+ + + + +
+ + + + child + +
+
+ + + + + + border-top: 1px solid black; + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + : + + + + info b3 + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + 8% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + string + + + span + + + number + + + + + sort(); + cursor:hand; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ +
+ + + + + + + + + + w__ + + popup() + .style.display='none' + + + + + + + + + + + + + + + + + + + + + + popup_ + + popup() + .style.display='none' + + + + + +
+
+ +
+
+
+
+
+ +
+ + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + +
+
+ + + + + + + + + + + + + + + b3 + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +
Information
+
+ +
Warning
+
+ +
Error
+
+
+
+ + + # + + + + + + + + + + + + + + + + + + + + help('') + + + +
+
+
+
+
+ + +
+ +
+ +
+
+ i +
+
+
+ + +
+ +
+ ! +
+
+ +
+
+ ! +
+
+
+ + +
+ +
+ +
+
+ +
+
+
+ + +
+ +
+ +
+
+
+ + + + + + +
+
+ + +
+
+
+
+
+
+ + + diff --git a/src/Orchard.Profile/settings.txt b/src/Orchard.Profile/settings.txt new file mode 100644 index 000000000..1b18b33ae --- /dev/null +++ b/src/Orchard.Profile/settings.txt @@ -0,0 +1,104 @@ +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // + // clientfile = "ubr\lcw2.light.ubr"; + // server = "webserver"; + // clients = 10; + // virtualclients = 100; + // + //-------------------------------------------------------------------------- + + virtualclients = 1; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs new file mode 100644 index 000000000..6635ab22b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ProfilingCommands.cs @@ -0,0 +1,61 @@ +using Orchard.Commands; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Core.Common.Models; +using Orchard.Core.Navigation.Models; +using Orchard.Security; + +namespace Orchard.DevTools.Commands { + public class ProfilingCommands : DefaultOrchardCommandHandler { + private readonly IContentManager _contentManager; + private readonly IMembershipService _membershipService; + + public ProfilingCommands(IContentManager contentManager, IMembershipService membershipService) { + _contentManager = contentManager; + _membershipService = membershipService; + } + + [CommandName("add profiling data")] + public string AddProfilingData() { + var admin = _membershipService.GetUser("admin"); + + for (var index = 0; index != 5; ++index) { + + var pageName = "page" + index; + var page = _contentManager.Create("page", VersionOptions.Draft); + page.As().Owner = admin; + page.As().Slug = pageName; + page.As().Title = pageName; + page.As().Text = pageName; + page.As().OnMainMenu = true; + page.As().MenuPosition = "5." + index; + page.As().MenuText = pageName; + _contentManager.Publish(page); + + var blogName = "blog" + index; + var blog = _contentManager.New("blog"); + blog.As().Owner = admin; + blog.As().Slug = blogName; + blog.As().Title = blogName; + blog.As().OnMainMenu = true; + blog.As().MenuPosition = "6." + index; + blog.As().MenuText = blogName; + _contentManager.Create(blog); + + // "blogpost" content type can't be created w/out http context at the moment + //for (var index2 = 0; index2 != 5; ++index2) { + // var postName = "post" + index; + // var post = _contentManager.New("blogpost"); + // post.As().Owner = admin; + // post.As().Container = blog; + // post.As().Slug = postName; + // post.As().Title = postName; + // post.As().Text = postName; + // _contentManager.Create(post); + //} + } + + return "AddProfilingData completed"; + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/_Module.txt b/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt similarity index 100% rename from src/Orchard.Web/Modules/Orchard.DevTools/_Module.txt rename to src/Orchard.Web/Modules/Orchard.DevTools/Module.txt diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index b6061e236..ed107f784 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -70,6 +70,7 @@ + @@ -82,9 +83,9 @@ + - @@ -98,6 +99,10 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + diff --git a/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt b/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt new file mode 100644 index 000000000..ca967af74 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt @@ -0,0 +1 @@ +name: Sandbox diff --git a/src/Orchard.sln b/src/Orchard.sln index ea0128b58..316a45174 100644 --- a/src/Orchard.sln +++ b/src/Orchard.sln @@ -61,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Themes", "Orchard.W EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Modules", "Orchard.Web\Modules\Orchard.Modules\Orchard.Modules.csproj", "{17F86780-9A1F-4AA1-86F1-875EEC2730C7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Profile", "Orchard.Profile\Orchard.Profile.csproj", "{94E694A2-D140-468D-A277-C5FCE1D13E9B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -171,11 +173,16 @@ Global {17F86780-9A1F-4AA1-86F1-875EEC2730C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {17F86780-9A1F-4AA1-86F1-875EEC2730C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {17F86780-9A1F-4AA1-86F1-875EEC2730C7}.Release|Any CPU.Build.0 = Release|Any CPU + {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94E694A2-D140-468D-A277-C5FCE1D13E9B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {94E694A2-D140-468D-A277-C5FCE1D13E9B} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA} {954CA994-D204-468B-9D69-51F6AD3E1C29} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {D9A7B330-CD22-4DA1-A95A-8DE1982AD8EB} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {79AED36E-ABD0-4747-93D3-8722B042454B} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} diff --git a/src/Tools/Orchard/Orchard.csproj b/src/Tools/Orchard/Orchard.csproj index e382e2c58..2d6194c7b 100644 --- a/src/Tools/Orchard/Orchard.csproj +++ b/src/Tools/Orchard/Orchard.csproj @@ -51,6 +51,7 @@ TRACE prompt 4 + x86 AllRules.ruleset