public void TriggerAnalysisAsync_AnalysisIsCancelled_NotifiesOfCancellation()
        {
            var mockConsumer = new Mock <IIssueConsumer>();
            var subProcess   = new SubProcessSimulator();

            var testSubject = new TestableCLangAnalyzer(telemetryManagerMock.Object, new ConfigurableSonarLintSettings(),
                                                        rulesConfigProviderMock.Object, serviceProviderWithValidProjectItem.Object, analysisNotifierMock.Object, testLogger, cFamilyIssueConverterMock.Object);

            testSubject.SetCallSubProcessBehaviour(subProcess.CallSubProcess);

            using var cts = new CancellationTokenSource();
            try
            {
                // Call the CLangAnalyzer on another thread (that thread is blocked by subprocess wrapper)
                var filePath     = "c:\\test.cpp";
                var analysisTask = Task.Run(() => testSubject.TriggerAnalysisAsync(new Request {
                    File = filePath
                }, mockConsumer.Object, analysisNotifierMock.Object, cts.Token));
                subProcess.WaitUntilSubProcessCalledByAnalyzer();

                cts.Cancel();

                // Tell the subprocess mock there are no more messages and wait for the analyzer method to complete
                subProcess.SignalNoMoreIssues();
                bool succeeded = analysisTask.Wait(10000);
                succeeded.Should().BeTrue();

                analysisNotifierMock.Verify(x => x.AnalysisStarted(filePath), Times.Once);
                analysisNotifierMock.Verify(x => x.AnalysisCancelled(filePath), Times.Once);
                analysisNotifierMock.VerifyNoOtherCalls();
            }
            finally
            {
                // Unblock the subprocess wrapper in case of errors so it can finish
                subProcess.SignalNoMoreIssues();
            }
        }
        public void TriggerAnalysisAsync_IssuesForInactiveRulesAreNotStreamed()
        {
            const string fileName    = "c:\\data\\aaa\\bbb\file.txt";
            var          rulesConfig = new DummyCFamilyRulesConfig("c")
                                       .AddRule("inactiveRule", isActive: false)
                                       .AddRule("activeRule", isActive: true);

            var request = new Request
            {
                File = fileName,
                RulesConfiguration = rulesConfig,
                CFamilyLanguage    = rulesConfig.LanguageKey
            };

            var inactiveRuleMessage = new Message("inactiveRule", fileName, 1, 1, 1, 1, "inactive message", false, Array.Empty <MessagePart>());
            var activeRuleMessage   = new Message("activeRule", fileName, 2, 2, 2, 2, "active message", false, Array.Empty <MessagePart>());

            var convertedActiveMessage = Mock.Of <IAnalysisIssue>();

            cFamilyIssueConverterMock
            .Setup(x => x.Convert(activeRuleMessage, request.CFamilyLanguage, rulesConfig))
            .Returns(convertedActiveMessage);

            var mockConsumer = new Mock <IIssueConsumer>();
            var subProcess   = new SubProcessSimulator();

            var testSubject = new TestableCLangAnalyzer(telemetryManagerMock.Object, new ConfigurableSonarLintSettings(),
                                                        rulesConfigProviderMock.Object, serviceProviderWithValidProjectItem.Object, analysisNotifierMock.Object, testLogger, cFamilyIssueConverterMock.Object);

            testSubject.SetCallSubProcessBehaviour(subProcess.CallSubProcess);

            try
            {
                // Call the CLangAnalyzer on another thread (that thread is blocked by subprocess wrapper)
                var analysisTask = Task.Run(() => testSubject.TriggerAnalysisAsync(request, mockConsumer.Object, analysisNotifierMock.Object, CancellationToken.None));
                subProcess.WaitUntilSubProcessCalledByAnalyzer();

                // Stream the inactive rule message to the analyzer
                subProcess.PassMessageToCLangAnalyzer(inactiveRuleMessage);
                mockConsumer.Verify(x => x.Accept(fileName, It.IsAny <IEnumerable <IAnalysisIssue> >()), Times.Never);

                // Now stream an active rule message
                subProcess.PassMessageToCLangAnalyzer(activeRuleMessage);

                mockConsumer.Verify(x => x.Accept(fileName, It.IsAny <IEnumerable <IAnalysisIssue> >()), Times.Once);
                var suppliedIssues = (IEnumerable <IAnalysisIssue>)mockConsumer.Invocations[0].Arguments[1];
                suppliedIssues.Count().Should().Be(1);
                suppliedIssues.First().Should().Be(convertedActiveMessage);

                // Tell the subprocess mock there are no more messages and wait for the analyzer method to complete
                subProcess.SignalNoMoreIssues();
                bool succeeded = analysisTask.Wait(10000);
                succeeded.Should().BeTrue();

                analysisNotifierMock.Verify(x => x.AnalysisStarted(fileName), Times.Once);
                analysisNotifierMock.Verify(x => x.AnalysisFinished(fileName, 1, It.IsAny <TimeSpan>()), Times.Once);
                analysisNotifierMock.VerifyNoOtherCalls();
            }
            finally
            {
                // Unblock the subprocess wrapper in case of errors so it can finish
                subProcess.SignalNoMoreIssues();
            }
        }