Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use pure DI #80

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,4 @@ MockAssemblyResult.xml
PortabilityAnalysis*.html
tools/nuget.exe
tools/
.idea/
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# base image
image: Visual Studio 2019
image: Visual Studio 2022

build_script:
- ps: .\build.ps1 -Target "Appveyor"
Expand Down
48 changes: 48 additions & 0 deletions src/extension/Composer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// ***********************************************************************
// Copyright (c) 2015 Charlie Poole
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

// ReSharper disable UnusedMember.Local
namespace NUnit.Engine.Listeners
{
using System;
using System.IO;
using Pure.DI;

public static partial class Composer
{
private static void Setup()
{
DI.Setup()
.Bind<TextWriter>().To(ctx => Console.Out)
.Bind<Statistics>().To<Statistics>()
.Bind<IServiceMessageWriter>().To<ServiceMessageWriter>()
.Bind<ITeamCityInfo>().To<TeamCityInfo>()
.Bind<ISuiteNameReplacer>().To<SuiteNameReplacer>()
.Bind<IServiceMessageFactory>().To<ServiceMessageFactory>()
.Bind<IHierarchy>().To<Hierarchy>()
.Bind<IEventConverter>(2).To<EventConverter2>()
.Bind<IEventConverter>(3).To<EventConverter3>()
.Bind<ITestEventListener>().To<EventListener>();
}
}
}
26 changes: 25 additions & 1 deletion src/extension/Event.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
namespace NUnit.Engine.Listeners
// ***********************************************************************
// Copyright (c) 2015 Charlie Poole
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

