automate the autobahn test suite (#101)
However, we only run that automation if the Autobahn test suite runner (wstest) is installed. After this is in and we can verify it on the CI we'll look at making it mandatory for building the repo. Also includes test applications and scripts for running Autobahn suites against arbitrary ASP.NET 4.6, ASP.NET Core and HttpListener applications.
This commit is contained in:
parent
80437e878a
commit
91e94b1353
|
|
@ -26,4 +26,5 @@ nuget.exe
|
|||
project.lock.json
|
||||
/.vs/
|
||||
.testPublish/
|
||||
.build/
|
||||
.build/
|
||||
autobahnreports/
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ install:
|
|||
- make install
|
||||
- export LD_LIBRARY_PATH="$HOME/libuvinstall/lib"
|
||||
- cd $OLDPWD
|
||||
- sudo pip install autobahntestsuite "six>=1.9.0"
|
||||
mono:
|
||||
- 4.0.5
|
||||
python:
|
||||
- "2.7"
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
|
@ -33,6 +36,6 @@ branches:
|
|||
- dev
|
||||
- /^(.*\/)?ci-.*$/
|
||||
before_install:
|
||||
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi
|
||||
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl python; brew link --force openssl; fi
|
||||
script:
|
||||
- ./build.sh --quiet verify
|
||||
|
|
|
|||
|
|
@ -10,4 +10,10 @@ Contains a managed implementation of the WebSocket protocol, along with client a
|
|||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
|
||||
|
||||
|
||||
## System Requirements
|
||||
|
||||
This repo has a few special system requirements/prerequisites.
|
||||
|
||||
1. Windows IIS Express tests require IIS Express 10 and Windows 8 for WebSockets support
|
||||
2. HttpListener/ASP.NET 4.6 samples require at least Windows 8
|
||||
3. Autobahn Test Suite requires special installation see the README.md in test/AutobahnTestApp
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22216.0
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer", "test\TestServer\TestServer.csproj", "{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C45106D0-76C8-4776-A140-F7DD83CA2958}"
|
||||
|
|
@ -15,8 +12,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.WebSoc
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.WebSockets.Protocol.Test", "test\Microsoft.AspNetCore.WebSockets.Protocol.Test\Microsoft.AspNetCore.WebSockets.Protocol.Test.xproj", "{62A07A24-4D06-4DDA-B6BF-02D0C9CB7D32}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestClient", "test\TestClient\TestClient.xproj", "{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.WebSockets.Client", "src\Microsoft.AspNetCore.WebSockets.Client\Microsoft.AspNetCore.WebSockets.Client.xproj", "{4A1C4875-AE21-4A78-979A-F0E4DF5EB518}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.WebSockets.Client.Test", "test\Microsoft.AspNetCore.WebSockets.Client.Test\Microsoft.AspNetCore.WebSockets.Client.Test.xproj", "{6604D154-817F-4BC5-BE95-FF7E851179D9}"
|
||||
|
|
@ -28,9 +23,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
global.json = global.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutobahnTestServer", "test\AutobahnTestServer\AutobahnTestServer.xproj", "{C03C43FE-9201-48A6-B434-AD67EF627D67}"
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestClient", "samples\TestClient\TestClient.xproj", "{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutobahnTestClient", "test\AutobahnTestClient\AutobahnTestClient.xproj", "{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer", "samples\TestServer\TestServer.csproj", "{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.WebSockets.Server.Test", "test\Microsoft.AspNetCore.WebSockets.Server.Test\Microsoft.AspNetCore.WebSockets.Server.Test.xproj", "{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutobahnTestApp", "test\AutobahnTestApp\AutobahnTestApp.xproj", "{9755F612-A155-4BDD-9E20-37ADE0B4B3BA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutobahnTestAppAspNet4", "samples\AutobahnTestAppAspNet4\AutobahnTestAppAspNet4.csproj", "{72E3AB32-682F-42AF-B7C7-0B777244FF11}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutobahnTestAppHttpListener", "samples\AutobahnTestAppHttpListener\AutobahnTestAppHttpListener.csproj", "{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
@ -38,10 +41,6 @@ Global
|
|||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0C10DEC-3339-4A47-85BC-3100C5D34AD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0C10DEC-3339-4A47-85BC-3100C5D34AD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0C10DEC-3339-4A47-85BC-3100C5D34AD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -50,10 +49,6 @@ Global
|
|||
{62A07A24-4D06-4DDA-B6BF-02D0C9CB7D32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62A07A24-4D06-4DDA-B6BF-02D0C9CB7D32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62A07A24-4D06-4DDA-B6BF-02D0C9CB7D32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A1C4875-AE21-4A78-979A-F0E4DF5EB518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A1C4875-AE21-4A78-979A-F0E4DF5EB518}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A1C4875-AE21-4A78-979A-F0E4DF5EB518}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -66,27 +61,45 @@ Global
|
|||
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78A097D0-C0A4-4AED-93E2-84A65392FB52}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C03C43FE-9201-48A6-B434-AD67EF627D67}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9755F612-A155-4BDD-9E20-37ADE0B4B3BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9755F612-A155-4BDD-9E20-37ADE0B4B3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9755F612-A155-4BDD-9E20-37ADE0B4B3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9755F612-A155-4BDD-9E20-37ADE0B4B3BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72E3AB32-682F-42AF-B7C7-0B777244FF11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72E3AB32-682F-42AF-B7C7-0B777244FF11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72E3AB32-682F-42AF-B7C7-0B777244FF11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72E3AB32-682F-42AF-B7C7-0B777244FF11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
{E0C10DEC-3339-4A47-85BC-3100C5D34AD4} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}
|
||||
{62A07A24-4D06-4DDA-B6BF-02D0C9CB7D32} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
{4A1C4875-AE21-4A78-979A-F0E4DF5EB518} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}
|
||||
{6604D154-817F-4BC5-BE95-FF7E851179D9} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{78A097D0-C0A4-4AED-93E2-84A65392FB52} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}
|
||||
{C03C43FE-9201-48A6-B434-AD67EF627D67} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{BC4D2BB1-05A8-4816-8BC1-3A664F09EE32} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{8C8EAC01-DC49-4C5E-B348-E4E46FE675F9} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
{E82D9F64-8AFA-4DCB-A842-2283FDA73BE8} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{9755F612-A155-4BDD-9E20-37ADE0B4B3BA} = {C45106D0-76C8-4776-A140-F7DD83CA2958}
|
||||
{72E3AB32-682F-42AF-B7C7-0B777244FF11} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
{B7246F23-6A4B-492F-AB61-292AA1A9E9D5} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ branches:
|
|||
- /^(.*\/)?ci-.*$/
|
||||
build_script:
|
||||
- build.cmd --quiet verify
|
||||
install:
|
||||
- set PATH=C:\Python27\scripts;%PATH%
|
||||
- pip install autobahntestsuite
|
||||
clone_depth: 1
|
||||
test: off
|
||||
deploy: off
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
use namespace="System.IO"
|
||||
|
||||
var VERSION='0.1'
|
||||
var FULL_VERSION='0.1'
|
||||
var AUTHORS='Microsoft'
|
||||
|
||||
use-standard-lifecycle
|
||||
k-standard-goals
|
||||
|
||||
var AUTOBAHN_REPORTS_DIR='${Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "autobahnreports")}'
|
||||
|
||||
#set-autobahn-report-dir target='initialize'
|
||||
@{
|
||||
E("AUTOBAHN_SUITES_REPORT_DIR", AUTOBAHN_REPORTS_DIR);
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
|
||||
<Import Project="..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" />
|
||||
<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>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{72E3AB32-682F-42AF-B7C7-0B777244FF11}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AutobahnTestAppAspNet4</RootNamespace>
|
||||
<AssemblyName>AutobahnTestAppAspNet4</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.EnterpriseServices" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
<Content Include="EchoSocket.ashx" />
|
||||
<Content Include="wstest-spec.json" />
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Web.Release.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="EchoSocket.ashx.cs">
|
||||
<DependentUpon>EchoSocket.ashx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>29392</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:29392</IISUrl>
|
||||
<OverrideIISAppRootUrl>True</OverrideIISAppRootUrl>
|
||||
<IISAppRootUrl>http://localhost:29392/EchoSocket.ashx</IISAppRootUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
|
||||
</Target>
|
||||
<!-- 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>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%@ WebHandler Language="C#" CodeBehind="EchoSocket.ashx.cs" Class="AutobahnTestAppAspNet4.EchoSocket" %>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace AutobahnTestAppAspNet4
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for EchoSocket
|
||||
/// </summary>
|
||||
public class EchoSocket : IHttpHandler
|
||||
{
|
||||
public bool IsReusable => false;
|
||||
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
if (context.IsWebSocketRequest)
|
||||
{
|
||||
context.AcceptWebSocketRequest(async socketContext =>
|
||||
{
|
||||
await Echo(socketContext.WebSocket);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.Write("Ready to accept WebSocket request at: " + context.Request.Url.ToString().Replace("https://", "wss://").Replace("http://", "ws://"));
|
||||
context.Response.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
var buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
while (!result.CloseStatus.HasValue)
|
||||
{
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
}
|
||||
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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("AutobahnTestAppAspNet4")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AutobahnTestAppAspNet4")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[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("72e3ab32-682f-42af-b7c7-0b777244ff11")]
|
||||
|
||||
// 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 Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation xdt:Transform="RemoveAttributes(debug)" />
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
For more information on how to configure your ASP.NET application, please visit
|
||||
http://go.microsoft.com/fwlink/?LinkId=169433
|
||||
-->
|
||||
<configuration>
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.6.1"/>
|
||||
<httpRuntime targetFramework="4.6.1"/>
|
||||
</system.web>
|
||||
<system.codedom>
|
||||
<compilers>
|
||||
<compiler language="c#;cs;csharp" extension=".cs"
|
||||
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
|
||||
warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
|
||||
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
|
||||
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
|
||||
warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+"/>
|
||||
</compilers>
|
||||
</system.codedom>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net461" />
|
||||
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net461" developmentDependency="true" />
|
||||
</packages>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"options": { "failByDrop": false },
|
||||
"outdir": "./bin/wstest-report",
|
||||
"servers": [
|
||||
{
|
||||
"agent": "ASP.NET 4",
|
||||
"url": "ws://localhost:29392/EchoSocket.ashx",
|
||||
"options": { "version": 18 }
|
||||
}
|
||||
],
|
||||
"cases": ["*"],
|
||||
"exclude-cases": ["12.*", "13.*"],
|
||||
"exclude-agent-cases": {}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.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>{B7246F23-6A4B-492F-AB61-292AA1A9E9D5}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AutobahnTestAppHttpListener</RootNamespace>
|
||||
<AssemblyName>AutobahnTestAppHttpListener</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</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="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</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>
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AutobahnTestAppHttpListener
|
||||
{
|
||||
class Program
|
||||
{
|
||||
// This app only works on Windows 8+
|
||||
static int Main(string[] args)
|
||||
{
|
||||
using (var listener = StartListener())
|
||||
{
|
||||
if (listener == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
var httpUrl = listener.Prefixes.Single();
|
||||
var wsUrl = httpUrl.Replace("http://", "ws://");
|
||||
|
||||
var stopTokenSource = new CancellationTokenSource();
|
||||
var task = Run(listener, wsUrl, stopTokenSource.Token);
|
||||
|
||||
Console.CancelKeyPress += (sender, a) =>
|
||||
{
|
||||
a.Cancel = true;
|
||||
stopTokenSource.Cancel();
|
||||
};
|
||||
|
||||
Console.WriteLine($"HTTP: {httpUrl}");
|
||||
Console.WriteLine($"WS : {wsUrl}");
|
||||
Console.WriteLine("Press Ctrl-C to stop...");
|
||||
|
||||
task.Wait();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static async Task Run(HttpListener listener, string wsUrl, CancellationToken stopToken)
|
||||
{
|
||||
while (!stopToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var context = await listener.GetContextAsync();
|
||||
|
||||
if (context.Request.IsWebSocketRequest)
|
||||
{
|
||||
var socket = await context.AcceptWebSocketAsync(null);
|
||||
await Echo(socket.WebSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var writer = new StreamWriter(context.Response.OutputStream))
|
||||
{
|
||||
await writer.WriteLineAsync($"Ready to accept WebSocket request at: {wsUrl}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Request failed: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
var buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
while (!result.CloseStatus.HasValue)
|
||||
{
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
}
|
||||
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
}
|
||||
|
||||
static HttpListener StartListener()
|
||||
{
|
||||
var port = 49152; // IANA recommends starting at port 49152 for dynamic ports
|
||||
while (port < 65535)
|
||||
{
|
||||
HttpListener listener = new HttpListener();
|
||||
listener.Prefixes.Add($"http://localhost:{port}/");
|
||||
try
|
||||
{
|
||||
listener.Start();
|
||||
return listener;
|
||||
}
|
||||
catch
|
||||
{
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
Console.Error.WriteLine("Failed to find a free port!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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("AutobahnTestAppHttpListener")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AutobahnTestAppHttpListener")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[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("b7246f23-6a4b-492f-ab61-292aa1a9e9d5")]
|
||||
|
||||
// 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")]
|
||||
|
|
@ -4,14 +4,22 @@
|
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>c03c43fe-9201-48a6-b434-ad67ef627d67</ProjectGuid>
|
||||
<ProjectGuid>9755f612-a155-4bdd-9e20-37ade0b4b3ba</ProjectGuid>
|
||||
<RootNamespace>AutobahnTestApp</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<DnxInvisibleContent Include="bower.json" />
|
||||
<DnxInvisibleContent Include=".bowerrc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AutobahnTestApp
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddCommandLine(args)
|
||||
.Build();
|
||||
|
||||
var builder = new WebHostBuilder()
|
||||
.UseConfiguration(config)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>();
|
||||
|
||||
if (string.Equals(builder.GetSetting("server"), "Microsoft.AspNetCore.Server.WebListener", System.StringComparison.Ordinal))
|
||||
{
|
||||
builder.UseWebListener();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.UseKestrel(options =>
|
||||
{
|
||||
var certPath = Path.Combine(AppContext.BaseDirectory, "TestResources", "testCert.pfx");
|
||||
options.UseHttps(certPath, "testPassword");
|
||||
});
|
||||
}
|
||||
|
||||
var host = builder.Build();
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:6155/",
|
||||
"sslPort": 44371
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
|
||||
}
|
||||
},
|
||||
"AutobahnTestApp": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
|
||||
}
|
||||
},
|
||||
"AutobahnTestApp (SSL)": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "https://localhost:5443",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
|
||||
}
|
||||
},
|
||||
"WebListener": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--server Microsoft.AspNetCore.Server.WebListener",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Autobahn Testing
|
||||
|
||||
This application is used to provide the server for the [Autobahn Test Suite](http://autobahn.ws/testsuite) 'fuzzingclient' mode to test. It is a simple echo server that echos each frame recieved back to the client.
|
||||
|
||||
In order to run these tests you must install CPython 2.7, Pip, and the test suite modules. You must also have
|
||||
the `wstest` executable provided by the Autobahn Suite on the `PATH`. See http://autobahn.ws/testsuite/installation.html#installation for more info
|
||||
|
||||
Once Autobahn is installed, launch this application in the desired configuration (in IIS Express, or using Kestrel directly) from Visual Studio and get the WebSocket URL from the HTTP response. Use that URL in place of `ws://server:1234` and invoke the `scripts\RunAutobahnTests.ps1` script in this project like so:
|
||||
|
||||
```
|
||||
> .\scripts\RunAutobahnTests.ps1 -ServerUrl ws://server:1234
|
||||
```
|
||||
|
||||
By default, all cases are run and the report is written to the `autobahnreports` sub-directory of the directory in which you run the script. You can change either by using the `-Cases` and `-OutputDir` switches, use `.\script\RunAutobahnTests.ps1 -?` for help.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace AutobahnTestApp
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
if (!env.IsEnvironment("NativeSockets"))
|
||||
{
|
||||
app.UseWebSockets(new WebSocketOptions
|
||||
{
|
||||
ReplaceFeature = true
|
||||
});
|
||||
}
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
await Echo(webSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
var wsScheme = context.Request.IsHttps ? "wss" : "ws";
|
||||
var wsUrl = $"{wsScheme}://{context.Request.Host.Host}:{context.Request.Host.Port}{context.Request.Path}";
|
||||
await context.Response.WriteAsync($"Ready to accept a WebSocket request at: {wsUrl}");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
var buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
while (!result.CloseStatus.HasValue)
|
||||
{
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
}
|
||||
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
The password for this is 'testPassword'
|
||||
|
||||
DO NOT EVER TRUST THIS CERT. The private key for it is publicly released.
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.WebSockets.Server": { "target": "project" },
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.WebListener": "0.2.0-*",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Https": "1.1.0-*",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0-*",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0-*"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-*"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"copyToOutput": [
|
||||
"TestResources/testCert.pfx"
|
||||
]
|
||||
},
|
||||
|
||||
"runtimeOptions": {
|
||||
"configProperties": {
|
||||
"System.GC.Server": true
|
||||
}
|
||||
},
|
||||
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"wwwroot",
|
||||
"web.config",
|
||||
"TestResources/testCert.pfx"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# RunAutobahnTests.ps1
|
||||
#
|
||||
param([Parameter(Mandatory=$true)][string]$ServerUrl, [string[]]$Cases = @("*"), [string]$OutputDir)
|
||||
|
||||
if(!(Get-Command wstest -ErrorAction SilentlyContinue)) {
|
||||
throw "Missing required command 'wstest'. See README.md in Microsoft.AspNetCore.WebSockets.Server.Test project for information on installing Autobahn Test Suite."
|
||||
}
|
||||
|
||||
if(!$OutputDir) {
|
||||
$OutputDir = Convert-Path "."
|
||||
$OutputDir = Join-Path $OutputDir "autobahnreports"
|
||||
}
|
||||
|
||||
$Spec = Convert-Path (Join-Path $PSScriptRoot "autobahn.spec.json")
|
||||
|
||||
$CasesArray = [string]::Join(",", @($Cases | ForEach-Object { "`"$_`"" }))
|
||||
|
||||
$SpecJson = [IO.File]::ReadAllText($Spec).Replace("OUTPUTDIR", $OutputDir.Replace("\", "\\")).Replace("WEBSOCKETURL", $ServerUrl).Replace("`"CASES`"", $CasesArray)
|
||||
|
||||
$TempFile = [IO.Path]::GetTempFileName()
|
||||
|
||||
try {
|
||||
[IO.File]::WriteAllText($TempFile, $SpecJson)
|
||||
& wstest -m fuzzingclient -s $TempFile
|
||||
} finally {
|
||||
if(Test-Path $TempFile) {
|
||||
rm $TempFile
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"options": { "failByDrop": false },
|
||||
"outdir": "OUTPUTDIR",
|
||||
"servers": [
|
||||
{
|
||||
"agent": "Server",
|
||||
"url": "WEBSOCKETURL",
|
||||
"options": { "version": 18 }
|
||||
}
|
||||
],
|
||||
"cases": ["CASES"],
|
||||
"exclude-cases": ["12.*", "13.*"],
|
||||
"exclude-agent-cases": {}
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.WebSockets.Client;
|
||||
|
||||
namespace AutobahnTestClient
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new Program().Run(args).Wait();
|
||||
}
|
||||
|
||||
private async Task Run(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string serverAddress = "ws://localhost:5000";
|
||||
string agent =
|
||||
"ManagedWebSockets";
|
||||
// "NativeWebSockets";
|
||||
|
||||
Console.WriteLine("Getting case count.");
|
||||
var caseCount = await GetCaseCountAsync(serverAddress, agent);
|
||||
Console.WriteLine(caseCount + " case(s).");
|
||||
|
||||
for (int i = 1; i <= caseCount; i++)
|
||||
{
|
||||
await RunCaseAsync(serverAddress, i, agent);
|
||||
}
|
||||
|
||||
await UpdateReportsAsync(serverAddress, agent);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
Console.WriteLine("Done");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
private async Task<WebSocket> ConnectAsync(string address, string agent)
|
||||
{
|
||||
if (string.Equals(agent, "NativeWebSockets"))
|
||||
{
|
||||
var client = new ClientWebSocket();
|
||||
await client.ConnectAsync(new Uri(address), CancellationToken.None);
|
||||
return client;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: BUG: Require ws or wss schemes
|
||||
var client = new WebSocketClient();
|
||||
return await client.ConnectAsync(new Uri(address), CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<int> GetCaseCountAsync(string serverAddress, string agent)
|
||||
{
|
||||
var webSocket = await ConnectAsync(serverAddress + "/getCaseCount", agent);
|
||||
byte[] buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
||||
var caseCountText = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
||||
return int.Parse(caseCountText);
|
||||
}
|
||||
|
||||
private async Task RunCaseAsync(string serverAddress, int caseId, string agent)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Running case " + caseId);
|
||||
var webSocket = await ConnectAsync(serverAddress + "/runCase?case=" + caseId + "&agent=" + agent, agent);
|
||||
await Echo(webSocket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
byte[] buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
while (!result.CloseStatus.HasValue)
|
||||
{
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
}
|
||||
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
}
|
||||
|
||||
private async Task UpdateReportsAsync(string serverAddress, string agent)
|
||||
{
|
||||
var webSocket = await ConnectAsync(serverAddress + "/updateReports?agent=" + agent, agent);
|
||||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
This test server is for use in testing client side implementations of the WebSocekt protocol. It is currently implemented to test
|
||||
Microsoft.AspNetCore.WebSockets.Client.WebSocketClient and System.Net.WebSockets.ClientWebSocket.
|
||||
|
||||
See http://autobahn.ws/ to download and install the test framework.
|
||||
|
||||
Usage:
|
||||
Run the test server:
|
||||
"C:\Program Files\Python\2.7.6\Scripts\wstest" -d -m fuzzingserver -s fuzzingserver.json
|
||||
Where fuzzingserver.json contains the following:
|
||||
|
||||
{
|
||||
"url": "ws://127.0.0.1:9001",
|
||||
|
||||
"options": {"failByDrop": false},
|
||||
"outdir": "./reports/clients",
|
||||
"webport": 8080,
|
||||
|
||||
"cases": ["*"],
|
||||
"exclude-cases": [],
|
||||
"exclude-agent-cases": {}
|
||||
}
|
||||
|
||||
Then run the client of your choice, taking care to update the serverAddress and agent fields in the client code.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.WebSockets.Client": "0.2.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
This test server is for use in testing server side implementations of the WebSocekt protocol. It should work with Helios, WebListener (native),
|
||||
and the managed implementation of WebSockets in this project (running on WebListener, Kestrel, etc.). The tests only require that the server implement
|
||||
a basic WebSocket accept and then echo any content received.
|
||||
|
||||
See http://autobahn.ws/ to download and install the test framework.
|
||||
|
||||
Usage:
|
||||
Configure and start the server of your choice.
|
||||
Run the test client:
|
||||
"C:\Program Files\Python\2.7.6\Scripts\wstest.exe" -d -m fuzzingclient -s fuzzingclient.json
|
||||
Where fussingclient.json contains:
|
||||
{
|
||||
"options": {"failByDrop": false},
|
||||
"outdir": "./reports/servers",
|
||||
|
||||
"servers": [
|
||||
{"agent": "NameOfImplementationBeingTested",
|
||||
"url": "ws://localhost:12345",
|
||||
"options": {"version": 18}}
|
||||
],
|
||||
|
||||
"cases": ["*"],
|
||||
"exclude-cases": [],
|
||||
"exclude-agent-cases": {}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace AutobahnTestServer
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.Map("/Managed", managedWebSocketsApp =>
|
||||
{
|
||||
// Comment this out to test native server implementations
|
||||
managedWebSocketsApp.UseWebSockets(new WebSocketOptions
|
||||
{
|
||||
ReplaceFeature = true
|
||||
});
|
||||
|
||||
managedWebSocketsApp.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
Console.WriteLine("Echo: " + context.Request.Path);
|
||||
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
await Echo(webSocket);
|
||||
return;
|
||||
}
|
||||
await next();
|
||||
});
|
||||
});
|
||||
|
||||
app.Map("/Native", nativeWebSocketsApp =>
|
||||
{
|
||||
nativeWebSocketsApp.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
Console.WriteLine("Echo: " + context.Request.Path);
|
||||
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
await Echo(webSocket);
|
||||
return;
|
||||
}
|
||||
await next();
|
||||
});
|
||||
});
|
||||
|
||||
app.Run(context =>
|
||||
{
|
||||
Console.WriteLine("Hello World");
|
||||
return context.Response.WriteAsync("Hello World");
|
||||
});
|
||||
}
|
||||
|
||||
private async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
byte[] buffer = new byte[1024 * 4];
|
||||
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
while (!result.CloseStatus.HasValue)
|
||||
{
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
}
|
||||
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.WebSockets.Server": "0.2.0-*",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*"
|
||||
},
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0-*",
|
||||
"type": "platform"
|
||||
},
|
||||
"dotnet-test-xunit": "2.2.0-*"
|
||||
}
|
||||
},
|
||||
"net451": {}
|
||||
},
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"web.config"
|
||||
]
|
||||
},
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": {
|
||||
"version": "1.0.0-*",
|
||||
"imports": "portable-net45+wp80+win8+wpa81+dnxcore50"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"postpublish": "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
|
||||
}
|
||||
}
|
||||
|
|
@ -13,5 +13,8 @@
|
|||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -13,5 +13,8 @@
|
|||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnCaseResult
|
||||
{
|
||||
public string Name { get; }
|
||||
public string ActualBehavior { get; }
|
||||
|
||||
public AutobahnCaseResult(string name, string actualBehavior)
|
||||
{
|
||||
Name = name;
|
||||
ActualBehavior = actualBehavior;
|
||||
}
|
||||
|
||||
public static AutobahnCaseResult FromJson(JProperty prop)
|
||||
{
|
||||
var caseObj = (JObject)prop.Value;
|
||||
var actualBehavior = (string)caseObj["behavior"];
|
||||
return new AutobahnCaseResult(prop.Name, actualBehavior);
|
||||
}
|
||||
|
||||
public bool BehaviorIs(params string[] behaviors)
|
||||
{
|
||||
return behaviors.Any(b => string.Equals(b, ActualBehavior, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Server.Testing;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnExpectations
|
||||
{
|
||||
private Dictionary<string, Expectation> _expectations = new Dictionary<string, Expectation>();
|
||||
public bool Ssl { get; }
|
||||
public ServerType Server { get; }
|
||||
public string Environment { get; }
|
||||
|
||||
public AutobahnExpectations(ServerType server, bool ssl, string environment)
|
||||
{
|
||||
Server = server;
|
||||
Ssl = ssl;
|
||||
Environment = environment;
|
||||
}
|
||||
|
||||
public AutobahnExpectations Fail(params string[] caseSpecs) => Expect(Expectation.Fail, caseSpecs);
|
||||
public AutobahnExpectations NonStrict(params string[] caseSpecs) => Expect(Expectation.NonStrict, caseSpecs);
|
||||
public AutobahnExpectations OkOrNonStrict(params string[] caseSpecs) => Expect(Expectation.OkOrNonStrict, caseSpecs);
|
||||
public AutobahnExpectations OkOrFail(params string[] caseSpecs) => Expect(Expectation.OkOrFail, caseSpecs);
|
||||
|
||||
public AutobahnExpectations Expect(Expectation expectation, params string[] caseSpecs)
|
||||
{
|
||||
foreach (var caseSpec in caseSpecs)
|
||||
{
|
||||
_expectations[caseSpec] = expectation;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
internal void Verify(AutobahnServerResult serverResult, StringBuilder failures)
|
||||
{
|
||||
foreach (var caseResult in serverResult.Cases)
|
||||
{
|
||||
// If this is an informational test result, we can't compare it to anything
|
||||
if (!string.Equals(caseResult.ActualBehavior, "INFORMATIONAL", StringComparison.Ordinal))
|
||||
{
|
||||
Expectation expectation;
|
||||
if (!_expectations.TryGetValue(caseResult.Name, out expectation))
|
||||
{
|
||||
expectation = Expectation.Ok;
|
||||
}
|
||||
|
||||
switch (expectation)
|
||||
{
|
||||
case Expectation.Fail:
|
||||
if (!caseResult.BehaviorIs("FAILED"))
|
||||
{
|
||||
failures.AppendLine($"Case {serverResult.Name}:{caseResult.Name}. Expected 'FAILED', but got '{caseResult.ActualBehavior}'");
|
||||
}
|
||||
break;
|
||||
case Expectation.NonStrict:
|
||||
if (!caseResult.BehaviorIs("NON-STRICT"))
|
||||
{
|
||||
failures.AppendLine($"Case {serverResult.Name}:{caseResult.Name}. Expected 'NON-STRICT', but got '{caseResult.ActualBehavior}'");
|
||||
}
|
||||
break;
|
||||
case Expectation.Ok:
|
||||
if (!caseResult.BehaviorIs("OK"))
|
||||
{
|
||||
failures.AppendLine($"Case {serverResult.Name}:{caseResult.Name}. Expected 'OK', but got '{caseResult.ActualBehavior}'");
|
||||
}
|
||||
break;
|
||||
case Expectation.OkOrNonStrict:
|
||||
if (!caseResult.BehaviorIs("NON-STRICT") && !caseResult.BehaviorIs("OK"))
|
||||
{
|
||||
failures.AppendLine($"Case {serverResult.Name}:{caseResult.Name}. Expected 'NON-STRICT' or 'OK', but got '{caseResult.ActualBehavior}'");
|
||||
}
|
||||
break;
|
||||
case Expectation.OkOrFail:
|
||||
if (!caseResult.BehaviorIs("FAILED") && !caseResult.BehaviorIs("OK"))
|
||||
{
|
||||
failures.AppendLine($"Case {serverResult.Name}:{caseResult.Name}. Expected 'FAILED' or 'OK', but got '{caseResult.ActualBehavior}'");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Server.Testing;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnResult
|
||||
{
|
||||
public IEnumerable<AutobahnServerResult> Servers { get; }
|
||||
|
||||
public AutobahnResult(IEnumerable<AutobahnServerResult> servers)
|
||||
{
|
||||
Servers = servers;
|
||||
}
|
||||
|
||||
public static AutobahnResult FromReportJson(JObject indexJson)
|
||||
{
|
||||
// Load the report
|
||||
return new AutobahnResult(indexJson.Properties().Select(AutobahnServerResult.FromJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Server.Testing;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnServerResult
|
||||
{
|
||||
public ServerType Server { get; }
|
||||
public bool Ssl { get; }
|
||||
public string Environment { get; }
|
||||
public string Name { get; }
|
||||
public IEnumerable<AutobahnCaseResult> Cases { get; }
|
||||
|
||||
public AutobahnServerResult(string name, IEnumerable<AutobahnCaseResult> cases)
|
||||
{
|
||||
Name = name;
|
||||
|
||||
var splat = name.Split('|');
|
||||
if (splat.Length < 3)
|
||||
{
|
||||
throw new FormatException("Results incorrectly formatted");
|
||||
}
|
||||
|
||||
Server = (ServerType)Enum.Parse(typeof(ServerType), splat[0]);
|
||||
Ssl = string.Equals(splat[1], "SSL", StringComparison.Ordinal);
|
||||
Environment = splat[2];
|
||||
Cases = cases;
|
||||
}
|
||||
|
||||
public static AutobahnServerResult FromJson(JProperty prop)
|
||||
{
|
||||
var valueObj = ((JObject)prop.Value);
|
||||
return new AutobahnServerResult(prop.Name, valueObj.Properties().Select(AutobahnCaseResult.FromJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnSpec
|
||||
{
|
||||
public string OutputDirectory { get; }
|
||||
public IList<ServerSpec> Servers { get; } = new List<ServerSpec>();
|
||||
public IList<string> Cases { get; } = new List<string>();
|
||||
public IList<string> ExcludedCases { get; } = new List<string>();
|
||||
|
||||
public AutobahnSpec(string outputDirectory)
|
||||
{
|
||||
OutputDirectory = outputDirectory;
|
||||
}
|
||||
|
||||
public AutobahnSpec WithServer(string name, string url)
|
||||
{
|
||||
Servers.Add(new ServerSpec(name, url));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AutobahnSpec IncludeCase(params string[] caseSpecs)
|
||||
{
|
||||
foreach (var caseSpec in caseSpecs)
|
||||
{
|
||||
Cases.Add(caseSpec);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AutobahnSpec ExcludeCase(params string[] caseSpecs)
|
||||
{
|
||||
foreach (var caseSpec in caseSpecs)
|
||||
{
|
||||
ExcludedCases.Add(caseSpec);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void WriteJson(string file)
|
||||
{
|
||||
File.WriteAllText(file, GetJson().ToString(Formatting.Indented));
|
||||
}
|
||||
|
||||
public JObject GetJson() => new JObject(
|
||||
new JProperty("options", new JObject(
|
||||
new JProperty("failByDrop", false))),
|
||||
new JProperty("outdir", OutputDirectory),
|
||||
new JProperty("servers", new JArray(Servers.Select(s => s.GetJson()).ToArray())),
|
||||
new JProperty("cases", new JArray(Cases.ToArray())),
|
||||
new JProperty("exclude-cases", new JArray(ExcludedCases.ToArray())),
|
||||
new JProperty("exclude-agent-cases", new JObject()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.Testing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class AutobahnTester : IDisposable
|
||||
{
|
||||
private int _nextPort;
|
||||
private readonly List<IApplicationDeployer> _deployers = new List<IApplicationDeployer>();
|
||||
private readonly List<AutobahnExpectations> _expectations = new List<AutobahnExpectations>();
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public AutobahnSpec Spec { get; }
|
||||
|
||||
public AutobahnTester(ILoggerFactory loggerFactory, AutobahnSpec baseSpec) : this(7000, loggerFactory, baseSpec) { }
|
||||
|
||||
public AutobahnTester(int startPort, ILoggerFactory loggerFactory, AutobahnSpec baseSpec)
|
||||
{
|
||||
_nextPort = startPort;
|
||||
_loggerFactory = loggerFactory;
|
||||
_logger = _loggerFactory.CreateLogger("AutobahnTester");
|
||||
|
||||
Spec = baseSpec;
|
||||
}
|
||||
|
||||
public async Task<AutobahnResult> Run()
|
||||
{
|
||||
var specFile = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
Spec.WriteJson(specFile);
|
||||
|
||||
// Run the test (write something to the console so people know this will take a while...)
|
||||
_logger.LogInformation("Now launching Autobahn Test Suite. This will take a while.");
|
||||
var exitCode = await Wstest.Default.ExecAsync("-m fuzzingclient -s " + specFile);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
throw new Exception("wstest failed");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(specFile))
|
||||
{
|
||||
File.Delete(specFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the output.
|
||||
var outputFile = Path.Combine(Directory.GetCurrentDirectory(), Spec.OutputDirectory, "index.json");
|
||||
using (var reader = new StreamReader(File.OpenRead(outputFile)))
|
||||
{
|
||||
return AutobahnResult.FromReportJson(JObject.Parse(await reader.ReadToEndAsync()));
|
||||
}
|
||||
}
|
||||
|
||||
public void Verify(AutobahnResult result)
|
||||
{
|
||||
var failures = new StringBuilder();
|
||||
foreach (var serverResult in result.Servers)
|
||||
{
|
||||
var serverExpectation = _expectations.FirstOrDefault(e => e.Server == serverResult.Server && e.Ssl == serverResult.Ssl);
|
||||
if (serverExpectation == null)
|
||||
{
|
||||
failures.AppendLine($"Expected no results for server: {serverResult.Name} but found results!");
|
||||
}
|
||||
else
|
||||
{
|
||||
serverExpectation.Verify(serverResult, failures);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(failures.Length == 0, "Autobahn results did not meet expectations:" + Environment.NewLine + failures.ToString());
|
||||
}
|
||||
|
||||
public async Task DeployTestAndAddToSpec(ServerType server, bool ssl, string environment, Action<AutobahnExpectations> expectationConfig = null)
|
||||
{
|
||||
var port = Interlocked.Increment(ref _nextPort);
|
||||
var baseUrl = ssl ? $"https://localhost:{port}" : $"http://localhost:{port}";
|
||||
var sslNamePart = ssl ? "SSL" : "NoSSL";
|
||||
var name = $"{server}|{sslNamePart}|{environment}";
|
||||
var logger = _loggerFactory.CreateLogger($"AutobahnTestApp:{server}:{sslNamePart}:{environment}");
|
||||
|
||||
var appPath = Helpers.GetApplicationPath("AutobahnTestApp");
|
||||
var parameters = new DeploymentParameters(appPath, server, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
|
||||
{
|
||||
ApplicationBaseUriHint = baseUrl,
|
||||
ApplicationType = ApplicationType.Portable,
|
||||
TargetFramework = "netcoreapp1.0",
|
||||
EnvironmentName = environment
|
||||
};
|
||||
|
||||
var deployer = ApplicationDeployerFactory.Create(parameters, logger);
|
||||
var result = deployer.Deploy();
|
||||
|
||||
#if NET451
|
||||
System.Net.ServicePointManager.ServerCertificateValidationCallback = (_, __, ___, ____) => true;
|
||||
var client = new HttpClient();
|
||||
#else
|
||||
var handler = new HttpClientHandler();
|
||||
if (ssl)
|
||||
{
|
||||
// Don't take this out of the "if(ssl)". If we set it on some platforms, it crashes
|
||||
// So we avoid running SSL tests on those platforms (for now).
|
||||
// See https://github.com/dotnet/corefx/issues/9728
|
||||
handler.ServerCertificateCustomValidationCallback = (_, __, ___, ____) => true;
|
||||
}
|
||||
var client = new HttpClient(handler);
|
||||
#endif
|
||||
|
||||
// Make sure the server works
|
||||
var resp = await RetryHelper.RetryRequest(() =>
|
||||
{
|
||||
return client.GetAsync(result.ApplicationBaseUri);
|
||||
}, logger, result.HostShutdownToken, retryCount: 5);
|
||||
resp.EnsureSuccessStatusCode();
|
||||
|
||||
// Add to the current spec
|
||||
var wsUrl = result.ApplicationBaseUri.Replace("https://", "wss://").Replace("http://", "ws://");
|
||||
Spec.WithServer(name, wsUrl);
|
||||
|
||||
_deployers.Add(deployer);
|
||||
|
||||
var expectations = new AutobahnExpectations(server, ssl, environment);
|
||||
expectationConfig?.Invoke(expectations);
|
||||
_expectations.Add(expectations);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var deployer in _deployers)
|
||||
{
|
||||
deployer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class Executable
|
||||
{
|
||||
private static readonly string _exeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
|
||||
private readonly string _path;
|
||||
|
||||
protected Executable(string path)
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public static string Locate(string name)
|
||||
{
|
||||
foreach (var dir in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
|
||||
{
|
||||
var candidate = Path.Combine(dir, name + _exeSuffix);
|
||||
if (File.Exists(candidate))
|
||||
{
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<int> ExecAsync(string args)
|
||||
{
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = _path,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
|
||||
process.Exited += (_, __) => tcs.TrySetResult(process.ExitCode);
|
||||
|
||||
process.Start();
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public enum Expectation
|
||||
{
|
||||
Fail,
|
||||
NonStrict,
|
||||
OkOrFail,
|
||||
Ok,
|
||||
OkOrNonStrict
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
public class ServerSpec
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Url { get; }
|
||||
|
||||
public ServerSpec(string name, string url)
|
||||
{
|
||||
Name = name;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public JObject GetJson() => new JObject(
|
||||
new JProperty("agent", Name),
|
||||
new JProperty("url", Url),
|
||||
new JProperty("options", new JObject(
|
||||
new JProperty("version", 18))));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper around the Autobahn Test Suite's "wstest" app.
|
||||
/// </summary>
|
||||
public class Wstest : Executable
|
||||
{
|
||||
private static Lazy<Wstest> _instance = new Lazy<Wstest>(Create);
|
||||
|
||||
public static Wstest Default => _instance.Value;
|
||||
|
||||
public Wstest(string path) : base(path) { }
|
||||
|
||||
private static Wstest Create()
|
||||
{
|
||||
var location = Locate("wstest");
|
||||
return location == null ? null : new Wstest(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test
|
||||
{
|
||||
public class AutobahnTests
|
||||
{
|
||||
// Skip if wstest is not installed for now, see https://github.com/aspnet/WebSockets/issues/95
|
||||
// We will enable Wstest on every build once we've gotten the necessary infrastructure sorted out :).
|
||||
[ConditionalFact]
|
||||
[SkipIfWsTestNotPresent]
|
||||
public async Task AutobahnTestSuite()
|
||||
{
|
||||
var reportDir = Environment.GetEnvironmentVariable("AUTOBAHN_SUITES_REPORT_DIR");
|
||||
var outDir = !string.IsNullOrEmpty(reportDir) ?
|
||||
reportDir :
|
||||
Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "autobahnreports");
|
||||
|
||||
if (Directory.Exists(outDir))
|
||||
{
|
||||
Directory.Delete(outDir, recursive: true);
|
||||
}
|
||||
|
||||
outDir = outDir.Replace("\\", "\\\\");
|
||||
|
||||
// 9.* is Limits/Performance which is VERY SLOW; 12.*/13.* are compression which we don't implement
|
||||
var spec = new AutobahnSpec(outDir)
|
||||
.IncludeCase("*")
|
||||
.ExcludeCase("9.*", "12.*", "13.*");
|
||||
|
||||
var loggerFactory = new LoggerFactory(); // No logging! It's very loud...
|
||||
|
||||
AutobahnResult result;
|
||||
using (var tester = new AutobahnTester(loggerFactory, spec))
|
||||
{
|
||||
await tester.DeployTestAndAddToSpec(ServerType.Kestrel, ssl: false, environment: "ManagedSockets", expectationConfig: expect => expect
|
||||
.NonStrict("6.4.3", "6.4.4")); // https://github.com/aspnet/WebSockets/issues/99
|
||||
|
||||
// Windows-only IIS tests, and Kestrel SSL tests (due to: https://github.com/aspnet/WebSockets/issues/102)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
await tester.DeployTestAndAddToSpec(ServerType.Kestrel, ssl: true, environment: "ManagedSockets", expectationConfig: expect => expect
|
||||
.NonStrict("6.4.3", "6.4.4")); // https://github.com/aspnet/WebSockets/issues/99
|
||||
|
||||
if (IsIISExpress10Installed())
|
||||
{
|
||||
// IIS Express tests are a bit flaky, some tests fail occasionally or get non-strict passes
|
||||
// https://github.com/aspnet/WebSockets/issues/100
|
||||
await tester.DeployTestAndAddToSpec(ServerType.IISExpress, ssl: false, environment: "ManagedSockets", expectationConfig: expect => expect
|
||||
.OkOrFail(Enumerable.Range(1, 20).Select(i => $"5.{i}").ToArray()) // 5.* occasionally fail on IIS express
|
||||
.OkOrNonStrict("3.2", "3.3", "3.4", "4.1.3", "4.1.4", "4.1.5", "4.2.3", "4.2.4", "4.2.5", "5.15")); // These occasionally get non-strict results
|
||||
}
|
||||
|
||||
if (IsWindows8OrHigher())
|
||||
{
|
||||
await tester.DeployTestAndAddToSpec(ServerType.WebListener, ssl: false, environment: "ManagedSockets", expectationConfig: expect => expect
|
||||
.Fail("6.1.2", "6.1.3") // https://github.com/aspnet/WebSockets/issues/97
|
||||
.NonStrict("6.4.3", "6.4.4")); // https://github.com/aspnet/WebSockets/issues/99
|
||||
}
|
||||
}
|
||||
|
||||
// REQUIRES a build of WebListener that supports native WebSockets, which we don't have right now
|
||||
//await tester.DeployTestAndAddToSpec(ServerType.WebListener, ssl: false, environment: "NativeSockets");
|
||||
|
||||
result = await tester.Run();
|
||||
tester.Verify(result);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsWindows8OrHigher()
|
||||
{
|
||||
const string WindowsName = "Microsoft Windows ";
|
||||
const int VersionOffset = 18;
|
||||
|
||||
if (RuntimeInformation.OSDescription.StartsWith(WindowsName))
|
||||
{
|
||||
var versionStr = RuntimeInformation.OSDescription.Substring(VersionOffset);
|
||||
Version version;
|
||||
if (Version.TryParse(versionStr, out version))
|
||||
{
|
||||
return version.Major > 6 || (version.Major == 6 && version.Minor >= 2);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsIISExpress10Installed()
|
||||
{
|
||||
var pf = Environment.GetEnvironmentVariable("PROGRAMFILES");
|
||||
var iisExpressExe = Path.Combine(pf, "IIS Express", "iisexpress.exe");
|
||||
return File.Exists(iisExpressExe) && FileVersionInfo.GetVersionInfo(iisExpressExe).FileMajorPart >= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test
|
||||
{
|
||||
public class Helpers
|
||||
{
|
||||
public static string GetApplicationPath(string projectName)
|
||||
{
|
||||
var applicationBasePath = PlatformServices.Default.Application.ApplicationBasePath;
|
||||
|
||||
var directoryInfo = new DirectoryInfo(applicationBasePath);
|
||||
do
|
||||
{
|
||||
var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, "WebSockets.sln"));
|
||||
if (solutionFileInfo.Exists)
|
||||
{
|
||||
return Path.GetFullPath(Path.Combine(directoryInfo.FullName, "test", projectName));
|
||||
}
|
||||
|
||||
directoryInfo = directoryInfo.Parent;
|
||||
}
|
||||
while (directoryInfo.Parent != null);
|
||||
|
||||
throw new Exception($"Solution root could not be found using {applicationBasePath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,14 +4,17 @@
|
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>bc4d2bb1-05a8-4816-8bc1-3a664f09ee32</ProjectGuid>
|
||||
<ProjectGuid>e82d9f64-8afa-4dcb-a842-2283fda73be8</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
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: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Microsoft.AspNetCore.WebSockets.Server.Test")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// 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("e82d9f64-8afa-4dcb-a842-2283fda73be8")]
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.AspNetCore.WebSockets.Server.Test.Autobahn;
|
||||
|
||||
namespace Microsoft.AspNetCore.WebSockets.Server.Test
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class SkipIfWsTestNotPresentAttribute : Attribute, ITestCondition
|
||||
{
|
||||
public bool IsMet => Wstest.Default != null;
|
||||
public string SkipReason => "Autobahn Test Suite is not installed on the host machine.";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"dotnet-test-xunit": "2.2.0-*",
|
||||
"Microsoft.AspNetCore.Server.Testing": "0.2.0-*",
|
||||
"Microsoft.AspNetCore.Testing": "1.1.0-*",
|
||||
"Microsoft.Extensions.Logging": "1.1.0-*",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0-*",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.1.0-*",
|
||||
"System.Diagnostics.FileVersionInfo": "4.0.0",
|
||||
"xunit": "2.2.0-*"
|
||||
},
|
||||
"testRunner": "xunit",
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0-*",
|
||||
"type": "platform"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue