Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ namespace Telerik.JustMock.Core.Context
{
internal abstract class HierarchicalTestFrameworkContextResolver : MockingContextResolverBase
{
private static bool useMsTest2RepositoryGuarding =
Environment.GetEnvironmentVariable("JUST_MOCK_USE_MSTEST2_REPOSITORY_GUARDING") == "1";

private readonly List<RepositoryOperationsBase> repoOperations = new List<RepositoryOperationsBase>();
private readonly Dictionary<Assembly, HashSet<Type>> knownTestClasses = new Dictionary<Assembly, HashSet<Type>>();

Expand All @@ -40,15 +43,29 @@ public HierarchicalTestFrameworkContextResolver(string assertFailedExceptionType

public override MocksRepository ResolveRepository(UnresolvedContextBehavior unresolvedContextBehavior)
{
lock (this.repositorySync)
int repoIdx = 0;
RepositoryOperationsBase entryOps = null;
Comment thread
ivo-stoilov marked this conversation as resolved.
Outdated
MethodBase testMethod = null;

if (!useMsTest2RepositoryGuarding)
{
int repoIdx;
RepositoryOperationsBase entryOps = null;
var testMethod = FindTestMethod(out repoIdx, out entryOps);
if (testMethod == null || entryOps == null)
testMethod = FindTestMethod(out repoIdx, out entryOps);
if (testMethod == null)
{
return null;
}
}

lock (this.repositorySync)
{
if (useMsTest2RepositoryGuarding)
{
testMethod = FindTestMethod(out repoIdx, out entryOps);
if (testMethod == null)
{
return null;
}
}

object entryKey = entryOps.GetKey(testMethod);
MocksRepository repo = this.FindRepositoryInOps(entryOps, entryKey);
Expand Down Expand Up @@ -104,15 +121,29 @@ public override MocksRepository ResolveRepository(UnresolvedContextBehavior unre

public override bool RetireRepository()
{
lock (this.repositorySync)
int repoIdx = 0;
RepositoryOperationsBase entryOps = null;
MethodBase testMethod = null;
Comment thread
ValentinaPetrova marked this conversation as resolved.
Outdated

if (!useMsTest2RepositoryGuarding)
{
RepositoryOperationsBase entryOps = null;
int repoIdx;
var testMethod = FindTestMethod(out repoIdx, out entryOps);
testMethod = FindTestMethod(out repoIdx, out entryOps);
if (testMethod == null)
{
return false;
}
}

lock (this.repositorySync)
{
if (useMsTest2RepositoryGuarding)
{
testMethod = FindTestMethod(out repoIdx, out entryOps);
if (testMethod == null)
{
return false;
}
}

var entryKey = entryOps.GetKey(testMethod);
MocksRepository repo = FindRepositoryInOps(entryOps, entryKey);
Expand Down
89 changes: 89 additions & 0 deletions Telerik.JustMock/Core/Context/MSTestBaseMockingContextResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
JustMock Lite
Copyright © 2010-2015 Progress Software Corporation

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;
using System.Threading;

namespace Telerik.JustMock.Core.Context
{
internal abstract class MSTestBaseMockingContextResolver : HierarchicalTestFrameworkContextResolver
{
protected MSTestBaseMockingContextResolver(string assertionFailedName, string assemblyName)
: base(assertionFailedName)
{
this.SetupStandardHierarchicalTestStructure(
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute, " + assemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute, " + assemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute, " + assemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute, " + assemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute, " + assemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyInitializeAttribute, " + assemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyCleanupAttribute, " + assemblyName },
FixtureConstuctorSemantics.InstanceConstructorCalledOncePerFixture);
}

#if !SILVERLIGHT
private const int DefaultGcFrequency = 50;
private int createdRepoCount;
private int lastGcCount;
private int gcFrequency = GetGcFrequency();
private bool synchronousGc = GetSynchronousGc();

private static int GetGcFrequency()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "MSTestGcFrequency");
int value;
if (!String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value >= 1)
return value;

return DefaultGcFrequency;
}

private static bool GetSynchronousGc()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "SynchronousGc");
int value;
return !String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value == 1;
}

protected override void OnMocksRepositoryCreated(MocksRepository repo)
{
// MSTest runs every test in a different thread. We'd like to collect Thread objects often so that their handle is released.
// At every N created repos (we assume that each test creates a single repo, so the number of repos created is close to
// the number of threads created) do a garbage collection, but only if it hasn't been already done in this interval.

createdRepoCount++;

if (createdRepoCount % gcFrequency == 0)
{
var gen2Collections = GC.CollectionCount(GC.MaxGeneration);
if (gen2Collections == lastGcCount)
{
if (synchronousGc)
{
GC.Collect();
}
else
{
ThreadPool.QueueUserWorkItem(_ => GC.Collect());
}

gen2Collections++;
}
lastGcCount = gen2Collections;
}
}
#endif
}
}
63 changes: 2 additions & 61 deletions Telerik.JustMock/Core/Context/MSTestMockingContextResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ limitations under the License.

namespace Telerik.JustMock.Core.Context
{
internal class MSTestMockingContextResolver : HierarchicalTestFrameworkContextResolver
internal class MSTestMockingContextResolver : MSTestBaseMockingContextResolver
{
#if SILVERLIGHT
private const string MstestAssemblyName = "Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight";
Expand All @@ -32,72 +32,13 @@ internal class MSTestMockingContextResolver : HierarchicalTestFrameworkContextRe
private const string MstestAssertionFailedName = "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException, " + MstestAssemblyName;

public MSTestMockingContextResolver()
: base(MstestAssertionFailedName)
: base(MstestAssertionFailedName, MstestAssemblyName)
{
this.SetupStandardHierarchicalTestStructure(
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute, " + MstestAssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute, " + MstestAssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute, " + MstestAssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute, " + MstestAssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute, " + MstestAssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyInitializeAttribute, " + MstestAssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyCleanupAttribute, " + MstestAssemblyName },
FixtureConstuctorSemantics.InstanceConstructorCalledOncePerFixture);
}

public static bool IsAvailable
{
get { return FindType(MstestAssertionFailedName, false) != null; }
}

#if !SILVERLIGHT
private const int DefaultGcFrequency = 50;
private int createdRepoCount;
private int lastGcCount;
private int gcFrequency = GetGcFrequency();
private bool synchronousGc = GetSynchronousGc();

private static int GetGcFrequency()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "MSTestGcFrequency");
int value;
if (!String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value >= 1)
return value;

return DefaultGcFrequency;
}

private static bool GetSynchronousGc()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "SynchronousGc");
int value;
return !String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value == 1;
}

protected override void OnMocksRepositoryCreated(MocksRepository repo)
{
// MSTest runs every test in a different thread. We'd like to collect Thread objects often so that their handle is released.
// At every N created repos (we assume that each test creates a single repo, so the number of repos created is close to
// the number of threads created) do a garbage collection, but only if it hasn't been already done in this interval.

createdRepoCount++;

if (createdRepoCount % gcFrequency == 0)
{
var gen2Collections = GC.CollectionCount(GC.MaxGeneration);
if (gen2Collections == lastGcCount)
{
if (synchronousGc)
{
GC.Collect();
}
else
{
ThreadPool.QueueUserWorkItem(_ => GC.Collect());
}

gen2Collections++;
}
lastGcCount = gen2Collections;
}
}
#endif
}
}
63 changes: 2 additions & 61 deletions Telerik.JustMock/Core/Context/MSTestV2MockingContextResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,78 +20,19 @@ limitations under the License.

namespace Telerik.JustMock.Core.Context
{
internal class MSTestV2MockingContextResolver : HierarchicalTestFrameworkContextResolver
internal class MSTestV2MockingContextResolver : MSTestBaseMockingContextResolver
{
private const string Mstestv2AssemblyName = "Microsoft.VisualStudio.TestPlatform.TestFramework";
private const string Mstestv2AssertionFailedName = "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException, " + Mstestv2AssemblyName;

public MSTestV2MockingContextResolver()
: base(Mstestv2AssertionFailedName)
: base(Mstestv2AssertionFailedName, Mstestv2AssemblyName)
{
this.SetupStandardHierarchicalTestStructure(
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute, " + Mstestv2AssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute, " + Mstestv2AssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute, " + Mstestv2AssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute, " + Mstestv2AssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute, " + Mstestv2AssemblyName },
new[] { "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyInitializeAttribute, " + Mstestv2AssemblyName, "Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyCleanupAttribute, " + Mstestv2AssemblyName },
FixtureConstuctorSemantics.InstanceConstructorCalledOncePerFixture);
}

public static bool IsAvailable
{
get { return FindType(Mstestv2AssertionFailedName, false) != null; }
}

private const int DefaultGcFrequency = 50;
private int createdRepoCount;
private int lastGcCount;
private int gcFrequency = GetGcFrequency();
private bool synchronousGc = GetSynchronousGc();

private static int GetGcFrequency()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "MSTestGcFrequency");
int value;
if (!String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value >= 1)
return value;

return DefaultGcFrequency;
}

private static bool GetSynchronousGc()
{
var valueStr = SecuredRegistryMethods.GetValue(false, @"Software\Telerik\JustMock", "SynchronousGc");
int value;
return !String.IsNullOrEmpty(valueStr) && int.TryParse(valueStr, out value) && value == 1;
}

#if !SILVERLIGHT
protected override void OnMocksRepositoryCreated(MocksRepository repo)
{
// MSTest runs every test in a different thread. We'd like to collect Thread objects often so that their handle is released.
// At every N created repos (we assume that each test creates a single repo, so the number of repos created is close to
// the number of threads created) do a garbage collection, but only if it hasn't been already done in this interval.

createdRepoCount++;

if (createdRepoCount % gcFrequency == 0)
{
var gen2Collections = GC.CollectionCount(GC.MaxGeneration);
if (gen2Collections == lastGcCount)
{
if (synchronousGc)
{
GC.Collect();
}
else
{
ThreadPool.QueueUserWorkItem(_ => GC.Collect());
}

gen2Collections++;
}
lastGcCount = gen2Collections;
}
}
#endif
}
}
21 changes: 21 additions & 0 deletions Telerik.JustMock/Core/Context/MSTestV4MockingContextResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Threading;

namespace Telerik.JustMock.Core.Context
{
internal class MSTestV4MockingContextResolver : MSTestBaseMockingContextResolver
{
private const string Mstestv4AssemblyName = "MSTest.TestFramework";
private const string Mstestv4AssertionFailedName = "Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException, " + Mstestv4AssemblyName;

public MSTestV4MockingContextResolver()
: base(Mstestv4AssertionFailedName, Mstestv4AssemblyName)
{
}

public static bool IsAvailable
{
get { return FindType(Mstestv4AssertionFailedName, false) != null; }
}
}
}
2 changes: 2 additions & 0 deletions Telerik.JustMock/Core/Context/MockingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ static MockingContext()
registeredContextResolvers.Add(new MSTestMockingContextResolver());
if (MSTestV2MockingContextResolver.IsAvailable)
registeredContextResolvers.Add(new MSTestV2MockingContextResolver());
if (MSTestV4MockingContextResolver.IsAvailable)
registeredContextResolvers.Add(new MSTestV4MockingContextResolver());
#endif

foreach (var resolver in registeredContextResolvers)
Expand Down