private void RefreshAndRunTask(IUnitTestRun run, TaskCompletionSource <bool> tcs, Lifetime taskLifetime)
        {
            var cancellationTs    = run.GetData(ourCancellationTokenSourceKey);
            var cancellationToken = cancellationTs.NotNull().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;
                    }

                    if (myBackendUnityHost.BackendUnityModel.Value == 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 frontendBackendModel = mySolution.GetProtocolSolution().GetFrontendBackendModel();
                    myUsageStatistics.TrackActivity("UnityUnitTestPreference", frontendBackendModel.UnitTestPreference.Value.ToString());
                    var mode = TestMode.Edit;
                    if (frontendBackendModel.UnitTestPreference.Value == UnitTestLaunchPreference.PlayMode)
                    {
                        mode = TestMode.Play;
                    }
                    var launch = new UnitTestLaunch(run.Launch.Session.Id, filters, mode, unityClientControllerInfo);

                    myBackendUnityHost.BackendUnityModel.ViewNotNull(taskLifetime, (lt, model) =>
                    {
                        // recreate UnitTestLaunch in case of AppDomain.Reload, which is the case with PlayMode tests
                        myLogger.Trace("UnitTestLaunch.SetValue.");
                        if (frontendBackendModel.UnitTestPreference.Value == UnitTestLaunchPreference.Both)
                        {
                            model.UnitTestLaunch.SetValue(launch);
                            SubscribeResults(run, lt, launch);
                            launch.RunResult.Advise(lt, result =>
                            {
                                if (launch.TestMode == TestMode.Play)
                                {
                                    tcs.SetResult(result.Passed);
                                }
                                else
                                {
                                    launch = new UnitTestLaunch(launch.SessionId, launch.TestFilters, TestMode.Play,
                                                                launch.ClientControllerInfo);
                                    model.UnitTestLaunch.SetValue(launch);
                                    SubscribeResults(run, lt, launch);
                                    StartTests(run, tcs, lt);
                                }
                            });
                        }
                        else
                        {
                            model.UnitTestLaunch.SetValue(launch);
                            SubscribeResults(run, lt, launch);
                            launch.RunResult.Advise(lt, result => { tcs.SetResult(result.Passed); });
                        }
                    });

                    StartTests(run, tcs, taskLifetime);

                    // set results for explicit tests
                    foreach (var element in run.Elements.OfType <NUnitElementBase>().Where(a =>
                                                                                           a.RunState == RunState.Explicit && !run.Launch.Criterion.Explicit.Contains(a)))
                    {
                        myUnitTestResultManager.TestFinishing(element, run.Launch.Session,
                                                              "Test should be run explicitly", UnitTestStatus.Ignored);
                    }
                });
            }, cancellationToken);
        }
Esempio n. 2
0
        public static ClientControllerWrapper TryCreate(string sessionId, UnitTestLaunchClientControllerInfo clientControllerInfo)
        {
            if (clientControllerInfo == null)
            {
                ourLogger.Verbose($"ClientController not specified (SessionId={sessionId})");
                return(null);
            }

            ourLogger.Verbose($"ClientController specified (SessionId={sessionId}): {clientControllerInfo.TypeName}, {clientControllerInfo.CodeBase}");

            try
            {
                if (clientControllerInfo.CodeBaseDependencies != null)
                {
                    foreach (var dependency in clientControllerInfo.CodeBaseDependencies)
                    {
                        ourLogger.Trace("Loading assembly from '{0}'", dependency);
                        Assembly.LoadFrom(dependency);
                    }
                }

                ourLogger.Trace("Loading assembly from '{0}'", clientControllerInfo.CodeBase);
                var assembly = Assembly.LoadFrom(clientControllerInfo.CodeBase);

                var type = assembly.GetType(clientControllerInfo.TypeName);
                if (type == null)
                {
                    ourLogger.Error("Type '{0}' not found in assembly '{1}'", clientControllerInfo.TypeName, assembly.FullName);
                    return(null);
                }

                ourLogger.Trace("ClientController type found: {0}", type.AssemblyQualifiedName);

                var clientController = Activator.CreateInstance(type, sessionId);

                var onSessionStartedMethodInfo = type.GetMethod("OnSessionStarted", BindingFlags.Instance | BindingFlags.Public);
                if (onSessionStartedMethodInfo == null)
                {
                    ourLogger.Error("OnSessionStarted method not found in ClientController of type='{0}'", type.AssemblyQualifiedName);
                    return(null);
                }

                var onTestStartedMethodInfo = type.GetMethod("OnTestStarted", BindingFlags.Instance | BindingFlags.Public);
                if (onTestStartedMethodInfo == null)
                {
                    ourLogger.Error("OnTestStarted method not found in ClientController of type='{0}'", type.AssemblyQualifiedName);
                    return(null);
                }

                var onTestFinishedMethodInfo = type.GetMethod("OnTestFinished", BindingFlags.Instance | BindingFlags.Public);
                if (onTestFinishedMethodInfo == null)
                {
                    ourLogger.Error("OnTestFinished method not found in ClientController of type='{0}'", type.AssemblyQualifiedName);
                    return(null);
                }

                var onSessionFinishedMethodInfo = type.GetMethod("OnSessionFinished", BindingFlags.Instance | BindingFlags.Public);
                if (onSessionFinishedMethodInfo == null)
                {
                    ourLogger.Error("OnSessionFinished method not found in ClientController of type='{0}'", type.AssemblyQualifiedName);
                    return(null);
                }

                return(new ClientControllerWrapper(clientController,
                                                   onSessionStartedMethodInfo,
                                                   onTestStartedMethodInfo,
                                                   onTestFinishedMethodInfo,
                                                   onSessionFinishedMethodInfo));
            }
            catch (Exception e)
            {
                ourLogger.Error("Failed to create ClientController", e);
                return(null);
            }
        }