public IEnumerator Polling_HappensOncePerFrame()
        {
            using (var executor = new UnityTestInstructionExecutor(logErrors: false))
            {
                var pollCount = 0;

                Responsibly
                .WaitForCondition("Never", () =>
                {
                    ++pollCount;
                    return(false);
                })
                .ExpectWithinSeconds(1)
                .ToYieldInstruction(executor);

                Assert.AreEqual(1, pollCount, "Should poll once synchronously");

                yield return(null);

                Assert.AreEqual(2, pollCount, "Should poll once per frame");

                yield return(null);

                Assert.AreEqual(3, pollCount, "Should poll once per frame");
            }
        }
示例#2
0
        public IEnumerator ToYieldInstruction_Throws_WhenThrowOnErrorTrue()
        {
            this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame());

            var exception        = new Exception("Test exception");
            var yieldInstruction = Responsibly
                                   .WaitForCondition("may complete", () => this.mayComplete)
                                   .Select <object, int>(_ => throw exception)
                                   .ExpectWithinSeconds(1)
                                   .ToYieldInstruction(this.Executor, throwOnError: true);

            TestFailureException failureException;

            while (true)
            {
                try
                {
                    yieldInstruction.MoveNext();
                }
                catch (TestFailureException e)
                {
                    failureException = e;
                    break;
                }

                yield return(null);

                this.mayComplete = true;
            }

            Assert.AreEqual(exception, failureException.InnerException);
        }
 public IEnumerator AssertIgnore_DoesNotCauseTestFailure()
 {
     using (var executor = new UnityTestInstructionExecutor())
     {
         yield return(Responsibly
                      .Do("Assert.Ignore", () => Assert.Ignore("Should not fail"))
                      .ToYieldInstruction(executor));
     }
 }
示例#4
0
        public void WaitForCoroutineMethod_ContainsCorrectDescription()
        {
            var instruction = Responsibly
                              .WaitForCoroutineMethod(this.ThrowImmediately)
                              .ExpectWithinSeconds(1)
                              .ToYieldInstruction(this.Executor);

            Assert.IsTrue(instruction.CompletedWithError);
            StringAssert.Contains("ThrowImmediately (Coroutine)", instruction.Error.Message);
        }
 public void Errors_AreNotLogged_WhenLogErrorsIsFalse()
 {
     using (var executor = new UnityTestInstructionExecutor(logErrors: false))
     {
         var instruction = Responsibly
                           .Do("Throw exception", () => throw new Exception())
                           .ToYieldInstruction(executor, throwOnError: false);
         Assert.IsTrue(instruction.CompletedWithError);
         // Should not fail the test with logged errors
     }
 }
示例#6
0
        public void WaitForCoroutine_ThrowsWithInvalidExecutor()
        {
            var nonUnityExecutor = new TestInstructionExecutor(new MockTestScheduler());
            var instruction      = Responsibly
                                   .WaitForCoroutineMethod(this.Forever)
                                   .ExpectWithinSeconds(1)
                                   .ToYieldInstruction(nonUnityExecutor);

            Assert.IsTrue(instruction.CompletedWithError);
            StringAssert.Contains(nameof(MonoBehaviour), instruction.Error.Message);
        }
 public void Errors_AreLogged_WhenLogErrorsIsTrue()
 {
     using (var executor = new UnityTestInstructionExecutor(logErrors: true))
     {
         var message = "Should be in log";
         Responsibly
         .Do("Throw exception", () => throw new Exception(message))
         .ToYieldInstruction(executor, throwOnError: false);                         // Should complete synchronously
         LogAssert.Expect(LogType.Error, new Regex(message));
     }
 }
