Exemple #1
0
        /// <inheritdoc/>
        public void AddAttachment(FileTransferInformation fileTransferInfo, AsyncCompletedEventHandler sendFileCompletedCallback, Uri uri, string friendlyName)
        {
            ValidateArg.NotNull(fileTransferInfo, nameof(fileTransferInfo));

            if (string.IsNullOrEmpty(this.SessionOutputDirectory))
            {
                if (EqtTrace.IsErrorEnabled)
                {
                    EqtTrace.Error(
                        "DataCollectionAttachmentManager.AddAttachment: Initialize not invoked.");
                }

                return;
            }

            if (!this.AttachmentSets.ContainsKey(fileTransferInfo.Context))
            {
                var uriAttachmentSetMap = new Dictionary <Uri, AttachmentSet>();
                this.AttachmentSets.Add(fileTransferInfo.Context, uriAttachmentSetMap);
                this.attachmentTasks.Add(fileTransferInfo.Context, new List <Task>());
            }

            if (!this.AttachmentSets[fileTransferInfo.Context].ContainsKey(uri))
            {
                this.AttachmentSets[fileTransferInfo.Context].Add(uri, new AttachmentSet(uri, friendlyName));
            }

            this.AddNewFileTransfer(fileTransferInfo, sendFileCompletedCallback, uri, friendlyName);
        }
        public void GetAttachmentsShouldNotReturnAttachmentsAfterCancelled()
        {
            var fileHelper = new Mock <IFileHelper>();
            var testableAttachmentManager = new TestableDataCollectionAttachmentManager(fileHelper.Object);
            var attachmentPath            = Path.Combine(TempDirectoryPath, "filename.txt");

            File.WriteAllText(attachmentPath, string.Empty);
            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri = new Uri("datacollector://Company/Product/Version");
            var dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, attachmentPath, true);
            var waitHandle = new AutoResetEvent(false);
            var handler    = new AsyncCompletedEventHandler((a, e) => { Assert.Fail("Handler shouldn't be called since operation is canceled."); });

            // We cancel the operation in the actual operation. This ensures the follow up task to is never called, attachments
            // are not added.
            Action cancelAddAttachment = () => testableAttachmentManager.Cancel();

            fileHelper.Setup(fh => fh.MoveFile(It.IsAny <string>(), It.IsAny <string>())).Callback(cancelAddAttachment);
            testableAttachmentManager.Initialize(this.sessionId, TempDirectoryPath, this.messageSink.Object);
            testableAttachmentManager.AddAttachment(dataCollectorDataMessage, handler, uri, friendlyName);

            // Wait for the attachment transfer tasks to complete
            var result = testableAttachmentManager.GetAttachments(datacollectioncontext);

            Assert.AreEqual(0, result[0].Attachments.Count);
        }
        public void GetAttachmentsShouldReturnAllAttachmets()
        {
            var filename = "filename1.txt";

            File.WriteAllText(Path.Combine(TempDirectoryPath, filename), string.Empty);

            this.attachmentManager.Initialize(this.sessionId, TempDirectoryPath, this.messageSink.Object);

            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri = new Uri("datacollector://Company/Product/Version");

            var dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(TempDirectoryPath, filename), true);

            this.attachmentManager.AddAttachment(dataCollectorDataMessage, null, uri, friendlyName);

            Assert.AreEqual(1, this.attachmentManager.AttachmentSets.Count);
            var result = this.attachmentManager.GetAttachments(datacollectioncontext);

            Assert.AreEqual(0, this.attachmentManager.AttachmentSets.Count);
            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(friendlyName, result[0].DisplayName);
            Assert.AreEqual(uri, result[0].Uri);
            Assert.AreEqual(1, result[0].Attachments.Count);
        }
Exemple #4
0
        public override string tryGetFileFromGuest(string srcpath, out Exception errorOrNull)
        {
            try
            {
                NamePasswordAuthentication Auth = new NamePasswordAuthentication
                {
                    Username           = _spec.kernelVMUsername,
                    Password           = _spec.kernelVMPassword,
                    InteractiveSession = true
                };

                VimClientImpl  vClient      = conn.getConnection();
                VirtualMachine underlyingVM = conn.getMachine();

                GuestOperationsManager gom = (GuestOperationsManager)vClient.GetView(vClient.ServiceContent.GuestOperationsManager, null);
                GuestAuthManager       guestAuthManager = vClient.GetView(gom.AuthManager, null) as GuestAuthManager;
                guestAuthManager.ValidateCredentialsInGuest(underlyingVM.MoRef, Auth);
                GuestFileManager GFM = vClient.GetView(gom.FileManager, null) as GuestFileManager;

                FileTransferInformation transferOutput = GFM.InitiateFileTransferFromGuest(underlyingVM.MoRef, Auth, srcpath);
                string nodeIpAddress = vClient.ServiceUrl;
                nodeIpAddress = nodeIpAddress.Remove(nodeIpAddress.LastIndexOf('/'));
                string url = transferOutput.Url.Replace("https://*", nodeIpAddress);
                using (WebClient webClient = new WebClient())
                {
                    errorOrNull = null;
                    return(webClient.DownloadString(url));
                }
            }
            catch (Exception e)
            {
                errorOrNull = e;
                return(null);
            }
        }
        public void AddAttachmentShouldAddNewFileTransferAndCopyFileToOutputDirectoryIfDeleteFileIsFalse()
        {
            var filename = "filename.txt";

            File.WriteAllText(Path.Combine(TempDirectoryPath, filename), string.Empty);


            this.attachmentManager.Initialize(this.sessionId, TempDirectoryPath, this.messageSink.Object);

            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri = new Uri("datacollector://Company/Product/Version");

            EventWaitHandle waitHandle = new AutoResetEvent(false);
            var             handler    = new AsyncCompletedEventHandler((a, e) => { waitHandle.Set(); });
            var             dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(TempDirectoryPath, filename), false);


            this.attachmentManager.AddAttachment(dataCollectorDataMessage, handler, uri, friendlyName);

            // Wait for file operations to complete
            waitHandle.WaitOne(Timeout);

            Assert.IsTrue(File.Exists(Path.Combine(TempDirectoryPath, filename)));
            Assert.IsTrue(File.Exists(Path.Combine(TempDirectoryPath, this.sessionId.Id.ToString(), filename)));
            Assert.AreEqual(1, this.attachmentManager.AttachmentSets[datacollectioncontext][uri].Attachments.Count);
        }
        public void AddAttachmentsShouldAddFilesCorrespondingToDifferentDataCollectors()
        {
            var filename  = "filename.txt";
            var filename1 = "filename1.txt";

            File.WriteAllText(Path.Combine(TempDirectoryPath, filename), string.Empty);
            File.WriteAllText(Path.Combine(TempDirectoryPath, filename1), string.Empty);

            this.attachmentManager.Initialize(this.sessionId, TempDirectoryPath, this.messageSink.Object);

            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri  = new Uri("datacollector://Company/Product/Version");
            var uri1 = new Uri("datacollector://Company/Product/Version1");

            EventWaitHandle waitHandle = new AutoResetEvent(false);
            var             handler    = new AsyncCompletedEventHandler((a, e) => { waitHandle.Set(); });
            var             dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(TempDirectoryPath, filename), false);

            this.attachmentManager.AddAttachment(dataCollectorDataMessage, handler, uri, friendlyName);

            // Wait for file operations to complete
            waitHandle.WaitOne(Timeout);

            waitHandle.Reset();
            dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(TempDirectoryPath, filename1), false);
            this.attachmentManager.AddAttachment(dataCollectorDataMessage, handler, uri1, friendlyName);

            // Wait for file operations to complete
            waitHandle.WaitOne(Timeout);

            Assert.AreEqual(1, this.attachmentManager.AttachmentSets[datacollectioncontext][uri].Attachments.Count);
            Assert.AreEqual(1, this.attachmentManager.AttachmentSets[datacollectioncontext][uri1].Attachments.Count);
        }