namespace NUnit.Engine.Listeners
{
using System.Xml;

Expand All @@ -10,6 +33,7 @@ public struct Event
public readonly string Name;
public readonly string Id;
public readonly string ParentId;
// ReSharper disable once InconsistentNaming
public readonly string TestId;
// ReSharper disable once InconsistentNaming
public readonly XmlNode TestEvent;
Expand Down
2 changes: 1 addition & 1 deletion src/extension/EventConverter2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace NUnit.Engine.Listeners
using System.Xml;
using System.Collections.Generic;

internal class EventConverter2: IEventConverter
public class EventConverter2: IEventConverter
{
private readonly IServiceMessageFactory _serviceMessageFactory;
private readonly IHierarchy _hierarchy;
Expand Down
10 changes: 6 additions & 4 deletions src/extension/EventConverter3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace NUnit.Engine.Listeners
using System.Xml;
using System.Collections.Generic;

internal class EventConverter3: IEventConverter
public class EventConverter3: IEventConverter
{
private readonly IServiceMessageFactory _serviceMessageFactory;
private readonly IHierarchy _hierarchy;
Expand Down Expand Up @@ -151,11 +151,13 @@ private IEnumerable<ServiceMessage> ProcessNotStartedTests(string flowId, string
var parentId = notStartedTest.Key;
while (_hierarchy.TryFindParentId(parentId, out parentId))
{
if (id == parentId)
if (id != parentId)
{
testToProcess.Add(notStartedTest.Key);
break;
continue;
}

testToProcess.Add(notStartedTest.Key);
break;
}
}

Expand Down
27 changes: 25 additions & 2 deletions src/extension/EventId.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
namespace NUnit.Engine.Listeners
// ***********************************************************************
// Copyright (c) 2015 Charlie Poole
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

namespace NUnit.Engine.Listeners
{
internal struct EventId
public struct EventId
{
public readonly string FlowId;
public readonly string FullName;
Expand Down
157 changes: 157 additions & 0 deletions src/extension/EventListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// ***********************************************************************
// Copyright (c) 2015 Charlie Poole
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

namespace NUnit.Engine.Listeners
{
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System;
using System.IO;
using System.Xml;
using Extensibility;
using Pure.DI;

// Note: Setting minimum engine version in this case is
// purely documentary since engines prior to 3.4 do not
// check the EngineVersion property and will try to
// load this extension anyway.
[Extension(Enabled = false, EngineVersion = "3.4")]
[SuppressMessage("ReSharper", "UseNameofExpression")]
public class EventListener : ITestEventListener
{
private readonly IServiceMessageWriter _serviceMessageWriter;
private readonly IEventConverter _eventConverter2;
private readonly IEventConverter _eventConverter3;
private readonly Statistics _statistics;
private readonly ITeamCityInfo _teamCityInfo;
private readonly object _lockObject = new object();
private readonly TextWriter _outWriter;
private string _rootFlowId = string.Empty;

// ReSharper disable once UnusedMember.Global
public EventListener(
TextWriter outWriter,
ITeamCityInfo teamCityInfo,
Statistics statistics,
IServiceMessageWriter serviceMessageWriter,
[Tag(2)] IEventConverter eventConverter2,
[Tag(3)] IEventConverter eventConverter3)
{
if (outWriter == null) throw new ArgumentNullException("outWriter");
if (teamCityInfo == null) throw new ArgumentNullException("teamCityInfo");
if (statistics == null) throw new ArgumentNullException("statistics");
_outWriter = outWriter;
_teamCityInfo = teamCityInfo;
_statistics = statistics;
_serviceMessageWriter = serviceMessageWriter;
_eventConverter2 = eventConverter2;
_eventConverter3 = eventConverter3;
RootFlowId = _teamCityInfo.RootFlowId;
}

public string RootFlowId
{
set
{
_rootFlowId = value ?? string.Empty;
}
}

public void OnTestEvent(string report)
{
if (_teamCityInfo.AllowDiagnostics)
{
_outWriter.WriteLine();
_outWriter.WriteLine("PID_" + _teamCityInfo.ProcessId + " !!!!{ " + report + " }!!!!");
}

var doc = new XmlDocument();
doc.LoadXml(report);

var testEvent = doc.FirstChild;
RegisterMessage(testEvent);
}

public void RegisterMessage(XmlNode xmlEvent)
{
if (xmlEvent == null) throw new ArgumentNullException("xmlEvent");
var messageName = xmlEvent.Name;
if (string.IsNullOrEmpty(messageName))
{
return;
}

var fullName = xmlEvent.GetAttribute("fullname");
if (string.IsNullOrEmpty(fullName))
{
fullName = xmlEvent.GetAttribute("testname");
if (string.IsNullOrEmpty(fullName))
{
return;
}
}

var name = xmlEvent.GetAttribute("name");
if (string.IsNullOrEmpty(name))
{
name = fullName;
}

var id = xmlEvent.GetAttribute("id") ?? string.Empty;
var parentId = xmlEvent.GetAttribute("parentId");
var testId = xmlEvent.GetAttribute("testid");

var isNUnit3 = parentId != null;
var eventConverter = isNUnit3 ? _eventConverter3 : _eventConverter2;
var testEvent = new Event(_rootFlowId, messageName.ToLowerInvariant(), fullName, name, GetId(_rootFlowId, id), GetId(_rootFlowId, parentId), GetId(_rootFlowId, testId), xmlEvent);
lock (_lockObject)
{
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
foreach (var messages in eventConverter.Convert(testEvent))
{
_serviceMessageWriter.Write(writer, messages);
}
}

_outWriter.Write(sb.ToString());
}

if (_teamCityInfo.AllowDiagnostics)
{
_outWriter.WriteLine("@@ NUnit3: " + isNUnit3 + ", " + _statistics + ", " + testEvent);
}
}

private static string GetId(string rootFlowId, string flowId)
{
if (string.IsNullOrEmpty(flowId) || string.IsNullOrEmpty(rootFlowId))
{
return flowId;
}

return rootFlowId + "_" + flowId;
}
}
}
36 changes: 30 additions & 6 deletions src/extension/Hierarchy.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
namespace NUnit.Engine.Listeners
// ***********************************************************************
// Copyright (c) 2015 Charlie Poole
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

namespace NUnit.Engine.Listeners
{
using System;
using System.Collections.Generic;

internal class Hierarchy : IHierarchy
public class Hierarchy : IHierarchy
{
private readonly Dictionary<string, string> _links = new Dictionary<string, string>();

public bool AddLink(string childId, string parentId)
{
string curParentId;
if (!_links.TryGetValue(childId, out curParentId) || curParentId != parentId)
if (_links.TryGetValue(childId, out curParentId) && curParentId == parentId)
{
_links[childId] = parentId;
return true;
return false;
}

return false;
_links[childId] = parentId;
return true;

}

public void Clear()
Expand Down
Loading