예제 #1
0
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            mySolution.Locks.ExecuteOrQueueEx(mySolution.GetLifetime(), "ExecuteRunUT", () =>
            {
                if (myUnityEditorProtocol.UnityModel.Value == null)
                {
                    return;
                }

                var currentConnectionLifetime = Lifetimes.Define(mySolution.GetLifetime());
                myUnityEditorProtocol.UnityModel.Change.Advise_NoAcknowledgement(currentConnectionLifetime.Lifetime, (args) =>
                {
                    if (args.HasNew && args.New == null)
                    {
                        currentConnectionLifetime.Terminate();
                    }
                });

                RunInternal(run, currentConnectionLifetime.Lifetime, myUnityEditorProtocol.UnityModel.Value, tcs);
            });

            return(tcs.Task);
        }
        public async Task PrepareForRun(IUnitTestRun run)
        {
            var lifetimeDef = Lifetime.Define();

            run.PutData(ourLifetimeDefinitionKey, lifetimeDef);

            await myInnerHostController.PrepareForRun(run).ConfigureAwait(false);

            if (!myUnityController.IsUnityEditorUnitTestRunStrategy(run.RunStrategy))
            {
                return;
            }

            lock (myStartUnitySync)
            {
                myStartUnityTask = myStartUnityTask.ContinueWith(_ =>
                {
                    var unityEditorProcessId = myUnityController.TryGetUnityProcessId();
                    return(unityEditorProcessId.HasValue
                        ? Task.CompletedTask
                        : myShellLocks.Tasks.StartNew(lifetimeDef.Lifetime, Scheduling.FreeThreaded, () => StartUnityIfNeed(lifetimeDef.Lifetime)));
                }, lifetimeDef.Lifetime, TaskContinuationOptions.None, myShellLocks.Tasks.GuardedMainThreadScheduler).Unwrap();
            }

            await myStartUnityTask.ConfigureAwait(false);
        }
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            lock (myCurrentLaunchesTaskAccess)
            {
                var cancellationTs = new CancellationTokenSource();
                run.Lifetime.OnTermination(cancellationTs.Cancel);
                run.PutData(ourCancellationTokenSourceKey, cancellationTs);

                var newLaunchTask = myCurrentLaunchesTask.ContinueWith(_ => Run(run), cancellationTs.Token).Unwrap();
                myCurrentLaunchesTask = Task.WhenAll(myCurrentLaunchesTask, newLaunchTask);

                return(newLaunchTask);
            }
        }
        public Task PrepareForRun(IUnitTestRun run, ITaskRunnerHostController next)
        {
            var lifetimeDef = myLifetime.CreateNested();

            run.PutData(ourLifetimeDefinitionKey, lifetimeDef);

            lock (myStartUnitySync)
            {
                WrapStartUnityTask(() => PrepareForRunInternal(lifetimeDef.Lifetime, run));
                WrapStartUnityTask(() => next.PrepareForRun(run));

                return(myStartUnityTask);
            }
        }
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            var hostId = run.HostController.HostId;

            switch (hostId)
            {
            case WellKnownHostProvidersIds.DebugProviderId:
                mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "AttachDebuggerToUnityEditor", () =>
                {
                    var task = myUnityHost.GetValue(model =>
                                                    model.AttachDebuggerToUnityEditor.Start(Unit.Instance));
                    task.Result.AdviseNotNull(run.Lifetime, result =>
                    {
                        if (!result.Result)
                        {
                            tcs.SetException(new Exception("Unable to attach debugger."));
                        }
                        else
                        {
                            RefreshAndRunTask(run, tcs);
                        }
                    });
                });
                break;

            case WellKnownHostProvidersIds.RunProviderId:
                RefreshAndRunTask(run, tcs);
                break;

            default:
                run.Launch.Output.Error(
                    $"Starting Unity tests from '{hostId}' is currently unsupported. Please use `Run`.");
                return(Task.FromResult(false));
            }

            return(tcs.Task);
        }