Exemple #7
0
        /// <inheritdoc/>
        public void AddAttachment(FileTransferInformation fileTransferInfo, AsyncCompletedEventHandler sendFileCompletedCallback, Uri uri, string friendlyName)
        {
            ValidateArg.NotNull(fileTransferInfo, nameof(fileTransferInfo));

            if (string.IsNullOrEmpty(this.SessionOutputDirectory))
            {
                if (EqtTrace.IsErrorEnabled)
                {
                    EqtTrace.Error(
                        "DataCollectionAttachmentManager.AddAttachment: Initialize not invoked.");
                }

                return;
            }

            if (!this.AttachmentSets.ContainsKey(uri))
            {
                this.AttachmentSets.Add(uri, new AttachmentSet(uri, friendlyName));
            }

            if (fileTransferInfo != null)
            {
                this.AddNewFileTransfer(fileTransferInfo, sendFileCompletedCallback, uri, friendlyName);
            }
            else
            {
                if (EqtTrace.IsErrorEnabled)
                {
                    EqtTrace.Error("DataCollectionAttachmentManager.AddAttachment: Got unexpected message of type FileTransferInformationExtension.");
                }
            }
        }
        public void SendFileAsyncShouldInvokeSendFileCompletedIfRegistered()
        {
            var filename = Path.Combine(AppContext.BaseDirectory, "filename.txt");

            File.WriteAllText(filename, string.Empty);

            var guid      = Guid.NewGuid();
            var sessionId = new SessionId(guid);
            var context   = new DataCollectionContext(sessionId);

            var fileTransferInfo = new FileTransferInformation(context, filename, false);

            var attachmentManager = new DataCollectionAttachmentManager();

            attachmentManager.Initialize(sessionId, AppContext.BaseDirectory, new Mock <IMessageSink>().Object);

            this.dataCollectionSink = new TestPlatformDataCollectionSink(attachmentManager, this.dataCollectorConfig);
            this.dataCollectionSink.SendFileCompleted += SendFileCompleted_Handler;
            this.dataCollectionSink.SendFileAsync(fileTransferInfo);

            var result = attachmentManager.GetAttachments(context);

            Assert.IsNotNull(result);
            Assert.IsTrue(this.isEventHandlerInvoked);
        }
        /// <summary>
        /// Disposes of the timer when called to prevent further calls.
        /// Kills the other instance of procdump if launched for collecting trigger based dumps.
        /// Starts and waits for a new proc dump process to collect a single dump and then
        /// kills the testhost process.
        /// </summary>
        private void CollectDumpAndAbortTesthost()
        {
            EqtTrace.Info(string.Format(CultureInfo.CurrentUICulture, Resources.Resources.InactivityTimeout, (int)this.inactivityTimespan.TotalMinutes));
            this.inactivityTimerAlreadyFired = true;

            try
            {
                EqtTrace.Verbose("Calling dispose on Inactivity timer.");
                this.inactivityTimer.Dispose();
            }
            catch
            {
                EqtTrace.Verbose("Inactivity timer is already disposed.");
            }

            if (this.collectProcessDumpOnTrigger)
            {
                // Detach procdump from the testhost process to prevent testhost process from crashing
                // if/when we try to kill the existing proc dump process.
                this.processDumpUtility.DetachFromTargetProcess(this.testHostProcessId);
            }

            try
            {
                this.processDumpUtility.StartHangBasedProcessDump(this.testHostProcessId, this.attachmentGuid, this.GetResultsDirectory(), this.processFullDumpEnabled);
            }
            catch (Exception ex)
            {
                EqtTrace.Error($"BlameCollector.CollectDumpAndAbortTesthost: Failed with error {ex}");
            }

            try
            {
                var dumpFile = this.processDumpUtility.GetDumpFile();
                if (!string.IsNullOrEmpty(dumpFile))
                {
                    var fileTransferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true, this.fileHelper);
                    this.dataCollectionSink.SendFileAsync(fileTransferInformation);
                }
                else
                {
                    EqtTrace.Error("BlameCollector.CollectDumpAndAbortTesthost: blame:CollectDumpOnHang was enabled but dump file was not generated.");
                }
            }
            catch (Exception ex)
            {
                // Eat up any exception here and log it but proceed with killing the test host process.
                EqtTrace.Error(ex);
            }

            try
            {
                Process.GetProcessById(this.testHostProcessId).Kill();
            }
            catch (Exception ex)
            {
                EqtTrace.Error(ex);
            }
        }
 public override void SendFileAsync(FileTransferInformation fileTransferInformation)
 {
     this.IsSendFileAsyncInvoked = true;
     if (this.SendFileCompleted == null)
     {
         return;
     }
 }
        /// <summary>
        /// Sends a file asynchronously.
        /// </summary>
        /// <param name="fileTransferInformation">Information about the file being transferred.</param>
        public override void SendFileAsync(FileTransferInformation fileTransferInformation)
        {
            ValidateArg.NotNull(fileTransferInformation, "fileTransferInformation");

            Debug.Assert(System.IO.File.Exists(fileTransferInformation.Path), "DataCollector file '" + fileTransferInformation.Path + "' does not exist!");

            this.AttachmentManager.AddAttachment(fileTransferInformation, this.SendFileCompleted, this.DataCollectorConfig.TypeUri, this.DataCollectorConfig.FriendlyName);
        }
        /// <summary>
        /// Called when Session End event is invoked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">SessionEndEventArgs</param>
        private void SessionEnded_Handler(object sender, SessionEndEventArgs args)
        {
            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("Blame Collector : Session End");
            }

            try
            {
                // If the last test crashes, it will not invoke a test case end and therefore
                // In case of crash testStartCount will be greater than testEndCount and we need to write the sequence
                // And send the attachment
                if (this.testStartCount > this.testEndCount)
                {
                    var filepath = Path.Combine(this.GetResultsDirectory(), Constants.AttachmentFileName + "_" + this.attachmentGuid);
                    filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, this.testObjectDictionary, filepath);
                    var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true);
                    this.dataCollectionSink.SendFileAsync(fileTranferInformation);
                }

                if (this.processDumpEnabled)
                {
                    // If there was a test case crash or if we need to collect dump on process exit.
                    if (this.testStartCount > this.testEndCount || this.collectDumpAlways)
                    {
                        try
                        {
                            var dumpFile = this.processDumpUtility.GetDumpFile();
                            if (!string.IsNullOrEmpty(dumpFile))
                            {
                                var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true);
                                this.dataCollectionSink.SendFileAsync(fileTranferInformation);
                            }
                            else
                            {
                                EqtTrace.Warning("BlameCollector.SessionEnded_Handler: blame:CollectDump was enabled but dump file was not generated.");
                                this.logger.LogWarning(args.Context, Resources.Resources.ProcDumpNotGenerated);
                            }
                        }
                        catch (FileNotFoundException ex)
                        {
                            EqtTrace.Warning(ex.Message);
                            this.logger.LogWarning(args.Context, ex.Message);
                        }
                    }
                }
            }
            finally
            {
                // Attempt to terminate the proc dump process if proc dump was enabled
                if (this.processDumpEnabled)
                {
                    this.processDumpUtility.TerminateProcess();
                }

                this.DeregisterEvents();
            }
        }
