From 2d39a18b70e09dd58597638ff573af8e3d5e920e Mon Sep 17 00:00:00 2001 From: deeptowncitizen Date: Sat, 7 Oct 2017 09:05:02 -0400 Subject: [PATCH] Observable logs (#51) * observable log entries * event test --- src/WireMock.Net/Owin/WireMockMiddleware.cs | 14 ++++-- .../Owin/WireMockMiddlewareOptions.cs | 5 +- .../Server/FluentMockServer.LogEntries.cs | 23 +++++++++ .../ObservableLogEntriesTest.cs | 50 +++++++++++++++++++ 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 test/WireMock.Net.Tests/ObservableLogEntriesTest.cs diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs index 02048fd3b..75ea28dba 100644 --- a/src/WireMock.Net/Owin/WireMockMiddleware.cs +++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections; +using System.Collections.ObjectModel; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; @@ -161,13 +162,20 @@ private void LogRequest(LogEntry entry, bool addRequest) if (_options.MaxRequestLogCount != null) { - _options.LogEntries = _options.LogEntries.Skip(_options.LogEntries.Count - _options.MaxRequestLogCount.Value).ToList(); + var amount = _options.LogEntries.Count - _options.MaxRequestLogCount.Value; + for (var i = 0; i < amount; i++, _options.LogEntries.RemoveAt(0)) ; } if (_options.RequestLogExpirationDuration != null) { var checkTime = DateTime.Now.AddHours(-_options.RequestLogExpirationDuration.Value); - _options.LogEntries = _options.LogEntries.Where(le => le.RequestMessage.DateTime > checkTime).ToList(); + + for (var i = _options.LogEntries.Count - 1; i >= 0; i--) + { + var le = _options.LogEntries[i]; + if (le.RequestMessage.DateTime <= checkTime) + _options.LogEntries.RemoveAt(i); + } } } } diff --git a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs index f6cd3a173..e9ca46bd9 100644 --- a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using WireMock.Logging; using WireMock.Matchers; @@ -15,7 +16,7 @@ internal class WireMockMiddlewareOptions public IList Mappings { get; set; } - public IList LogEntries { get; set; } + public ObservableCollection LogEntries { get; set; } public int? RequestLogExpirationDuration { get; set; } @@ -24,7 +25,7 @@ internal class WireMockMiddlewareOptions public WireMockMiddlewareOptions() { Mappings = new List(); - LogEntries = new List(); + LogEntries = new ObservableCollection(); } } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.LogEntries.cs b/src/WireMock.Net/Server/FluentMockServer.LogEntries.cs index 81a421201..0fcc77efa 100644 --- a/src/WireMock.Net/Server/FluentMockServer.LogEntries.cs +++ b/src/WireMock.Net/Server/FluentMockServer.LogEntries.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using JetBrains.Annotations; using WireMock.Logging; using WireMock.Matchers.Request; @@ -11,6 +12,28 @@ namespace WireMock.Server { public partial class FluentMockServer { + /// + /// Log entries notification handler + /// + [PublicAPI] + public event NotifyCollectionChangedEventHandler LogEntriesChanged + { + add + { + lock (((ICollection) _options.LogEntries).SyncRoot) + { + _options.LogEntries.CollectionChanged += value; + } + } + remove + { + lock (((ICollection)_options.LogEntries).SyncRoot) + { + _options.LogEntries.CollectionChanged -= value; + } + } + } + /// /// Gets the request logs. /// diff --git a/test/WireMock.Net.Tests/ObservableLogEntriesTest.cs b/test/WireMock.Net.Tests/ObservableLogEntriesTest.cs new file mode 100644 index 000000000..c5178ae54 --- /dev/null +++ b/test/WireMock.Net.Tests/ObservableLogEntriesTest.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using NFluent; +using RestEase; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using Xunit; + +namespace WireMock.Net.Tests +{ + public class ObservableLogEntriesTest: IDisposable + { + private FluentMockServer _server; + + [Fact] + public async void Test() + { + // given + _server = FluentMockServer.Start(); + + _server + .Given(Request.Create() + .WithPath("/foo") + .UsingGet()) + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithBody(@"{ msg: ""Hello world!""}")); + + var count = 0; + _server.LogEntriesChanged += (sender, args) => count++; + + // when + var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo"); + + // then + Check.That(count).Equals(1); + } + + public void Dispose() + { + _server?.Dispose(); + } + } +}