U4-9322 - filesystems & cleanup

This commit is contained in:
Stephan
2017-02-03 20:01:43 +01:00
parent 478ca30948
commit 820069d5d5
18 changed files with 664 additions and 251 deletions

View File

@@ -0,0 +1,157 @@
using System;
using System.IO;
using System.Text;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Scoping
{
[TestFixture]
[DatabaseTestBehavior(DatabaseBehavior.EmptyDbFilePerTest)]
public class ScopeFileSystemsTests : BaseDatabaseFactoryTest
{
[SetUp]
public override void Initialize()
{
base.Initialize();
SafeCallContext.Clear();
ClearFiles();
}
[TearDown]
public override void TearDown()
{
base.TearDown();
SafeCallContext.Clear();
ClearFiles();
}
private static void ClearFiles()
{
TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests"));
TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data"));
}
[TestCase(true)]
[TestCase(false)]
public void CreateMediaTest(bool complete)
{
var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore");
var mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
var scopeProvider = ApplicationContext.ScopeProvider;
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
mediaFileSystem.AddFile("f1.txt", ms);
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
if (complete)
scope.Complete();
Assert.IsTrue(mediaFileSystem.FileExists("f1.txt"));
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
}
if (complete)
{
Assert.IsTrue(FileSystemProviderManager.Current.MediaFileSystem.FileExists("f1.txt"));
Assert.IsTrue(physMediaFileSystem.FileExists("f1.txt"));
}
else
{
Assert.IsFalse(FileSystemProviderManager.Current.MediaFileSystem.FileExists("f1.txt"));
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
}
}
[Test]
public void MultiThread()
{
var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore");
var mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
var scopeProvider = ApplicationContext.ScopeProvider;
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
mediaFileSystem.AddFile("f1.txt", ms);
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")))
mediaFileSystem.AddFile("f2.txt", ms);
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()
{
var scopeProvider = ApplicationContext.ScopeProvider;
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
{
using (new SafeCallContext()) // not nesting!
{
// ok to create a 'normal' other scope
using (var other = scopeProvider.CreateScope())
{
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>(() =>
{
var other = scopeProvider.CreateScope(scopeFileSystems: true);
});
}
}
}
[Test]
public void SingleShadowEvenDetached()
{
var scopeProvider = ApplicationContext.ScopeProvider as IScopeProviderInternal;
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
{
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>(() =>
{
var other = scopeProvider.CreateDetachedScope(scopeFileSystems: true);
});
}
}
var detached = scopeProvider.CreateDetachedScope(scopeFileSystems: true);
Assert.IsNull(scopeProvider.AmbientScope);
Assert.Throws<InvalidOperationException>(() =>
{
// even if there is no ambient scope, there's a single shadow
using (var other = scopeProvider.CreateScope(scopeFileSystems: true))
{ }
});
scopeProvider.AttachScope(detached);
detached.Dispose();
}
}
}

View File

@@ -540,5 +540,108 @@ namespace Umbraco.Tests.Scoping
Assert.IsNull(ambientScope); // the scope is gone
Assert.IsNotNull(ambientContext); // the context is still there
}
[Test]
public void ScopeContextException()
{
var scopeProvider = DatabaseContext.ScopeProvider;
bool? completed = null;
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope())
{
var detached = scopeProvider.CreateDetachedScope();
scopeProvider.AttachScope(detached);
// the exception does not prevent other enlisted items to run
// *and* it does not prevent the scope from properly going down
scopeProvider.Context.Enlist("name", c =>
{
throw new Exception("bang");
});
scopeProvider.Context.Enlist("other", c =>
{
completed = c;
});
detached.Complete();
Assert.Throws<AggregateException>(() =>
{
detached.Dispose();
});
// even though disposing of the scope has thrown, it has exited
// properly ie it has removed itself, and the app remains clean
Assert.AreSame(scope, scopeProvider.AmbientScope);
scope.Complete();
}
Assert.IsNull(scopeProvider.AmbientScope);
Assert.IsNull(scopeProvider.AmbientContext);
Assert.IsNotNull(completed);
Assert.AreEqual(true, completed);
}
[Test]
public void DetachableScope()
{
var scopeProvider = DatabaseContext.ScopeProvider;
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope())
{
Assert.IsInstanceOf<Scope>(scope);
Assert.IsNotNull(scopeProvider.AmbientScope);
Assert.AreSame(scope, scopeProvider.AmbientScope);
Assert.IsNotNull(scopeProvider.AmbientContext); // the ambient context
Assert.IsNotNull(scopeProvider.Context); // the ambient context too (getter only)
var context = scopeProvider.Context;
var detached = scopeProvider.CreateDetachedScope();
scopeProvider.AttachScope(detached);
Assert.AreEqual(detached, scopeProvider.AmbientScope);
Assert.AreNotSame(context, scopeProvider.Context);
// nesting under detached!
using (var nested = scopeProvider.CreateScope())
{
Assert.Throws<InvalidOperationException>(() =>
{
// cannot detach a non-detachable scope
scopeProvider.DetachScope();
});
nested.Complete();
}
Assert.AreEqual(detached, scopeProvider.AmbientScope);
Assert.AreNotSame(context, scopeProvider.Context);
// can detach
Assert.AreSame(detached, scopeProvider.DetachScope());
Assert.AreSame(scope, scopeProvider.AmbientScope);
Assert.AreSame(context, scopeProvider.AmbientContext);
Assert.Throws<InvalidOperationException>(() =>
{
// cannot disposed a non-attached scope
// in fact, only the ambient scope can be disposed
detached.Dispose();
});
scopeProvider.AttachScope(detached);
detached.Complete();
detached.Dispose();
// has self-detached, and is gone!
Assert.AreSame(scope, scopeProvider.AmbientScope);
Assert.AreSame(context, scopeProvider.AmbientContext);
}
Assert.IsNull(scopeProvider.AmbientScope);
Assert.IsNull(scopeProvider.AmbientContext);
}
}
}