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;
     }
 }
Example #3
0
        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);
     }
 }
Example #5
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) {
                    }
                }
            }
        }
Example #6
0
        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();
        }
Example #7
0
        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");
                }
        }
Example #8
0
        public void InitializeWithoutCrashing()
        {
            using (var updater = new AnalyzerStatusUpdater("InitializeWithoutCrashing")) { }

            using (var updater = new AnalyzerStatusListener(x => { })) { }
        }
Example #9
0
        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();
            }
        }
Example #10
0
        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);
            }
        }
Example #11
0
        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));
                    }
        }