diff --git a/Telerik.JustMock/Core/Context/MSTestBaseMockingContextResolver.cs b/Telerik.JustMock/Core/Context/MSTestBaseMockingContextResolver.cs new file mode 100644 index 00000000..234b40be --- /dev/null +++ b/Telerik.JustMock/Core/Context/MSTestBaseMockingContextResolver.cs @@ -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 + } +} diff --git a/Telerik.JustMock/Core/Context/MSTestMockingContextResolver.cs b/Telerik.JustMock/Core/Context/MSTestMockingContextResolver.cs index e67bb043..e57fdcf2 100644 --- a/Telerik.JustMock/Core/Context/MSTestMockingContextResolver.cs +++ b/Telerik.JustMock/Core/Context/MSTestMockingContextResolver.cs @@ -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"; @@ -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 } } diff --git a/Telerik.JustMock/Core/Context/MSTestV2MockingContextResolver.cs b/Telerik.JustMock/Core/Context/MSTestV2MockingContextResolver.cs index ecbb92c2..751b7040 100644 --- a/Telerik.JustMock/Core/Context/MSTestV2MockingContextResolver.cs +++ b/Telerik.JustMock/Core/Context/MSTestV2MockingContextResolver.cs @@ -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 } } diff --git a/Telerik.JustMock/Core/Context/MSTestV4MockingContextResolver.cs b/Telerik.JustMock/Core/Context/MSTestV4MockingContextResolver.cs new file mode 100644 index 00000000..7a9b85ce --- /dev/null +++ b/Telerik.JustMock/Core/Context/MSTestV4MockingContextResolver.cs @@ -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; } + } + } +} diff --git a/Telerik.JustMock/Core/Context/MockingContext.cs b/Telerik.JustMock/Core/Context/MockingContext.cs index 24abd75b..6b5ec7f9 100644 --- a/Telerik.JustMock/Core/Context/MockingContext.cs +++ b/Telerik.JustMock/Core/Context/MockingContext.cs @@ -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)