Skip to content

Commit

Permalink
Merge pull request #6 from BastianBlokland/feature/wrapping-tasks-test
Browse files Browse the repository at this point in the history
Add integration test for wrapping tasks
  • Loading branch information
BastianBlokland authored Jul 24, 2019
2 parents a908be7 + 67dca07 commit 519508a
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 0 deletions.
48 changes: 48 additions & 0 deletions tests/playmode/Helpers/ComponentContextAsserter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using UnityEngine;
using System.Threading;
using NUnit.Framework;
using System.Reflection;

namespace ComponentTask.Tests.PlayMode.Helpers
{
public static class ComponentContextAsserter
{
/// <summary>
/// Assert that current execution is running in the context of the given component.
/// </summary>
/// <remarks>
/// Uses implementation details to assert this behaviour but can be usefull to assert that
/// sync-context is flowed correctly.
/// </remarks>
public static void AssertRunningInComponentContext(
Component component,
TaskRunOptions options = TaskRunOptions.Default)
{
var currentSyncContext = SynchronizationContext.Current;
var compSyncContext = GetComponentSyncContext(component, options);

Assert.True(
condition: object.ReferenceEquals(compSyncContext, currentSyncContext),
message: $"Not running in the context of '{component}'");
}

private static SynchronizationContext GetComponentSyncContext(
Component component,
TaskRunOptions options)
{
/* These are internal implementation details but is usefull to be able to assert
that sync-context is flowed correctly. */

var monoBehaviourRunner = component.GetTaskRunner(options);
var taskRunnerImpl = monoBehaviourRunner.
GetType().
GetField("taskRunner", BindingFlags.Instance | BindingFlags.NonPublic).
GetValue(monoBehaviourRunner);
var context = taskRunnerImpl.
GetType().
GetField("context", BindingFlags.Instance | BindingFlags.NonPublic).
GetValue(taskRunnerImpl);
return context as SynchronizationContext;
}
}
}
11 changes: 11 additions & 0 deletions tests/playmode/Helpers/ComponentContextAsserter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

107 changes: 107 additions & 0 deletions tests/playmode/Integration/WrappingTasks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Collections;
using System.Threading.Tasks;
using ComponentTask.Tests.PlayMode.Helpers;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;

namespace ComponentTask.Tests.PlayMode.Integration
{
public sealed class WrappingTasks
{
private sealed class ClassA : MonoBehaviour
{
public TaskWrapper Wrapper { get; set; }

public bool IsFinished { get; set; }

private void Start()
{
this.StartTask(this.RunAsync);
}

private async Task RunAsync()
{
ComponentContextAsserter.AssertRunningInComponentContext(this);

await Task.Yield();
for (int i = 0; i < 3; i++)
{
await this.Wrapper.WrapWork(() => this.StartTask(this.DoWorkAsync));
ComponentContextAsserter.AssertRunningInComponentContext(this);
}

this.IsFinished = true;
}

private async Task DoWorkAsync()
{
ComponentContextAsserter.AssertRunningInComponentContext(this);
await Task.Yield();
ComponentContextAsserter.AssertRunningInComponentContext(this);
await Task.Yield();
ComponentContextAsserter.AssertRunningInComponentContext(this);
}
}

private sealed class TaskWrapper : MonoBehaviour
{
public Task WrapWork(Func<Task> taskCreator)
{
return this.StartTask(RunAsync);

async Task RunAsync()
{
ComponentContextAsserter.AssertRunningInComponentContext(this);

// Do something before.
await Task.Yield();

ComponentContextAsserter.AssertRunningInComponentContext(this);

// Execute work.
await taskCreator.Invoke();

ComponentContextAsserter.AssertRunningInComponentContext(this);

// Do something after.
await Task.Yield();

ComponentContextAsserter.AssertRunningInComponentContext(this);
}
}
}

[OneTimeSetUp]
public void OneTimeSetup()
{
TraceAsserter.Register();
}

[UnityTest]
public IEnumerator SyncContextIsFlowedCorrectlyWhenWrappingTasks()
{
var goB = new GameObject("B");
var classB = goB.AddComponent<TaskWrapper>();

var goA = new GameObject("A");
var classA = goA.AddComponent<ClassA>();
classA.Wrapper = classB;

for (int i = 0; i < 25; i++)
{
if (classA.IsFinished)
break;

yield return null;
}

Assert.True(classA.IsFinished, "Work did not finish");

// Cleanup.
UnityEngine.Object.Destroy(goA);
UnityEngine.Object.Destroy(goB);
}
}
}
11 changes: 11 additions & 0 deletions tests/playmode/Integration/WrappingTasks.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 519508a

Please sign in to comment.