示例#8
0
        public IEnumerator WaitForCoroutine_CompletesWithError_WhenCoroutineThrows()
        {
            var instruction = Responsibly
                              .WaitForCoroutine("Throw", this.ThrowAfterOneFrame)
                              .ExpectWithinSeconds(1)
                              .ToYieldInstruction(this.Executor, throwOnError: false);

            yield return(instruction);

            Assert.IsTrue(instruction.CompletedWithError);
            Assert.AreSame(this.testException, instruction.Error.InnerException);
        }
        public void UnhandledErrorLog_IsLoggedAsWarning_WhenLogErrorsIsTrue()
        {
            using (var executor = new UnityTestInstructionExecutor(logErrors: true))
            {
                var expected = "expected message";
                Responsibly
                .Do("Throw exception", () => Debug.LogError(expected))
                .ToYieldInstruction(executor, throwOnError: false);                     // Should complete synchronously

                LogAssert.Expect(LogType.Warning, new Regex(expected));                 // The one from us
            }
        }
        public void GlobalContext_IsIncludedInErrors()
        {
            var globalContextProvider = Substitute.For <IGlobalContextProvider>();

            globalContextProvider.BuildGlobalContext(Arg.Do(
                                                         (StateStringBuilder builder) => builder.AddDetails("Global details")));
            using (var executor = new UnityTestInstructionExecutor(globalContextProvider: globalContextProvider))
            {
                Responsibly
                .Do("Throw exception", () => throw new Exception())
                .ToYieldInstruction(executor, throwOnError: false);                         // Should complete synchronously
                LogAssert.Expect(LogType.Error, new Regex("Global details"));
            }
        }
示例#11
0
        public void ContinueWith_PropagatesError_WhenContinuationThrows()
        {
            var task = Responsibly
                       .Return(new object())
                       .ContinueWith <object, object>(_ => throw new Exception("Test exception"))
                       .ToTask(this.Executor);

            var exception = GetFailureException(task);

            StateAssert.StringContainsInOrder(exception.Message)
            .Completed("Return")
            .Failed("...")
            .Details("Test exception");
        }
        public void LoggingError_CausesFailureSynchronously()
        {
            using (var executor = new UnityTestInstructionExecutor(logErrors: false))
            {
                var yieldInstruction = Responsibly
                                       .WaitForCondition("Never", () => false)
                                       .ExpectWithinSeconds(1)
                                       .ToYieldInstruction(executor);

                Debug.LogError("Should fail the instruction");

                Assert.IsTrue(yieldInstruction.CompletedWithError);
            }
        }
示例#13
0
        public IEnumerator ToYieldInstruction_CompletesAsExpected_WhenConstructedFromWait()
        {
            this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame());

            var yieldInstruction = Responsibly
                                   .WaitForCondition("may complete", () => this.mayComplete)
                                   .CreateState()
                                   .ToYieldInstruction(this.Executor);

            yield return(yieldInstruction);

            // Completes one frame "late", because of Update ordering
            Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount);
            Assert.IsTrue(yieldInstruction.CompletedSuccessfully);
        }
示例#14
0
        public IEnumerator CompoundCoroutineWait_ContainsCorrectDescription()
        {
            var instruction = Responsibly
                              .WaitForCoroutineMethod(this.CompleteAfterOneFrame)
                              .AndThen(Responsibly.WaitForCoroutineMethod(this.ThrowImmediately))
                              .ExpectWithinSeconds(1)
                              .ToYieldInstruction(this.Executor, throwOnError: false);

            yield return(instruction);

            Assert.IsTrue(instruction.CompletedWithError);
            Assert.That(
                instruction.Error.Message,
                Does.Match(@"\[✓\] CompleteAfterOneFrame.*\n.*\[!\] ThrowImmediately"));
        }
示例#15
0
        public IEnumerator WaitForCoroutine_CompletesWithCoroutine()
        {
            var startFrame = Time.frameCount;

            yield return(Responsibly
                         .WaitForCoroutine("Coroutine", this.CompleteAfterOneFrame)
                         .ExpectWithinSeconds(1)
                         .ToYieldInstruction(this.Executor));

            Assert.AreEqual(
                1,
                Time.frameCount - startFrame,
                "Coroutine should complete after one frame");
            Assert.IsTrue(this.coroutineCompleted);
        }
        public void StateString_TruncatesExceptionAt100Chars()
        {
            var message = new string('x', 99) + "^~";
            var state   = Responsibly.Do(
                "Fail",
                () => throw new Exception(message))
                          .CreateState();

            state.ToTask(this.Executor);             // Complete task

            var stateString = state.ToString();

            StateAssert.StringContainsInOrder(stateString)
            .Failed("Fail")
            .Details(@"xxxxxxx\^")
            .Nowhere("~");
        }
        public void StateString_ContainsOnlyFirstLineOfException_WhenMultiline()
        {
            var firstLine  = "First line";
            var secondLine = "Second line";
            var state      = Responsibly.Do(
                "Fail",
                () => throw new Exception($"{firstLine}\n{secondLine}"))
                             .CreateState();

            state.ToTask(this.Executor);             // Complete task

            var stateString = state.ToString();

            StateAssert.StringContainsInOrder(stateString)
            .Failed("Fail")
            .Details(firstLine)
            .Nowhere(secondLine);
        }
        public void LoggingError_DoesNotFail_WhenUsingExpectLog()
        {
            using (var executor = new UnityTestInstructionExecutor(logErrors: false))
            {
                var yieldInstruction = Responsibly
                                       .WaitForCondition("Never", () => false)
                                       .ExpectWithinSeconds(1)
                                       .ToYieldInstruction(executor);

                var message = "Should not fail the instruction";
                executor.ExpectLog(LogType.Error, new Regex(message));
                Debug.LogError(message);

                Assert.IsFalse(yieldInstruction.WasCanceled);
                Assert.IsFalse(yieldInstruction.CompletedSuccessfully);
                Assert.IsFalse(yieldInstruction.CompletedWithError);
            }
        }
