-
-
Save loudej/756952 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using NUnit.Framework; | |
namespace FuncGist { | |
// signature exposed by middleware and app | |
using FnApp = Action< | |
IDictionary<string, object> /* env */, | |
Action<Exception> /* fault(ex) */, | |
Action<int, IDictionary<string, string>, IEnumerable<object>> /* result(status, headers, body) */ >; | |
// signature that can be used by host or middleware callers if they choose wrap with AsTask() adapter | |
using FnAppTask = Func< | |
IDictionary<string, object> /* env */, | |
Task<Tuple<int, IDictionary<string, string>, IEnumerable<object>>> /* task<result> */>; | |
[TestFixture] | |
public class Sample { | |
public static FnAppTask AsTask(FnApp app) { | |
// wrap Task conventions around a callback func | |
return env => { | |
var source = new TaskCompletionSource<Tuple<int, IDictionary<string, string>, IEnumerable<object>>>(TaskCreationOptions.AttachedToParent); | |
try { | |
app(env, source.SetException, (status, headers, body) => source.SetResult(Tuple.Create(status, headers, body))); | |
} | |
catch (Exception ex) { | |
source.SetException(ex); | |
} | |
return source.Task; | |
}; | |
} | |
/// <summary> | |
/// Host-side, calling app using callback delegates | |
/// </summary> | |
[Test] | |
public void FireAsCallback() { | |
FnApp app1 = SyncApp; | |
FnApp app2 = AsyncApp; | |
var env = new Dictionary<string, object>(); | |
IEnumerable<object> body1 = null; | |
app1(env, | |
ex => { }, | |
(status, headers, body) => { body1 = body; }); | |
IEnumerable<object> body2 = null; | |
app2(env, | |
ex => { }, | |
(status, headers, body) => { body2 = body; }); | |
// sorry, no such thing as async unit tests | |
SpinWait.SpinUntil(() => body1 != null); | |
SpinWait.SpinUntil(() => body2 != null); | |
AssertBody(body1, "<p>hello world</p>"); | |
AssertBody(body2, "<p>hello async</p>"); | |
} | |
/// <summary> | |
/// Host-side, calling app using Task | |
/// </summary> | |
[Test] | |
public void FireAsTask() { | |
var app1 = AsTask(SyncApp); | |
var app2 = AsTask(AsyncApp); | |
var env = new Dictionary<string, object>(); | |
var task1 = app1(env); | |
var task2 = app2(env); | |
AssertBody(task1.Result.Item3, "<p>hello world</p>"); | |
AssertBody(task2.Result.Item3, "<p>hello async</p>"); | |
} | |
static void AssertBody(IEnumerable<object> body, string value) { | |
Assert.That(body.Aggregate("", (a, b) => a + b), Is.EqualTo(value)); | |
} | |
/// <summary> | |
/// Application-side, implemented synchronously | |
/// </summary> | |
private static void SyncApp( | |
IDictionary<string, object> env, | |
Action<Exception> fault, | |
Action<int, IDictionary<string, string>, IEnumerable<object>> result) { | |
try { | |
result( | |
200, | |
new Dictionary<string, string> { { "Content-Type", "text/html" } }, | |
new[] { "<p>hello world</p>" }); | |
} | |
catch (Exception ex) { | |
fault(ex); | |
} | |
} | |
/// <summary> | |
/// Application-side, implemented asynchronously (by whatever means is appropriate, Thread is obviously not) | |
/// </summary> | |
private static void AsyncApp( | |
IDictionary<string, object> env, | |
Action<Exception> fault, | |
Action<int, IDictionary<string, string>, IEnumerable<object>> result) { | |
try { | |
// the classic fake async maneuver | |
new Thread(_ => { | |
try { | |
Thread.Sleep(1000); | |
result( | |
200, | |
new Dictionary<string, string> { { "Content-Type", "text/html" } }, | |
new[] { "<p>hello async</p>" }); | |
} | |
catch (Exception ex) { | |
fault(ex); | |
} | |
}).Start(); | |
} | |
catch (Exception ex) { | |
fault(ex); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment