1
0
Форкнуть 0

Added EmptyApp20 and FunctionalTestUtils20

This commit is contained in:
Cijo Thomas 2017-08-31 13:22:56 -07:00
Родитель 36d363c61c
Коммит 4d91ca68aa
15 изменённых файлов: 675 добавлений и 4 удалений

Просмотреть файл

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
VisualStudioVersion = 15.0.26730.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2E6DDE9E-8C75-4F9C-8906-08EBDD6E73EF}"
EndProject
@ -38,6 +38,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmptyApp.FunctionalTests",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCFramework45.FunctionalTests", "test\MVCFramework45.FunctionalTests\MVCFramework45.FunctionalTests.csproj", "{9F83564A-F84D-494A-9658-B080757EA82C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmptyApp20.FunctionalTests", "test\EmptyApp20.FunctionalTests\EmptyApp20.FunctionalTests.csproj", "{C47AFD8A-3326-4391-8115-69349C04C3DA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTestUtils20", "test\FunctionalTestUtils20\FunctionalTestUtils20.csproj", "{937AF006-898E-43FD-80A6-B20D7E3A1944}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -68,6 +72,14 @@ Global
{9F83564A-F84D-494A-9658-B080757EA82C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F83564A-F84D-494A-9658-B080757EA82C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F83564A-F84D-494A-9658-B080757EA82C}.Release|Any CPU.Build.0 = Release|Any CPU
{C47AFD8A-3326-4391-8115-69349C04C3DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C47AFD8A-3326-4391-8115-69349C04C3DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C47AFD8A-3326-4391-8115-69349C04C3DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C47AFD8A-3326-4391-8115-69349C04C3DA}.Release|Any CPU.Build.0 = Release|Any CPU
{937AF006-898E-43FD-80A6-B20D7E3A1944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{937AF006-898E-43FD-80A6-B20D7E3A1944}.Debug|Any CPU.Build.0 = Debug|Any CPU
{937AF006-898E-43FD-80A6-B20D7E3A1944}.Release|Any CPU.ActiveCfg = Release|Any CPU
{937AF006-898E-43FD-80A6-B20D7E3A1944}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -80,5 +92,10 @@ Global
{11FB2EE6-7199-4AFF-BC73-25F35675F233} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{71CE2DB2-C7AA-4454-B5F2-774BC575E321} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{9F83564A-F84D-494A-9658-B080757EA82C} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{C47AFD8A-3326-4391-8115-69349C04C3DA} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{937AF006-898E-43FD-80A6-B20D7E3A1944} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {047855A4-470F-43B1-8B74-69651DD6B8A6}
EndGlobalSection
EndGlobal

Двоичные данные
NuGet.exe

Двоичный файл не отображается.

Просмотреть файл

@ -12,10 +12,14 @@
<ItemGroup>
<!--<Solution Include="src\Microsoft.ApplicationInsights.AspNetCore\Microsoft.ApplicationInsights.AspNetCore.xproj" />-->
<!-- Tests -->
<TestProject Include="test\Microsoft.ApplicationInsights.AspNetCore.Tests\ " />
<!--
<TestProject Include="test\Microsoft.ApplicationInsights.AspNetCore.Tests\ " />
<TestProject Include="test\WebApiShimFw46.FunctionalTests\ " />
<TestProject Include="test\EmptyApp.FunctionalTests\ " />
<TestProject Include="test\EmptyApp20.FunctionalTests\ " />
<TestProject Include="test\MVCFramework45.FunctionalTests\ " />
-->
<TestProject Include="test\EmptyApp20.FunctionalTests\ " />
</ItemGroup>
<UsingTask TaskName="DownloadFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
@ -169,7 +173,7 @@
<Exec Command=".\nuget.exe locals all -clear" ContinueOnError="ErrorAndStop" />
</Target>
<Target Name="Build" DependsOnTargets="CheckBuildParameters;DownloadCLI">
<Target Name="Build">
<Exec Command='"$(CliToolsPath)\dotnet.exe" --version' />
<Exec Command='"nuget.exe" restore' ContinueOnError="ErrorAndStop" />
<Exec Command='"$(CliToolsPath)\dotnet.exe" build $(ProjectToBuild) -c $(Configuration)' ContinueOnError="ErrorAndStop" />
@ -178,7 +182,7 @@
<Target Name="Test" AfterTargets="Build" DependsOnTargets="Build">
<Message Condition="$(RunTests) != '' And $(RunTests)" Importance="high" Text="Running tests..."></Message>
<Exec Condition="$(RunTests) != '' And $(RunTests)" Command='"$(CliToolsPath)\dotnet.exe" test' WorkingDirectory='%(TestProject.Identity)' ContinueOnError="ErrorAndStop" />
<Exec Condition="$(RunTests) != '' And $(RunTests)" Command='"$(CliToolsPath)\dotnet.exe" test -l trx' WorkingDirectory='%(TestProject.Identity)' ContinueOnError="ErrorAndContinue" />
</Target>
<Target Name="Clean">

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="4.0.0.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="4.0.0.0" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<TargetFrameworks>net46;netcoreapp2.0</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' == 'net46' ">win7-x86</RuntimeIdentifier>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>EmptyApp20.FunctionalTests</AssemblyName>
<AssemblyOriginatorKeyFile>../../keys/35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>EmptyApp.FunctionalTests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">2.0.0</RuntimeFrameworkVersion>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\test\$(MSBuildProjectName)</OutputPath>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Condition=" '$(TargetFramework)' != 'net46' " Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionalTestUtils20\FunctionalTestUtils20.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="App.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Generator>SettingsSingleFileGenerator</Generator>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,44 @@
using System.Diagnostics;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace EmptyApp20.FunctionalTests.FunctionalTest
{
using System;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
public class ExceptionTelemetryEmptyAppTests : TelemetryTestsBase
{
private const string assemblyName = "EmptyApp20.FunctionalTests";
[Fact]
public void TestBasicRequestPropertiesAfterRequestingRequestThatThrows()
{
using (var server = new InProcessServer(assemblyName))
{
const string RequestPath = "/Exception";
var expectedRequestTelemetry = new RequestTelemetry();
expectedRequestTelemetry.Name = "GET /Exception";
expectedRequestTelemetry.ResponseCode = "500";
expectedRequestTelemetry.Success = false;
expectedRequestTelemetry.Url = new System.Uri(server.BaseHost + RequestPath);
this.ValidateBasicRequest(server, "/Exception", expectedRequestTelemetry);
}
}
[Fact]
public void TestBasicExceptionPropertiesAfterRequestingRequestThatThrows()
{
using (var server = new InProcessServer(assemblyName))
{
var expectedExceptionTelemetry = new ExceptionTelemetry();
expectedExceptionTelemetry.Exception = new InvalidOperationException();
this.ValidateBasicException(server, "/Exception", expectedExceptionTelemetry);
}
}
}
}

Просмотреть файл

@ -0,0 +1,72 @@
namespace EmptyApp20.FunctionalTests.FunctionalTest
{
using System.Linq;
using System.Net.Http;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
public class RequestTelemetryEmptyAppTests : TelemetryTestsBase
{
private const string assemblyName = "EmptyApp20.FunctionalTests";
[Fact]
public void TestBasicRequestPropertiesAfterRequestingBasicPage()
{
using (var server = new InProcessServer(assemblyName))
{
const string RequestPath = "/";
var expectedRequestTelemetry = new RequestTelemetry();
expectedRequestTelemetry.Name = "GET /";
expectedRequestTelemetry.ResponseCode = "200";
expectedRequestTelemetry.Success = true;
expectedRequestTelemetry.Url = new System.Uri(server.BaseHost + RequestPath);
this.ValidateBasicRequest(server, RequestPath, expectedRequestTelemetry);
}
}
[Fact]
public void TestBasicRequestPropertiesAfterRequestingNotExistingPage()
{
using (var server = new InProcessServer(assemblyName))
{
const string RequestPath = "/not/existing/controller";
var expectedRequestTelemetry = new RequestTelemetry();
expectedRequestTelemetry.Name = "GET /not/existing/controller";
expectedRequestTelemetry.ResponseCode = "404";
expectedRequestTelemetry.Success = false;
expectedRequestTelemetry.Url = new System.Uri(server.BaseHost + RequestPath);
this.ValidateBasicRequest(server, RequestPath, expectedRequestTelemetry);
}
}
[Fact]
public void TestMixedTelemetryItemsReceived()
{
InProcessServer server;
using (server = new InProcessServer(assemblyName))
{
using (var httpClient = new HttpClient())
{
var task = httpClient.GetAsync(server.BaseHost + "/Mixed");
task.Wait(TestTimeoutMs);
}
}
var telemetries = server.BackChannel.Buffer;
Assert.Contains(telemetries.OfType<DependencyTelemetry>(), t => t.Name == "GET /Mixed");
Assert.True(telemetries.Count >= 4);
Assert.Contains(telemetries.OfType<RequestTelemetry>(), t => t.Name == "GET /Mixed");
Assert.Contains(telemetries.OfType<EventTelemetry>(), t => t.Name == "GetContact");
Assert.Contains(telemetries.OfType<MetricTelemetry>(),
t => t.Name == "ContactFile" && t.Value == 1);
Assert.Contains(telemetries.OfType<TraceTelemetry>(),
t => t.Message == "Fetched contact details." && t.SeverityLevel == SeverityLevel.Information);
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
namespace EmptyApp20.FunctionalTests.FunctionalTest
{
using FunctionalTestUtils;
using Xunit;
public class TelemetryModuleWorkingEmptyAppTests : TelemetryTestsBase
{
private const string assemblyName = "EmptyApp20.FunctionalTests";
// The NET451 conditional check is wrapped inside the test to make the tests visible in the test explorer. We can move them to the class level once if the issue is resolved.
[Fact]
public void TestBasicDependencyPropertiesAfterRequestingBasicPage()
{
this.ValidateBasicDependency(assemblyName, "/");
}
[Fact]
public void TestIfPerformanceCountersAreCollected()
{
#if NET451 || NET46
ValidatePerformanceCountersAreCollected(assemblyName);
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4828/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNET_ENVIRONMENT": "Development"
}
},
"web": {
"commandName": "web",
"environmentVariables": {
"ASPNET_ENVIRONMENT": "Development"
}
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
namespace EmptyApp.FunctionalTests
{
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.ApplicationInsights.Channel;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
public class Startup
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITelemetryChannel>(new BackTelemetryChannel());
var builder = new ConfigurationBuilder();
builder.AddApplicationInsightsSettings(instrumentationKey: "Foo");
services.AddApplicationInsightsTelemetry(builder.Build());
}
public void Configure(IApplicationBuilder app)
{
#if !NET46
app.UseDeveloperExceptionPage();
#endif
app.Use(next =>
{
return async context =>
{
if (context.Request.GetUri().ToString().Contains("Exception"))
{
throw new InvalidOperationException();
}
else if (context.Request.GetUri().PathAndQuery == "/")
{
await context.Response.WriteAsync("Hello!");
}
else if (context.Request.GetUri().ToString().Contains("Mixed"))
{
TelemetryClient telemetryClient = (TelemetryClient)context.RequestServices.GetService(typeof(TelemetryClient));
telemetryClient.TrackEvent("GetContact");
telemetryClient.TrackMetric("ContactFile", 1);
telemetryClient.TrackTrace("Fetched contact details.", SeverityLevel.Information);
await context.Response.WriteAsync("Hello!");
}
else
{
await next(context);
}
};
});
}
}
}

Просмотреть файл

@ -0,0 +1,61 @@
namespace FunctionalTestUtils
{
using System;
using System.Collections.Generic;
using Microsoft.ApplicationInsights.Channel;
public class BackTelemetryChannel : ITelemetryChannel
{
private IList<ITelemetry> buffer;
public BackTelemetryChannel()
{
this.buffer = new List<ITelemetry>();
}
public IList<ITelemetry> Buffer
{
get
{
return this.buffer;
}
}
public bool? DeveloperMode
{
get
{
return true;
}
set
{
}
}
public string EndpointAddress
{
get
{
return "https://dc.services.visualstudio.com/v2/track";
}
set
{
}
}
public void Dispose()
{
}
public void Flush()
{
throw new NotImplementedException();
}
public void Send(ITelemetry item)
{
this.buffer.Add(item);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>1.0.2</VersionPrefix>
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>FunctionalTestUtils20</AssemblyName>
<AssemblyOriginatorKeyFile>../../keys/35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>FunctionalTestUtils</PackageId>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\test\$(MSBuildProjectName)</OutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.ApplicationInsights.AspNetCore\Microsoft.ApplicationInsights.AspNetCore.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Condition=" '$(TargetFramework)' == 'net46' " Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.0.3" />
<PackageReference Condition=" '$(TargetFramework)' != 'net46' " Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Condition=" '$(TargetFramework)' != 'net46' " Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Condition=" '$(TargetFramework)' != 'net46' " Include="NETStandard.Library" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,86 @@
namespace FunctionalTestUtils
{
using System;
using System.IO;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore;
// a variant of aspnet/Hosting/test/Microsoft.AspNetCore.Hosting.Tests/HostingEngineTests.cs
public class InProcessServer : IDisposable
{
private static Random random = new Random();
public static Func<IWebHostBuilder, IWebHostBuilder> UseApplicationInsights =
builder => builder.UseApplicationInsights();
private readonly Func<IWebHostBuilder, IWebHostBuilder> configureHost;
private IWebHost hostingEngine;
private string url;
private readonly BackTelemetryChannel backChannel;
public BackTelemetryChannel BackChannel
{
get
{
return this.backChannel;
}
}
public InProcessServer(string assemblyName, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
{
this.configureHost = configureHost;
var machineName = Environment.GetEnvironmentVariable("COMPUTERNAME");
this.url = "http://" + machineName + ":" + random.Next(5000, 14000).ToString();
this.backChannel = this.Start(assemblyName);
}
public string BaseHost
{
get
{
return this.url;
}
}
public IServiceProvider ApplicationServices { get; private set; }
private BackTelemetryChannel Start(string assemblyName)
{
#if NET46
var builder = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(this.BaseHost)
.UseKestrel()
.UseStartup(assemblyName)
.UseEnvironment("Production");
#else
var builder = WebHost.CreateDefaultBuilder().UseStartup(assemblyName);
#endif
if (configureHost != null)
{
builder = configureHost(builder);
}
this.hostingEngine = builder.Build();
this.hostingEngine.Start();
this.ApplicationServices = this.hostingEngine.Services;
return (BackTelemetryChannel)this.hostingEngine.Services.GetService<ITelemetryChannel>();
}
public void Dispose()
{
if (this.hostingEngine != null)
{
this.hostingEngine.Dispose();
}
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4824/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNET_ENVIRONMENT": "Development"
}
}
}
}

Просмотреть файл

@ -0,0 +1,159 @@
namespace FunctionalTestUtils
{
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
#if NET451 || NET46
using System.Net;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector;
using Microsoft.ApplicationInsights.Extensibility;
#endif
public abstract class TelemetryTestsBase
{
protected const int TestTimeoutMs = 10000;
private object noParallelism = new object();
[MethodImpl(MethodImplOptions.NoOptimization)]
public void ValidateBasicRequest(InProcessServer server, string requestPath, RequestTelemetry expected)
{
lock (noParallelism)
{
// Subtract 50 milliseconds to hack around strange behavior on build server where the RequestTelemetry.Timestamp is somehow sometimes earlier than now by a few milliseconds.
expected.Timestamp = DateTimeOffset.Now.Subtract(TimeSpan.FromMilliseconds(50));
server.BackChannel.Buffer.Clear();
Stopwatch timer = Stopwatch.StartNew();
var httpClientHandler = new HttpClientHandler();
httpClientHandler.UseDefaultCredentials = true;
Task<HttpResponseMessage> task;
using (HttpClient httpClient = new HttpClient(httpClientHandler, true))
{
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
timer.Stop();
server.Dispose();
RequestTelemetry actual = server.BackChannel.Buffer.OfType<RequestTelemetry>().Where(t => t.Name == expected.Name).Single();
server.BackChannel.Buffer.Clear();
Assert.Equal(expected.ResponseCode, actual.ResponseCode);
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.Success, actual.Success);
Assert.Equal(expected.Url, actual.Url);
InRange(actual.Timestamp, expected.Timestamp, DateTimeOffset.Now);
Assert.True(actual.Duration < timer.Elapsed, "duration");
}
}
public void ValidateBasicException(InProcessServer server, string requestPath, ExceptionTelemetry expected)
{
var httpClientHandler = new HttpClientHandler();
httpClientHandler.UseDefaultCredentials = true;
Task<HttpResponseMessage> task;
using (var httpClient = new HttpClient(httpClientHandler, true))
{
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
var result = task.Result;
server.Dispose();
var actual = server.BackChannel.Buffer.OfType<ExceptionTelemetry>().Single();
Assert.Equal(expected.Exception.GetType(), actual.Exception.GetType());
Assert.NotEmpty(actual.Exception.StackTrace);
Assert.NotEmpty(actual.Context.Operation.Name);
Assert.NotEmpty(actual.Context.Operation.Id);
}
public void ValidateBasicDependency(string assemblyName, string requestPath, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
{
DependencyTelemetry expected = new DependencyTelemetry();
expected.ResultCode = "200";
expected.Success = true;
expected.Name = "GET " + requestPath;
InProcessServer server;
using (server = new InProcessServer(assemblyName, configureHost))
{
expected.Data = server.BaseHost + requestPath;
var timer = Stopwatch.StartNew();
Task<HttpResponseMessage> task;
using (var httpClient = new HttpClient())
{
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
var result = task.Result;
timer.Stop();
}
IEnumerable<DependencyTelemetry> dependencies = server.BackChannel.Buffer.OfType<DependencyTelemetry>();
Assert.NotNull(dependencies);
Assert.NotEmpty(dependencies);
var dependencyTelemetry = dependencies.FirstOrDefault(d => d.Name == expected.Name
&& d.Data == expected.Data
&& d.Success == expected.Success
&& d.ResultCode == expected.ResultCode);
Assert.NotNull(dependencyTelemetry);
#if !NET451
var requestTelemetry = server.BackChannel.Buffer.OfType<RequestTelemetry>().Single();
Assert.Equal(requestTelemetry.Context.Operation.ParentId, dependencyTelemetry.Id);
#endif
}
#if NET451 || NET46
public void ValidatePerformanceCountersAreCollected(string assemblyName, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
{
using (var server = new InProcessServer(assemblyName, configureHost))
{
// Reconfigure the PerformanceCollectorModule timer.
Type perfModuleType = typeof(PerformanceCollectorModule);
PerformanceCollectorModule perfModule = (PerformanceCollectorModule)server.ApplicationServices.GetServices<ITelemetryModule>().FirstOrDefault(m => m.GetType() == perfModuleType);
FieldInfo timerField = perfModuleType.GetField("timer", BindingFlags.NonPublic | BindingFlags.Instance);
var timer = timerField.GetValue(perfModule);
timerField.FieldType.InvokeMember("ScheduleNextTick", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, timer, new object[] { TimeSpan.FromMilliseconds(10) });
DateTime timeout = DateTime.UtcNow.AddMilliseconds(TestTimeoutMs);
int numberOfCountersSent = 0;
do
{
Thread.Sleep(1000);
numberOfCountersSent += server.BackChannel.Buffer.OfType<MetricTelemetry>().Distinct().Count();
} while (numberOfCountersSent == 0 && DateTime.UtcNow < timeout);
Assert.True(numberOfCountersSent > 0);
}
}
#endif
/// <summary>
/// Tests if a DateTimeOffset is in a specified range and prints a more detailed error message if it is not.
/// </summary>
/// <param name="actual">The actual value to test.</param>
/// <param name="low">The minimum of the range.</param>
/// <param name="high">The maximum of the range.</param>
private void InRange(DateTimeOffset actual, DateTimeOffset low, DateTimeOffset high)
{
string dateFormat = "yyyy-MM-dd HH:mm:ss.ffffzzz";
Assert.True(low <= actual && actual <= high, $"Range: ({low.ToString(dateFormat)} - {high.ToString(dateFormat)})\nActual: {actual.ToString(dateFormat)}");
}
}
}