2020-12-23 11:35:49 +01:00
|
|
|
// Copyright (c) Umbraco.
|
|
|
|
|
// See LICENSE for more details.
|
|
|
|
|
|
|
|
|
|
using System;
|
2017-05-12 14:49:44 +02:00
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
2020-09-17 11:35:29 +02:00
|
|
|
using Microsoft.Extensions.Logging;
|
2017-05-12 14:49:44 +02:00
|
|
|
using NUnit.Framework;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Umbraco.Cms.Core;
|
|
|
|
|
using Umbraco.Cms.Core.Hosting;
|
|
|
|
|
using Umbraco.Cms.Core.IO;
|
2021-02-10 14:45:44 +01:00
|
|
|
using Umbraco.Cms.Tests.Common.Testing;
|
2020-10-26 10:47:14 +00:00
|
|
|
using Umbraco.Core.Scoping;
|
2021-02-09 11:26:22 +01:00
|
|
|
using Umbraco.Extensions;
|
2020-10-26 10:47:14 +00:00
|
|
|
using Umbraco.Tests.Integration.Testing;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Constants = Umbraco.Cms.Core.Constants;
|
|
|
|
|
using FileSystems = Umbraco.Cms.Core.IO.FileSystems;
|
2017-05-12 14:49:44 +02:00
|
|
|
|
2020-10-28 14:54:16 +01:00
|
|
|
namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Scoping
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
[TestFixture]
|
|
|
|
|
[UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)]
|
2020-10-26 10:47:14 +00:00
|
|
|
public class ScopeFileSystemsTests : UmbracoIntegrationTest
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
2020-10-26 10:47:14 +00:00
|
|
|
private IMediaFileSystem MediaFileSystem => GetRequiredService<IMediaFileSystem>();
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
private IHostingEnvironment HostingEnvironment => GetRequiredService<IHostingEnvironment>();
|
2017-05-12 14:49:44 +02:00
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
[SetUp]
|
|
|
|
|
public void SetUp()
|
|
|
|
|
{
|
2017-05-12 14:49:44 +02:00
|
|
|
SafeCallContext.Clear();
|
2019-11-20 12:14:42 +01:00
|
|
|
ClearFiles(IOHelper);
|
2017-05-12 14:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
[TearDown]
|
|
|
|
|
public void Teardown()
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
SafeCallContext.Clear();
|
2018-11-19 14:40:59 +01:00
|
|
|
FileSystems.ResetShadowId();
|
2019-11-20 12:14:42 +01:00
|
|
|
ClearFiles(IOHelper);
|
2017-05-12 14:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
private void ClearFiles(IIOHelper ioHelper)
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
2019-11-13 21:00:54 +01:00
|
|
|
TestHelper.DeleteDirectory(ioHelper.MapPath("media"));
|
|
|
|
|
TestHelper.DeleteDirectory(ioHelper.MapPath("FileSysTests"));
|
2019-11-18 19:46:32 +01:00
|
|
|
TestHelper.DeleteDirectory(ioHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"));
|
2017-05-12 14:49:44 +02:00
|
|
|
}
|
2020-10-28 14:54:16 +01:00
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
[Test]
|
2020-12-23 11:35:49 +01:00
|
|
|
public void MediaFileSystem_does_not_write_to_physical_file_system_when_scoped_if_scope_does_not_complete()
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
string rootPath = HostingEnvironment.MapPathWebRoot(GlobalSettings.UmbracoMediaPath);
|
|
|
|
|
string rootUrl = HostingEnvironment.ToAbsolute(GlobalSettings.UmbracoMediaPath);
|
2020-10-26 10:47:14 +00:00
|
|
|
var physMediaFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, GetRequiredService<ILogger<PhysicalFileSystem>>(), rootPath, rootUrl);
|
2020-12-23 11:35:49 +01:00
|
|
|
IMediaFileSystem mediaFileSystem = MediaFileSystem;
|
2017-05-12 14:49:44 +02:00
|
|
|
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
using (ScopeProvider.CreateScope(scopeFileSystems: true))
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
2020-12-23 11:35:49 +01:00
|
|
|
{
|
2017-05-12 14:49:44 +02:00
|
|
|
mediaFileSystem.AddFile("f1.txt", ms);
|
2020-12-23 11:35:49 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 14:49:44 +02:00
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
2020-10-28 14:54:16 +01:00
|
|
|
|
2017-05-12 14:49:44 +02:00
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
// After scope is disposed ensure shadow wrapper didn't commit to physical
|
|
|
|
|
Assert.IsFalse(MediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
2020-12-23 11:35:49 +01:00
|
|
|
public void MediaFileSystem_writes_to_physical_file_system_when_scoped_and_scope_is_completed()
|
2020-10-26 10:47:14 +00:00
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
string rootPath = HostingEnvironment.MapPathWebRoot(GlobalSettings.UmbracoMediaPath);
|
|
|
|
|
string rootUrl = HostingEnvironment.ToAbsolute(GlobalSettings.UmbracoMediaPath);
|
2020-10-26 10:47:14 +00:00
|
|
|
var physMediaFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, GetRequiredService<ILogger<PhysicalFileSystem>>(), rootPath, rootUrl);
|
2020-12-23 11:35:49 +01:00
|
|
|
IMediaFileSystem mediaFileSystem = MediaFileSystem;
|
2020-10-26 10:47:14 +00:00
|
|
|
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
|
2020-12-23 11:35:49 +01:00
|
|
|
using (IScope scope = ScopeProvider.CreateScope(scopeFileSystems: true))
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
2020-10-26 10:47:14 +00:00
|
|
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
2020-12-23 11:35:49 +01:00
|
|
|
{
|
2020-10-26 10:47:14 +00:00
|
|
|
mediaFileSystem.AddFile("f1.txt", ms);
|
2020-12-23 11:35:49 +01:00
|
|
|
}
|
|
|
|
|
|
2020-10-26 10:47:14 +00:00
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
|
|
|
|
|
scope.Complete();
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
|
2017-05-12 14:49:44 +02:00
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
}
|
2020-10-26 10:47:14 +00:00
|
|
|
|
|
|
|
|
// After scope is disposed ensure shadow wrapper writes to physical file system
|
|
|
|
|
Assert.IsTrue(MediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsTrue(physMediaFileSystem.FileExists("f1.txt"));
|
2017-05-12 14:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void MultiThread()
|
|
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
string rootPath = HostingEnvironment.MapPathWebRoot(GlobalSettings.UmbracoMediaPath);
|
|
|
|
|
string rootUrl = HostingEnvironment.ToAbsolute(GlobalSettings.UmbracoMediaPath);
|
2020-10-26 10:47:14 +00:00
|
|
|
var physMediaFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, GetRequiredService<ILogger<PhysicalFileSystem>>(), rootPath, rootUrl);
|
2020-12-23 11:35:49 +01:00
|
|
|
IMediaFileSystem mediaFileSystem = MediaFileSystem;
|
2017-05-12 14:49:44 +02:00
|
|
|
|
2020-12-23 11:35:49 +01:00
|
|
|
IScopeProvider scopeProvider = ScopeProvider;
|
|
|
|
|
using (IScope scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
2020-12-23 11:35:49 +01:00
|
|
|
{
|
2017-05-12 14:49:44 +02:00
|
|
|
mediaFileSystem.AddFile("f1.txt", ms);
|
2020-12-23 11:35:49 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 14:49:44 +02:00
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
|
|
|
|
|
using (new SafeCallContext())
|
|
|
|
|
{
|
|
|
|
|
Assert.IsFalse(mediaFileSystem.FileExists("f1.txt"));
|
|
|
|
|
|
|
|
|
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
2020-12-23 11:35:49 +01:00
|
|
|
{
|
2017-05-12 14:49:44 +02:00
|
|
|
mediaFileSystem.AddFile("f2.txt", ms);
|
2020-12-23 11:35:49 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 14:49:44 +02:00
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f2.txt"));
|
|
|
|
|
Assert.IsTrue(physMediaFileSystem.FileExists("f2.txt"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(mediaFileSystem.FileExists("f2.txt"));
|
|
|
|
|
Assert.IsTrue(physMediaFileSystem.FileExists("f2.txt"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void SingleShadow()
|
|
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
IScopeProvider scopeProvider = ScopeProvider;
|
|
|
|
|
using (IScope scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
using (new SafeCallContext()) // not nesting!
|
|
|
|
|
{
|
|
|
|
|
// ok to create a 'normal' other scope
|
2020-12-23 11:35:49 +01:00
|
|
|
using (IScope other = scopeProvider.CreateScope())
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
other.Complete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// not ok to create a 'scoped filesystems' other scope
|
|
|
|
|
// because at the moment we don't support concurrent scoped filesystems
|
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
IScope other = scopeProvider.CreateScope(scopeFileSystems: true);
|
2017-05-12 14:49:44 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void SingleShadowEvenDetached()
|
|
|
|
|
{
|
2020-10-26 10:47:14 +00:00
|
|
|
var scopeProvider = (ScopeProvider)ScopeProvider;
|
2020-12-23 11:35:49 +01:00
|
|
|
using (IScope scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
2017-05-12 14:49:44 +02:00
|
|
|
{
|
|
|
|
|
using (new SafeCallContext()) // not nesting!
|
|
|
|
|
{
|
|
|
|
|
// not ok to create a 'scoped filesystems' other scope
|
|
|
|
|
// because at the moment we don't support concurrent scoped filesystems
|
|
|
|
|
// even a detached one
|
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
|
|
|
{
|
2020-12-23 11:35:49 +01:00
|
|
|
IScope other = scopeProvider.CreateDetachedScope(scopeFileSystems: true);
|
2017-05-12 14:49:44 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-23 11:35:49 +01:00
|
|
|
IScope detached = scopeProvider.CreateDetachedScope(scopeFileSystems: true);
|
2017-05-12 14:49:44 +02:00
|
|
|
|
|
|
|
|
Assert.IsNull(scopeProvider.AmbientScope);
|
|
|
|
|
|
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
|
|
|
{
|
|
|
|
|
// even if there is no ambient scope, there's a single shadow
|
2020-12-23 11:35:49 +01:00
|
|
|
using (IScope other = scopeProvider.CreateScope(scopeFileSystems: true))
|
|
|
|
|
{
|
|
|
|
|
}
|
2017-05-12 14:49:44 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scopeProvider.AttachScope(detached);
|
|
|
|
|
detached.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|