Skip to content

Commit

Permalink
Add the first stub of the AutoWebPerf. It works and it's in a good place
Browse files Browse the repository at this point in the history
right now, with more work ahead.  This is just a checkpoint.
  • Loading branch information
brewdente committed Apr 24, 2015
1 parent 93311e7 commit 51679b6
Show file tree
Hide file tree
Showing 38 changed files with 1,410 additions and 0 deletions.
63 changes: 63 additions & 0 deletions .gitattributes
@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary

###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
6 changes: 6 additions & 0 deletions AutoWebPerf/App.config
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
98 changes: 98 additions & 0 deletions AutoWebPerf/AutoWebPerf.csproj
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{36138327-0A72-44E3-B9DB-C4E6155AAFD5}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AutoWebPerf</RootNamespace>
<AssemblyName>AutoWebPerf</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
<HintPath>packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebSocket4Net">
<HintPath>packages\WebSocket4Net.0.12\lib\net45\WebSocket4Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ChromeWrapper.cs" />
<Compile Include="ChromeProcessInfo.cs" />
<Compile Include="Chrome\IChromeProxy.cs" />
<Compile Include="Chrome\MessageContractResolver.cs" />
<Compile Include="Chrome\Messages\ChromeProxy.cs" />
<Compile Include="Chrome\Messages\ErrorResponse.cs" />
<Compile Include="Chrome\Messages\IdResponse.cs" />
<Compile Include="Chrome\Messages\IError.cs" />
<Compile Include="Chrome\Messages\IRequest.cs" />
<Compile Include="Chrome\Messages\IRequestFactory.cs" />
<Compile Include="Chrome\Messages\IResponse.cs" />
<Compile Include="Chrome\Messages\IResponseFactory.cs" />
<Compile Include="Chrome\Messages\MethodName.cs" />
<Compile Include="Chrome\Messages\MethodNameAttribute.cs" />
<Compile Include="Chrome\Messages\Network\DataReceivedResponse.cs" />
<Compile Include="Chrome\Messages\Network\EnableRequest.cs" />
<Compile Include="Chrome\Messages\Network\EnableResponse.cs" />
<Compile Include="Chrome\Messages\Network\LoadingFinishedResponse.cs" />
<Compile Include="Chrome\Messages\Network\RequestServedFromCacheResponse.cs" />
<Compile Include="Chrome\Messages\Network\RequestWillBeSentResponse.cs" />
<Compile Include="Chrome\Messages\Network\ResponseReceivedResponse.cs" />
<Compile Include="Chrome\Messages\Page\NavigateRequest.cs" />
<Compile Include="Chrome\Messages\Page\NavigateRequestParams.cs" />
<Compile Include="Chrome\Messages\Page\NavigateResponse.cs" />
<Compile Include="Chrome\Messages\Page\NavigateResponseResult.cs" />
<Compile Include="Chrome\Messages\Request.cs" />
<Compile Include="Chrome\Messages\RequestFactory.cs" />
<Compile Include="Chrome\Messages\ResponseFactory.cs" />
<Compile Include="Chrome\Messages\ResponseHandler.cs" />
<Compile Include="Chrome\Messages\Response.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RemoveSessions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
22 changes: 22 additions & 0 deletions AutoWebPerf/AutoWebPerf.sln
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoWebPerf", "AutoWebPerf.csproj", "{36138327-0A72-44E3-B9DB-C4E6155AAFD5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{36138327-0A72-44E3-B9DB-C4E6155AAFD5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
18 changes: 18 additions & 0 deletions AutoWebPerf/Chrome/IChromeProxy.cs
@@ -0,0 +1,18 @@
using AutoWebPerf.Chrome.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoWebPerf.Chrome
{
interface IChromeProxy : IDisposable
{
Task Init();

Task<IResponse> PublishAsync(IRequest request);

void Subscribe<T>(ResponseHandler handler);
}
}
17 changes: 17 additions & 0 deletions AutoWebPerf/Chrome/MessageContractResolver.cs
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;

namespace AutoWebPerf.Chrome
{
class MessageContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToLower();
}
}
}
138 changes: 138 additions & 0 deletions AutoWebPerf/Chrome/Messages/ChromeProxy.cs
@@ -0,0 +1,138 @@
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocket4Net;

