Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/429 deserialize failure retryer security disabler #440

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/SharedAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[assembly: AssemblyProduct("Unicorn")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("4.1.6.0")]
[assembly: AssemblyFileVersion("4.1.6.0")]
[assembly: AssemblyInformationalVersion("4.1.6")]
[assembly: AssemblyVersion("4.1.6.1")]
[assembly: AssemblyFileVersion("4.1.6.1")]
[assembly: AssemblyInformationalVersion("4.1.6-Issue429")]
[assembly: CLSCompliant(false)]
35 changes: 25 additions & 10 deletions src/Unicorn.Tests/Loader/DeserializeFailureRetryerTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using NSubstitute;
using NSubstitute;
using Rainbow.Model;
using Sitecore.SecurityModel;
using System;
using Unicorn.Data;
using Unicorn.Loader;
using Xunit;
Expand All @@ -12,31 +13,45 @@ public class DeserializeFailureRetryerTests
[Fact]
public void ShouldRetrieveItemRetry()
{
// Arrange
var retryer = new DeserializeFailureRetryer();
var item = CreateTestItem();
var exception = new Exception();
retryer.AddItemRetry(item, exception);

var callback = Substitute.For<Action<IItemData>>();
SecurityState securityStatePre = SecurityStateSwitcher.CurrentValue;
SecurityState? securityStatePost = null;

retryer.AddItemRetry(item, exception);

retryer.RetryAll(Substitute.For<ISourceDataStore>(), callback, callback);
// Act
retryer.RetryAll(Substitute.For<ISourceDataStore>(), x => { callback(x); securityStatePost = SecurityStateSwitcher.CurrentValue; }, callback);

callback.Received()(item);
callback.Received()(item); // Check that item is retried
Assert.Equal(SecurityState.Default, securityStatePre); // Check that Switcher value is Default before test
Assert.True(securityStatePost.HasValue
&& securityStatePost.Value == SecurityState.Disabled); // Check that switcher is set to disabled while item is being retried
}

[Fact]
public void ShouldRetrieveTreeRetry()
{
// Arrange
var retryer = new DeserializeFailureRetryer();
var item = CreateTestItem();
var exception = new Exception();
retryer.AddTreeRetry(item, exception);

var callback = Substitute.For<Action<IItemData>>();
SecurityState securityStatePre = SecurityStateSwitcher.CurrentValue;
SecurityState? securityStatePost = null;

retryer.AddTreeRetry(item, exception);

retryer.RetryAll(Substitute.For<ISourceDataStore>(), callback, callback);
// Act
retryer.RetryAll(Substitute.For<ISourceDataStore>(), callback, x => { callback(x); securityStatePost = SecurityStateSwitcher.CurrentValue; });

callback.Received()(item);
callback.Received()(item); // Check that item is retried
Assert.Equal(SecurityState.Default, securityStatePre); // Check that Switcher value is Default before test
Assert.True(securityStatePost.HasValue
&& securityStatePost.Value == SecurityState.Disabled); // Check that switcher is set to disabled while item is being retried
}

[Fact]
Expand Down
7 changes: 7 additions & 0 deletions src/Unicorn.Tests/Unicorn.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -211,6 +212,12 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
1 change: 1 addition & 0 deletions src/Unicorn.Tests/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@
<package id="xunit.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net452" />
<package id="xunit.runner.visualstudio" version="2.1.0" targetFramework="net452" />
</packages>
63 changes: 35 additions & 28 deletions src/Unicorn/Loader/DeserializeFailureRetryer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Rainbow.Model;
using Rainbow.Model;
using Rainbow.Storage.Sc.Deserialization;
using Sitecore.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using Unicorn.Data;

namespace Unicorn.Loader
Expand Down Expand Up @@ -62,32 +62,36 @@ public virtual void RetryAll(ISourceDataStore sourceDataStore, Action<IItemData>
// clear the failures collection - we'll re-add any that fail again by evaluating originalFailures
_itemFailures.Clear();

foreach (var failure in originalItemFailures)
using (new UnicornOperationContext())
{
// retry loading a single item failure
var item = failure.Item;
if (item != null)
foreach (var failure in originalItemFailures)
{
try
// retry loading a single item failure
var item = failure.Item;
if (item != null)
{
retrySingleItemAction(item);
}
catch (Exception reason)
{
_itemFailures.Add(CreateFailure(failure.Item, reason));
try
{
retrySingleItemAction(item);
}
catch (Exception reason)
{
_itemFailures.Add(CreateFailure(failure.Item, reason));
}

continue;
}

continue;
// retry loading a reference failure (note the continues in the above ensure execution never arrives here for items)
retryTreeAction(failure.Item);
}

// retry loading a reference failure (note the continues in the above ensure execution never arrives here for items)
retryTreeAction(failure.Item);
}
} while (_itemFailures.Count > 0 && _itemFailures.Count < originalItemFailures.Count);
// continue retrying until all possible failures have been fixed
// continue retrying until all possible failures have been fixed
}

if(_treeFailures.Count > 0) {
if (_treeFailures.Count > 0)
{
List<Failure> originalTreeFailures;

do
Expand All @@ -100,16 +104,19 @@ public virtual void RetryAll(ISourceDataStore sourceDataStore, Action<IItemData>
// clear the failures collection - we'll re-add any that fail again by evaluating originalFailures
_treeFailures.Clear();

foreach (var failure in originalTreeFailures)
using (new UnicornOperationContext())
{
try
foreach (var failure in originalTreeFailures)
{
// retry loading a tree failure
retryTreeAction(failure.Item);
}
catch (Exception reason)
{
_treeFailures.Add(CreateFailure(failure.Item, reason));
try
{
// retry loading a tree failure
retryTreeAction(failure.Item);
}
catch (Exception reason)
{
_treeFailures.Add(CreateFailure(failure.Item, reason));
}
}
}
}
Expand Down