ExpressionObserverTests_ExpressionTree.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reactive.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Avalonia.Data.Core;
  7. using Avalonia.UnitTests;
  8. using Xunit;
  9. namespace Avalonia.Base.UnitTests.Data.Core
  10. {
  11. public class ExpressionObserverTests_ExpressionTree
  12. {
  13. [Fact]
  14. public async Task IdentityExpression_Creates_IdentityObserver()
  15. {
  16. var target = new object();
  17. var observer = ExpressionObserver.Create(target, o => o);
  18. Assert.Equal(target, await observer.Take(1));
  19. GC.KeepAlive(target);
  20. }
  21. [Fact]
  22. public async Task Property_Access_Expression_Observes_Property()
  23. {
  24. var target = new Class1();
  25. var observer = ExpressionObserver.Create(target, o => o.Foo);
  26. Assert.Null(await observer.Take(1));
  27. using (observer.Subscribe(_ => {}))
  28. {
  29. target.Foo = "Test";
  30. }
  31. Assert.Equal("Test", await observer.Take(1));
  32. GC.KeepAlive(target);
  33. }
  34. [Fact]
  35. public void Property_Access_Expression_Can_Set_Property()
  36. {
  37. var data = new Class1();
  38. var target = ExpressionObserver.Create(data, o => o.Foo);
  39. using (target.Subscribe(_ => { }))
  40. {
  41. Assert.True(target.SetValue("baz"));
  42. }
  43. GC.KeepAlive(data);
  44. }
  45. [Fact]
  46. public async Task Indexer_Accessor_Can_Read_Value()
  47. {
  48. var data = new[] { 1, 2, 3, 4 };
  49. var target = ExpressionObserver.Create(data, o => o[0]);
  50. Assert.Equal(data[0], await target.Take(1));
  51. GC.KeepAlive(data);
  52. }
  53. [Fact]
  54. public async Task Indexer_List_Accessor_Can_Read_Value()
  55. {
  56. var data = new List<int> { 1, 2, 3, 4 };
  57. var target = ExpressionObserver.Create(data, o => o[0]);
  58. Assert.Equal(data[0], await target.Take(1));
  59. GC.KeepAlive(data);
  60. }
  61. [Fact]
  62. public async Task Indexer_Accessor_Can_Read_Complex_Index()
  63. {
  64. var data = new Dictionary<object, object>();
  65. var key = new object();
  66. data.Add(key, new object());
  67. var target = ExpressionObserver.Create(data, o => o[key]);
  68. Assert.Equal(data[key], await target.Take(1));
  69. GC.KeepAlive(data);
  70. }
  71. [Fact]
  72. public void Indexer_Can_Set_Value()
  73. {
  74. var data = new[] { 1, 2, 3, 4 };
  75. var target = ExpressionObserver.Create(data, o => o[0]);
  76. using (target.Subscribe(_ => { }))
  77. {
  78. Assert.True(target.SetValue(2));
  79. }
  80. GC.KeepAlive(data);
  81. }
  82. [Fact]
  83. public async Task Inheritance_Casts_Should_Be_Ignored()
  84. {
  85. NotifyingBase test = new Class1 { Foo = "Test" };
  86. var target = ExpressionObserver.Create(test, o => ((Class1)o).Foo);
  87. Assert.Equal("Test", await target.Take(1));
  88. GC.KeepAlive(test);
  89. }
  90. [Fact]
  91. public void Convert_Casts_Should_Error()
  92. {
  93. var test = 1;
  94. Assert.Throws<ExpressionParseException>(() => ExpressionObserver.Create(test, o => (double)o));
  95. }
  96. [Fact]
  97. public async Task As_Operator_Should_Be_Ignored()
  98. {
  99. NotifyingBase test = new Class1 { Foo = "Test" };
  100. var target = ExpressionObserver.Create(test, o => (o as Class1).Foo);
  101. Assert.Equal("Test", await target.Take(1));
  102. GC.KeepAlive(test);
  103. }
  104. [Fact]
  105. public async Task Avalonia_Property_Indexer_Reads_Avalonia_Property_Value()
  106. {
  107. var test = new Class2();
  108. var target = ExpressionObserver.Create(test, o => o[Class2.FooProperty]);
  109. Assert.Equal("foo", await target.Take(1));
  110. GC.KeepAlive(test);
  111. }
  112. [Fact]
  113. public async Task Complex_Expression_Correctly_Parsed()
  114. {
  115. var test = new Class1 { Foo = "Test" };
  116. var target = ExpressionObserver.Create(test, o => o.Foo.Length);
  117. Assert.Equal(test.Foo.Length, await target.Take(1));
  118. GC.KeepAlive(test);
  119. }
  120. [Fact]
  121. public void Should_Get_Completed_Task_Value()
  122. {
  123. using (var sync = UnitTestSynchronizationContext.Begin())
  124. {
  125. var data = new { Foo = Task.FromResult("foo") };
  126. var target = ExpressionObserver.Create(data, o => o.Foo.StreamBinding());
  127. var result = new List<object>();
  128. var sub = target.Subscribe(x => result.Add(x));
  129. Assert.Equal(new[] { "foo" }, result);
  130. GC.KeepAlive(data);
  131. }
  132. }
  133. [Fact]
  134. public async Task Should_Create_Method_Binding()
  135. {
  136. var data = new Class3();
  137. var target = ExpressionObserver.Create(data, o => (Action)o.Method);
  138. var value = await target.Take(1);
  139. Assert.IsAssignableFrom<Delegate>(value);
  140. GC.KeepAlive(data);
  141. }
  142. private class Class1 : NotifyingBase
  143. {
  144. private string _foo;
  145. public string Foo
  146. {
  147. get { return _foo; }
  148. set
  149. {
  150. _foo = value;
  151. RaisePropertyChanged(nameof(Foo));
  152. }
  153. }
  154. }
  155. private class Class2 : AvaloniaObject
  156. {
  157. public static readonly StyledProperty<string> FooProperty =
  158. AvaloniaProperty.Register<Class2, string>("Foo", defaultValue: "foo");
  159. public string ClrProperty { get; } = "clr-property";
  160. }
  161. private class Class3
  162. {
  163. public void Method() { }
  164. }
  165. }
  166. }