in resharper/resharper-unity/src/Unity.Rider/Integration/Core/Feature/UnitTesting/RunViaUnityEditorStrategy.cs [160:255]
private void RefreshAndRunTask(IUnitTestRun run, TaskCompletionSource<bool> tcs, Lifetime taskLifetime)
{
var cancellationTs = run.GetData(ourCancellationTokenSourceKey).NotNull();
var cancellationToken = cancellationTs.Token;
myLogger.Trace("Before calling Refresh.");
Refresh(run.Lifetime, tcs, cancellationToken).ContinueWith(_ =>
{
if (tcs.Task.IsCanceled || tcs.Task.IsFaulted) // Refresh failed or was stopped
return;
myLogger.Trace("Refresh. OnCompleted.");
// KS: Can't use run.Lifetime for ExecuteOrQueueEx here and in all similar places: run.Lifetime is terminated when
// Unit Test Session is closed from UI without cancelling the run. This will leave task completion source in running state forever.
mySolution.Locks.ExecuteOrQueueEx(myLifetime, "Check compilation", () =>
{
if (!run.Lifetime.IsAlive || cancellationTs.IsCancellationRequested)
{
tcs.TrySetCanceled();
return;
}
var backendUnityModel = myBackendUnityHost.BackendUnityModel.Value;
if (backendUnityModel == null)
{
tcs.SetException(new Exception("Unity Editor connection unavailable."));
return;
}
var filters = GetFilters(run);
UnitTestLaunchClientControllerInfo? unityClientControllerInfo = null;
var clientControllerInfo = run.HostController.GetClientControllerInfo(run);
if (clientControllerInfo != null)
{
unityClientControllerInfo = new UnitTestLaunchClientControllerInfo(
clientControllerInfo.AssemblyLocation,
clientControllerInfo.ExtraDependencies?.ToList(),
clientControllerInfo.TypeName);
}
var preference = mySolution.GetProtocolSolution().GetFrontendBackendModel().UnitTestPreference.Value;
if (preference == null)
return;
// If we select Both, then start with Edit mode tests
var mode = preference == UnitTestLaunchPreference.PlayMode ? TestMode.Play : TestMode.Edit;
var launch = new UnitTestLaunch(run.Launch.Session.Id, filters, mode, unityClientControllerInfo);
// Set up the launch and subscribe to results. Called immediately, because we know the model isn't
// null. Also called when the appdomain is reloaded for play mode tests. The lifetime will correctly
// unsubscribe when the appdomain is unloaded
myBackendUnityHost.BackendUnityModel!.ViewNotNull<BackendUnityModel>(taskLifetime, (lt, model) =>
{
myLogger.Trace("UnitTestLaunch.SetValue.");
model.UnitTestLaunch.SetValue(launch);
SubscribeResults(run, lt, launch);
if (preference == UnitTestLaunchPreference.Both)
{
launch.RunResult.Advise(lt, result =>
{
if (launch.TestMode == TestMode.Play)
tcs.SetResult(result.Passed);
else
{
// Now run Play mode
launch = new UnitTestLaunch(launch.SessionId, launch.TestFilters, TestMode.Play,
launch.ClientControllerInfo);
model.UnitTestLaunch.SetValue(launch);
SubscribeResults(run, lt, launch);
launch.RunResult.Advise(lt, result => { tcs.SetResult(result.Passed); });
StartTests(model, run, tcs, lt);
}
});
}
else
{
launch.RunResult.Advise(lt, result => { tcs.SetResult(result.Passed); });
}
});
StartTests(backendUnityModel, run, tcs, taskLifetime);
// set results for explicit tests
foreach (var element in run.Elements.OfType<INUnitTestElement>().Where(a =>
a.RunState == RunState.Explicit && !run.Launch.Criterion.Explicit.Contains(a.Id)))
{
myUnitTestResultManager.TestFinishing(element, run.Launch.Session,
UnitTestStatus.Ignored, "Test should be run explicitly");
}
});
}, cancellationToken);
}