From 640e7eb413465649fc49ae13a9b48c5035103f26 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 3 Oct 2022 17:03:13 -0400 Subject: [PATCH] Test that templating AppDomains are unloaded --- Mono.TextTemplating.Tests/AppDomainTests.cs | 29 +++++++++++++++++-- .../AssemblyLoadTests.cs | 5 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Mono.TextTemplating.Tests/AppDomainTests.cs b/Mono.TextTemplating.Tests/AppDomainTests.cs index 0d5efe7..b41b270 100644 --- a/Mono.TextTemplating.Tests/AppDomainTests.cs +++ b/Mono.TextTemplating.Tests/AppDomainTests.cs @@ -16,7 +16,20 @@ namespace Mono.TextTemplating.Tests; public class AppDomainTests : AssemblyLoadTests> { protected override TemplateGenerator CreateGenerator ([CallerMemberName] string testName = null) => CreateGeneratorWithAppDomain (testName: testName); + + protected override void CleanupGenerator (TemplateGenerator generator) + { + // verify that the AppDomain is collected + var weakRef = ((TestTemplateGeneratorWithAppDomain)generator).ReleaseDomain (); + int count = 0; + while (weakRef.IsAlive) { + GC.Collect (); + Assert.InRange (count++, 0, 5); + } + } + protected override SnapshotSet GetInitialState () => Snapshot.LoadedAssemblies (); + protected override void VerifyFinalState (SnapshotSet state) { (var added, var removed) = state.GetChanges (); @@ -40,6 +53,7 @@ public async Task BadAppDomain () var templateText = await testDir["LoadOpenApiDll.tt"].ReadAllTextNormalizedAsync (); await Assert.ThrowsAnyAsync (() => badGen.ProcessTemplateAsync ("LoadOpenApiDll.tt", templateText, null)); + CleanupGenerator (badGen); } [Fact] @@ -56,6 +70,7 @@ public async Task RunsInAppDomain () Assert.Null (gen.Errors.OfType ().FirstOrDefault ()); Assert.Equal (expectedOutputText, result.content); + CleanupGenerator (gen); VerifyFinalState (state); } @@ -82,12 +97,20 @@ static TestTemplateGeneratorWithAppDomain CreateGeneratorWithAppDomain ( } static string GetAppDomainNameForCurrentTest ([CallerMemberName] string testName = null) => $"Template Test - {testName ?? "(unknown)"}"; + class TestTemplateGeneratorWithAppDomain : TemplateGenerator { - public TestTemplateGeneratorWithAppDomain (AppDomain appDomain) => AppDomain = appDomain; + AppDomain appDomain; + public TestTemplateGeneratorWithAppDomain (AppDomain appDomain) => this.appDomain = appDomain; - public AppDomain AppDomain { get; private set; } - public override AppDomain ProvideTemplatingAppDomain (string content) => AppDomain; + public override AppDomain ProvideTemplatingAppDomain (string content) => appDomain; + + public WeakReference ReleaseDomain () + { + var weakRef = new WeakReference (appDomain); + appDomain = null; + return weakRef; + } } } diff --git a/Mono.TextTemplating.Tests/AssemblyLoadTests.cs b/Mono.TextTemplating.Tests/AssemblyLoadTests.cs index 18b5fe9..ce16f4d 100644 --- a/Mono.TextTemplating.Tests/AssemblyLoadTests.cs +++ b/Mono.TextTemplating.Tests/AssemblyLoadTests.cs @@ -12,6 +12,7 @@ namespace Mono.TextTemplating.Tests; public abstract class AssemblyLoadTests : StatefulTest { protected virtual TemplateGenerator CreateGenerator ([CallerMemberName] string testName = null) => new (); + protected virtual void CleanupGenerator (TemplateGenerator generator) { } [Fact] public async Task LoadOpenApiDll () @@ -34,6 +35,7 @@ public async Task LoadOpenApiDll () Assert.Equal (expectedOutputText, result.content); Assert.Equal (expectedOutputPath, result.fileName); + CleanupGenerator (gen); VerifyFinalState (state); } @@ -56,6 +58,7 @@ public async Task LoadOpenApiReadersDll () Assert.Null (gen.Errors.OfType ().FirstOrDefault ()); Assert.Equal ("Example", result.content); + CleanupGenerator (gen); VerifyFinalState (state); } @@ -74,5 +77,7 @@ public async Task MissingTransitiveReference () var firstError = gen.Errors.OfType ().FirstOrDefault ()?.ErrorText; Assert.Contains ("FileNotFoundException: Could not load file or assembly 'SharpYaml, Version=1.6.5.0", firstError); + + CleanupGenerator (gen); } } \ No newline at end of file