private Dictionary <string, short> GetUserDefinedCompilationArguments(string projectId) { // use the TypeLib API to grab the user defined compilation arguments; must be obtained on the main thread. var task = _uiDispatcher.StartTask(() => { using (var typeLib = _typeLibWrapperProvider.TypeLibWrapperFromProject(projectId)) { return(typeLib?.VBEExtensions.ConditionalCompilationArguments ?? new Dictionary <string, short>()); } }); return(task.Result); }
/// <summary> /// Use only on the UI thread! /// </summary> /// <remarks> ///This method uses the typeLib API, which is only safe to use on the UI thread. /// </remarks> private bool TryLoadProject(string projectId, IVBProject project, out ComProject comProject) { if (!project.TryGetFullPath(out var path)) { //Only debug because this will always happen for unsaved projects. _logger.Debug($"Unable to get project path for project with projectId {projectId} when loading the COM project."); path = string.Empty; } using (var typeLib = _typeLibWrapperProvider.TypeLibWrapperFromProject(project)) { comProject = typeLib != null ? new ComProject(typeLib, path) : null; } return(comProject != null); }
private void RunWhileSuspendedOnUiThread(IEnumerable <TestMethod> tests) { var testMethods = tests as IList <TestMethod> ?? tests.ToList(); if (!testMethods.Any()) { return; } _lastRun.Clear(); try { EnsureRubberduckIsReferencedForEarlyBoundTests(); } catch (InvalidOperationException e) { Logger.Warn(e); foreach (var test in testMethods) { OnTestCompleted(test, new TestResult(TestOutcome.Failed, AssertMessages.Prerequisite_EarlyBindingReferenceMissing)); } return; } var overallTime = new Stopwatch(); overallTime.Start(); try { var testsByModule = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName) .ToDictionary(grouping => grouping.Key, grouping => grouping.ToList()); foreach (var moduleName in testsByModule.Keys) { var testInitialize = TestDiscovery.FindTestInitializeMethods(moduleName, _state).ToList(); var testCleanup = TestDiscovery.FindTestCleanupMethods(moduleName, _state).ToList(); var moduleTestMethods = testsByModule[moduleName]; var fakes = _fakesFactory.Create(); using (var typeLibWrapper = _wrapperProvider.TypeLibWrapperFromProject(moduleName.ProjectId)) { try { _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleInitializeMethods(moduleName, _state)); } catch (COMException ex) { Logger.Error(ex, "Unexpected COM exception while initializing tests for module {0}. The module will be skipped.", moduleName.Name); foreach (var method in moduleTestMethods) { OnTestCompleted(method, new TestResult(TestOutcome.Unknown, AssertMessages.TestRunner_ModuleInitializeFailure)); } continue; } foreach (var test in moduleTestMethods) { OnTestStarted(test); // no need to run setup/teardown for ignored tests if (test.Declaration.Annotations.Any(a => a.Annotation is IgnoreTestAnnotation)) { OnTestCompleted(test, new TestResult(TestOutcome.Ignored)); continue; } try { fakes.StartTest(); try { _declarationRunner.RunDeclarations(typeLibWrapper, testInitialize); } catch (COMException trace) { OnTestCompleted(test, new TestResult(TestOutcome.Inconclusive, AssertMessages.TestRunner_TestInitializeFailure)); Logger.Trace(trace, "Unexpected COMException when running TestInitialize"); continue; } // The message pump is flushed here to catch cancellation requests. This is the only place inside the main test running // loop where this is "safe" to do - any other location risks either potentially misses test teardown or risks not knowing // what teardown needs to be done via VBA. _uiDispatcher.FlushMessageQueue(); if (CancellationRequested) { RunTestCleanup(typeLibWrapper, testCleanup); fakes.StopTest(); break; } var result = RunTestMethod(typeLibWrapper, test); // we can trigger this event, because cleanup can fail without affecting the result OnTestCompleted(test, result); RunTestCleanup(typeLibWrapper, testCleanup); } finally { fakes.StopTest(); } } try { _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleCleanupMethods(moduleName, _state)); } catch (COMException ex) { // FIXME somehow notify the user of this mess Logger.Error(ex, "Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests", moduleName.Name); break; } } } } catch (Exception ex) { // FIXME somehow notify the user of this mess Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted"); } CancellationRequested = false; overallTime.Stop(); TestRunCompleted?.Invoke(this, new TestRunCompletedEventArgs(overallTime.ElapsedMilliseconds)); }
private void RunWhileSuspended(IEnumerable <TestMethod> tests) { var testMethods = tests as IList <TestMethod> ?? tests.ToList(); if (!testMethods.Any()) { return; } LastRun.Clear(); foreach (var resultAggregator in resultsByOutcome.Values) { resultAggregator.Clear(); } try { EnsureRubberduckIsReferencedForEarlyBoundTests(); } catch (InvalidOperationException e) { Logger.Warn(e); foreach (var test in testMethods) { OnTestCompleted(test, new TestResult(TestOutcome.Failed, AssertMessages.Prerequisite_EarlyBindingReferenceMissing, 0)); } return; } var overallTime = new Stopwatch(); overallTime.Start(); try { var testsByModule = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName) .ToDictionary(grouping => grouping.Key, grouping => grouping.ToList()); foreach (var moduleName in testsByModule.Keys) { var testInitialize = TestDiscovery.FindTestInitializeMethods(moduleName, _state).ToList(); var testCleanup = TestDiscovery.FindTestCleanupMethods(moduleName, _state).ToList(); var moduleTestMethods = testsByModule[moduleName]; var fakes = _fakesFactory.Create(); using (var typeLibWrapper = _wrapperProvider.TypeLibWrapperFromProject(moduleName.ProjectId)) { try { _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleInitializeMethods(moduleName, _state)); } catch (COMException ex) { Logger.Error(ex, "Unexpected COM exception while initializing tests for module {0}. The module will be skipped.", moduleName.Name); foreach (var method in moduleTestMethods) { OnTestCompleted(method, new TestResult(TestOutcome.Unknown, AssertMessages.TestRunner_ModuleInitializeFailure)); } continue; } foreach (var test in moduleTestMethods) { // no need to run setup/teardown for ignored tests if (test.Declaration.Annotations.Any(a => a.AnnotationType == AnnotationType.IgnoreTest)) { OnTestCompleted(test, new TestResult(TestOutcome.Ignored)); continue; } try { fakes.StartTest(); try { _declarationRunner.RunDeclarations(typeLibWrapper, testInitialize); } catch (COMException trace) { OnTestCompleted(test, new TestResult(TestOutcome.Inconclusive, AssertMessages.TestRunner_TestInitializeFailure)); Logger.Trace(trace, "Unexpected COMException when running TestInitialize"); continue; } var result = RunTestMethod(typeLibWrapper, test); // we can trigger this event, because cleanup can fail without affecting the result OnTestCompleted(test, result); try { _declarationRunner.RunDeclarations(typeLibWrapper, testCleanup); } catch (COMException cleanupFail) { // Apparently the user doesn't need to know when test results for subsequent tests could be incorrect Logger.Trace(cleanupFail, "Unexpected COMException when running TestCleanup"); } } finally { fakes.StopTest(); } } try { _declarationRunner.RunDeclarations(typeLibWrapper, TestDiscovery.FindModuleCleanupMethods(moduleName, _state)); } catch (COMException ex) { // FIXME somehow notify the user of this mess Logger.Error(ex, "Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests", moduleName.Name); break; } } } } catch (Exception ex) { // FIXME somehow notify the user of this mess Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted"); } overallTime.Stop(); TestRunCompleted?.Invoke(this, new TestRunCompletedEventArgs(overallTime.ElapsedMilliseconds)); }