diff --git a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
index e86aec4be1..8692cdef42 100644
--- a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
+++ b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
@@ -13,18 +13,6 @@
-
- {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
- Avalonia.Base
-
-
- {3E53A01A-B331-47F3-B828-4A5717E77A24}
- Avalonia.Markup.Xaml
-
-
- {88060192-33d5-4932-b0f9-8bd2763e857d}
- Avalonia.UnitTests
-
\ No newline at end of file
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
index 192f5258ab..529e35d92c 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
@@ -387,10 +387,8 @@ namespace Avalonia.Base.UnitTests
}
}
- [Theory]
- [InlineData(true)]
- [InlineData(false)]
- public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values(bool useXamlBinding)
+ [Fact]
+ public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values()
{
var viewModel = new TestStackOverflowViewModel()
{
@@ -404,19 +402,7 @@ namespace Avalonia.Base.UnitTests
var child = new Class1();
- if (useXamlBinding)
- {
- child.Bind(Class1.DoubleValueProperty,
- new Binding("DoubleValue")
- {
- Mode = BindingMode.TwoWay,
- Source = target
- });
- }
- else
- {
- child[!!Class1.DoubleValueProperty] = target[!!Class1.DoubleValueProperty];
- }
+ child[!!Class1.DoubleValueProperty] = target[!!Class1.DoubleValueProperty];
Assert.Equal(1, viewModel.SetterInvokedCount);
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
index 249528e9b2..ffea0fd2d6 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
@@ -440,10 +440,8 @@ namespace Avalonia.Base.UnitTests
Assert.Equal(BindingMode.OneWayToSource, bar.GetMetadata().DefaultBindingMode);
}
- [Theory]
- [InlineData(true)]
- [InlineData(false)]
- public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values(bool useXamlBinding)
+ [Fact]
+ public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values()
{
var viewModel = new TestStackOverflowViewModel()
{
@@ -460,19 +458,7 @@ namespace Avalonia.Base.UnitTests
var child = new Class1();
- if (useXamlBinding)
- {
- child.Bind(Class1.DoubleValueProperty,
- new Binding("DoubleValue")
- {
- Mode = BindingMode.TwoWay,
- Source = target
- });
- }
- else
- {
- child[!!Class1.DoubleValueProperty] = target[!!Class1.DoubleValueProperty];
- }
+ child[!!Class1.DoubleValueProperty] = target[!!Class1.DoubleValueProperty];
Assert.Equal(1, viewModel.SetterInvokedCount);
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
index 03bb71a383..b2d71d7fa8 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
@@ -22,6 +22,7 @@
+
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
index 230e61f300..11a1154b26 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
@@ -337,6 +337,145 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
Assert.Equal("foo", target.Content);
}
+
+ [Fact]
+ public void StyledProperty_SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values()
+ {
+ var viewModel = new TestStackOverflowViewModel()
+ {
+ Value = 50
+ };
+
+ var target = new StyledPropertyClass();
+
+ target.Bind(StyledPropertyClass.DoubleValueProperty,
+ new Binding("Value") { Mode = BindingMode.TwoWay, Source = viewModel });
+
+ var child = new StyledPropertyClass();
+
+ child.Bind(StyledPropertyClass.DoubleValueProperty,
+ new Binding("DoubleValue")
+ {
+ Mode = BindingMode.TwoWay,
+ Source = target
+ });
+
+ Assert.Equal(1, viewModel.SetterInvokedCount);
+
+ //here in real life stack overflow exception is thrown issue #855 and #824
+ target.DoubleValue = 51.001;
+
+ Assert.Equal(2, viewModel.SetterInvokedCount);
+
+ double expected = 51;
+
+ Assert.Equal(expected, viewModel.Value);
+ Assert.Equal(expected, target.DoubleValue);
+ Assert.Equal(expected, child.DoubleValue);
+ }
+
+ [Fact]
+ public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values()
+ {
+ var viewModel = new TestStackOverflowViewModel()
+ {
+ Value = 50
+ };
+
+ var target = new DirectPropertyClass();
+
+ target.Bind(DirectPropertyClass.DoubleValueProperty, new Binding("Value")
+ {
+ Mode = BindingMode.TwoWay,
+ Source = viewModel
+ });
+
+ var child = new DirectPropertyClass();
+
+ child.Bind(DirectPropertyClass.DoubleValueProperty,
+ new Binding("DoubleValue")
+ {
+ Mode = BindingMode.TwoWay,
+ Source = target
+ });
+
+ Assert.Equal(1, viewModel.SetterInvokedCount);
+
+ //here in real life stack overflow exception is thrown issue #855 and #824
+ target.DoubleValue = 51.001;
+
+ Assert.Equal(2, viewModel.SetterInvokedCount);
+
+ double expected = 51;
+
+ Assert.Equal(expected, viewModel.Value);
+ Assert.Equal(expected, target.DoubleValue);
+ Assert.Equal(expected, child.DoubleValue);
+ }
+
+ private class StyledPropertyClass : AvaloniaObject
+ {
+ public static readonly StyledProperty DoubleValueProperty =
+ AvaloniaProperty.Register(nameof(DoubleValue));
+
+ public double DoubleValue
+ {
+ get { return GetValue(DoubleValueProperty); }
+ set { SetValue(DoubleValueProperty, value); }
+ }
+ }
+
+ private class DirectPropertyClass : AvaloniaObject
+ {
+ public static readonly DirectProperty DoubleValueProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(DoubleValue),
+ o => o.DoubleValue,
+ (o, v) => o.DoubleValue = v);
+
+ private double _doubleValue;
+ public double DoubleValue
+ {
+ get { return _doubleValue; }
+ set { SetAndRaise(DoubleValueProperty, ref _doubleValue, value); }
+ }
+ }
+
+ private class TestStackOverflowViewModel : INotifyPropertyChanged
+ {
+ public int SetterInvokedCount { get; private set; }
+
+ public const int MaxInvokedCount = 1000;
+
+ private double _value;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public double Value
+ {
+ get { return _value; }
+ set
+ {
+ if (_value != value)
+ {
+ SetterInvokedCount++;
+ if (SetterInvokedCount < MaxInvokedCount)
+ {
+ _value = (int)value;
+ if (_value > 75) _value = 75;
+ if (_value < 25) _value = 25;
+ }
+ else
+ {
+ _value = value;
+ }
+
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
+ }
+ }
+ }
+ }
+
private class TwoWayBindingTest : Control
{
public static readonly StyledProperty TwoWayProperty =