/src/System.Threading.Tasks.Extensions/tests/ValueTaskTests.cs

https://gitlab.com/0072016/0072016-corefx- · C# · 380 lines · 309 code · 62 blank · 9 comment · 16 complexity · 7915de32b63ade3af9e379c2da69fe0b MD5 · raw file

  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Diagnostics;
  5. using Xunit;
  6. namespace System.Threading.Tasks.Channels.Tests
  7. {
  8. public class ValueTaskTests
  9. {
  10. [Fact]
  11. public void DefaultValueTask_ValueType_DefaultValue()
  12. {
  13. Assert.True(default(ValueTask<int>).IsCompleted);
  14. Assert.True(default(ValueTask<int>).IsCompletedSuccessfully);
  15. Assert.False(default(ValueTask<int>).IsFaulted);
  16. Assert.False(default(ValueTask<int>).IsCanceled);
  17. Assert.Equal(0, default(ValueTask<int>).Result);
  18. Assert.True(default(ValueTask<string>).IsCompleted);
  19. Assert.True(default(ValueTask<string>).IsCompletedSuccessfully);
  20. Assert.False(default(ValueTask<string>).IsFaulted);
  21. Assert.False(default(ValueTask<string>).IsCanceled);
  22. Assert.Equal(null, default(ValueTask<string>).Result);
  23. }
  24. [Fact]
  25. public void CreateFromValue_IsRanToCompletion()
  26. {
  27. ValueTask<int> t = new ValueTask<int>(42);
  28. Assert.True(t.IsCompleted);
  29. Assert.True(t.IsCompletedSuccessfully);
  30. Assert.False(t.IsFaulted);
  31. Assert.False(t.IsCanceled);
  32. Assert.Equal(42, t.Result);
  33. }
  34. [Fact]
  35. public void CreateFromCompletedTask_IsRanToCompletion()
  36. {
  37. ValueTask<int> t = new ValueTask<int>(Task.FromResult(42));
  38. Assert.True(t.IsCompleted);
  39. Assert.True(t.IsCompletedSuccessfully);
  40. Assert.False(t.IsFaulted);
  41. Assert.False(t.IsCanceled);
  42. Assert.Equal(42, t.Result);
  43. }
  44. [Fact]
  45. public void CreateFromNotCompletedTask_IsNotRanToCompletion()
  46. {
  47. var tcs = new TaskCompletionSource<int>();
  48. ValueTask<int> t = new ValueTask<int>(tcs.Task);
  49. Assert.False(t.IsCompleted);
  50. Assert.False(t.IsCompletedSuccessfully);
  51. Assert.False(t.IsFaulted);
  52. Assert.False(t.IsCanceled);
  53. tcs.SetResult(42);
  54. Assert.Equal(42, t.Result);
  55. Assert.True(t.IsCompleted);
  56. Assert.True(t.IsCompletedSuccessfully);
  57. Assert.False(t.IsFaulted);
  58. Assert.False(t.IsCanceled);
  59. }
  60. [Fact]
  61. public void CreateFromNullTask_Throws()
  62. {
  63. Assert.Throws<ArgumentNullException>(() => new ValueTask<int>((Task<int>)null));
  64. Assert.Throws<ArgumentNullException>(() => new ValueTask<string>((Task<string>)null));
  65. }
  66. [Fact]
  67. public void CastFromValue_IsRanToCompletion()
  68. {
  69. ValueTask<int> t = 42;
  70. Assert.Equal(42, t.Result);
  71. Assert.True(t.IsCompleted);
  72. Assert.True(t.IsCompletedSuccessfully);
  73. Assert.False(t.IsFaulted);
  74. Assert.False(t.IsCanceled);
  75. }
  76. [Fact]
  77. public void CastFromCompletedTask_IsRanToCompletion()
  78. {
  79. ValueTask<int> t = Task.FromResult(42);
  80. Assert.Equal(42, t.Result);
  81. Assert.True(t.IsCompleted);
  82. Assert.True(t.IsCompletedSuccessfully);
  83. Assert.False(t.IsFaulted);
  84. Assert.False(t.IsCanceled);
  85. }
  86. [Fact]
  87. public void CastFromFaultedTask_IsNotRanToCompletion()
  88. {
  89. ValueTask<int> t = Task.FromException<int>(new FormatException());
  90. Assert.Throws<FormatException>(() => t.Result);
  91. Assert.True(t.IsCompleted);
  92. Assert.False(t.IsCompletedSuccessfully);
  93. Assert.True(t.IsFaulted);
  94. Assert.False(t.IsCanceled);
  95. }
  96. [Fact]
  97. public void CastFromCanceledTask_IsNotRanToCompletion()
  98. {
  99. ValueTask<int> t = Task.FromCanceled<int>(new CancellationToken(true));
  100. Assert.Throws<TaskCanceledException>(() => t.Result);
  101. Assert.True(t.IsCompleted);
  102. Assert.False(t.IsCompletedSuccessfully);
  103. Assert.False(t.IsFaulted);
  104. Assert.True(t.IsCanceled);
  105. }
  106. [Fact]
  107. public void CastFromNullTask_Throws()
  108. {
  109. Task<int> ti = null;
  110. Assert.Throws<ArgumentNullException>(() => (ValueTask<int>)ti);
  111. Task<string> ts = null;
  112. Assert.Throws<ArgumentNullException>(() => (ValueTask<string>)ts);
  113. }
  114. [Fact]
  115. public void CreateFromTask_AsTaskIdempotent()
  116. {
  117. Task<int> source = Task.FromResult(42);
  118. ValueTask<int> t = new ValueTask<int>(source);
  119. Assert.Same(source, t.AsTask());
  120. Assert.Same(t.AsTask(), t.AsTask());
  121. }
  122. [Fact]
  123. public void CreateFromValue_AsTaskNotIdempotent()
  124. {
  125. ValueTask<int> t = new ValueTask<int>(42);
  126. Assert.NotSame(Task.FromResult(42), t.AsTask());
  127. Assert.NotSame(t.AsTask(), t.AsTask());
  128. }
  129. [Fact]
  130. public async Task CreateFromValue_Await()
  131. {
  132. ValueTask<int> t = new ValueTask<int>(42);
  133. Assert.Equal(42, await t);
  134. Assert.Equal(42, await t.ConfigureAwait(false));
  135. Assert.Equal(42, await t.ConfigureAwait(true));
  136. }
  137. [Fact]
  138. public async Task CreateFromTask_Await_Normal()
  139. {
  140. Task<int> source = Task.Delay(1).ContinueWith(_ => 42);
  141. ValueTask<int> t = new ValueTask<int>(source);
  142. Assert.Equal(42, await t);
  143. }
  144. [Fact]
  145. public async Task CreateFromTask_Await_ConfigureAwaitFalse()
  146. {
  147. Task<int> source = Task.Delay(1).ContinueWith(_ => 42);
  148. ValueTask<int> t = new ValueTask<int>(source);
  149. Assert.Equal(42, await t.ConfigureAwait(false));
  150. }
  151. [Fact]
  152. public async Task CreateFromTask_Await_ConfigureAwaitTrue()
  153. {
  154. Task<int> source = Task.Delay(1).ContinueWith(_ => 42);
  155. ValueTask<int> t = new ValueTask<int>(source);
  156. Assert.Equal(42, await t.ConfigureAwait(true));
  157. }
  158. [Fact]
  159. public void Awaiter_OnCompleted()
  160. {
  161. // Since ValueTask implements both OnCompleted and UnsafeOnCompleted,
  162. // OnCompleted typically won't be used by await, so we add an explicit test
  163. // for it here.
  164. ValueTask<int> t = 42;
  165. var mres = new ManualResetEventSlim();
  166. t.GetAwaiter().OnCompleted(() => mres.Set());
  167. Assert.True(mres.Wait(10000));
  168. }
  169. [Theory]
  170. [InlineData(true)]
  171. [InlineData(false)]
  172. public void ConfiguredAwaiter_OnCompleted(bool continueOnCapturedContext)
  173. {
  174. // Since ValueTask implements both OnCompleted and UnsafeOnCompleted,
  175. // OnCompleted typically won't be used by await, so we add an explicit test
  176. // for it here.
  177. ValueTask<int> t = 42;
  178. var mres = new ManualResetEventSlim();
  179. t.ConfigureAwait(continueOnCapturedContext).GetAwaiter().OnCompleted(() => mres.Set());
  180. Assert.True(mres.Wait(10000));
  181. }
  182. [Fact]
  183. public async Task Awaiter_ContinuesOnCapturedContext()
  184. {
  185. await Task.Run(() =>
  186. {
  187. var tsc = new TrackingSynchronizationContext();
  188. SynchronizationContext.SetSynchronizationContext(tsc);
  189. try
  190. {
  191. ValueTask<int> t = 42;
  192. var mres = new ManualResetEventSlim();
  193. t.GetAwaiter().OnCompleted(() => mres.Set());
  194. Assert.True(mres.Wait(10000));
  195. Assert.Equal(1, tsc.Posts);
  196. }
  197. finally
  198. {
  199. SynchronizationContext.SetSynchronizationContext(null);
  200. }
  201. });
  202. }
  203. [Theory]
  204. [InlineData(true)]
  205. [InlineData(false)]
  206. public async Task ConfiguredAwaiter_ContinuesOnCapturedContext(bool continueOnCapturedContext)
  207. {
  208. await Task.Run(() =>
  209. {
  210. var tsc = new TrackingSynchronizationContext();
  211. SynchronizationContext.SetSynchronizationContext(tsc);
  212. try
  213. {
  214. ValueTask<int> t = 42;
  215. var mres = new ManualResetEventSlim();
  216. t.ConfigureAwait(continueOnCapturedContext).GetAwaiter().OnCompleted(() => mres.Set());
  217. Assert.True(mres.Wait(10000));
  218. Assert.Equal(continueOnCapturedContext ? 1 : 0, tsc.Posts);
  219. }
  220. finally
  221. {
  222. SynchronizationContext.SetSynchronizationContext(null);
  223. }
  224. });
  225. }
  226. [Fact]
  227. public void GetHashCode_ContainsResult()
  228. {
  229. ValueTask<int> t = 42;
  230. Assert.Equal(t.Result.GetHashCode(), t.GetHashCode());
  231. }
  232. [Fact]
  233. public void GetHashCode_ContainsTask()
  234. {
  235. ValueTask<string> t = Task.FromResult("42");
  236. Assert.Equal(t.AsTask().GetHashCode(), t.GetHashCode());
  237. }
  238. [Fact]
  239. public void GetHashCode_ContainsNull()
  240. {
  241. ValueTask<string> t = (string)null;
  242. Assert.Equal(0, t.GetHashCode());
  243. }
  244. [Fact]
  245. public void OperatorEquals()
  246. {
  247. Assert.True((ValueTask<int>)42 == (ValueTask<int>)42);
  248. Assert.False((ValueTask<int>)42 == (ValueTask<int>)43);
  249. Assert.True((ValueTask<string>)"42" == (ValueTask<string>)"42");
  250. Assert.True((ValueTask<string>)(string)null == (ValueTask<string>)(string)null);
  251. Assert.False((ValueTask<string>)"42" == (ValueTask<string>)(string)null);
  252. Assert.False((ValueTask<string>)(string)null == (ValueTask<string>)"42");
  253. Assert.False((ValueTask<int>)42 == (ValueTask<int>)Task.FromResult(42));
  254. Assert.False((ValueTask<int>)Task.FromResult(42) == (ValueTask<int>)42);
  255. }
  256. [Fact]
  257. public void OperatorNotEquals()
  258. {
  259. Assert.False((ValueTask<int>)42 != (ValueTask<int>)42);
  260. Assert.True((ValueTask<int>)42 != (ValueTask<int>)43);
  261. Assert.False((ValueTask<string>)"42" != (ValueTask<string>)"42");
  262. Assert.False((ValueTask<string>)(string)null != (ValueTask<string>)(string)null);
  263. Assert.True((ValueTask<string>)"42" != (ValueTask<string>)(string)null);
  264. Assert.True((ValueTask<string>)(string)null != (ValueTask<string>)"42");
  265. Assert.True((ValueTask<int>)42 != (ValueTask<int>)Task.FromResult(42));
  266. Assert.True((ValueTask<int>)Task.FromResult(42) != (ValueTask<int>)42);
  267. }
  268. [Fact]
  269. public void Equals_ValueTask()
  270. {
  271. Assert.True(((ValueTask<int>)42).Equals((ValueTask<int>)42));
  272. Assert.False(((ValueTask<int>)42).Equals((ValueTask<int>)43));
  273. Assert.True(((ValueTask<string>)"42").Equals((ValueTask<string>)"42"));
  274. Assert.True(((ValueTask<string>)(string)null).Equals((ValueTask<string>)(string)null));
  275. Assert.False(((ValueTask<string>)"42").Equals((ValueTask<string>)(string)null));
  276. Assert.False(((ValueTask<string>)(string)null).Equals((ValueTask<string>)"42"));
  277. Assert.False(((ValueTask<int>)42).Equals((ValueTask<int>)Task.FromResult(42)));
  278. Assert.False(((ValueTask<int>)Task.FromResult(42)).Equals((ValueTask<int>)42));
  279. }
  280. [Fact]
  281. public void Equals_Object()
  282. {
  283. Assert.True(((ValueTask<int>)42).Equals((object)(ValueTask<int>)42));
  284. Assert.False(((ValueTask<int>)42).Equals((object)(ValueTask<int>)43));
  285. Assert.True(((ValueTask<string>)"42").Equals((object)(ValueTask<string>)"42"));
  286. Assert.True(((ValueTask<string>)(string)null).Equals((object)(ValueTask<string>)(string)null));
  287. Assert.False(((ValueTask<string>)"42").Equals((object)(ValueTask<string>)(string)null));
  288. Assert.False(((ValueTask<string>)(string)null).Equals((object)(ValueTask<string>)"42"));
  289. Assert.False(((ValueTask<int>)42).Equals((object)(ValueTask<int>)Task.FromResult(42)));
  290. Assert.False(((ValueTask<int>)Task.FromResult(42)).Equals((object)(ValueTask<int>)42));
  291. Assert.False(((ValueTask<int>)42).Equals((object)null));
  292. Assert.False(((ValueTask<int>)42).Equals(new object()));
  293. Assert.False(((ValueTask<int>)42).Equals((object)42));
  294. }
  295. [Fact]
  296. public void ToString_Success()
  297. {
  298. Assert.Equal("Hello", new ValueTask<string>("Hello").ToString());
  299. Assert.Equal(string.Empty, new ValueTask<string>(string.Empty).ToString());
  300. Assert.Equal("42", new ValueTask<int>(42).ToString());
  301. Assert.Equal("Hello", new ValueTask<string>(Task.FromResult("Hello")).ToString());
  302. Assert.Equal(string.Empty, new ValueTask<string>(Task.FromResult(string.Empty)).ToString());
  303. Assert.Equal("42", new ValueTask<int>(Task.FromResult(42)).ToString());
  304. Assert.Equal("Faulted", new ValueTask<string>(Task.FromException<string>(new InvalidOperationException())).ToString());
  305. Assert.Equal("Faulted", new ValueTask<string>(Task.FromException<string>(new OperationCanceledException())).ToString());
  306. Assert.Equal("Canceled", new ValueTask<string>(Task.FromCanceled<string>(new CancellationToken(true))).ToString());
  307. }
  308. private sealed class TrackingSynchronizationContext : SynchronizationContext
  309. {
  310. internal int Posts { get; set; }
  311. public override void Post(SendOrPostCallback d, object state)
  312. {
  313. Posts++;
  314. base.Post(d, state);
  315. }
  316. }
  317. }
  318. }