@@ -172,6 +172,91 @@ public async Task ShadowCopyE2EWorksWithFolderPresent()
172
172
Assert . True ( response . IsSuccessStatusCode ) ;
173
173
}
174
174
175
+ [ ConditionalFact ]
176
+ public async Task ShadowCopyE2EWorksWithOldFoldersPresent ( )
177
+ {
178
+ using var directory = TempDirectory . Create ( ) ;
179
+ var deploymentParameters = Fixture . GetBaseDeploymentParameters ( ) ;
180
+ deploymentParameters . HandlerSettings [ "experimentalEnableShadowCopy" ] = "true" ;
181
+ deploymentParameters . HandlerSettings [ "shadowCopyDirectory" ] = directory . DirectoryPath ;
182
+ var deploymentResult = await DeployAsync ( deploymentParameters ) ;
183
+
184
+ // Start with 1 to exercise the incremental logic
185
+ DirectoryCopy ( deploymentResult . ContentRoot , Path . Combine ( directory . DirectoryPath , "1" ) , copySubDirs : true ) ;
186
+
187
+ var response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
188
+ Assert . True ( response . IsSuccessStatusCode ) ;
189
+
190
+ using var secondTempDir = TempDirectory . Create ( ) ;
191
+
192
+ // copy back and forth to cause file change notifications.
193
+ DirectoryCopy ( deploymentResult . ContentRoot , secondTempDir . DirectoryPath , copySubDirs : true ) ;
194
+ DirectoryCopy ( secondTempDir . DirectoryPath , deploymentResult . ContentRoot , copySubDirs : true ) ;
195
+
196
+ response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
197
+ Assert . False ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "0" ) ) , "Expected 0 shadow copy directory to be skipped" ) ;
198
+
199
+ // Depending on timing, this could result in a shutdown failure, but sometimes it succeeds, handle both situations
200
+ if ( ! response . IsSuccessStatusCode )
201
+ {
202
+ Assert . Equal ( "Application Shutting Down" , response . ReasonPhrase ) ;
203
+ }
204
+
205
+ // This shutdown should trigger a copy to the next highest directory, which will be 2
206
+ await deploymentResult . AssertRecycledAsync ( ) ;
207
+
208
+ Assert . True ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "2" ) ) , "Expected 2 shadow copy directory" ) ;
209
+
210
+ response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
211
+ Assert . True ( response . IsSuccessStatusCode ) ;
212
+ }
213
+
214
+ [ ConditionalFact ]
215
+ public async Task ShadowCopyCleansUpOlderFolders ( )
216
+ {
217
+ using var directory = TempDirectory . Create ( ) ;
218
+ var deploymentParameters = Fixture . GetBaseDeploymentParameters ( ) ;
219
+ deploymentParameters . HandlerSettings [ "experimentalEnableShadowCopy" ] = "true" ;
220
+ deploymentParameters . HandlerSettings [ "shadowCopyDirectory" ] = directory . DirectoryPath ;
221
+ var deploymentResult = await DeployAsync ( deploymentParameters ) ;
222
+
223
+ // Start with a bunch of junk
224
+ DirectoryCopy ( deploymentResult . ContentRoot , Path . Combine ( directory . DirectoryPath , "1" ) , copySubDirs : true ) ;
225
+ DirectoryCopy ( deploymentResult . ContentRoot , Path . Combine ( directory . DirectoryPath , "3" ) , copySubDirs : true ) ;
226
+ DirectoryCopy ( deploymentResult . ContentRoot , Path . Combine ( directory . DirectoryPath , "10" ) , copySubDirs : true ) ;
227
+
228
+ var response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
229
+ Assert . True ( response . IsSuccessStatusCode ) ;
230
+
231
+ using var secondTempDir = TempDirectory . Create ( ) ;
232
+
233
+ // copy back and forth to cause file change notifications.
234
+ DirectoryCopy ( deploymentResult . ContentRoot , secondTempDir . DirectoryPath , copySubDirs : true ) ;
235
+ DirectoryCopy ( secondTempDir . DirectoryPath , deploymentResult . ContentRoot , copySubDirs : true ) ;
236
+
237
+ response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
238
+ Assert . False ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "0" ) ) , "Expected 0 shadow copy directory to be skipped" ) ;
239
+
240
+ // Depending on timing, this could result in a shutdown failure, but sometimes it succeeds, handle both situations
241
+ if ( ! response . IsSuccessStatusCode )
242
+ {
243
+ Assert . Equal ( "Application Shutting Down" , response . ReasonPhrase ) ;
244
+ }
245
+
246
+ // This shutdown should trigger a copy to the next highest directory, which will be 11
247
+ await deploymentResult . AssertRecycledAsync ( ) ;
248
+
249
+ Assert . True ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "11" ) ) , "Expected 11 shadow copy directory" ) ;
250
+
251
+ response = await deploymentResult . HttpClient . GetAsync ( "Wow!" ) ;
252
+ Assert . True ( response . IsSuccessStatusCode ) ;
253
+
254
+ // Verify old directories were cleaned up
255
+ Assert . False ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "1" ) ) , "Expected 1 shadow copy directory to be deleted" ) ;
256
+ Assert . False ( Directory . Exists ( Path . Combine ( directory . DirectoryPath , "3" ) ) , "Expected 3 shadow copy directory to be deleted" ) ;
257
+ }
258
+
259
+
175
260
[ ConditionalFact ]
176
261
[ MaximumOSVersion ( OperatingSystems . Windows , WindowsVersions . Win10_20H2 , SkipReason = "Shutdown hangs https://github.com/dotnet/aspnetcore/issues/25107" ) ]
177
262
public async Task ShadowCopyIgnoresItsOwnDirectoryWithRelativePathSegmentWhenCopying ( )
0 commit comments