Moves LightInjectValidation to common and validates the container as part of new tests
This commit is contained in:
@@ -91,7 +91,7 @@ namespace Umbraco.Core.Composing.LightInject
|
||||
/// <summary>
|
||||
/// Gets the LightInject container.
|
||||
/// </summary>
|
||||
protected ServiceContainer Container { get; }
|
||||
public ServiceContainer Container { get; }
|
||||
|
||||
/// <inheritdoc cref="IRegister"/>
|
||||
/// <inheritdoc cref="IFactory"/>
|
||||
|
||||
@@ -20,9 +20,9 @@ namespace Umbraco.Core.Composing
|
||||
/// <returns></returns>
|
||||
public static IRegister CreateFrom(IServiceCollection services, out IServiceProvider serviceProvider)
|
||||
{
|
||||
var liContainer = new ServiceContainer(ContainerOptions.Default.WithMicrosoftSettings());
|
||||
serviceProvider = liContainer.CreateServiceProvider(services);
|
||||
return new LightInjectContainer(liContainer);
|
||||
var lightInjectContainer = new ServiceContainer(ContainerOptions.Default.WithMicrosoftSettings());
|
||||
serviceProvider = lightInjectContainer.CreateServiceProvider(services);
|
||||
return new LightInjectContainer(lightInjectContainer);
|
||||
}
|
||||
|
||||
//TODO: The following can die when net framework is gone
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using LightInject;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Tests.Common.Composing;
|
||||
|
||||
namespace Umbraco.Tests.Common
|
||||
{
|
||||
public class Assertions
|
||||
{
|
||||
public static void AssertContainer(ServiceContainer container, bool reportOnly = false)
|
||||
{
|
||||
var results = container.Validate().ToList();
|
||||
foreach (var resultGroup in results.GroupBy(x => x.Severity).OrderBy(x => x.Key))
|
||||
{
|
||||
Console.WriteLine($"{resultGroup.Key}: {resultGroup.Count()}");
|
||||
}
|
||||
|
||||
foreach (var resultGroup in results.GroupBy(x => x.Severity).OrderBy(x => x.Key))
|
||||
{
|
||||
foreach (var result in resultGroup)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.Write(result.ToText());
|
||||
}
|
||||
}
|
||||
|
||||
if (!reportOnly)
|
||||
Assert.AreEqual(0, results.Count);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+6
-36
@@ -35,7 +35,7 @@ using ServiceMap = System.Collections.Generic.Dictionary<System.Type, System.Col
|
||||
http://twitter.com/bernhardrichter
|
||||
******************************************************************************/
|
||||
|
||||
namespace Umbraco.Tests.Composing
|
||||
namespace Umbraco.Tests.Common.Composing
|
||||
{
|
||||
public static class LightInjectValidation
|
||||
{
|
||||
@@ -110,7 +110,6 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
{
|
||||
var registration = GetServiceRegistration(serviceMap, validationTarget);
|
||||
if (registration == null)
|
||||
{
|
||||
if (validationTarget.ServiceType.IsFunc() || validationTarget.ServiceType.IsLazy())
|
||||
{
|
||||
var serviceType = validationTarget.ServiceType.GenericTypeArguments[0];
|
||||
@@ -118,17 +117,13 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
registration = GetServiceRegistration(serviceMap, underlyingvalidationTarget);
|
||||
|
||||
if (registration != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serviceMap.ContainsAmbiguousRegistrationFor(serviceType))
|
||||
{
|
||||
result.Add(new ValidationResult("", ValidationSeverity.Ambiguous, underlyingvalidationTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format(MissingDeferredDependency, validationTarget.ServiceType, underlyingvalidationTarget.ServiceType);
|
||||
var message = string.Format(MissingDeferredDependency, validationTarget.ServiceType, underlyingvalidationTarget.ServiceType);
|
||||
result.Add(new ValidationResult(message, ValidationSeverity.MissingDependency, underlyingvalidationTarget));
|
||||
}
|
||||
}
|
||||
@@ -140,21 +135,14 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
if (registrations.Any()) return;
|
||||
|
||||
// strict: there has to be at least 1
|
||||
string message = string.Format(MissingDeferredDependency, validationTarget.ServiceType, underlyingvalidationTarget.ServiceType);
|
||||
var message = string.Format(MissingDeferredDependency, validationTarget.ServiceType, underlyingvalidationTarget.ServiceType);
|
||||
result.Add(new ValidationResult(message, ValidationSeverity.MissingDependency, underlyingvalidationTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serviceMap.ContainsAmbiguousRegistrationFor(validationTarget.ServiceType))
|
||||
{
|
||||
result.Add(new ValidationResult("", ValidationSeverity.Ambiguous, validationTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new ValidationResult("", ValidationSeverity.MissingDependency, validationTarget));
|
||||
}
|
||||
}
|
||||
}
|
||||
result.Add(new ValidationResult("", ValidationSeverity.Ambiguous, validationTarget));
|
||||
else
|
||||
result.Add(new ValidationResult("", ValidationSeverity.MissingDependency, validationTarget));
|
||||
else
|
||||
{
|
||||
ValidateDisposable(validationTarget, result, registration);
|
||||
@@ -206,24 +194,16 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
private static ServiceRegistration GetServiceRegistration(ServiceMap serviceMap, ValidationTarget validationTarget)
|
||||
{
|
||||
if (!serviceMap.TryGetValue(validationTarget.ServiceType, out var registrations))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (registrations.TryGetValue(string.Empty, out var registration))
|
||||
{
|
||||
return registration;
|
||||
}
|
||||
|
||||
if (registrations.Count == 1)
|
||||
{
|
||||
return registrations.Values.First();
|
||||
}
|
||||
|
||||
if (registrations.TryGetValue(validationTarget.ServiceName, out registration))
|
||||
{
|
||||
return registration;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -231,22 +211,16 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
private static string GetLifetimeName(ILifetime lifetime)
|
||||
{
|
||||
if (lifetime == null)
|
||||
{
|
||||
return "Transient";
|
||||
}
|
||||
return lifetime.GetType().Name;
|
||||
}
|
||||
|
||||
private static int GetLifespan(ILifetime lifetime)
|
||||
{
|
||||
if (lifetime == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (LifeSpans.TryGetValue(lifetime.GetType(), out var lifespan))
|
||||
{
|
||||
return lifespan;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -274,9 +248,7 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
|
||||
|
||||
if (serviceType.GetTypeInfo().IsGenericType && serviceType.GetTypeInfo().ContainsGenericParameters)
|
||||
{
|
||||
ServiceType = serviceType.GetGenericTypeDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -340,9 +312,7 @@ Ensure that 'NameSpace.IBar' is registered with a lifetime that is equal to or h
|
||||
public static bool ContainsAmbiguousRegistrationFor(this ServiceMap serviceMap, Type serviceType)
|
||||
{
|
||||
if (!serviceMap.TryGetValue(serviceType, out var registrations))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return registrations.Count > 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.Common.Composing
|
||||
{
|
||||
public static class ValidationResultExtensions
|
||||
{
|
||||
public static string ToText(this ValidationResult result)
|
||||
{
|
||||
var text = new StringBuilder();
|
||||
|
||||
text.AppendLine($"{result.Severity}: {WordWrap(result.Message, 120)}");
|
||||
var target = result.ValidationTarget;
|
||||
text.Append("\tsvce: ");
|
||||
text.Append(target.ServiceName);
|
||||
text.Append(target.DeclaringService.ServiceType);
|
||||
if (!target.DeclaringService.ServiceName.IsNullOrWhiteSpace())
|
||||
{
|
||||
text.Append(" '");
|
||||
text.Append(target.DeclaringService.ServiceName);
|
||||
text.Append("'");
|
||||
}
|
||||
|
||||
text.Append(" (");
|
||||
if (target.DeclaringService.Lifetime == null)
|
||||
text.Append("Transient");
|
||||
else
|
||||
text.Append(target.DeclaringService.Lifetime.ToString().TrimStart("LightInject.").TrimEnd("Lifetime"));
|
||||
text.AppendLine(")");
|
||||
text.Append("\timpl: ");
|
||||
text.Append(target.DeclaringService.ImplementingType);
|
||||
text.AppendLine();
|
||||
text.Append("\tparm: ");
|
||||
text.Append(target.Parameter);
|
||||
text.AppendLine();
|
||||
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
private static string WordWrap(string text, int width)
|
||||
{
|
||||
int pos, next;
|
||||
var sb = new StringBuilder();
|
||||
var nl = Environment.NewLine;
|
||||
|
||||
// Lucidity check
|
||||
if (width < 1)
|
||||
return text;
|
||||
|
||||
// Parse each line of text
|
||||
for (pos = 0; pos < text.Length; pos = next)
|
||||
{
|
||||
// Find end of line
|
||||
var eol = text.IndexOf(nl, pos, StringComparison.Ordinal);
|
||||
|
||||
if (eol == -1)
|
||||
next = eol = text.Length;
|
||||
else
|
||||
next = eol + nl.Length;
|
||||
|
||||
// Copy this line of text, breaking into smaller lines as needed
|
||||
if (eol > pos)
|
||||
{
|
||||
do
|
||||
{
|
||||
var len = eol - pos;
|
||||
|
||||
if (len > width)
|
||||
len = BreakLine(text, pos, width);
|
||||
|
||||
if (pos > 0)
|
||||
sb.Append("\t\t");
|
||||
sb.Append(text, pos, len);
|
||||
sb.Append(nl);
|
||||
|
||||
// Trim whitespace following break
|
||||
pos += len;
|
||||
|
||||
while (pos < eol && char.IsWhiteSpace(text[pos]))
|
||||
pos++;
|
||||
|
||||
} while (eol > pos);
|
||||
}
|
||||
else sb.Append(nl); // Empty line
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static int BreakLine(string text, int pos, int max)
|
||||
{
|
||||
// Find last whitespace in line
|
||||
var i = max - 1;
|
||||
while (i >= 0 && !char.IsWhiteSpace(text[pos + i]))
|
||||
i--;
|
||||
if (i < 0)
|
||||
return max; // No whitespace found; break at maximum length
|
||||
// Find start of whitespace
|
||||
while (i >= 0 && char.IsWhiteSpace(text[pos + i]))
|
||||
i--;
|
||||
// Return length of text before whitespace
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Tests.Common;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
|
||||
namespace Umbraco.Tests.Integration
|
||||
@@ -56,6 +57,8 @@ namespace Umbraco.Tests.Integration
|
||||
Assert.AreNotSame(foo1, foo2);
|
||||
// These are the same because the umbraco container wraps the light inject container
|
||||
Assert.AreSame(foo2, foo3);
|
||||
|
||||
Assertions.AssertContainer(umbracoContainer.Container);
|
||||
}
|
||||
|
||||
private class Foo
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Runtime;
|
||||
using Umbraco.Tests.Common;
|
||||
using Umbraco.Tests.Common.Composing;
|
||||
using Umbraco.Tests.Integration.Implementations;
|
||||
|
||||
namespace Umbraco.Tests.Integration
|
||||
@@ -19,7 +23,7 @@ namespace Umbraco.Tests.Integration
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// LightInject / Umbraco
|
||||
var umbracoContainer = RegisterFactory.CreateFrom(services, out var lightInjectServiceProvider);
|
||||
var umbracoContainer = (LightInjectContainer)RegisterFactory.CreateFrom(services, out var lightInjectServiceProvider);
|
||||
|
||||
// Dependencies needed for Core Runtime
|
||||
var testHelper = new TestHelper();
|
||||
@@ -35,17 +39,21 @@ namespace Umbraco.Tests.Integration
|
||||
Assert.IsNull(coreRuntime.State.BootFailedException);
|
||||
Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level);
|
||||
Assert.IsTrue(MyComposer.IsComposed);
|
||||
}
|
||||
}
|
||||
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Install)]
|
||||
public class MyComposer : IUserComposer
|
||||
{
|
||||
public void Compose(Composition composition)
|
||||
{
|
||||
IsComposed = true;
|
||||
Assertions.AssertContainer(umbracoContainer.Container, reportOnly: true); // TODO Change that to false eventually when we clean up the container
|
||||
}
|
||||
|
||||
public static bool IsComposed { get; private set; }
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Install)]
|
||||
public class MyComposer : IUserComposer
|
||||
{
|
||||
public void Compose(Composition composition)
|
||||
{
|
||||
IsComposed = true;
|
||||
}
|
||||
|
||||
public static bool IsComposed { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ using Umbraco.Core.Runtime;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Tests.Composing;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Cache;
|
||||
@@ -36,6 +35,7 @@ using Umbraco.Web.Runtime;
|
||||
using File = System.IO.File;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
using Umbraco.Tests.Common;
|
||||
using Umbraco.Tests.Common.Composing;
|
||||
|
||||
namespace Umbraco.Tests.Runtimes
|
||||
{
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
var profilingLogger = new ProfilingLogger(logger, profiler);
|
||||
var appCaches = AppCaches.Disabled;
|
||||
var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy<IMapperCollection>(() => factory.GetInstance<IMapperCollection>()), TestHelper.GetConfigs(), TestHelper.DbProviderFactoryCreator);
|
||||
var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly));
|
||||
var typeFinder = TestHelper.GetTypeFinder();
|
||||
var ioHelper = TestHelper.IOHelper;
|
||||
var hostingEnvironment = Mock.Of<IHostingEnvironment>();
|
||||
var typeLoader = new TypeLoader(ioHelper, typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger);
|
||||
@@ -73,6 +73,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
var runtimeState = new RuntimeState(logger, null, new Lazy<IMainDom>(() => mainDom), new Lazy<IServerRegistrar>(() => factory.GetInstance<IServerRegistrar>()), umbracoVersion, hostingEnvironment, backOfficeInfo);
|
||||
var configs = TestHelper.GetConfigs();
|
||||
var variationContextAccessor = TestHelper.VariationContextAccessor;
|
||||
|
||||
|
||||
// create the register and the composition
|
||||
var register = TestHelper.GetRegister();
|
||||
@@ -80,7 +81,8 @@ namespace Umbraco.Tests.Runtimes
|
||||
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator);
|
||||
|
||||
// create the core runtime and have it compose itself
|
||||
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom);coreRuntime.Compose(composition);
|
||||
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
|
||||
coreRuntime.Compose(composition);
|
||||
|
||||
// determine actual runtime level
|
||||
runtimeState.DetermineRuntimeLevel(databaseFactory, logger);
|
||||
@@ -274,7 +276,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator);
|
||||
|
||||
// create the core runtime and have it compose itself
|
||||
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom);
|
||||
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
|
||||
coreRuntime.Compose(composition);
|
||||
|
||||
// get the components
|
||||
@@ -313,107 +315,14 @@ namespace Umbraco.Tests.Runtimes
|
||||
foreach (var result in resultGroup)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.Write(ToText(result));
|
||||
Console.Write(result.ToText());
|
||||
}
|
||||
|
||||
Assert.AreEqual(0, results.Count);
|
||||
}
|
||||
|
||||
private static string ToText(ValidationResult result)
|
||||
{
|
||||
var text = new StringBuilder();
|
||||
|
||||
|
||||
text.AppendLine($"{result.Severity}: {WordWrap(result.Message, 120)}");
|
||||
var target = result.ValidationTarget;
|
||||
text.Append("\tsvce: ");
|
||||
text.Append(target.ServiceName);
|
||||
text.Append(target.DeclaringService.ServiceType);
|
||||
if (!target.DeclaringService.ServiceName.IsNullOrWhiteSpace())
|
||||
{
|
||||
text.Append(" '");
|
||||
text.Append(target.DeclaringService.ServiceName);
|
||||
text.Append("'");
|
||||
}
|
||||
|
||||
text.Append(" (");
|
||||
if (target.DeclaringService.Lifetime == null)
|
||||
text.Append("Transient");
|
||||
else
|
||||
text.Append(target.DeclaringService.Lifetime.ToString().TrimStart("LightInject.").TrimEnd("Lifetime"));
|
||||
text.AppendLine(")");
|
||||
text.Append("\timpl: ");
|
||||
text.Append(target.DeclaringService.ImplementingType);
|
||||
text.AppendLine();
|
||||
text.Append("\tparm: ");
|
||||
text.Append(target.Parameter);
|
||||
text.AppendLine();
|
||||
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
private static string WordWrap(string text, int width)
|
||||
{
|
||||
int pos, next;
|
||||
var sb = new StringBuilder();
|
||||
var nl = Environment.NewLine;
|
||||
|
||||
// Lucidity check
|
||||
if (width < 1)
|
||||
return text;
|
||||
|
||||
// Parse each line of text
|
||||
for (pos = 0; pos < text.Length; pos = next)
|
||||
{
|
||||
// Find end of line
|
||||
var eol = text.IndexOf(nl, pos, StringComparison.Ordinal);
|
||||
|
||||
if (eol == -1)
|
||||
next = eol = text.Length;
|
||||
else
|
||||
next = eol + nl.Length;
|
||||
|
||||
// Copy this line of text, breaking into smaller lines as needed
|
||||
if (eol > pos)
|
||||
{
|
||||
do
|
||||
{
|
||||
var len = eol - pos;
|
||||
|
||||
if (len > width)
|
||||
len = BreakLine(text, pos, width);
|
||||
|
||||
if (pos > 0)
|
||||
sb.Append("\t\t");
|
||||
sb.Append(text, pos, len);
|
||||
sb.Append(nl);
|
||||
|
||||
// Trim whitespace following break
|
||||
pos += len;
|
||||
|
||||
while (pos < eol && char.IsWhiteSpace(text[pos]))
|
||||
pos++;
|
||||
|
||||
} while (eol > pos);
|
||||
}
|
||||
else sb.Append(nl); // Empty line
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static int BreakLine(string text, int pos, int max)
|
||||
{
|
||||
// Find last whitespace in line
|
||||
var i = max - 1;
|
||||
while (i >= 0 && !char.IsWhiteSpace(text[pos + i]))
|
||||
i--;
|
||||
if (i < 0)
|
||||
return max; // No whitespace found; break at maximum length
|
||||
// Find start of whitespace
|
||||
while (i >= 0 && char.IsWhiteSpace(text[pos + i]))
|
||||
i--;
|
||||
// Return length of text before whitespace
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,6 @@
|
||||
<Compile Include="Clr\ReflectionUtilitiesTests.cs" />
|
||||
<Compile Include="Collections\OrderedHashSetTests.cs" />
|
||||
<Compile Include="Composing\CompositionTests.cs" />
|
||||
<Compile Include="Composing\LightInjectValidation.cs" />
|
||||
<Compile Include="Composing\ContainerConformingTests.cs" />
|
||||
<Compile Include="Configurations\GlobalSettingsTests.cs" />
|
||||
<Compile Include="CoreThings\CallContextTests.cs" />
|
||||
|
||||
Reference in New Issue
Block a user