From edf2018149018c9bfd7da44d5e01c19a23f1cd78 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 25 Oct 2017 23:50:02 -0500 Subject: [PATCH] Refactored tests to move XAML Binding class tests into Avalonia.Markup.Xaml.UnitTests. --- .../Avalonia.Base.UnitTests.csproj | 12 -- .../AvaloniaObjectTests_Binding.cs | 20 +-- .../AvaloniaObjectTests_Direct.cs | 20 +-- .../Avalonia.Markup.Xaml.UnitTests.csproj | 1 + .../Data/BindingTests.cs | 139 ++++++++++++++++++ 5 files changed, 146 insertions(+), 46 deletions(-) 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 =