예제 #6
0
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var hostId = run.HostController.HostId;

            if (hostId == WellKnownHostProvidersIds.DebugProviderId)
            {
                run.Launch.Output.Error("Starting Unity tests from 'Debug' is currently unsupported. Please attach to editor and use 'Run'.");
                return(Task.FromResult(false));
            }

            if (hostId != WellKnownHostProvidersIds.RunProviderId)
            {
                run.Launch.Output.Error($"Starting Unity tests from '{hostId}' is currently unsupported. Please use `Run`.");
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            mySolution.Locks.ExecuteOrQueueEx(mySolution.GetLifetime(), "ExecuteRunUT", () =>
            {
                if (myUnityEditorProtocol.UnityModel.Value == null)
                {
                    return;
                }

                var currentConnectionLifetime = Lifetimes.Define(mySolution.GetLifetime());
                myUnityEditorProtocol.UnityModel.Change.Advise_NoAcknowledgement(currentConnectionLifetime.Lifetime, (args) =>
                {
                    if (args.HasNew && args.New == null)
                    {
                        currentConnectionLifetime.Terminate();
                    }
                });

                RunInternal(run, currentConnectionLifetime.Lifetime, myUnityEditorProtocol.UnityModel.Value, tcs);
            });

            return(tcs.Task);
        }
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            lock (myCurrentLaunchesTaskAccess)
            {
                var key = run.Launch.GetData(ourLaunchedInUnityKey);
                if (key != null)
                {
                    return(Task.FromResult(false));
                }

                run.Launch.PutData(ourLaunchedInUnityKey, "smth");

                var cancellationTs = new CancellationTokenSource();
                run.Lifetime.OnTermination(cancellationTs.Cancel);
                run.PutData(ourCancellationTokenSourceKey, cancellationTs);

                var newLaunchTask = myCurrentLaunchesTask.ContinueWith(_ => Run(run), cancellationTs.Token).Unwrap();
                myCurrentLaunchesTask = Task.WhenAll(myCurrentLaunchesTask, newLaunchTask);

                return(newLaunchTask);
            }
        }
예제 #8
0
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var hostId = run.HostController.HostId;

            if (hostId == WellKnownHostProvidersIds.DebugProviderId)
            {
                run.Launch.Output.Error(
                    "Starting Unity tests from 'Debug' is currently unsupported. Please attach to editor and use 'Run'.");
                return(Task.FromResult(false));
            }

            if (hostId != WellKnownHostProvidersIds.RunProviderId)
            {
                run.Launch.Output.Error(
                    $"Starting Unity tests from '{hostId}' is currently unsupported. Please use `Run`.");
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            myLogger.Verbose("Before calling Refresh.");
            Refresh(mySolution.Locks, run.Lifetime).GetAwaiter().OnCompleted(() =>
            {
                mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "Check compilation", () =>
                {
                    if (myEditorProtocol.UnityModel.Value == null)
                    {
                        myLogger.Verbose("Unity Editor connection unavailable.");
                        tcs.SetException(new Exception("Unity Editor connection unavailable."));
                        return;
                    }

                    var task = myEditorProtocol.UnityModel.Value.GetCompilationResult.Start(Unit.Instance);
                    task.Result.AdviseNotNull(run.Lifetime, result =>
                    {
                        if (!result.Result)
                        {
                            tcs.SetException(new Exception("There are errors during compilation in Unity."));

                            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "RunViaUnityEditorStrategy compilation failed", () =>
                            {
                                var notification = new NotificationModel("Compilation failed", "Script compilation in Unity failed, so tests were not started.", true, RdNotificationEntryType.INFO);
                                myNotificationsModel.Notification(notification);
                            });
                            myUnityHost.PerformModelAction(model => model.ActivateUnityLogView());
                        }
                        else
                        {
                            var launch = SetupLaunch(run);
                            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "ExecuteRunUT", () =>
                            {
                                if (myEditorProtocol.UnityModel.Value == null)
                                {
                                    tcs.SetException(new Exception("Unity Editor connection unavailable."));
                                    return;
                                }

                                myEditorProtocol.UnityModel.ViewNotNull(run.Lifetime, (lt, model) =>
                                {
                                    // recreate UnitTestLaunch in case of AppDomain.Reload, which is the case with PlayMode tests
                                    model.UnitTestLaunch.SetValue(launch);
                                    SubscribeResults(run, lt, tcs, launch);
                                });

                                myEditorProtocol.UnityModel.Value.RunUnitTestLaunch();
                            });
                        }
                    });
                });
            });

            return(tcs.Task);
        }
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var hostId = run.HostController.HostId;

            if (hostId == WellKnownHostProvidersIds.DebugProviderId)
            {
                run.Launch.Output.Error("Starting Unity tests from 'Debug' is currently unsupported. Please attach to editor and use 'Run'.");
                return(Task.FromResult(false));
            }

            if (hostId != WellKnownHostProvidersIds.RunProviderId)
            {
                run.Launch.Output.Error($"Starting Unity tests from '{hostId}' is currently unsupported. Please use `Run`.");
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            // todo: Refresh Assets DB before running tests #558
            // You can check EditorApplication.isCompiling after the refresh and if it is true, then a refresh will happen if there are no compile errors.
            // You can also hook into these event, this will tell you when compilation of assemblies started/finished.
            // https://docs.unity3d.com/ScriptReference/Compilation.CompilationPipeline-assemblyCompilationFinished.html
            // https://docs.unity3d.com/ScriptReference/Compilation.CompilationPipeline-assemblyCompilationStarted.html
            // Note that those events are only available for Unity 5.6+
//            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "RefreshBeforeUT", () =>
//            {
//                myRiderSolutionSaver.Save(run.Lifetime, mySolution, async () =>
//                {
//                    await myUnityRefresher.Refresh(true);
//                });
//            });

            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "ExecuteRunUT", () =>
            {
                if (myUnityEditorProtocol.UnityModel.Value == null)
                {
                    tcs.SetException(new Exception("Unity Editor connection unavailable."));
                    return;
                }

                var currentConnectionLifetime = Lifetimes.Define(run.Lifetime);
                myUnityEditorProtocol.UnityModel.Change.Advise_NoAcknowledgement(currentConnectionLifetime.Lifetime, args =>
                {
                    if (args.HasNew && args.New == null)
                    {
                        currentConnectionLifetime.Terminate();
                    }
                });

                RunInternal(run, currentConnectionLifetime.Lifetime, myUnityEditorProtocol.UnityModel.Value, tcs);
            });

            return(tcs.Task);
        }
