Add and update some Unit tests

This commit is contained in:
Dave Tillman 2017-06-26 10:59:23 -06:00
Родитель 392f264a0f
Коммит 6d3a1cc244
14 изменённых файлов: 393 добавлений и 19 удалений

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

@ -41,7 +41,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Controllers
Response.Headers.Add("Pragma", "no-cache");
sampleSubscription = sampleStream
.ObserveOn(Scheduler.Default)
.ObserveOn(NewThreadScheduler.Default)
.Subscribe(
async (sampleDataAsString) =>
{

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

@ -16,15 +16,21 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Steeltoe.CircuitBreaker.Hystrix.MetricsStream;
using System;
namespace Steeltoe.CircuitBreaker.Hystrix
{
public static class HystrixApplicationBuilderExtensions
{
public static IApplicationBuilder UseHystrixMetricsStream(this IApplicationBuilder app)
public static IApplicationBuilder UseHystrixMetricsStream(this IApplicationBuilder builder)
{
var service = app.ApplicationServices.GetRequiredService<HystrixMetricsStreamPublisher>();
return app;
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
var service = builder.ApplicationServices.GetRequiredService<HystrixMetricsStreamPublisher>();
return builder;
}
}
}

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

@ -32,14 +32,14 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
public class HystrixMetricsStreamPublisher
{
IObservable<List<string>> observable;
ConnectionFactory factory;
IDisposable sampleSubscription;
internal ConnectionFactory factory;
internal IDisposable sampleSubscription;
IDiscoveryClient discoveryClient;
ILogger<HystrixMetricsStreamPublisher> logger;
private const string SPRING_CLOUD_HYSTRIX_STREAM_EXCHANGE = "spring.cloud.hystrix.stream";
public HystrixMetricsStreamPublisher(HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger<HystrixMetricsStreamPublisher> logger, IDiscoveryClient discoveryClient = null)
public HystrixMetricsStreamPublisher(HystrixDashboardStream stream, HystrixConnectionFactory factory, ILogger<HystrixMetricsStreamPublisher> logger = null, IDiscoveryClient discoveryClient = null)
{
this.discoveryClient = discoveryClient;
this.logger = logger;
@ -49,15 +49,15 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
this.factory = factory.ConnectionFactory as ConnectionFactory;
Task.Factory.StartNew(() => { StartMetricsPublishing(); });
StartMetricsPublishing();
}
public void StartMetricsPublishing()
{
logger.LogInformation("Hystrix Metrics starting");
logger?.LogInformation("Hystrix Metrics starting");
sampleSubscription = observable
.ObserveOn(Scheduler.Default)
.ObserveOn(NewThreadScheduler.Default)
.Subscribe(
(jsonList) =>
{
@ -72,7 +72,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
{
if (!string.IsNullOrEmpty(sampleDataAsString))
{
logger.LogDebug("Hystrix Metrics: {0}", sampleDataAsString.ToString());
logger?.LogDebug("Hystrix Metrics: {0}", sampleDataAsString.ToString());
var body = Encoding.UTF8.GetBytes(sampleDataAsString);
var props = channel.CreateBasicProperties();
@ -85,7 +85,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
}
catch (Exception e)
{
logger.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", e);
logger?.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", e);
if (sampleSubscription != null)
{
sampleSubscription.Dispose();
@ -96,7 +96,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
},
(error) =>
{
logger.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", error);
logger?.LogError("Error sending metrics to Hystrix dashboard, metrics streaming disabled: {0}", error);
if (sampleSubscription != null)
{
sampleSubscription.Dispose();
@ -105,7 +105,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream
},
() =>
{
logger.LogInformation("Hystrix Metrics shutdown");
logger?.LogInformation("Hystrix Metrics shutdown");
if (sampleSubscription != null)
{
sampleSubscription.Dispose();

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

@ -21,7 +21,7 @@ using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer;
using Steeltoe.CircuitBreaker.Hystrix.Metric.Sample;
using Steeltoe.CircuitBreaker.Hystrix.MetricsStream;
using Steeltoe.CloudFoundry.Connector.Hystrix;
using System;
namespace Steeltoe.CircuitBreaker.Hystrix
@ -30,6 +30,11 @@ namespace Steeltoe.CircuitBreaker.Hystrix
{
public static void AddHystrixMetricsStream(this IServiceCollection services, IConfiguration config)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<HystrixDashboardStream>(HystrixDashboardStream.GetInstance());
services.AddHystrixConnection(config);
services.AddSingleton<HystrixMetricsStreamPublisher>();
@ -37,20 +42,40 @@ namespace Steeltoe.CircuitBreaker.Hystrix
public static void AddHystrixRequestEventStream(this IServiceCollection services, IConfiguration config)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<HystrixRequestEventsStream>(HystrixRequestEventsStream.GetInstance());
}
public static void AddHystrixUtilizationStream(this IServiceCollection services, IConfiguration config)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<HystrixUtilizationStream>(HystrixUtilizationStream.GetInstance());
}
public static void AddHystrixConfigStream(this IServiceCollection services, IConfiguration config)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddSingleton<HystrixConfigurationStream>(HystrixConfigurationStream.GetInstance());
}
public static void AddHystrixMonitoringStreams(this IServiceCollection services, IConfiguration config)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddHystrixMetricsStream(config);
services.AddHystrixConfigStream(config);
services.AddHystrixRequestEventStream(config);

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

@ -26,10 +26,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="$(RabbitClientVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="RabbitMQ.Client" Version="$(RabbitClientVersion)" />
<PackageReference Include="System.Reactive" Version="$(ReactiveVersion)" />
<PackageReference Include="System.Reactive.Observable.Aliases" Version="$(ReactiveVersion)" />
<PackageReference Include="Steeltoe.CloudFoundry.Connector.Hystrix" Version="$(SteeltoeConnectorVersion)" />

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

@ -25,7 +25,7 @@ namespace Steeltoe.CircuitBreaker.Hystrix.MetricsEvents.Test
{
[Fact]
public void AddHystrixCommand_ThrowsIfServiceContainerNull()
public void AddHystrixStreams_ThrowsIfServiceContainerNull()
{
IServiceCollection services = null;
IConfiguration config = new ConfigurationBuilder().Build();

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

@ -0,0 +1,31 @@
//
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Threading;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public static class CountDownEventExtensions
{
public static void SignalEx(this CountdownEvent target)
{
if (target.CurrentCount == 0)
{
return;
}
target.Signal();
}
}
}

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

@ -0,0 +1,32 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.AspNetCore.Builder;
using System;
using System.Linq;
using Xunit;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public class HystrixApplicationBuilderExtensionsTest : HystrixTestBase
{
[Fact]
public void UseHystrixMetricsStream_ThrowsIfBuilderNull()
{
IApplicationBuilder builder = null;
var ex = Assert.Throws<ArgumentNullException>(() => builder.UseHystrixMetricsStream());
Assert.Contains(nameof(builder), ex.Message);
}
}
}

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

@ -0,0 +1,38 @@
//
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using RabbitMQ.Client;
using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer;
using Steeltoe.CloudFoundry.Connector.Hystrix;
using Xunit;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public class HystrixMetricsStreamPublisherTest: HystrixTestBase
{
[Fact]
public void Constructor_SetsupStream()
{
var stream = HystrixDashboardStream.GetInstance();
var factory = new HystrixConnectionFactory(new ConnectionFactory());
var publisher = new HystrixMetricsStreamPublisher(stream, factory);
Assert.NotNull(publisher.sampleSubscription);
Assert.NotNull(publisher.factory);
publisher.sampleSubscription.Dispose();
}
}
}

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

@ -0,0 +1,69 @@
//
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer;
using Steeltoe.CloudFoundry.Connector.Hystrix;
using System;
using Xunit;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public class HystrixServiceCollectionExtensionsTest : HystrixTestBase
{
[Fact]
public void AddHystrixStreams_ThrowsIfServiceContainerNull()
{
IServiceCollection services = null;
IConfiguration config = new ConfigurationBuilder().Build();
var ex = Assert.Throws<ArgumentNullException>(() => services.AddHystrixConfigStream(config));
Assert.Contains(nameof(services), ex.Message);
var ex2 = Assert.Throws<ArgumentNullException>(() => services.AddHystrixMetricsStream(config));
Assert.Contains(nameof(services), ex2.Message);
var ex3 = Assert.Throws<ArgumentNullException>(() => services.AddHystrixMonitoringStreams(config));
Assert.Contains(nameof(services), ex3.Message);
var ex4 = Assert.Throws<ArgumentNullException>(() => services.AddHystrixRequestEventStream(config));
Assert.Contains(nameof(services), ex4.Message);
var ex5 = Assert.Throws<ArgumentNullException>(() => services.AddHystrixMonitoringStreams(config));
Assert.Contains(nameof(services), ex5.Message);
}
[Fact]
public void AddHystrixMetricsStream_AddsExpectedServices()
{
IServiceCollection services = new ServiceCollection();
IConfiguration config = new ConfigurationBuilder().Build();
services.AddHystrixMetricsStream(config);
var provider = services.BuildServiceProvider();
var dashStream = provider.GetService<HystrixDashboardStream>();
Assert.NotNull(dashStream);
var publisher = provider.GetService<HystrixMetricsStreamPublisher>();
Assert.NotNull(publisher);
var factory = provider.GetService<HystrixConnectionFactory>();
Assert.NotNull(factory);
publisher.sampleSubscription.Dispose();
}
}
}

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

@ -0,0 +1,56 @@
//
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Steeltoe.CircuitBreaker.Hystrix.CircuitBreaker;
using Steeltoe.CircuitBreaker.Hystrix.Collapser;
using Steeltoe.CircuitBreaker.Hystrix.Strategy;
using Steeltoe.CircuitBreaker.Hystrix.Strategy.Concurrency;
using Steeltoe.CircuitBreaker.Hystrix.Strategy.Options;
using Steeltoe.CircuitBreaker.Hystrix.ThreadPool;
using System;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public class HystrixTestBase : IDisposable
{
protected HystrixRequestContext context;
public HystrixTestBase()
{
this.context = HystrixRequestContext.InitializeContext();
HystrixCommandMetrics.Reset();
HystrixThreadPoolMetrics.Reset();
HystrixCollapserMetrics.Reset();
// clear collapsers
RequestCollapserFactory.Reset();
// clear circuit breakers
HystrixCircuitBreakerFactory.Reset();
HystrixPlugins.Reset();
HystrixOptionsFactory.Reset();
}
public virtual void Dispose()
{
if (this.context != null)
{
this.context.Dispose();
this.context = null;
}
HystrixThreadPoolFactory.Shutdown();
}
}
}

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

@ -0,0 +1,104 @@
//
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Steeltoe.CircuitBreaker.Hystrix.Metric.Consumer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Threading;
using Xunit;
namespace Steeltoe.CircuitBreaker.Hystrix.MetricsStream.Test
{
public class SerializeTest : HystrixTestBase
{
[Fact]
public void ToJsonList_ReturnsExpected()
{
var stream = HystrixDashboardStream.GetInstance();
CountdownEvent latch = new CountdownEvent(1);
List<string> result = null;
var subscription = stream.Observe()
.SubscribeOn(NewThreadScheduler.Default)
.ObserveOn(NewThreadScheduler.Default)
.Subscribe(
(data) =>
{
result = Serialize.ToJsonList(data, null);
if (result.Count > 0)
{
latch.SignalEx();
}
},
(e) =>
{
latch.SignalEx();
},
() =>
{
latch.SignalEx();
});
MyCommand cmd = new MyCommand();
cmd.Execute();
latch.Wait(10000);
Assert.NotNull(result);
Assert.True(result.Count > 0);
var jsonObject = result[0];
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonObject);
Assert.NotNull(dict);
Assert.NotNull(dict["origin"]);
Assert.NotNull(dict["data"]);
JObject cmdData = (JObject)dict["data"];
Assert.NotNull(cmdData["type"]);
var type = cmdData["type"].Value<string>();
Assert.True("HystrixCommand".Equals(type) || "HystrixThreadPool".Equals(type));
Assert.NotNull(cmdData["name"]);
var name = cmdData["name"].Value<string>(); ;
Assert.True("MyCommand".Equals(name) || "MyCommandGroup".Equals(name));
subscription.Dispose();
}
}
class MyCommand : HystrixCommand<int>
{
public MyCommand() :
base(HystrixCommandGroupKeyDefault.AsKey("MyCommandGroup"),
() => { return 1; },
() => { return 2; })
{
}
}
}

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

@ -21,13 +21,26 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Steeltoe.CircuitBreaker.Hystrix.MetricsStream\Steeltoe.CircuitBreaker.Hystrix.MetricsStream.csproj" />
<ProjectReference Include="..\..\src\Steeltoe.CircuitBreaker.Hystrix\Steeltoe.CircuitBreaker.Hystrix.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="$(RabbitClientVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="System.Reactive" Version="$(ReactiveVersion)" />
<PackageReference Include="System.Reactive.Observable.Aliases" Version="$(ReactiveVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitStudioVersion)" />
<DotNetCliToolReference Include="dotnet-xunit" Version="$(XunitVersion)" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

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

@ -17,8 +17,7 @@ using Xunit;
using Xunit.Abstractions;
using Microsoft.AspNetCore.Builder;
using System;
using Microsoft.AspNetCore.Builder.Internal;
using Microsoft.Extensions.DependencyInjection;
namespace Steeltoe.CircuitBreaker.Hystrix.Test
{