U4-9322 - filesystems & cleanup
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.IO
|
||||
@@ -23,6 +24,7 @@ namespace Umbraco.Tests.IO
|
||||
{
|
||||
SafeCallContext.Clear();
|
||||
ClearFiles();
|
||||
ShadowFileSystems.ResetId();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -30,6 +32,7 @@ namespace Umbraco.Tests.IO
|
||||
{
|
||||
SafeCallContext.Clear();
|
||||
ClearFiles();
|
||||
ShadowFileSystems.ResetId();
|
||||
}
|
||||
|
||||
private static void ClearFiles()
|
||||
@@ -373,8 +376,11 @@ namespace Umbraco.Tests.IO
|
||||
var appdata = IOHelper.MapPath("App_Data");
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
var scopedFileSystems = false;
|
||||
var scopeProvider = MockScopeProvider(() => scopedFileSystems);
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
@@ -394,46 +400,52 @@ namespace Umbraco.Tests.IO
|
||||
Assert.IsFalse(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
|
||||
// shadow with scope but no complete does not complete
|
||||
var scope = ShadowFileSystemsScope.CreateScope(id = Guid.NewGuid(), swa);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);
|
||||
Assert.IsTrue(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f3.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f3.txt"));
|
||||
Assert.AreEqual(1, Directory.GetDirectories(appdata + "/Shadow").Length);
|
||||
scope.Dispose();
|
||||
scopedFileSystems = false;
|
||||
Assert.IsFalse(fs.FileExists("sub/f3.txt"));
|
||||
Assert.IsFalse(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
|
||||
// shadow with scope and complete does complete
|
||||
scope = ShadowFileSystemsScope.CreateScope(id = Guid.NewGuid(), swa);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);
|
||||
Assert.IsTrue(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f4.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f4.txt"));
|
||||
Assert.AreEqual(1, Directory.GetDirectories(appdata + "/Shadow").Length);
|
||||
scope.Complete();
|
||||
Assert.IsTrue(fs.FileExists("sub/f4.txt"));
|
||||
TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(appdata + "/Shadow").Length));
|
||||
scope.Dispose();
|
||||
scopedFileSystems = false;
|
||||
TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(appdata + "/Shadow").Length));
|
||||
Assert.IsTrue(fs.FileExists("sub/f4.txt"));
|
||||
Assert.IsFalse(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
|
||||
// test scope for "another thread"
|
||||
|
||||
scope = ShadowFileSystemsScope.CreateScope(id = Guid.NewGuid(), swa);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);
|
||||
Assert.IsTrue(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f5.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f5.txt"));
|
||||
using (new SafeCallContext()) // pretend we're another thread w/out scope
|
||||
{
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f6.txt", ms);
|
||||
}
|
||||
|
||||
// pretend we're another thread w/out scope
|
||||
scopedFileSystems = false;
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f6.txt", ms);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
|
||||
Assert.IsTrue(fs.FileExists("sub/f6.txt")); // other thread has written out to fs
|
||||
scope.Complete();
|
||||
Assert.IsTrue(fs.FileExists("sub/f5.txt"));
|
||||
scope.Dispose();
|
||||
scopedFileSystems = false;
|
||||
Assert.IsTrue(fs.FileExists("sub/f5.txt"));
|
||||
Assert.IsFalse(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
}
|
||||
@@ -445,8 +457,11 @@ namespace Umbraco.Tests.IO
|
||||
var appdata = IOHelper.MapPath("App_Data");
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
var scopedFileSystems = false;
|
||||
var scopeProvider = MockScopeProvider(() => scopedFileSystems);
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
@@ -455,20 +470,23 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
Guid id;
|
||||
|
||||
var scope = ShadowFileSystemsScope.CreateScope(id = Guid.NewGuid(), swa);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);
|
||||
Assert.IsTrue(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f2.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f2.txt"));
|
||||
using (new SafeCallContext()) // pretend we're another thread w/out scope
|
||||
{
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
|
||||
sw.AddFile("sub/f2.txt", ms);
|
||||
}
|
||||
|
||||
// pretend we're another thread w/out scope
|
||||
scopedFileSystems = false;
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
|
||||
sw.AddFile("sub/f2.txt", ms);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
|
||||
Assert.IsTrue(fs.FileExists("sub/f2.txt")); // other thread has written out to fs
|
||||
scope.Complete();
|
||||
Assert.IsTrue(fs.FileExists("sub/f2.txt"));
|
||||
scope.Dispose();
|
||||
scopedFileSystems = false;
|
||||
Assert.IsTrue(fs.FileExists("sub/f2.txt"));
|
||||
TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(appdata + "/Shadow/" + id)));
|
||||
|
||||
@@ -488,8 +506,11 @@ namespace Umbraco.Tests.IO
|
||||
var appdata = IOHelper.MapPath("App_Data");
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
var scopedFileSystems = false;
|
||||
var scopeProvider = MockScopeProvider(() => scopedFileSystems);
|
||||
|
||||
var fs = new PhysicalFileSystem(path, "ignore");
|
||||
var sw = new ShadowWrapper(fs, "shadow");
|
||||
var sw = new ShadowWrapper(fs, "shadow", scopeProvider);
|
||||
var swa = new[] { sw };
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
@@ -498,27 +519,32 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
Guid id;
|
||||
|
||||
var scope = ShadowFileSystemsScope.CreateScope(id = Guid.NewGuid(), swa);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);
|
||||
Assert.IsTrue(Directory.Exists(appdata + "/Shadow/" + id));
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f2.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f2.txt"));
|
||||
using (new SafeCallContext()) // pretend we're another thread w/out scope
|
||||
{
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
|
||||
sw.AddFile("sub/f2.txt/f2.txt", ms);
|
||||
}
|
||||
|
||||
// pretend we're another thread w/out scope
|
||||
scopedFileSystems = false;
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
|
||||
sw.AddFile("sub/f2.txt/f2.txt", ms);
|
||||
scopedFileSystems = true; // pretend we have a scope
|
||||
|
||||
Assert.IsTrue(fs.FileExists("sub/f2.txt/f2.txt")); // other thread has written out to fs
|
||||
|
||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
||||
sw.AddFile("sub/f3.txt", ms);
|
||||
Assert.IsFalse(fs.FileExists("sub/f3.txt"));
|
||||
|
||||
scope.Complete();
|
||||
|
||||
try
|
||||
{
|
||||
// no way this can work since we're trying to write a file
|
||||
// but there's now a directory with the same name on the real fs
|
||||
scope.Complete();
|
||||
scope.Dispose();
|
||||
Assert.Fail("Expected AggregateException.");
|
||||
}
|
||||
catch (AggregateException ae)
|
||||
@@ -576,5 +602,25 @@ namespace Umbraco.Tests.IO
|
||||
TestHelper.Try(() => Directory.Delete(path, true));
|
||||
TestHelper.TryAssert(() => Assert.IsFalse(File.Exists(path + "/test/inner/f3.txt")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MockTest()
|
||||
{
|
||||
var scoped = false;
|
||||
var provider = MockScopeProvider(() => scoped);
|
||||
|
||||
Assert.IsFalse(provider.AmbientScope.ScopedFileSystems);
|
||||
scoped = true;
|
||||
Assert.IsTrue(provider.AmbientScope.ScopedFileSystems);
|
||||
}
|
||||
|
||||
private static IScopeProviderInternal MockScopeProvider(Func<bool> f)
|
||||
{
|
||||
var scopeMock = new Mock<IScopeInternal>();
|
||||
scopeMock.Setup(x => x.ScopedFileSystems).Returns(f);
|
||||
var providerMock = new Mock<IScopeProviderInternal>();
|
||||
providerMock.Setup(x => x.AmbientScope).Returns(scopeMock.Object);
|
||||
return providerMock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
157
src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs
Normal file
157
src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,7 @@
|
||||
<Compile Include="Scoping\PassThroughEventDispatcherTests.cs" />
|
||||
<Compile Include="Scoping\ScopeEventDispatcherTests.cs" />
|
||||
<Compile Include="Scoping\ScopedXmlTests.cs" />
|
||||
<Compile Include="Scoping\ScopeFileSystemsTests.cs" />
|
||||
<Compile Include="Scoping\ScopeTests.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedPropertyTypes.cs" />
|
||||
<Compile Include="TryConvertToTests.cs" />
|
||||
|
||||
Reference in New Issue
Block a user