예제 #10
0
        Task IUnitTestRunStrategy.Run(IUnitTestRun run)
        {
            var key = run.Launch.GetData(ourLaunchedInUnityKey);

            if (key != null)
            {
                return(Task.FromResult(false));
            }

            var hostId = run.HostController.HostId;

            if (hostId == WellKnownHostProvidersIds.DebugProviderId)
            {
                run.Launch.Output.Error(
                    "Starting Unity tests from 'Debug' is currently unsupported. Please attach to editor and use 'Run'.");
                return(Task.FromResult(false));
            }

            if (hostId != WellKnownHostProvidersIds.RunProviderId)
            {
                run.Launch.Output.Error(
                    $"Starting Unity tests from '{hostId}' is currently unsupported. Please use `Run`.");
                return(Task.FromResult(false));
            }

            var tcs = new TaskCompletionSource <bool>();

            run.Launch.PutData(ourLaunchedInUnityKey, "smth");
            run.PutData(ourCompletionSourceKey, tcs);

            // todo: Refresh Assets DB before running tests #558
            // You can check EditorApplication.isCompiling after the refresh and if it is true, then a refresh will happen if there are no compile errors.
            // You can also hook into these event, this will tell you when compilation of assemblies started/finished.
            // https://docs.unity3d.com/ScriptReference/Compilation.CompilationPipeline-assemblyCompilationFinished.html
            // https://docs.unity3d.com/ScriptReference/Compilation.CompilationPipeline-assemblyCompilationStarted.html
            // Note that those events are only available for Unity 5.6+
            myLogger.Verbose("Before calling Refresh.");
            Refresh(mySolution.Locks, run.Lifetime).GetAwaiter().OnCompleted(() =>
            {
                mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "Check compilation", () =>
                {
                    if (myEditorProtocol.UnityModel.Value == null)
                    {
                        myLogger.Verbose("Unity Editor connection unavailable.");
                        tcs.SetException(new Exception("Unity Editor connection unavailable."));
                        return;
                    }

                    var task = myEditorProtocol.UnityModel.Value.GetCompilationResult.Start(RdVoid.Instance);
                    task.Result.AdviseNotNull(run.Lifetime, result =>
                    {
                        if (!result.Result)
                        {
                            tcs.SetException(new Exception("There are errors during compilation in Unity."));

                            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "RunViaUnityEditorStrategy compilation failed", () =>
                            {
                                var notification = new RdNotificationEntry("Compilation failed", "Script compilation in Unity failed, so tests were not started.", true, RdNotificationEntryType.INFO);
                                myNotificationsModel.Notification.Fire(notification);
                            });
                            myUnityHost.PerformModelAction(model => model.ActivateUnityLogView.Fire());
                        }
                        else
                        {
                            var launch = SetupLaunch(run);
                            mySolution.Locks.ExecuteOrQueueEx(run.Lifetime, "ExecuteRunUT", () =>
                            {
                                if (myEditorProtocol.UnityModel.Value == null)
                                {
                                    tcs.SetException(new Exception("Unity Editor connection unavailable."));
                                    return;
                                }

                                myEditorProtocol.UnityModel.ViewNotNull(run.Lifetime, (lt, model) =>
                                {
                                    // recreate UnitTestLaunch in case of AppDomain.Reload, which is the case with PlayMode tests
                                    model.UnitTestLaunch.SetValue(launch);
                                    SubscribeResults(run, lt, tcs, launch);
                                });

                                myEditorProtocol.UnityModel.Value.RunUnitTestLaunch.Fire(RdVoid.Instance);
                            });
                        }
                    });
                });
            });

            return(tcs.Task);
        }