1+ // -----------------------------------------------------------------------
2+ // <copyright file="ResultSpec.cs" company="Akka.NET Project">
3+ // Copyright (C) 2009-2024 Lightbend Inc. <http://www.lightbend.com>
4+ // Copyright (C) 2013-2024 .NET Foundation <https://github.com/akkadotnet/akka.net>
5+ // </copyright>
6+ // -----------------------------------------------------------------------
7+
8+ using System ;
9+ using System . Threading . Tasks ;
10+ using Akka . Util ;
11+ using FluentAssertions ;
12+ using Xunit ;
13+ using static FluentAssertions . FluentActions ;
14+
15+ namespace Akka . Tests . Util ;
16+
17+ public class ResultSpec
18+ {
19+ [ Fact ( DisplayName = "Result constructor with value should return success" ) ]
20+ public void SuccessfulResult ( )
21+ {
22+ var result = new Result < int > ( 1 ) ;
23+
24+ result . IsSuccess . Should ( ) . BeTrue ( ) ;
25+ result . Value . Should ( ) . Be ( 1 ) ;
26+ result . Exception . Should ( ) . BeNull ( ) ;
27+ }
28+
29+ [ Fact ( DisplayName = "Result constructor with exception should return failed" ) ]
30+ public void ExceptionResult ( )
31+ {
32+ var result = new Result < int > ( new TestException ( "BOOM" ) ) ;
33+
34+ result . IsSuccess . Should ( ) . BeFalse ( ) ;
35+ result . Exception . Should ( ) . NotBeNull ( ) ;
36+ result . Exception . Should ( ) . BeOfType < TestException > ( ) ;
37+ }
38+
39+ [ Fact ( DisplayName = "Result.Success with value should return success" ) ]
40+ public void SuccessfulStaticSuccess ( )
41+ {
42+ var result = Result . Success ( 1 ) ;
43+
44+ result . IsSuccess . Should ( ) . BeTrue ( ) ;
45+ result . Value . Should ( ) . Be ( 1 ) ;
46+ result . Exception . Should ( ) . BeNull ( ) ;
47+ }
48+
49+ [ Fact ( DisplayName = "Result.Failure with exception should return failed" ) ]
50+ public void ExceptionStaticFailure ( )
51+ {
52+ var result = Result . Failure < int > ( new TestException ( "BOOM" ) ) ;
53+
54+ result . IsSuccess . Should ( ) . BeFalse ( ) ;
55+ result . Exception . Should ( ) . NotBeNull ( ) ;
56+ result . Exception . Should ( ) . BeOfType < TestException > ( ) ;
57+ }
58+
59+ [ Fact ( DisplayName = "Result.From with successful Func should return success" ) ]
60+ public void SuccessfulFuncResult ( )
61+ {
62+ var result = Result . From ( ( ) => 1 ) ;
63+
64+ result . IsSuccess . Should ( ) . BeTrue ( ) ;
65+ result . Value . Should ( ) . Be ( 1 ) ;
66+ result . Exception . Should ( ) . BeNull ( ) ;
67+ }
68+
69+ [ Fact ( DisplayName = "Result.From with throwing Func should return failed" ) ]
70+ public void ThrowFuncResult ( )
71+ {
72+ var result = Result . From < int > ( ( ) => throw new TestException ( "BOOM" ) ) ;
73+
74+ result . IsSuccess . Should ( ) . BeFalse ( ) ;
75+ result . Exception . Should ( ) . NotBeNull ( ) ;
76+ result . Exception . Should ( ) . BeOfType < TestException > ( ) ;
77+ }
78+
79+ [ Fact ( DisplayName = "Result.FromTask with successful task should return success" ) ]
80+ public void SuccessfulTaskResult ( )
81+ {
82+ var task = CompletedTask ( 1 ) ;
83+ var result = Result . FromTask ( task ) ;
84+
85+ result . IsSuccess . Should ( ) . BeTrue ( ) ;
86+ result . Value . Should ( ) . Be ( 1 ) ;
87+ result . Exception . Should ( ) . BeNull ( ) ;
88+ }
89+
90+ [ Fact ( DisplayName = "Result.FromTask with faulted task should return failed" ) ]
91+ public void FaultedTaskResult ( )
92+ {
93+ var task = FaultedTask ( 1 ) ;
94+ var result = Result . FromTask ( task ) ;
95+
96+ result . IsSuccess . Should ( ) . BeFalse ( ) ;
97+ result . Exception . Should ( ) . NotBeNull ( ) ;
98+ result . Exception . Should ( ) . BeOfType < AggregateException > ( )
99+ . Which . InnerException . Should ( ) . BeOfType < TestException > ( ) ;
100+ }
101+
102+ [ Fact ( DisplayName = "Result.FromTask with cancelled task should return failed" ) ]
103+ public void CancelledTaskResult ( )
104+ {
105+ var task = CancelledTask ( 1 ) ;
106+ var result = Result . FromTask ( task ) ;
107+
108+ result . IsSuccess . Should ( ) . BeFalse ( ) ;
109+ result . Exception . Should ( ) . NotBeNull ( ) ;
110+ result . Exception . Should ( ) . BeOfType < TaskCanceledException > ( ) ;
111+ }
112+
113+ [ Fact ( DisplayName = "Result.FromTask with incomplete task should throw" ) ]
114+ public void IncompleteTaskResult ( )
115+ {
116+ var tcs = new TaskCompletionSource < int > ( ) ;
117+ Invoking ( ( ) => Result . FromTask ( tcs . Task ) )
118+ . Should ( ) . Throw < ArgumentException > ( ) . WithMessage ( "Task is not completed.*" ) ;
119+ }
120+
121+ private static Task < int > CompletedTask ( int n )
122+ {
123+ var tcs = new TaskCompletionSource < int > ( ) ;
124+ Task . Run ( async ( ) =>
125+ {
126+ await Task . Yield ( ) ;
127+ tcs . TrySetResult ( n ) ;
128+ } ) ;
129+ tcs . Task . Wait ( ) ;
130+ return tcs . Task ;
131+ }
132+
133+ private static Task < int > CancelledTask ( int n )
134+ {
135+ var tcs = new TaskCompletionSource < int > ( ) ;
136+ Task . Run ( async ( ) =>
137+ {
138+ await Task . Yield ( ) ;
139+ tcs . TrySetCanceled ( ) ;
140+ } ) ;
141+
142+ try
143+ {
144+ tcs . Task . Wait ( ) ;
145+ }
146+ catch
147+ {
148+ // no-op
149+ }
150+
151+ return tcs . Task ;
152+ }
153+
154+ private static Task < int > FaultedTask ( int n )
155+ {
156+ var tcs = new TaskCompletionSource < int > ( ) ;
157+ Task . Run ( async ( ) =>
158+ {
159+ await Task . Yield ( ) ;
160+ try
161+ {
162+ throw new TestException ( "BOOM" ) ;
163+ }
164+ catch ( Exception ex )
165+ {
166+ tcs . TrySetException ( ex ) ;
167+ }
168+ } ) ;
169+
170+ try
171+ {
172+ tcs . Task . Wait ( ) ;
173+ }
174+ catch
175+ {
176+ // no-op
177+ }
178+
179+ return tcs . Task ;
180+ }
181+
182+ private class TestException : Exception
183+ {
184+ public TestException ( string message ) : base ( message )
185+ {
186+ }
187+
188+ public TestException ( string message , Exception innerException ) : base ( message , innerException )
189+ {
190+ }
191+ }
192+ }
0 commit comments