示例#19
0
        public IEnumerator ToYieldInstruction_CompletesAsExpected()
        {
            this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame());

            var yieldInstruction = Responsibly
                                   .WaitForCondition("may complete", () => this.mayComplete)
                                   .ExpectWithinSeconds(1)
                                   .ToYieldInstruction(this.Executor);

            yield return(yieldInstruction);

            // Completes one frame after
            Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount);

            object unused;

            Assert.IsFalse(yieldInstruction.WasCanceled);
            Assert.IsFalse(yieldInstruction.CompletedWithError);
            Assert.IsTrue(yieldInstruction.CompletedSuccessfully);
            Assert.IsNotNull(yieldInstruction.Result);
            Assert.Throws <InvalidOperationException>(() => unused = yieldInstruction.Error);
        }
        public IEnumerator Polling_IsStopped_WhenDisposed()
        {
            var pollCount = 0;

            using (var executor = new UnityTestInstructionExecutor(logErrors: false))
            {
                Responsibly
                .WaitForCondition("Never", () =>
                {
                    ++pollCount;
                    return(false);
                })
                .ExpectWithinSeconds(1)
                .ToYieldInstruction(executor);
            }

            Assert.AreEqual(1, pollCount, "Should poll once synchronously");

            yield return(null);

            Assert.AreEqual(1, pollCount, "Should not poll after being disposed");
        }
示例#21
0
        public IEnumerator WaitForCoroutine_CancelsCoroutine_WhenOperationCanceled()
        {
            using (var cancellationSource = new CancellationTokenSource())
            {
                var instruction = Responsibly
                                  .WaitForCoroutine("Forever", this.Forever)
                                  .ExpectWithinSeconds(1)
                                  .ToYieldInstruction(this.Executor, throwOnError: false, cancellationSource.Token);

                Assert.IsTrue(this.coroutineRan);
                yield return(null);

                this.coroutineRan = false;
                cancellationSource.Cancel();

                yield return(null);

                yield return(null);

                Assert.IsFalse(this.coroutineRan);
                Assert.IsTrue(instruction.WasCanceled);
            }
        }
示例#22
0
        public IEnumerator ToYieldInstruction_ErrorsAsExpected()
        {
            this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame());

            var exception        = new Exception("Test exception");
            var yieldInstruction = Responsibly
                                   .WaitForCondition("may complete", () => this.mayComplete)
                                   .Select <object, int>(_ => throw exception)
                                   .ExpectWithinSeconds(1)
                                   .ToYieldInstruction(this.Executor, false);

            yield return(yieldInstruction);

            // Completes one frame "late", because of Update ordering
            Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount);

            object unused;

            Assert.IsFalse(yieldInstruction.WasCanceled);
            Assert.IsTrue(yieldInstruction.CompletedWithError);
            Assert.IsFalse(yieldInstruction.CompletedSuccessfully);
            Assert.Throws <InvalidOperationException>(() => unused = yieldInstruction.Result);
            Assert.AreSame(exception, yieldInstruction.Error.InnerException);
        }
示例#23
0
        public void Instruction_IsCanceled_WhenExternalResult([Values] bool error)
        {
            var polled = false;
            var unused = Responsibly
                         .WaitForCondition("Fake condition", () =>
            {
                polled = true;
                return(false);
            })
                         .ExpectWithinSeconds(1);

            if (error)
            {
                this.completionSource.SetException(new Exception());
            }
            else
            {
                this.completionSource.SetResult(1);
            }

            this.AdvanceDefaultFrame();

            Assert.IsFalse(polled);
        }