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

            testSubject.RequestToReturn = null;

            testSubject.ExecuteAnalysis("path", "charset", new[] { AnalysisLanguage.CFamily }, Mock.Of <IIssueConsumer>(), null, CancellationToken.None);

            testSubject.CreateRequestCallCount.Should().Be(1);
            testSubject.TriggerAnalysisCallCount.Should().Be(0);
        }
        public async Task TriggerAnalysisAsync_AnalysisFails_NotifiesOfFailure()
        {
            void MockSubProcessCall(Action <Message> message, Request request, ISonarLintSettings settings, ILogger logger, CancellationToken token)
            {
                throw new NullReferenceException("test");
            }

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

            testSubject.SetCallSubProcessBehaviour(MockSubProcessCall);

            var filePath = "c:\\test.cpp";
            await testSubject.TriggerAnalysisAsync(new Request { File = filePath }, Mock.Of <IIssueConsumer>(), analysisNotifierMock.Object, CancellationToken.None);

            analysisNotifierMock.Verify(x => x.AnalysisStarted(filePath), Times.Once);
            analysisNotifierMock.Verify(x => x.AnalysisFailed(filePath, It.Is <NullReferenceException>(e => e.Message == "test")), Times.Once);
            analysisNotifierMock.VerifyNoOtherCalls();
        }
        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();
            }
        }