Exemple #13
0
        public void FileTransferFromGuest(string guestFilePath, string localFilePath)
        {
            //throw new NotImplementedException();
            FileTransferInformation fti = _vimService.InitiateFileTransferFromGuest(
                _morFileManager,             //VimLib.VimServiceReference.ManagedObjectReference _this,
                _morVM,                      //VimLib.VimServiceReference.ManagedObjectReference vm,
                _NamePasswordAuthentication, //VimLib.VimServiceReference.GuestAuthentication auth,
                guestFilePath
                );
            WebClient webClient = new WebClient();

            webClient.DownloadFile(fti.url, localFilePath);
        }
        public void SendFileAsyncShouldInvokeAttachmentManagerWithValidFileTransferInfo()
        {
            var filename = Path.Combine(AppContext.BaseDirectory, "filename.txt");

            File.WriteAllText(filename, string.Empty);

            var guid      = Guid.NewGuid();
            var sessionId = new SessionId(guid);
            var context   = new DataCollectionContext(sessionId);

            var fileTransferInfo = new FileTransferInformation(context, filename, false);

            this.dataCollectionSink.SendFileAsync(fileTransferInfo);

            this.attachmentManager.Verify(x => x.AddAttachment(It.IsAny <FileTransferInformation>(), It.IsAny <AsyncCompletedEventHandler>(), It.IsAny <Uri>(), It.IsAny <string>()), Times.Once());
        }
        public void AddAttachmentShouldNotAddNewFileTransferIfSessionIsNotConfigured()
        {
            var filename = "filename.txt";

            File.WriteAllText(Path.Combine(TempDirectoryPath, filename), string.Empty);

            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri = new Uri("datacollector://Company/Product/Version");

            var dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(TempDirectoryPath, filename), false);

            this.attachmentManager.AddAttachment(dataCollectorDataMessage, null, uri, friendlyName);

            Assert.AreEqual(this.attachmentManager.AttachmentSets.Count, 0);
        }
Exemple #16
0
        /// <summary>
        /// Called when Session End event is invoked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">SessionEndEventArgs</param>
        private void SessionEnded_Handler(object sender, SessionEndEventArgs args)
        {
            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("Blame Collector : Session End");
            }

            // If the last test crashes, it will not invoke a test case end and therefore
            // In case of crash testStartCount will be greater than testEndCount and we need to write the sequence
            // And send the attachment
            if (this.testStartCount > this.testEndCount)
            {
                var filepath = Path.Combine(this.GetResultsDirectory(), Constants.AttachmentFileName);
                filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, filepath);
                var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true);
                this.dataCollectionSink.SendFileAsync(fileTranferInformation);
            }

            this.DeregisterEvents();
        }
Exemple #17
0
        /// <summary>
        /// Sanity checks on CopyRequestData
        /// </summary>
        /// <param name="fileTransferInfo">
        /// The file Transfer Info.
        /// </param>
        /// <param name="localFilePath">
        /// The local File Path.
        /// </param>
        private static void Validate(FileTransferInformation fileTransferInfo, string localFilePath)
        {
            if (!File.Exists(fileTransferInfo.FileName))
            {
                throw new FileNotFoundException(
                          string.Format(
                              CultureInfo.CurrentCulture,
                              "Could not find source file '{0}'.",
                              fileTransferInfo.FileName));
            }

            var directoryName = Path.GetDirectoryName(localFilePath);

            if (!Directory.Exists(directoryName))
            {
                Directory.CreateDirectory(directoryName);
            }
            else if (File.Exists(localFilePath))
            {
                File.Delete(localFilePath);
            }
        }
        public void GetAttachmentsShouldNotReturnAttachmentsAfterCancelled()
        {
            var filename = "filename1.txt";

            File.WriteAllText(Path.Combine(AppContext.BaseDirectory, filename), string.Empty);

            this.attachmentManager.Initialize(this.sessionId, AppContext.BaseDirectory, this.messageSink.Object);

            var datacollectioncontext = new DataCollectionContext(this.sessionId);
            var friendlyName          = "TestDataCollector";
            var uri = new Uri("datacollector://Company/Product/Version");

            var dataCollectorDataMessage = new FileTransferInformation(datacollectioncontext, Path.Combine(AppContext.BaseDirectory, filename), true);

            this.attachmentManager.AddAttachment(dataCollectorDataMessage, null, uri, friendlyName);

            this.attachmentManager.Cancel();

            var result = this.attachmentManager.GetAttachments(datacollectioncontext);

            Assert.AreEqual(0, result[0].Attachments.Count);
        }
