1
0

ExpressionObserverTests_Task.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Reactive.Linq;
  6. using System.Threading.Tasks;
  7. using Avalonia.Data;
  8. using Avalonia.Data.Core;
  9. using Avalonia.Markup.Parsers;
  10. using Avalonia.UnitTests;
  11. using Xunit;
  12. namespace Avalonia.Base.UnitTests.Data.Core
  13. {
  14. public class ExpressionObserverTests_Task
  15. {
  16. [Fact]
  17. public void Should_Not_Get_Task_Result_Without_StreamBinding()
  18. {
  19. using (var sync = UnitTestSynchronizationContext.Begin())
  20. {
  21. var tcs = new TaskCompletionSource<string>();
  22. var data = new { Foo = tcs.Task };
  23. var target = ExpressionObserver.Create(data, o => o.Foo);
  24. var result = new List<object>();
  25. var sub = target.Subscribe(x => result.Add(x));
  26. tcs.SetResult("foo");
  27. sync.ExecutePostedCallbacks();
  28. Assert.Single(result);
  29. Assert.IsType<Task<string>>(result[0]);
  30. GC.KeepAlive(data);
  31. }
  32. }
  33. [Fact]
  34. public void Should_Get_Completed_Task_Value()
  35. {
  36. using (var sync = UnitTestSynchronizationContext.Begin())
  37. {
  38. var data = new { Foo = Task.FromResult("foo") };
  39. var target = ExpressionObserver.Create(data, o => o.Foo.StreamBinding());
  40. var result = new List<object>();
  41. var sub = target.Subscribe(x => result.Add(x));
  42. Assert.Equal(new[] { "foo" }, result);
  43. GC.KeepAlive(data);
  44. }
  45. }
  46. [Fact]
  47. public void Should_Get_Property_Value_From_Task()
  48. {
  49. using (var sync = UnitTestSynchronizationContext.Begin())
  50. {
  51. var tcs = new TaskCompletionSource<Class2>();
  52. var data = new Class1(tcs.Task);
  53. var target = ExpressionObserver.Create(data, o => o.Next.StreamBinding().Foo);
  54. var result = new List<object>();
  55. var sub = target.Subscribe(x => result.Add(x));
  56. tcs.SetResult(new Class2("foo"));
  57. sync.ExecutePostedCallbacks();
  58. Assert.Equal(new[] { "foo" }, result);
  59. GC.KeepAlive(data);
  60. }
  61. }
  62. [Fact]
  63. public void Should_Return_BindingNotification_Error_On_Task_Exception()
  64. {
  65. using (var sync = UnitTestSynchronizationContext.Begin())
  66. {
  67. var tcs = new TaskCompletionSource<string>();
  68. var data = new { Foo = tcs.Task };
  69. var target = ExpressionObserver.Create(data, o => o.Foo.StreamBinding());
  70. var result = new List<object>();
  71. var sub = target.Subscribe(x => result.Add(x));
  72. tcs.SetException(new NotSupportedException());
  73. sync.ExecutePostedCallbacks();
  74. Assert.Equal(
  75. new[]
  76. {
  77. new BindingNotification(
  78. new AggregateException(new NotSupportedException()),
  79. BindingErrorType.Error)
  80. },
  81. result);
  82. GC.KeepAlive(data);
  83. }
  84. }
  85. [Fact]
  86. public void Should_Return_BindingNotification_Error_For_Faulted_Task()
  87. {
  88. using (var sync = UnitTestSynchronizationContext.Begin())
  89. {
  90. var data = new { Foo = TaskFromException(new NotSupportedException()) };
  91. var target = ExpressionObserver.Create(data, o => o.Foo.StreamBinding());
  92. var result = new List<object>();
  93. var sub = target.Subscribe(x => result.Add(x));
  94. Assert.Equal(
  95. new[]
  96. {
  97. new BindingNotification(
  98. new AggregateException(new NotSupportedException()),
  99. BindingErrorType.Error)
  100. },
  101. result);
  102. GC.KeepAlive(data);
  103. }
  104. }
  105. [Fact]
  106. public void Should_Get_Simple_Task_Value_With_Data_DataValidation_Enabled()
  107. {
  108. using (var sync = UnitTestSynchronizationContext.Begin())
  109. {
  110. var tcs = new TaskCompletionSource<string>();
  111. var data = new { Foo = tcs.Task };
  112. var target = ExpressionObserver.Create(data, o => o.Foo.StreamBinding(), true);
  113. var result = new List<object>();
  114. var sub = target.Subscribe(x => result.Add(x));
  115. tcs.SetResult("foo");
  116. sync.ExecutePostedCallbacks();
  117. // What does it mean to have data validation on a Task? Without a use-case it's
  118. // hard to know what to do here so for the moment the value is returned.
  119. Assert.Equal(new [] { "foo" }, result);
  120. GC.KeepAlive(data);
  121. }
  122. }
  123. private Task TaskFromException(Exception e)
  124. {
  125. var tcs = new TaskCompletionSource<object>();
  126. tcs.SetException(e);
  127. return tcs.Task;
  128. }
  129. private class Class1 : NotifyingBase
  130. {
  131. public Class1(Task<Class2> next)
  132. {
  133. Next = next;
  134. }
  135. public Task<Class2> Next { get; }
  136. }
  137. private class Class2 : NotifyingBase
  138. {
  139. public Class2(string foo)
  140. {
  141. Foo = foo;
  142. }
  143. public string Foo { get; }
  144. }
  145. }
  146. }