Skip to content

Commit

Permalink
Add failing test for #16746
Browse files Browse the repository at this point in the history
  • Loading branch information
grokys committed Sep 20, 2024
1 parent 85fff4a commit d8a9379
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,31 @@ public void OneWayToSource_Binding_Does_Not_Override_TwoWay_Binding()
Assert.Equal("TwoWay", source.Foo);
}

[Fact]
public void Target_Undoing_Property_Change_During_TwoWay_Binding_Does_Not_Cause_StackOverflow()
{
var source = new TestStackOverflowViewModel { BoolValue = true };
var target = new TwoWayBindingTest();

source.ResetSetterInvokedCount();

// The AlwaysFalse property is set to false in the PropertyChanged callback. Ensure
// that binding it to an initial `true` value with a two-way binding does not cause a
// stack overflow.
target.Bind(
TwoWayBindingTest.AlwaysFalseProperty,
new Binding(nameof(TestStackOverflowViewModel.BoolValue))
{
Mode = BindingMode.TwoWay,
});

target.DataContext = source;

Assert.Equal(1, source.SetterInvokedCount);
Assert.False(source.BoolValue);
Assert.False(target.AlwaysFalse);
}

private class StyledPropertyClass : AvaloniaObject
{
public static readonly StyledProperty<double> DoubleValueProperty =
Expand Down Expand Up @@ -725,10 +750,24 @@ private class TestStackOverflowViewModel : INotifyPropertyChanged

public const int MaxInvokedCount = 1000;

private bool _boolValue;
private double _value;

public event PropertyChangedEventHandler PropertyChanged;

public bool BoolValue
{
get => _boolValue;
set
{
if (_boolValue != value)
{
_boolValue = value;
SetterInvokedCount++;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BoolValue)));
}
} }

public double Value
{
get => _value;
Expand All @@ -754,20 +793,38 @@ public double Value
}
}
}

public void ResetSetterInvokedCount() => SetterInvokedCount = 0;
}

private class TwoWayBindingTest : Control
{
public static readonly StyledProperty<bool> AlwaysFalseProperty =
AvaloniaProperty.Register<StyledPropertyClass, bool>(nameof(AlwaysFalse));
public static readonly StyledProperty<string> TwoWayProperty =
AvaloniaProperty.Register<TwoWayBindingTest, string>(
"TwoWay",
defaultBindingMode: BindingMode.TwoWay);

public bool AlwaysFalse
{
get => GetValue(AlwaysFalseProperty);
set => SetValue(AlwaysFalseProperty, value);
}

public string TwoWay
{
get => GetValue(TwoWayProperty);
set => SetValue(TwoWayProperty, value);
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);

if (change.Property == AlwaysFalseProperty)
SetCurrentValue(AlwaysFalseProperty, false);
}
}

public class Source : INotifyPropertyChanged
Expand Down

0 comments on commit d8a9379

Please sign in to comment.