Exemple #19
0
        /// <summary>
        /// Add a new file transfer (either copy/move) request.
        /// </summary>
        /// <param name="fileTransferInfo">
        /// The file Transfer Info.
        /// </param>
        /// <param name="sendFileCompletedCallback">
        /// The send File Completed Callback.
        /// </param>
        /// <param name="uri">
        /// The uri.
        /// </param>
        /// <param name="friendlyName">
        /// The friendly Name.
        /// </param>
        private void AddNewFileTransfer(FileTransferInformation fileTransferInfo, AsyncCompletedEventHandler sendFileCompletedCallback, Uri uri, string friendlyName)
        {
            var context = fileTransferInfo.Context;

            Debug.Assert(
                context != null,
                "DataCollectionManager.AddNewFileTransfer: FileDataHeaderMessage with null context.");

            var testCaseId = fileTransferInfo.Context.HasTestCase
                                 ? fileTransferInfo.Context.TestExecId.Id.ToString()
                                 : string.Empty;

            var directoryPath = Path.Combine(
                this.SessionOutputDirectory,
                testCaseId);
            var localFilePath = Path.Combine(directoryPath, Path.GetFileName(fileTransferInfo.FileName));

            var task = Task.Factory.StartNew(
                () =>
            {
                Validate(fileTransferInfo, localFilePath);

                if (this.cancellationTokenSource.Token.IsCancellationRequested)
                {
                    this.cancellationTokenSource.Token.ThrowIfCancellationRequested();
                }

                try
                {
                    if (fileTransferInfo.PerformCleanup)
                    {
                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Moving file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }

                        File.Move(fileTransferInfo.FileName, localFilePath);

                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Moved file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }
                    }
                    else
                    {
                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Copying file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }

                        File.Copy(fileTransferInfo.FileName, localFilePath);

                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Copied file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.LogError(
                        ex.Message,
                        uri,
                        friendlyName,
                        Guid.Parse(testCaseId));

                    throw;
                }
            },
                this.cancellationTokenSource.Token);

            var continuationTask = task.ContinueWith(
                (t) =>
            {
                try
                {
                    if (t.Exception == null)
                    {
                        this.AttachmentSets[uri].Attachments.Add(new UriDataAttachment(new Uri(localFilePath), fileTransferInfo.Description));
                    }

                    if (sendFileCompletedCallback != null)
                    {
                        sendFileCompletedCallback(this, new AsyncCompletedEventArgs(t.Exception, false, fileTransferInfo.UserToken));
                    }
                }
                catch (Exception e)
                {
                    if (EqtTrace.IsErrorEnabled)
                    {
                        EqtTrace.Error(
                            "DataCollectionAttachmentManager.TriggerCallBack: Error occurred while raising the file transfer completed callback for {0}. Error: {1}",
                            localFilePath,
                            e.ToString());
                    }
                }
            },
                this.cancellationTokenSource.Token);

            this.attachmentTasks.Add(continuationTask);
        }
Exemple #20
0
        /// <summary>
        /// Called when Session End event is invoked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">SessionEndEventArgs</param>
        private void SessionEndedHandler(object sender, SessionEndEventArgs args)
        {
            this.ResetInactivityTimer();

            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("Blame Collector : Session End");
            }

            try
            {
                // If the last test crashes, it will not invoke a test case end and therefore
                // In case of crash testStartCount will be greater than testEndCount and we need to write the sequence
                // And send the attachment
                if (this.testStartCount > this.testEndCount)
                {
                    var filepath = Path.Combine(this.GetTempDirectory(), Constants.AttachmentFileName + "_" + this.attachmentGuid);

                    filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, this.testObjectDictionary, filepath);
                    var fti = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true);
                    this.dataCollectionSink.SendFileAsync(fti);
                }
                else
                {
                    if (this.collectProcessDumpOnTestHostHang)
                    {
                        this.logger.LogWarning(this.context.SessionDataCollectionContext, Resources.Resources.NotGeneratingSequenceFile);
                    }
                }

                if (this.uploadDumpFiles)
                {
                    try
                    {
                        var dumpFiles = this.processDumpUtility.GetDumpFiles(warnOnNoDumpFiles: this.collectDumpAlways);
                        foreach (var dumpFile in dumpFiles)
                        {
                            if (!string.IsNullOrEmpty(dumpFile))
                            {
                                try
                                {
                                    var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true);
                                    this.dataCollectionSink.SendFileAsync(fileTranferInformation);
                                }
                                catch (FileNotFoundException ex)
                                {
                                    EqtTrace.Warning(ex.ToString());
                                    this.logger.LogWarning(args.Context, ex.ToString());
                                }
                            }
                        }
                    }
                    catch (FileNotFoundException ex)
                    {
                        EqtTrace.Warning(ex.ToString());
                        this.logger.LogWarning(args.Context, ex.ToString());
                    }
                }
                else
                {
                    EqtTrace.Info("BlameCollector.CollectDumpAndAbortTesthost: Custom path to dump directory was provided via VSTEST_DUMP_PATH. Skipping attachment upload, the caller is responsible for collecting and uploading the dumps themselves.");
                }
            }
            finally
            {
                // Attempt to terminate the proc dump process if proc dump was enabled
                if (this.collectProcessDumpOnTrigger)
                {
                    this.processDumpUtility.DetachFromTargetProcess(this.testHostProcessId);
                }

                this.DeregisterEvents();
            }
        }