namespace AutoWebPerf.Chrome.Messages
{
class ChromeProxy : IChromeProxy
{
private ManualResetEvent _openEvent = new ManualResetEvent(false);
private ManualResetEvent _publishEvent = new ManualResetEvent(false);
private readonly string _endpoint;
private WebSocket _webSocket;
private readonly ConcurrentDictionary<string, ConcurrentBag<ResponseHandler>> _handlers = new ConcurrentDictionary<string, ConcurrentBag<ResponseHandler>>();
private IResponseFactory _responseFactory;
private ConcurrentDictionary<long, ManualResetEvent> _requestWaitHandles = new ConcurrentDictionary<long, ManualResetEvent>();
private ConcurrentDictionary<long, IResponse> _responses = new ConcurrentDictionary<long, IResponse>();

public ChromeProxy(string endpoint, IResponseFactory responseFactory)
{
_endpoint = endpoint;
_responseFactory = responseFactory;
}

public Task Init()
{
_openEvent.Reset();
_webSocket = new WebSocket(_endpoint);
_webSocket.Opened += delegate(System.Object o, EventArgs e)
{
_openEvent.Set();
};

_webSocket.MessageReceived += delegate(System.Object o, MessageReceivedEventArgs e)
{
var response = _responseFactory.Create(e.Message);
var idResponse = response as IdResponse;
ManualResetEvent requestMre = null;
long responseId;
if (null != idResponse
&& long.TryParse(idResponse.Id, out responseId)
&& _requestWaitHandles.TryGetValue(responseId, out requestMre))
{
_responses.AddOrUpdate(responseId, response, (i, r) => response);
requestMre.Set();
}
else
{
HandleResponse(response);
}
};

_webSocket.Error += delegate(System.Object o, SuperSocket.ClientEngine.ErrorEventArgs e)
{
throw e.Exception;
};

_webSocket.Closed += delegate(System.Object o, EventArgs e)
{
};

_webSocket.DataReceived += delegate(System.Object o, WebSocket4Net.DataReceivedEventArgs e)
{
var response = _responseFactory.Create(e.Data);
HandleResponse(response);
};

_webSocket.Open();
return Task.Run(() =>
{
_openEvent.WaitOne();
});
}

private void HandleResponse(IResponse response)
{
var type = response.GetType();
var handlerKey = type.FullName;
ConcurrentBag<ResponseHandler> handlers = null;
if(_handlers.TryGetValue(handlerKey, out handlers))
{
var localHandlers = handlers.ToArray();
foreach(var handler in localHandlers)
{
handler(this, response);
}
}
}

public Task<IResponse> PublishAsync(IRequest request)
{
var settings = new JsonSerializerSettings
{
ContractResolver = new MessageContractResolver()
};
var requestString = JsonConvert.SerializeObject(request, settings);

var requestResetEvent = new ManualResetEvent(false);
_requestWaitHandles.AddOrUpdate(request.Id, requestResetEvent, (id, r) => requestResetEvent);
return Task.Run(() =>
{
_webSocket.Send(requestString);
requestResetEvent.WaitOne();
IResponse response = null;
_requestWaitHandles.TryRemove(request.Id, out requestResetEvent);
_responses.TryRemove(request.Id, out response);
return response;
});
}

public void Subscribe<T>(ResponseHandler handler)
{
var handlerType = typeof(T);
_handlers.AddOrUpdate(handlerType.FullName,
(m) => new ConcurrentBag<ResponseHandler>(new[] { handler }),
(m, currentBag) =>
{
currentBag.Add(handler);
return currentBag;
});
}

public void Dispose()
{
if (null == _webSocket) return;
if (_webSocket.State == WebSocketState.Open)
{
_webSocket.Close();
}
_webSocket.Dispose();
}
}
}
24 changes: 24 additions & 0 deletions AutoWebPerf/Chrome/Messages/ErrorResponse.cs
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoWebPerf.Chrome.Messages
{
public class Error
{
public int Code { get; set; }
public string message { get; set; }
}

class ErrorResponse : IdResponse
{
public Error Error { get; set; }
public int Id { get; set; }
}




}

0 comments on commit 51679b6

Please sign in to comment.