From 1c9f1d26afc54f5d9fe834345042ae75c835cf2d Mon Sep 17 00:00:00 2001
From: Hao Kung <HaoK@users.noreply.github.com>
Date: Wed, 11 Aug 2021 16:45:26 -0700
Subject: [PATCH] Add a new shadowcopy test (#35249)

---
 .../IIS.FunctionalTests/ShadowCopyTests.cs    | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/ShadowCopyTests.cs b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/ShadowCopyTests.cs
index 1a449c9bf99..375bf607eae 100644
--- a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/ShadowCopyTests.cs
+++ b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/ShadowCopyTests.cs
@@ -172,6 +172,91 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
             Assert.True(response.IsSuccessStatusCode);
         }
 
+        [ConditionalFact]
+        public async Task ShadowCopyE2EWorksWithOldFoldersPresent()
+        {
+            using var directory = TempDirectory.Create();
+            var deploymentParameters = Fixture.GetBaseDeploymentParameters();
+            deploymentParameters.HandlerSettings["experimentalEnableShadowCopy"] = "true";
+            deploymentParameters.HandlerSettings["shadowCopyDirectory"] = directory.DirectoryPath;
+            var deploymentResult = await DeployAsync(deploymentParameters);
+
+            // Start with 1 to exercise the incremental logic
+            DirectoryCopy(deploymentResult.ContentRoot, Path.Combine(directory.DirectoryPath, "1"), copySubDirs: true);
+
+            var response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.True(response.IsSuccessStatusCode);
+
+            using var secondTempDir = TempDirectory.Create();
+
+            // copy back and forth to cause file change notifications.
+            DirectoryCopy(deploymentResult.ContentRoot, secondTempDir.DirectoryPath, copySubDirs: true);
+            DirectoryCopy(secondTempDir.DirectoryPath, deploymentResult.ContentRoot, copySubDirs: true);
+
+            response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.False(Directory.Exists(Path.Combine(directory.DirectoryPath, "0")), "Expected 0 shadow copy directory to be skipped");
+
+            // Depending on timing, this could result in a shutdown failure, but sometimes it succeeds, handle both situations
+            if (!response.IsSuccessStatusCode)
+            {
+                Assert.Equal("Application Shutting Down", response.ReasonPhrase);
+            }
+
+            // This shutdown should trigger a copy to the next highest directory, which will be 2
+            await deploymentResult.AssertRecycledAsync();
+
+            Assert.True(Directory.Exists(Path.Combine(directory.DirectoryPath, "2")), "Expected 2 shadow copy directory");
+
+            response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.True(response.IsSuccessStatusCode);
+        }
+
+        [ConditionalFact]
+        public async Task ShadowCopyCleansUpOlderFolders()
+        {
+            using var directory = TempDirectory.Create();
+            var deploymentParameters = Fixture.GetBaseDeploymentParameters();
+            deploymentParameters.HandlerSettings["experimentalEnableShadowCopy"] = "true";
+            deploymentParameters.HandlerSettings["shadowCopyDirectory"] = directory.DirectoryPath;
+            var deploymentResult = await DeployAsync(deploymentParameters);
+
+            // Start with a bunch of junk
+            DirectoryCopy(deploymentResult.ContentRoot, Path.Combine(directory.DirectoryPath, "1"), copySubDirs: true);
+            DirectoryCopy(deploymentResult.ContentRoot, Path.Combine(directory.DirectoryPath, "3"), copySubDirs: true);
+            DirectoryCopy(deploymentResult.ContentRoot, Path.Combine(directory.DirectoryPath, "10"), copySubDirs: true);
+
+            var response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.True(response.IsSuccessStatusCode);
+
+            using var secondTempDir = TempDirectory.Create();
+
+            // copy back and forth to cause file change notifications.
+            DirectoryCopy(deploymentResult.ContentRoot, secondTempDir.DirectoryPath, copySubDirs: true);
+            DirectoryCopy(secondTempDir.DirectoryPath, deploymentResult.ContentRoot, copySubDirs: true);
+
+            response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.False(Directory.Exists(Path.Combine(directory.DirectoryPath, "0")), "Expected 0 shadow copy directory to be skipped");
+
+            // Depending on timing, this could result in a shutdown failure, but sometimes it succeeds, handle both situations
+            if (!response.IsSuccessStatusCode)
+            {
+                Assert.Equal("Application Shutting Down", response.ReasonPhrase);
+            }
+
+            // This shutdown should trigger a copy to the next highest directory, which will be 11
+            await deploymentResult.AssertRecycledAsync();
+
+            Assert.True(Directory.Exists(Path.Combine(directory.DirectoryPath, "11")), "Expected 11 shadow copy directory");
+
+            response = await deploymentResult.HttpClient.GetAsync("Wow!");
+            Assert.True(response.IsSuccessStatusCode);
+ 
+            // Verify old directories were cleaned up
+            Assert.False(Directory.Exists(Path.Combine(directory.DirectoryPath, "1")), "Expected 1 shadow copy directory to be deleted");
+            Assert.False(Directory.Exists(Path.Combine(directory.DirectoryPath, "3")), "Expected 3 shadow copy directory to be deleted");
+        }
+
+
         [ConditionalFact]
         [MaximumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10_20H2, SkipReason = "Shutdown hangs https://github.com/dotnet/aspnetcore/issues/25107")]
         public async Task ShadowCopyIgnoresItsOwnDirectoryWithRelativePathSegmentWhenCopying()
-- 
GitLab