Exemple #21
0
        /// <summary>
        /// Disposes of the timer when called to prevent further calls.
        /// Kills the other instance of proc dump if launched for collecting trigger based dumps.
        /// Starts and waits for a new proc dump process to collect a single dump and then
        /// kills the testhost process.
        /// </summary>
        private void CollectDumpAndAbortTesthost()
        {
            this.inactivityTimerAlreadyFired = true;

            string value;
            string unit;

            if (this.inactivityTimespan.TotalSeconds <= 90)
            {
                value = ((int)this.inactivityTimespan.TotalSeconds).ToString();
                unit  = Resources.Resources.Seconds;
            }
            else
            {
                value = Math.Round(this.inactivityTimespan.TotalMinutes, 2).ToString();
                unit  = Resources.Resources.Minutes;
            }

            var message = string.Format(CultureInfo.CurrentUICulture, Resources.Resources.InactivityTimeout, value, unit);

            EqtTrace.Warning(message);
            this.logger.LogWarning(this.context.SessionDataCollectionContext, message);

            try
            {
                EqtTrace.Verbose("Calling dispose on Inactivity timer.");
                this.inactivityTimer.Dispose();
            }
            catch
            {
                EqtTrace.Verbose("Inactivity timer is already disposed.");
            }

            try
            {
                Action <string> logWarning    = m => this.logger.LogWarning(this.context.SessionDataCollectionContext, m);
                var             dumpDirectory = this.GetDumpDirectory();
                this.processDumpUtility.StartHangBasedProcessDump(this.testHostProcessId, dumpDirectory, this.processFullDumpEnabled, this.targetFramework, logWarning);
            }
            catch (Exception ex)
            {
                this.logger.LogError(this.context.SessionDataCollectionContext, $"Blame: Creating hang dump failed with error.", ex);
            }

            if (this.collectProcessDumpOnTrigger)
            {
                // Detach procdump from the testhost process to prevent testhost process from crashing
                // if/when we try to kill the existing proc dump process.
                this.processDumpUtility.DetachFromTargetProcess(this.testHostProcessId);
            }

            if (this.uploadDumpFiles)
            {
                try
                {
                    var dumpFiles = this.processDumpUtility.GetDumpFiles();
                    foreach (var dumpFile in dumpFiles)
                    {
                        try
                        {
                            if (!string.IsNullOrEmpty(dumpFile))
                            {
                                var fileTransferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true, this.fileHelper);
                                this.dataCollectionSink.SendFileAsync(fileTransferInformation);
                            }
                        }
                        catch (Exception ex)
                        {
                            // Eat up any exception here and log it but proceed with killing the test host process.
                            EqtTrace.Error(ex);
                        }

                        if (!dumpFiles.Any())
                        {
                            EqtTrace.Error("BlameCollector.CollectDumpAndAbortTesthost: blame:CollectDumpOnHang was enabled but dump file was not generated.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.logger.LogError(this.context.SessionDataCollectionContext, $"Blame: Collecting hang dump failed with error.", ex);
                }
            }
            else
            {
                EqtTrace.Info("BlameCollector.CollectDumpAndAbortTesthost: Custom path to dump directory was provided via VSTEST_DUMP_PATH. Skipping attachment upload, the caller is responsible for collecting and uploading the dumps themselves.");
            }

            try
            {
                var p = Process.GetProcessById(this.testHostProcessId);
                try
                {
                    if (!p.HasExited)
                    {
                        p.Kill();
                    }
                }
                catch (InvalidOperationException)
                {
                }
            }
            catch (Exception ex)
            {
                EqtTrace.Error(ex);
            }
        }
        /// <summary>
        /// The write event logs.
        /// </summary>
        /// <param name="eventLogEntries">
        /// The event log entries.
        /// </param>
        /// <param name="maxLogEntries">
        /// Max Log Entries.
        /// </param>
        /// <param name="dataCollectionContext">
        /// The data collection context.
        /// </param>
        /// <param name="requestedDuration">
        /// The requested duration.
        /// </param>
        /// <param name="timeRequestReceived">
        /// The time request received.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        internal string WriteEventLogs(List <EventLogEntry> eventLogEntries, int maxLogEntries, DataCollectionContext dataCollectionContext, TimeSpan requestedDuration, DateTime timeRequestReceived)
        {
            // Generate a unique but friendly Directory name in the temp directory
            string eventLogDirName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}-{1}-{2:yyyy}{2:MM}{2:dd}-{2:HH}{2:mm}{2:ss}.{2:fff}",
                "Event Log",
                Environment.MachineName,
                DateTime.Now);

            string eventLogDirPath = Path.Combine(Path.GetTempPath(), eventLogDirName);

            // Create the directory
            this.fileHelper.CreateDirectory(eventLogDirPath);

            string eventLogBasePath    = Path.Combine(eventLogDirPath, EventLogFileName);
            bool   unusedFilenameFound = false;

            string eventLogPath = eventLogBasePath + ".xml";

            if (this.fileHelper.Exists(eventLogPath))
            {
                for (int i = 1; !unusedFilenameFound; i++)
                {
                    eventLogPath = eventLogBasePath + "-" + i.ToString(CultureInfo.InvariantCulture) + ".xml";

                    if (!this.fileHelper.Exists(eventLogPath))
                    {
                        unusedFilenameFound = true;
                    }
                }
            }

            DateTime minDate = DateTime.MinValue;

            // Limit entries to a certain time range if requested
            if (requestedDuration < TimeSpan.MaxValue)
            {
                try
                {
                    minDate = timeRequestReceived - requestedDuration;
                }
                catch (ArgumentOutOfRangeException)
                {
                    minDate = DateTime.MinValue;
                }
            }

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            EventLogXmlWriter.WriteEventLogEntriesToXmlFile(
                eventLogPath,
                eventLogEntries.Where(
                    entry => entry.TimeGenerated > minDate && entry.TimeGenerated < DateTime.MaxValue).OrderBy(x => x.TimeGenerated).ToList().Take(maxLogEntries).ToList(),
                this.fileHelper);

            stopwatch.Stop();

            if (EqtTrace.IsVerboseEnabled)
            {
                EqtTrace.Verbose(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "EventLogDataContainer: Wrote {0} event log entries to file '{1}' in {2} seconds",
                        eventLogEntries.Count,
                        eventLogPath,
                        stopwatch.Elapsed.TotalSeconds.ToString(CultureInfo.InvariantCulture)));
            }

            // Write the event log file
            FileTransferInformation fileTransferInformation =
                new FileTransferInformation(dataCollectionContext, eventLogPath, true, this.fileHelper);

            this.dataSink.SendFileAsync(fileTransferInformation);

            if (EqtTrace.IsVerboseEnabled)
            {
                EqtTrace.Verbose(
                    "EventLogDataContainer: Event log successfully sent for data collection context '{0}'.",
                    dataCollectionContext.ToString());
            }

            return(eventLogPath);
        }
 void IDataCollectionSink.SendFileAsync(FileTransferInformation fileInformation)
 {
     this.wrapped.SendFileAsync(fileInformation);
 }
        /// <summary>
        /// Add a new file transfer (either copy/move) request.
        /// </summary>
        /// <param name="fileTransferInfo">
        /// The file Transfer Info.
        /// </param>
        /// <param name="sendFileCompletedCallback">
        /// The send File Completed Callback.
        /// </param>
        /// <param name="uri">
        /// The uri.
        /// </param>
        /// <param name="friendlyName">
        /// The friendly Name.
        /// </param>
        private void AddNewFileTransfer(FileTransferInformation fileTransferInfo, AsyncCompletedEventHandler sendFileCompletedCallback, Uri uri, string friendlyName)
        {
            var context = fileTransferInfo.Context;

            Debug.Assert(
                context != null,
                "DataCollectionManager.AddNewFileTransfer: FileDataHeaderMessage with null context.");

            var testCaseId = fileTransferInfo.Context.HasTestCase
                                 ? fileTransferInfo.Context.TestExecId.Id.ToString()
                                 : string.Empty;

            var directoryPath = Path.Combine(
                this.SessionOutputDirectory,
                testCaseId);
            var localFilePath = Path.Combine(directoryPath, Path.GetFileName(fileTransferInfo.FileName));

            var task = Task.Factory.StartNew(
                () =>
            {
                Validate(fileTransferInfo, localFilePath);

                if (this.cancellationTokenSource.Token.IsCancellationRequested)
                {
                    this.cancellationTokenSource.Token.ThrowIfCancellationRequested();
                }

                try
                {
                    if (fileTransferInfo.PerformCleanup)
                    {
                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Moving file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }

                        this.fileHelper.MoveFile(fileTransferInfo.FileName, localFilePath);

                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Moved file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }
                    }
                    else
                    {
                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Copying file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }

                        this.fileHelper.CopyFile(fileTransferInfo.FileName, localFilePath);

                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info("DataCollectionAttachmentManager.AddNewFileTransfer : Copied file {0} to {1}", fileTransferInfo.FileName, localFilePath);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.LogError(
                        ex.ToString(),
                        uri,
                        friendlyName,
                        Guid.Parse(testCaseId));

                    throw;
                }
            },
                this.cancellationTokenSource.Token);

            var continuationTask = task.ContinueWith(
                (t) =>
            {
                try
                {
                    if (t.Exception == null)
                    {
                        // Uri doesn't recognize file paths in unix. See https://github.com/dotnet/corefx/issues/1745
                        var attachmentUri = new UriBuilder()
                        {
                            Scheme = "file", Host = "", Path = localFilePath
                        }.Uri;
                        lock (attachmentTaskLock)
                        {
                            this.AttachmentSets[fileTransferInfo.Context][uri].Attachments.Add(new UriDataAttachment(attachmentUri, fileTransferInfo.Description));
                        }
                    }

                    sendFileCompletedCallback?.Invoke(this, new AsyncCompletedEventArgs(t.Exception, false, fileTransferInfo.UserToken));
                }
                catch (Exception e)
                {
                    if (EqtTrace.IsErrorEnabled)
                    {
                        EqtTrace.Error(
                            "DataCollectionAttachmentManager.TriggerCallBack: Error occurred while raising the file transfer completed callback for {0}. Error: {1}",
                            localFilePath,
                            e.ToString());
                    }
                }
            },
                this.cancellationTokenSource.Token);

            this.attachmentTasks[fileTransferInfo.Context].Add(continuationTask);
        }
