public void EndGenerateCompletionDatabase(string id, bool success) { if (_updater != null) { for (int i = 0; i <= 100; i += 30) { _updater.UpdateStatus(i, 100); // Need to sleep to allow the update to go through. Thread.Sleep(500); } _updater.Dispose(); _updater = null; } // Also have to sleep after disposing to make sure that the // completion is picked up. Thread.Sleep(500); if (success) { IsCurrent = true; } else { IsCurrentReason = MissingModulesReason; // won't raise an event IsCurrent = false; } }
public void Dispose() { if (_updater != null) { _updater.Dispose(); _updater = null; } }
public void MessageMaximumLength() { Dictionary <string, AnalysisProgress> results = null; using (var ready = new AutoResetEvent(false)) using (var listener = new AnalyzerStatusListener(r => { results = r; ready.Set(); })) { listener.WaitForWorkerStarted(); listener.ThrowPendingExceptions(); // Ensure that updates are being received listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); if (results.Count > 0) { ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); if (results.Count > 0) { Console.WriteLine("WARNING: {0} results received from a previous test", results.Count); Console.WriteLine("Keys are:"); foreach (var key in results.Keys) { Console.WriteLine(" {0}", key); } } } using (var sender = new AnalyzerStatusUpdater("MessageMaximumLength")) { sender.WaitForWorkerStarted(); sender.ThrowPendingExceptions(); // Create a message that is deliberately too long string message = new string('x', AnalyzerStatusUpdater.MAX_MESSAGE_LENGTH * 2); sender.UpdateStatus(0, 0, 0, message); sender.FlushQueue(TimeSpan.FromSeconds(1.0)); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); AssertUtil.Contains(results.Keys, "MessageMaximumLength"); var receivedMessage = results["MessageMaximumLength"].Message; Console.WriteLine("Message: <{0}>", receivedMessage); Assert.AreEqual( AnalyzerStatusUpdater.MAX_MESSAGE_LENGTH, receivedMessage.Length, "Message length was not limited" ); } } }
public void GenerateDatabase(GenerateDatabaseOptions options, Action <int> onExit = null) { IsCurrentReason = GeneratingReason; IsCurrent = false; if (_useUpdater) { if (_updater != null) { _updater.Dispose(); } _updater = new AnalyzerStatusUpdater(_config.Id); _updater.WaitForWorkerStarted(); _updater.ThrowPendingExceptions(); _updater.UpdateStatus(0, 0); } }
public void IdentifierInUse() { using (var updater = new AnalyzerStatusUpdater("IdentifierInUse")) { updater.UpdateStatus(1, 100, 0); updater.WaitForWorkerStarted(); // Should not throw updater.ThrowPendingExceptions(); using (var updater2 = new AnalyzerStatusUpdater("IdentifierInUse")) { updater2.WaitForWorkerStarted(); updater2.UpdateStatus(99, 100, 0); try { updater2.ThrowPendingExceptions(); Assert.Fail("Expected IdentifierInUseException"); } catch (IdentifierInUseException) { } } } }
public void LotsOfUpdaters() { var updaters = new List <AnalyzerStatusUpdater>(); // We should stop creating new entries well before 10000 for (int j = 0; j < 10000; ++j) { Console.WriteLine("Creating LotsOfUpdaters{0}", j); var newUpdater = new AnalyzerStatusUpdater("LotsOfUpdaters" + j.ToString()); updaters.Add(newUpdater); } // Give the updaters a chance to start foreach (var updater in updaters) { updater.WaitForWorkerStarted(); } // Make sure that we got failures. int succeeded = 0; try { foreach (var u in updaters) { u.ThrowPendingExceptions(); succeeded += 1; } Assert.Fail("Should not have been able to create 10000 updaters"); } catch (InvalidOperationException) { } finally { foreach (var u in updaters) { u.Dispose(); } } Console.WriteLine("{0} updaters were created.", succeeded); updaters.Clear(); }
public void SendUpdates() { Dictionary <string, AnalysisProgress> results = null; using (var ready = new AutoResetEvent(false)) using (var listener = new AnalyzerStatusListener(r => { results = r; ready.Set(); })) { ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); if (results.Count > 0) { ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); if (results.Count > 0) { Console.WriteLine("WARNING: {0} results received from a previous test", results.Count); Console.WriteLine("Keys are:"); foreach (var key in results.Keys) { Console.WriteLine(" {0}", key); } } } using (var sender1 = new AnalyzerStatusUpdater("SendUpdates1")) using (var sender2 = new AnalyzerStatusUpdater("SendUpdates2")) { // Block until workers have started sender1.WaitForWorkerStarted(); sender1.ThrowPendingExceptions(); sender2.WaitForWorkerStarted(); sender2.ThrowPendingExceptions(); ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); AssertUtil.ContainsAtLeast(results.Keys, "SendUpdates1", "SendUpdates2"); Assert.AreEqual(int.MaxValue, results["SendUpdates1"].Progress, "SendUpdates1.Progress not initialized to MaxValue"); Assert.AreEqual(0, results["SendUpdates1"].Maximum, "SendUpdates1.Maximum not initialized to 0"); Assert.AreEqual(string.Empty, results["SendUpdates1"].Message, "SendUpdates1.Message not initialized to empty"); Assert.AreEqual(int.MaxValue, results["SendUpdates2"].Progress, "SendUpdates2.Progress not initialized to MaxValue"); Assert.AreEqual(0, results["SendUpdates2"].Maximum, "SendUpdates2.Maximum not initialized to 0"); Assert.AreEqual(string.Empty, results["SendUpdates2"].Message, "SendUpdates2.Message not initialized to empty"); sender1.UpdateStatus(100, 200, 300, "Message1"); sender1.FlushQueue(TimeSpan.FromSeconds(1.0)); ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.AreEqual(100, results["SendUpdates1"].Progress, "SendUpdates1.Progress not set to 100"); Assert.AreEqual(200, results["SendUpdates1"].Maximum, "SendUpdates1.Maximum not set to 200"); Assert.AreEqual(300, results["SendUpdates1"].Seconds, "SendUpdates1.Seconds not set to 300"); Assert.AreEqual("Message1", results["SendUpdates1"].Message, "SendUpdates1.Message not set"); Assert.AreEqual(int.MaxValue, results["SendUpdates2"].Progress, "SendUpdates2.Progress changed from MaxValue"); Assert.AreEqual(0, results["SendUpdates2"].Maximum, "SendUpdates2.Maximum changed from 0"); Assert.AreEqual(string.Empty, results["SendUpdates2"].Message, "SendUpdates2.Message changed from empty"); sender2.UpdateStatus(1000, 2000, 3000, "Message2"); sender2.FlushQueue(TimeSpan.FromSeconds(1.0)); ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.AreEqual(100, results["SendUpdates1"].Progress, "SendUpdates1.Progress changed from 100"); Assert.AreEqual(200, results["SendUpdates1"].Maximum, "SendUpdates1.Maximum changed from 200"); Assert.AreEqual(300, results["SendUpdates1"].Seconds, "SendUpdates1.Seconds changed from 300"); Assert.AreEqual("Message1", results["SendUpdates1"].Message, "SendUpdates1.Message changed"); Assert.AreEqual(1000, results["SendUpdates2"].Progress, "SendUpdates2.Progress not set to 1000"); Assert.AreEqual(2000, results["SendUpdates2"].Maximum, "SendUpdates2.Maximum not set to 2000"); Assert.AreEqual(3000, results["SendUpdates2"].Seconds, "SendUpdates2.Seconds not set to 3000"); Assert.AreEqual("Message2", results["SendUpdates2"].Message, "SendUpdates2.Message not set"); } Thread.Sleep(100); // allow updaters to terminate ready.Reset(); listener.RequestUpdate(); ready.WaitOne(); Assert.IsNotNull(results); if (results.Count > 0) { Console.WriteLine("WARNING: {0} results exist at end of test", results.Count); Console.WriteLine("Keys are:"); foreach (var key in results.Keys) { Console.WriteLine(" {0}", key); } } Assert.IsFalse(results.ContainsKey("SendUpdates1"), "results were not cleaned up"); Assert.IsFalse(results.ContainsKey("SendUpdates2"), "results were not cleaned up"); } }
public void InitializeWithoutCrashing() { using (var updater = new AnalyzerStatusUpdater("InitializeWithoutCrashing")) { } using (var updater = new AnalyzerStatusListener(x => { })) { } }
private async void Listener_ProgressUpdate(Dictionary <string, AnalysisProgress> status) { bool anyUpdates = status.Any(); if (!anyUpdates) { lock (_environmentsLock) { anyUpdates = _currentlyRefreshing.Count != 0; } } if (anyUpdates) { var updates = new List <DispatcherOperation>(); lock (_environmentsLock) { foreach (var env in _environments) { if (env.Factory == null) { continue; } AnalysisProgress progress; if (status.TryGetValue(AnalyzerStatusUpdater.GetIdentifier(env.Factory), out progress)) { _currentlyRefreshing.Add(env.Factory); updates.Add(env.Dispatcher.InvokeAsync(() => { if (progress.Maximum > 0) { var percent = progress.Progress * 100 / progress.Maximum; var current = env.RefreshDBProgress; // Filter out small instances of 'reverse' // progress, but allow big jumps backwards. if (percent > current || percent < current - 25) { env.RefreshDBProgress = percent; } env.IsRefreshDBProgressIndeterminate = false; } else { env.IsRefreshDBProgressIndeterminate = true; } env.RefreshDBMessage = progress.Message; env.IsRefreshingDB = true; })); } else if (_currentlyRefreshing.Remove(env.Factory)) { updates.Add(env.Dispatcher.InvokeAsync(() => { env.IsRefreshingDB = false; env.IsRefreshDBProgressIndeterminate = false; env.RefreshDBMessage = string.Empty; CommandManager.InvalidateRequerySuggested(); })); } } } try { await Task.WhenAll(updates.Select(d => d.Task).ToArray()); } catch (OperationCanceledException) { // Tasks were cancelled, which probably means we are closing. // In this case, _timer will be disposed before the next update. } } if (Interlocked.Decrement(ref _listenerTimeToLive) == 0) { // It's time to reset the listener. We do this periodically in // case the global mutex has become abandoned. By releasing our // handle, it should go away and any errors (which may be caused // by users killing the analyzer) become transient rather than // permanent. // Because we are currently on the listener's thread, we need to // recreate on a separate thread so that this one can terminate. Task.Run((Action)CreateListener) .HandleAllExceptions(Properties.Resources.PythonToolsForVisualStudio) .DoNotWait(); } }
public static async Task <int> GenerateAsync(PythonTypeDatabaseCreationRequest request) { var fact = request.Factory; var evt = request.OnExit; if (fact == null || !Directory.Exists(fact.Configuration.LibraryPath)) { if (evt != null) { evt(NotSupportedExitCode); } return(NotSupportedExitCode); } var outPath = request.OutputPath; var analyzerPath = PythonToolsInstallPath.GetFile("Microsoft.PythonTools.Analyzer.exe"); Directory.CreateDirectory(CompletionDatabasePath); var baseDb = BaselineDatabasePath; if (request.ExtraInputDatabases.Any()) { baseDb = baseDb + ";" + string.Join(";", request.ExtraInputDatabases); } var logPath = Path.Combine(outPath, "AnalysisLog.txt"); var glogPath = Path.Combine(CompletionDatabasePath, "AnalysisLog.txt"); using (var output = ProcessOutput.RunHiddenAndCapture( analyzerPath, "/id", fact.Configuration.Id, "/version", fact.Configuration.Version.ToString(), "/python", fact.Configuration.InterpreterPath, request.DetectLibraryPath ? null : "/library", request.DetectLibraryPath ? null : fact.Configuration.LibraryPath, "/outdir", outPath, "/basedb", baseDb, (request.SkipUnchanged ? null : "/all"), // null will be filtered out; empty strings are quoted "/log", logPath, "/glog", glogPath, "/wait", (request.WaitFor != null ? AnalyzerStatusUpdater.GetIdentifier(request.WaitFor) : "") )) { output.PriorityClass = ProcessPriorityClass.BelowNormal; int exitCode = await output; if (exitCode > -10 && exitCode < 0) { try { File.AppendAllLines( glogPath, new[] { string.Format("FAIL_STDLIB: ({0}) {1}", exitCode, output.Arguments) } .Concat(output.StandardErrorLines) ); } catch (IOException) { } catch (ArgumentException) { } catch (SecurityException) { } catch (UnauthorizedAccessException) { } } if (evt != null) { evt(exitCode); } return(exitCode); } }
public void RefreshDBStates() { using (var fact = new MockPythonInterpreterFactory( Guid.NewGuid(), "Test Factory 1", MockInterpreterConfiguration( PythonPaths.Versions.First().InterpreterPath ), true )) using (var wpf = new WpfProxy()) using (var list = new EnvironmentListProxy(wpf)) { list.CreateDBExtension = true; var mockService = new MockInterpreterOptionsService(); mockService.AddProvider(new MockPythonInterpreterFactoryProvider("Test Provider 1", fact)); list.Service = mockService; var view = list.Environments.Single(); Assert.IsFalse(wpf.Invoke(() => view.IsRefreshingDB)); Assert.IsTrue(list.CanExecute(DBExtension.StartRefreshDB, view)); Assert.IsFalse(fact.IsCurrent); Assert.AreEqual(MockPythonInterpreterFactory.NoDatabaseReason, fact.GetIsCurrentReason(null)); list.Execute(DBExtension.StartRefreshDB, view).GetAwaiter().GetResult(); for (int retries = 10; retries > 0 && !wpf.Invoke(() => view.IsRefreshingDB); --retries) { Thread.Sleep(200); } Assert.IsTrue(wpf.Invoke(() => view.IsRefreshingDB)); Assert.IsFalse(list.CanExecute(DBExtension.StartRefreshDB, view)); Assert.IsFalse(fact.IsCurrent); Assert.AreEqual(MockPythonInterpreterFactory.GeneratingReason, fact.GetIsCurrentReason(null)); fact.EndGenerateCompletionDatabase(AnalyzerStatusUpdater.GetIdentifier(fact), false); for (int retries = 10; retries > 0 && wpf.Invoke(() => view.IsRefreshingDB); --retries) { Thread.Sleep(1000); } Assert.IsFalse(wpf.Invoke(() => view.IsRefreshingDB)); Assert.IsTrue(list.CanExecute(DBExtension.StartRefreshDB, view)); Assert.IsFalse(fact.IsCurrent); Assert.AreEqual(MockPythonInterpreterFactory.MissingModulesReason, fact.GetIsCurrentReason(null)); list.Execute(DBExtension.StartRefreshDB, view).GetAwaiter().GetResult(); Assert.IsTrue(wpf.Invoke(() => view.IsRefreshingDB)); Assert.IsFalse(list.CanExecute(DBExtension.StartRefreshDB, view)); Assert.IsFalse(fact.IsCurrent); Assert.AreEqual(MockPythonInterpreterFactory.GeneratingReason, fact.GetIsCurrentReason(null)); fact.EndGenerateCompletionDatabase(AnalyzerStatusUpdater.GetIdentifier(fact), true); for (int retries = 10; retries > 0 && wpf.Invoke(() => view.IsRefreshingDB); --retries) { Thread.Sleep(1000); } Assert.IsFalse(wpf.Invoke(() => view.IsRefreshingDB)); Assert.IsTrue(list.CanExecute(DBExtension.StartRefreshDB, view)); Assert.IsTrue(fact.IsCurrent); Assert.AreEqual(MockPythonInterpreterFactory.UpToDateReason, fact.GetIsCurrentReason(null)); Assert.AreEqual(MockPythonInterpreterFactory.UpToDateReason, fact.GetIsCurrentReason(null)); } }