Exemple #25
0
        /// <summary>
        /// Sends a file asynchronously.
        /// </summary>
        /// <param name="fileTransferInformation">Information about the file being transferred.</param>
        public override void SendFileAsync(FileTransferInformation fileTransferInformation)
        {
            ValidateArg.NotNull(fileTransferInformation, nameof(fileTransferInformation));

            this.AttachmentManager.AddAttachment(fileTransferInformation, this.SendFileCompleted, this.DataCollectorConfig.TypeUri, this.DataCollectorConfig.FriendlyName);
        }
Exemple #26
0
        /// <summary>
        /// Called when Session End event is invoked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">SessionEndEventArgs</param>
        private void SessionEndedHandler(object sender, SessionEndEventArgs args)
        {
            this.ResetInactivityTimer();

            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("Blame Collector : Session End");
            }

            try
            {
                // If the last test crashes, it will not invoke a test case end and therefore
                // In case of crash testStartCount will be greater than testEndCount and we need to write the sequence
                // And send the attachment
                if (this.testStartCount > this.testEndCount)
                {
                    var filepath = Path.Combine(this.GetTempDirectory(), Constants.AttachmentFileName + "_" + this.attachmentGuid);

                    filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, this.testObjectDictionary, filepath);
                    var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true);
                    this.dataCollectionSink.SendFileAsync(fileTranferInformation);
                }

                if (this.collectProcessDumpOnTrigger)
                {
                    // If there was a test case crash or if we need to collect dump on process exit.
                    //
                    // Do not try to collect dump when we already collected one from the hang dump
                    // we won't dump the killed process again and that would just show a warning on the command line
                    if ((this.testStartCount > this.testEndCount || this.collectDumpAlways) && !this.dumpWasCollectedByHangDumper)
                    {
                        try
                        {
                            var dumpFile = this.processDumpUtility.GetDumpFile();
                            if (!string.IsNullOrEmpty(dumpFile))
                            {
                                var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true);
                                this.dataCollectionSink.SendFileAsync(fileTranferInformation);
                            }
                            else
                            {
                                EqtTrace.Warning("BlameCollector.SessionEndedHandler: blame:CollectDump was enabled but dump file was not generated.");
                                this.logger.LogWarning(args.Context, Resources.Resources.ProcDumpNotGenerated);
                            }
                        }
                        catch (FileNotFoundException ex)
                        {
                            EqtTrace.Warning(ex.ToString());
                            this.logger.LogWarning(args.Context, ex.ToString());
                        }
                    }
                }
            }
            finally
            {
                // Attempt to terminate the proc dump process if proc dump was enabled
                if (this.collectProcessDumpOnTrigger)
                {
                    this.processDumpUtility.DetachFromTargetProcess(this.testHostProcessId);
                }

                this.DeregisterEvents();
            }
        }