public void OnMessageReceived(object sender, MessageReceivedEventArgs messageReceivedArgs)
        {
            var message = this.dataSerializer.DeserializeMessage(messageReceivedArgs.Data);

            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("TestRequestHandler.ProcessRequests: received message: {0}", message);
            }

            switch (message.MessageType)
            {
            case MessageType.VersionCheck:
                var version = this.dataSerializer.DeserializePayload <int>(message);
                this.protocolVersion = Math.Min(version, highestSupportedVersion);

                // Send the negotiated protocol to request sender
                this.channel.Send(this.dataSerializer.SerializePayload(MessageType.VersionCheck, this.protocolVersion));

                // Can only do this after InitializeCommunication because TestHost cannot "Send Log" unless communications are initialized
                if (!string.IsNullOrEmpty(EqtTrace.LogFile))
                {
                    this.SendLog(TestMessageLevel.Informational, string.Format(CrossPlatResources.TesthostDiagLogOutputFile, EqtTrace.LogFile));
                }
                else if (!string.IsNullOrEmpty(EqtTrace.ErrorOnInitialization))
                {
                    this.SendLog(TestMessageLevel.Warning, EqtTrace.ErrorOnInitialization);
                }
                break;

            case MessageType.DiscoveryInitialize:
            {
                EqtTrace.Info("Discovery Session Initialize.");
                this.testHostManagerFactoryReady.Wait();
                var discoveryEventsHandler     = new TestDiscoveryEventHandler(this);
                var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload <IEnumerable <string> >(message);
                jobQueue.QueueJob(
                    () =>
                    testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions, discoveryEventsHandler), 0);
                break;
            }

            case MessageType.StartDiscovery:
            {
                EqtTrace.Info("Discovery started.");
                this.testHostManagerFactoryReady.Wait();
                var discoveryEventsHandler = new TestDiscoveryEventHandler(this);
                var discoveryCriteria      = this.dataSerializer.DeserializePayload <DiscoveryCriteria>(message);
                jobQueue.QueueJob(
                    () =>
                    testHostManagerFactory.GetDiscoveryManager()
                    .DiscoverTests(discoveryCriteria, discoveryEventsHandler), 0);

                break;
            }

            case MessageType.ExecutionInitialize:
            {
                EqtTrace.Info("Execution Session Initialize.");
                this.testHostManagerFactoryReady.Wait();
                var testInitializeEventsHandler = new TestInitializeEventsHandler(this);
                var pathToAdditionalExtensions  = this.dataSerializer.DeserializePayload <IEnumerable <string> >(message);
                jobQueue.QueueJob(
                    () =>
                    testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions, testInitializeEventsHandler), 0);
                break;
            }

            case MessageType.StartTestExecutionWithSources:
            {
                EqtTrace.Info("Execution started.");
                var testRunEventsHandler = new TestRunEventsHandler(this);
                this.testHostManagerFactoryReady.Wait();
                var testRunCriteriaWithSources = this.dataSerializer.DeserializePayload <TestRunCriteriaWithSources>(message);
                jobQueue.QueueJob(
                    () =>
                    testHostManagerFactory.GetExecutionManager()
                    .StartTestRun(
                        testRunCriteriaWithSources.AdapterSourceMap,
                        testRunCriteriaWithSources.Package,
                        testRunCriteriaWithSources.RunSettings,
                        testRunCriteriaWithSources.TestExecutionContext,
                        this.GetTestCaseEventsHandler(testRunCriteriaWithSources.RunSettings),
                        testRunEventsHandler),
                    0);

                break;
            }

            case MessageType.StartTestExecutionWithTests:
            {
                EqtTrace.Info("Execution started.");
                var testRunEventsHandler = new TestRunEventsHandler(this);
                this.testHostManagerFactoryReady.Wait();
                var testRunCriteriaWithTests =
                    this.dataSerializer.DeserializePayload <TestRunCriteriaWithTests>(message);

                jobQueue.QueueJob(
                    () =>
                    testHostManagerFactory.GetExecutionManager()
                    .StartTestRun(
                        testRunCriteriaWithTests.Tests,
                        testRunCriteriaWithTests.Package,
                        testRunCriteriaWithTests.RunSettings,
                        testRunCriteriaWithTests.TestExecutionContext,
                        this.GetTestCaseEventsHandler(testRunCriteriaWithTests.RunSettings),
                        testRunEventsHandler),
                    0);

                break;
            }

            case MessageType.CancelTestRun:
                jobQueue.Pause();
                this.testHostManagerFactoryReady.Wait();
                testHostManagerFactory.GetExecutionManager().Cancel(new TestRunEventsHandler(this));
                break;

            case MessageType.LaunchAdapterProcessWithDebuggerAttachedCallback:
                this.onAckMessageRecieved?.Invoke(message);
                break;

            case MessageType.AbortTestRun:
                jobQueue.Pause();
                this.testHostManagerFactoryReady.Wait();
                testHostManagerFactory.GetExecutionManager().Abort(new TestRunEventsHandler(this));
                break;

            case MessageType.SessionEnd:
            {
                EqtTrace.Info("Session End message received from server. Closing the connection.");
                sessionCompleted.Set();
                this.Close();
                break;
            }

            case MessageType.SessionAbort:
            {
                // Dont do anything for now.
                break;
            }

            default:
            {
                EqtTrace.Info("Invalid Message types");
                break;
            }
            }
        }
示例#2
0
        /// <summary>
        /// Invoked when test run is complete
        /// </summary>
        public void HandleTestRunComplete(TestRunCompleteEventArgs runCompleteArgs, TestRunChangedEventArgs lastChunkArgs, ICollection <AttachmentSet> runContextAttachments, ICollection <string> executorUris)
        {
            if (runCompleteArgs == null)
            {
                throw new ArgumentNullException(nameof(runCompleteArgs));
            }

            bool isAborted  = runCompleteArgs.IsAborted;
            bool isCanceled = runCompleteArgs.IsCanceled;

            EqtTrace.Verbose("TestRunRequest:TestRunComplete: Starting. IsAborted:{0} IsCanceled:{1}.", isAborted, isCanceled);

            lock (this.syncObject)
            {
                // If this object is disposed, dont do anything
                if (this.disposed)
                {
                    EqtTrace.Warning("TestRunRequest.TestRunComplete: Ignoring as the object is disposed.");
                    return;
                }

                if (this.runCompletionEvent.WaitOne(0))
                {
                    EqtTrace.Info("TestRunRequest:TestRunComplete:Ignoring duplicate event. IsAborted:{0} IsCanceled:{1}.", isAborted, isCanceled);
                    return;
                }

                // Disposing off the resources held by the execution manager so that the test host process can shut down.
                this.ExecutionManager?.Close();

                try
                {
                    this.runRequestTimeTracker.Stop();

                    if (lastChunkArgs != null)
                    {
                        // Raised the changed event also
                        this.OnRunStatsChange.SafeInvoke(this, lastChunkArgs, "TestRun.RunStatsChanged");
                    }

                    TestRunCompleteEventArgs runCompletedEvent =
                        new TestRunCompleteEventArgs(
                            runCompleteArgs.TestRunStatistics,
                            runCompleteArgs.IsCanceled,
                            runCompleteArgs.IsAborted,
                            runCompleteArgs.Error,
                            runContextAttachments as Collection <AttachmentSet>,
                            this.runRequestTimeTracker.Elapsed);

                    // Ignore the time sent (runCompleteArgs.ElapsedTimeInRunningTests)
                    // by either engines - as both calculate at different points
                    // If we use them, it would be an incorrect comparison between TAEF and Rocksteady
                    this.OnRunCompletion.SafeInvoke(this, runCompletedEvent, "TestRun.TestRunComplete");
                }
                finally
                {
                    if (isCanceled)
                    {
                        this.State = TestRunState.Canceled;
                    }
                    else if (isAborted)
                    {
                        this.State = TestRunState.Aborted;
                    }
                    else
                    {
                        this.State = TestRunState.Completed;
                    }

                    // Notify the waiting handle that run is complete
                    this.runCompletionEvent.Set();
                }

                EqtTrace.Info("TestRunRequest:TestRunComplete: Completed.");
            }
        }
示例#3
0
        /// <inheritdoc />
        public void CheckVersionWithTestHost()
        {
            // Negotiation follows these steps:
            // Runner sends highest supported version to Test host
            // Test host sends the version it can support (must be less than highest) to runner
            // Error case: test host can send a protocol error if it cannot find a supported version
            var protocolNegotiated = new ManualResetEvent(false);

            this.onMessageReceived = (sender, args) =>
            {
                var message = this.dataSerializer.DeserializeMessage(args.Data);

                if (EqtTrace.IsVerboseEnabled)
                {
                    EqtTrace.Verbose("TestRequestSender.CheckVersionWithTestHost: onMessageReceived received message: {0}", message);
                }

                if (message.MessageType == MessageType.VersionCheck)
                {
                    this.protocolVersion = this.dataSerializer.DeserializePayload <int>(message);
                }

                // TRH can also send TestMessage if tracing is enabled, so log it at runner end
                else if (message.MessageType == MessageType.TestMessage)
                {
                    // Ignore test messages. Currently we don't have handler(which sends messages to client/console.) here.
                    // Above we are logging it to EqtTrace.
                }
                else if (message.MessageType == MessageType.ProtocolError)
                {
                    throw new TestPlatformException(string.Format(CultureInfo.CurrentUICulture, CommonResources.VersionCheckFailed));
                }
                else
                {
                    throw new TestPlatformException(string.Format(
                                                        CultureInfo.CurrentUICulture,
                                                        CommonResources.UnexpectedMessage,
                                                        MessageType.VersionCheck,
                                                        message.MessageType));
                }

                protocolNegotiated.Set();
            };
            this.channel.MessageReceived += this.onMessageReceived;

            try
            {
                // Send the protocol negotiation request. Note that we always serialize this data
                // without any versioning in the message itself.
                var data = this.dataSerializer.SerializePayload(MessageType.VersionCheck, this.highestSupportedVersion);
                this.channel.Send(data);

                // Wait for negotiation response
                var timeout = EnvironmentHelper.GetConnectionTimeout();
                if (!protocolNegotiated.WaitOne(timeout * 1000))
                {
                    throw new TestPlatformException(string.Format(CultureInfo.CurrentUICulture, CommonResources.VersionCheckTimedout, timeout, EnvironmentHelper.VstestConnectionTimeout));
                }
            }
            finally
            {
                this.channel.MessageReceived -= this.onMessageReceived;
                this.onMessageReceived        = null;
            }
        }
示例#4
0
        /// <inheritdoc />
        public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEventsHandler2 discoveryEventsHandler)
        {
            this.messageEventHandler = discoveryEventsHandler;
            this.onDisconnected      = (disconnectedEventArgs) =>
            {
                this.OnDiscoveryAbort(discoveryEventsHandler, disconnectedEventArgs.Error, true);
            };
            this.onMessageReceived = (sender, args) =>
            {
                try
                {
                    var rawMessage = args.Data;

                    // Currently each of the operations are not separate tasks since they should not each take much time. This is just a notification.
                    if (EqtTrace.IsInfoEnabled)
                    {
                        EqtTrace.Info("TestRequestSender: Received message: {0}", rawMessage);
                    }

                    // Send raw message first to unblock handlers waiting to send message to IDEs
                    discoveryEventsHandler.HandleRawMessage(rawMessage);

                    var data = this.dataSerializer.DeserializeMessage(rawMessage);
                    switch (data.MessageType)
                    {
                    case MessageType.TestCasesFound:
                        var testCases = this.dataSerializer.DeserializePayload <IEnumerable <TestCase> >(data);
                        discoveryEventsHandler.HandleDiscoveredTests(testCases);
                        break;

                    case MessageType.DiscoveryComplete:
                        var discoveryCompletePayload =
                            this.dataSerializer.DeserializePayload <DiscoveryCompletePayload>(data);

                        var discoveryCompleteEventsArgs = new DiscoveryCompleteEventArgs(discoveryCompletePayload.TotalTests, discoveryCompletePayload.IsAborted, discoveryCompletePayload.Metrics);

                        discoveryEventsHandler.HandleDiscoveryComplete(
                            discoveryCompleteEventsArgs,
                            discoveryCompletePayload.LastDiscoveredTests);

                        this.SetOperationComplete();
                        break;

                    case MessageType.TestMessage:
                        var testMessagePayload = this.dataSerializer.DeserializePayload <TestMessagePayload>(
                            data);
                        discoveryEventsHandler.HandleLogMessage(
                            testMessagePayload.MessageLevel,
                            testMessagePayload.Message);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    this.OnDiscoveryAbort(discoveryEventsHandler, ex, false);
                }
            };

            this.channel.MessageReceived += this.onMessageReceived;
            var message = this.dataSerializer.SerializePayload(
                MessageType.StartDiscovery,
                discoveryCriteria,
                this.protocolVersion);

            this.channel.Send(message);
        }
示例#5
0
        public void Invoke(IDictionary <string, string> argsDictionary)
        {
            // Setup logging if enabled
            string logFile;

            if (argsDictionary.TryGetValue(LogFileArgument, out logFile))
            {
                EqtTrace.InitializeVerboseTrace(logFile);
            }

#if NET46
            if (EqtTrace.IsInfoEnabled)
            {
                var appConfigText = System.IO.File.ReadAllText(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                EqtTrace.Info("DefaultEngineInvoker: Using Application Configuration: '{0}'", appConfigText);
            }
#endif

            // Get port number and initialize communication
            var portNumber = GetIntArgFromDict(argsDictionary, PortArgument);

            // Start Processing of requests
            using (var requestHandler = new TestRequestHandler())
            {
                // Attach to exit of parent process
                var parentProcessId = GetIntArgFromDict(argsDictionary, ParentProcessIdArgument);
                EqtTrace.Info("DefaultEngineInvoker: Monitoring parent process with id: '{0}'", parentProcessId);
                var parentProcessMonitoringTask = WaitForParentProcessExitAsync(parentProcessId);

                // Initialize Communication
                EqtTrace.Info("DefaultEngineInvoker: Initialize communication on port number: '{0}'", portNumber);
                requestHandler.InitializeCommunication(portNumber);

                // Can only do this after InitializeCommunication because TestHost cannot "Send Log" unless communications are initialized
                if (!string.IsNullOrEmpty(EqtTrace.LogFile))
                {
                    requestHandler.SendLog(TestMessageLevel.Informational, string.Format("Logging TestHost Diagnostics in file: {0}", EqtTrace.LogFile));
                }

                // Initialize DataCollection Communication if data collection port is provided.
                var dcPort = GetIntArgFromDict(argsDictionary, DataCollectionPortArgument);
                if (dcPort > 0)
                {
                    var dataCollectionTestCaseEventSender = DataCollectionTestCaseEventSender.Create();
                    dataCollectionTestCaseEventSender.InitializeCommunication(dcPort);
                    dataCollectionTestCaseEventSender.WaitForRequestSenderConnection(ClientListenTimeOut);
                }

                // Start processing async in a different task
                EqtTrace.Info("DefaultEngineInvoker: Start Request Processing.");
                var processingTask = this.StartProcessingAsync(requestHandler, new TestHostManagerFactory());

                // Wait for either processing to complete or parent process exit
                Task.WaitAny(processingTask, parentProcessMonitoringTask);

                if (dcPort > 0)
                {
                    // Close socket communication connection.
                    DataCollectionTestCaseEventSender.Instance.Close();
                }
            }
        }
示例#6
0
        /// <summary>
        /// Loads and initializes data collector using data collector settings.
        /// </summary>
        /// <param name="dataCollectorSettings">
        /// The data collector settings.
        /// </param>
        /// <param name="settingsXml"> runsettings Xml</param>
        private void LoadAndInitialize(DataCollectorSettings dataCollectorSettings, string settingsXml)
        {
            DataCollectorInformation dataCollectorInfo;
            DataCollectorConfig      dataCollectorConfig;

            try
            {
                // Look up the extension and initialize it if one is found.
                var extensionManager = this.DataCollectorExtensionManager;
                var dataCollectorUri = string.Empty;
                this.TryGetUriFromFriendlyName(dataCollectorSettings.FriendlyName, out dataCollectorUri);

                DataCollector dataCollector = null;
                if (!string.IsNullOrWhiteSpace(dataCollectorUri))
                {
                    dataCollector = this.TryGetTestExtension(dataCollectorUri);
                }

                if (dataCollector == null)
                {
                    this.LogWarning(string.Format(CultureInfo.CurrentUICulture, Resources.Resources.DataCollectorNotFound, dataCollectorSettings.FriendlyName));
                    return;
                }

                if (this.RunDataCollectors.ContainsKey(dataCollector.GetType()))
                {
                    // Collector is already loaded (may be configured twice). Ignore duplicates and return.
                    return;
                }

                dataCollectorConfig = new DataCollectorConfig(dataCollector.GetType());

                // Attempt to get the data collector information verifying that all of the required metadata for the collector is available.
                dataCollectorInfo = new DataCollectorInformation(
                    dataCollector,
                    dataCollectorSettings.Configuration,
                    dataCollectorConfig,
                    this.dataCollectionEnvironmentContext,
                    this.attachmentManager,
                    this.events,
                    this.messageSink,
                    settingsXml);
            }
            catch (Exception ex)
            {
                if (EqtTrace.IsErrorEnabled)
                {
                    EqtTrace.Error("DataCollectionManager.LoadAndInitialize: exception while creating data collector {0} : {1}", dataCollectorSettings.FriendlyName, ex);
                }

                // No data collector info, so send the error with no direct association to the collector.
                this.LogWarning(string.Format(CultureInfo.CurrentUICulture, Resources.Resources.DataCollectorInitializationError, dataCollectorSettings.FriendlyName, ex));
                return;
            }

            try
            {
                dataCollectorInfo.InitializeDataCollector();
                lock (this.RunDataCollectors)
                {
                    // Add data collectors to run cache.
                    this.RunDataCollectors[dataCollectorConfig.DataCollectorType] = dataCollectorInfo;
                }
            }
            catch (Exception ex)
            {
                if (EqtTrace.IsErrorEnabled)
                {
                    EqtTrace.Error("DataCollectionManager.LoadAndInitialize: exception while initializing data collector {0} : {1}", dataCollectorSettings.FriendlyName, ex);
                }

                // Log error.
                dataCollectorInfo.Logger.LogError(this.dataCollectionEnvironmentContext.SessionDataCollectionContext, string.Format(CultureInfo.CurrentCulture, Resources.Resources.DataCollectorInitializationError, dataCollectorConfig.FriendlyName, ex.Message));

                // Dispose datacollector.
                dataCollectorInfo.DisposeDataCollector();
            }
        }
示例#7
0
 /// <summary>
 /// Handle discovery complete.
 /// </summary>
 /// <param name="totalTests"> The total tests. </param>
 /// <param name="lastChunk"> The last chunk. </param>
 /// <param name="isAborted"> The is aborted. </param>
 public void HandleDiscoveryComplete(long totalTests, IEnumerable <TestCase> lastChunk, bool isAborted)
 {
     EqtTrace.Info(isAborted ? "Discover Aborted." : "Discover Finished.");
     this.requestHandler.DiscoveryComplete(totalTests, lastChunk, isAborted);
 }
示例#8
0
        private Assembly SearchAndLoadAssembly(string assemblyPath, string assemblyName, AssemblyName requestedName, bool isReflectionOnly)
        {
            try
            {
                if (!this.DoesFileExist(assemblyPath))
                {
                    return(null);
                }

                var foundName = AssemblyName.GetAssemblyName(assemblyPath);

                if (!RequestedAssemblyNameMatchesFound(requestedName, foundName))
                {
                    return(null); // File exists but version/public key is wrong. Try next extension.
                }

                Assembly assembly;

                if (isReflectionOnly)
                {
                    assembly = this.ReflectionOnlyLoadAssemblyFrom(assemblyPath);
                    this.reflectionOnlyResolvedAssemblies[assemblyName] = assembly;
                }
                else
                {
                    assembly = this.LoadAssemblyFrom(assemblyPath);
                    this.resolvedAssemblies[assemblyName] = assembly;
                }

                this.SafeLog(
                    assemblyName,
                    () =>
                {
                    if (EqtTrace.IsInfoEnabled)
                    {
                        EqtTrace.Info("AssemblyResolver: Resolved assembly: {0}. ", assemblyName);
                    }
                });
                return(assembly);
            }
            catch (FileLoadException ex)
            {
                this.SafeLog(
                    assemblyName,
                    () =>
                {
                    if (EqtTrace.IsInfoEnabled)
                    {
                        EqtTrace.Info("AssemblyResolver: Failed to load assembly: {0}. Reason:{1} ", assemblyName, ex);
                    }
                });

                // Re-throw FileLoadException, because this exception means that the assembly
                // was found, but could not be loaded. This will allow us to report a more
                // specific error message to the user for things like access denied.
                throw;
            }
            catch (Exception ex)
            {
                // For all other exceptions, try the next extension.
                this.SafeLog(
                    assemblyName,
                    () =>
                {
                    if (EqtTrace.IsInfoEnabled)
                    {
                        EqtTrace.Info("AssemblyResolver: Failed to load assembly: {0}. Reason:{1} ", assemblyName, ex);
                    }
                });
            }

            return(null);
        }
示例#9
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);
        }
示例#10
0
        /// <summary>
        /// It will search for a particular assembly in the given list of directory.
        /// </summary>
        /// <param name="searchDirectorypaths"> The search Directorypaths. </param>
        /// <param name="name"> The name. </param>
        /// <param name="isReflectionOnly"> Indicates whether this is called under a Reflection Only Load context. </param>
        /// <returns> The <see cref="Assembly"/>. </returns>
        protected virtual Assembly SearchAssembly(List <string> searchDirectorypaths, string name, bool isReflectionOnly)
        {
            if (searchDirectorypaths == null || searchDirectorypaths.Count == 0)
            {
                return(null);
            }

            // args.Name is like: "Microsoft.VisualStudio.TestTools.Common, Version=[VersionMajor].0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
            AssemblyName requestedName = null;

            try
            {
                // Can throw ArgumentException, FileLoadException if arg is empty/wrong format, etc. Should not return null.
                requestedName = new AssemblyName(name);
            }
            catch (Exception ex)
            {
                this.SafeLog(
                    name,
                    () =>
                {
                    if (EqtTrace.IsInfoEnabled)
                    {
                        EqtTrace.Info(
                            "AssemblyResolver: {0}: Failed to create assemblyName. Reason:{1} ",
                            name,
                            ex);
                    }
                });

                return(null);
            }

            Debug.Assert(requestedName != null && !string.IsNullOrEmpty(requestedName.Name), "AssemblyResolver.OnResolve: requested is null or name is empty!");

            foreach (var dir in searchDirectorypaths)
            {
                if (string.IsNullOrEmpty(dir))
                {
                    continue;
                }

                this.SafeLog(
                    name,
                    () =>
                {
                    if (EqtTrace.IsVerboseEnabled)
                    {
                        EqtTrace.Verbose("AssemblyResolver: Searching assembly: {0} in the directory: {1}", requestedName.Name, dir);
                    }
                });

                foreach (var extension in new string[] { ".dll", ".exe" })
                {
                    var assemblyPath = Path.Combine(dir, requestedName.Name + extension);

                    var assembly = this.SearchAndLoadAssembly(assemblyPath, name, requestedName, isReflectionOnly);
                    if (assembly != null)
                    {
                        return(assembly);
                    }
                }
            }

            return(null);
        }
示例#11
0
        private Assembly OnResolveInternal(object senderAppDomain, ResolveEventArgs args, bool isReflectionOnly)
        {
            if (string.IsNullOrEmpty(args?.Name))
            {
                Debug.Assert(false, "AssemblyResolver.OnResolve: args.Name is null or empty.");
                return(null);
            }

            this.SafeLog(
                args.Name,
                () =>
            {
                if (EqtTrace.IsInfoEnabled)
                {
                    EqtTrace.Info("AssemblyResolver: Resolving assembly: {0}.", args.Name);
                }
            });

            string assemblyNameToLoad = AppDomain.CurrentDomain.ApplyPolicy(args.Name);

            this.SafeLog(
                assemblyNameToLoad,
                () =>
            {
                if (EqtTrace.IsInfoEnabled)
                {
                    EqtTrace.Info("AssemblyResolver: Resolving assembly after applying policy: {0}.", assemblyNameToLoad);
                }
            });

            lock (this.syncLock)
            {
                // Since both normal and reflection only cache are accessed in same block, putting only one lock should be sufficient.
                Assembly assembly = null;

                if (this.TryLoadFromCache(assemblyNameToLoad, isReflectionOnly, out assembly))
                {
                    return(assembly);
                }

                assembly = this.SearchAssembly(this.searchDirectories, assemblyNameToLoad, isReflectionOnly);

                if (assembly != null)
                {
                    return(assembly);
                }

                if (this.directoryList != null && this.directoryList.Any())
                {
                    // required assembly is not present in searchDirectories??
                    // see, if we can find it in user specified search directories.
                    while (assembly == null && this.directoryList.Count > 0)
                    {
                        // instead of loading whole search directory in one time, we are adding directory on the basis of need
                        var currentNode = this.directoryList.Dequeue();

                        List <string> increamentalSearchDirectory = new List <string>();

                        if (this.DoesDirectoryExist(currentNode.DirectoryPath))
                        {
                            increamentalSearchDirectory.Add(currentNode.DirectoryPath);

                            if (currentNode.IncludeSubDirectories)
                            {
                                // Add all its sub-directory in depth first search order.
                                this.AddSubdirectories(currentNode.DirectoryPath, increamentalSearchDirectory);
                            }

                            // Add this directory list in this.searchDirectories so that when we will try to resolve some other
                            // assembly, then it will look in this whole directory first.
                            this.searchDirectories.AddRange(increamentalSearchDirectory);

                            assembly = this.SearchAssembly(increamentalSearchDirectory, assemblyNameToLoad, isReflectionOnly);
                        }
                        else
                        {
                            // generate warning that path does not exist.
                            this.SafeLog(
                                assemblyNameToLoad,
                                () =>
                            {
                                if (EqtTrace.IsWarningEnabled)
                                {
                                    EqtTrace.Warning(
                                        "The Directory: {0}, does not exist",
                                        currentNode.DirectoryPath);
                                }
                            });
                        }
                    }

                    if (assembly != null)
                    {
                        return(assembly);
                    }
                }

                // Try for default load for System dlls that can't be found in search paths. Needs to loaded just by name.
                try
                {
                    if (isReflectionOnly)
                    {
                        // Put it in the resolved assembly cache so that if the Load call below
                        // triggers another assembly resolution, then we don't end up in stack overflow.
                        this.reflectionOnlyResolvedAssemblies[assemblyNameToLoad] = null;

                        assembly = Assembly.ReflectionOnlyLoad(assemblyNameToLoad);

                        if (assembly != null)
                        {
                            this.reflectionOnlyResolvedAssemblies[assemblyNameToLoad] = assembly;
                        }
                    }
                    else
                    {
                        // Put it in the resolved assembly cache so that if the Load call below
                        // triggers another assembly resolution, then we don't end up in stack overflow.
                        this.resolvedAssemblies[assemblyNameToLoad] = null;

                        assembly = Assembly.Load(assemblyNameToLoad);

                        if (assembly != null)
                        {
                            this.resolvedAssemblies[assemblyNameToLoad] = assembly;
                        }
                    }

                    return(assembly);
                }
                catch (Exception ex)
                {
                    this.SafeLog(
                        args?.Name,
                        () =>
                    {
                        if (EqtTrace.IsInfoEnabled)
                        {
                            EqtTrace.Info(
                                "AssemblyResolver: {0}: Failed to load assembly. Reason:{1} ",
                                assemblyNameToLoad,
                                ex);
                        }
                    });
                }

                return(assembly);
            }
        }
示例#12
0
        private IEnumerable <DeploymentItem> GetSatellites(IEnumerable <DeploymentItem> deploymentItems, string testSource, IList <string> warnings)
        {
            List <DeploymentItem> satellites = new List <DeploymentItem>();

            foreach (DeploymentItem item in deploymentItems)
            {
                // We do not care about deployment items which are directories because in that case we deploy all files underneath anyway.
                string path = null;
                try
                {
                    path = this.GetFullPathToDeploymentItemSource(item.SourcePath, testSource);
                    path = Path.GetFullPath(path);

                    if (string.IsNullOrEmpty(path) || !this.assemblyUtility.IsAssemblyExtension(Path.GetExtension(path)) ||
                        !this.fileUtility.DoesFileExist(path) || !this.assemblyUtility.IsAssembly(path))
                    {
                        continue;
                    }
                }
                catch (ArgumentException ex)
                {
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                }
                catch (SecurityException ex)
                {
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                }
                catch (IOException ex)
                {
                    // This covers PathTooLongException.
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                }
                catch (NotSupportedException ex)
                {
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                }

                // Note: now Path operations with itemPath should not result in any exceptions.
                // path is already canonicalized.

                // If we cannot access satellite due to security, etc, we report warning.
                try
                {
                    string itemDir = Path.GetDirectoryName(path).TrimEnd(
                        new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
                    List <string> itemSatellites = this.assemblyUtility.GetSatelliteAssemblies(path);
                    foreach (string satellite in itemSatellites)
                    {
                        Debug.Assert(!string.IsNullOrEmpty(satellite), "DeploymentManager.DoDeployment: got empty satellite!");
                        Debug.Assert(
                            satellite.IndexOf(itemDir, StringComparison.OrdinalIgnoreCase) == 0,
                            "DeploymentManager.DoDeployment: Got satellite that does not start with original item path");

                        string satelliteDir = Path.GetDirectoryName(satellite).TrimEnd(
                            new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });

                        Debug.Assert(!string.IsNullOrEmpty(satelliteDir), "DeploymentManager.DoDeployment: got empty satellite dir!");
                        Debug.Assert(satelliteDir.Length > itemDir.Length + 1, "DeploymentManager.DoDeployment: wrong satellite dir lenght!");

                        string localeDir = satelliteDir.Substring(itemDir.Length + 1);
                        Debug.Assert(!string.IsNullOrEmpty(localeDir), "DeploymentManager.DoDeployment: got empty dir name for satellite dir!");

                        string relativeOutputDir = Path.Combine(item.RelativeOutputDirectory, localeDir);

                        // Now finally add the item!
                        DeploymentItem satelliteItem = new DeploymentItem(satellite, relativeOutputDir, DeploymentItemOriginType.Satellite);
                        this.deploymentItemUtility.AddDeploymentItem(satellites, satelliteItem);
                    }
                }
                catch (ArgumentException ex)
                {
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                    string warning = string.Format(CultureInfo.CurrentCulture, Resource.DeploymentErrorGettingSatellite, item, ex.GetType(), ex.GetExceptionMessage());
                    warnings.Add(warning);
                }
                catch (SecurityException ex)
                {
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                    string warning = string.Format(CultureInfo.CurrentCulture, Resource.DeploymentErrorGettingSatellite, item, ex.GetType(), ex.GetExceptionMessage());
                    warnings.Add(warning);
                }
                catch (IOException ex)
                {
                    // This covers PathTooLongException.
                    EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DeploymentManager.GetSatellites: {0}", ex);
                    string warning = string.Format(CultureInfo.CurrentCulture, Resource.DeploymentErrorGettingSatellite, item, ex.GetType(), ex.GetExceptionMessage());
                    warnings.Add(warning);
                }
            }

            return(satellites);
        }
示例#13
0
        private IEnumerable <string> Deploy(IList <DeploymentItem> deploymentItems, string testSource, string deploymentDirectory, string resultsDirectory)
        {
            Validate.IsFalse(string.IsNullOrWhiteSpace(deploymentDirectory), "Deployment directory is null or empty");
            Validate.IsTrue(this.fileUtility.DoesDirectoryExist(deploymentDirectory), $"Deployment directory {deploymentDirectory} does not exist");
            Validate.IsFalse(string.IsNullOrWhiteSpace(testSource), "TestSource directory is null/empty");
            Validate.IsTrue(this.fileUtility.DoesFileExist(testSource), $"TestSource {testSource} does not exist.");

            testSource = Path.GetFullPath(testSource);
            var warnings = new List <string>();

            if (MSTestSettingsProvider.Settings.DeployTestSourceDependencies)
            {
                EqtTrace.Info("Adding the references and satellite assemblies to the deploymentitems list");

                // Get the referenced assemblies.
                this.ProcessNewStorage(testSource, deploymentItems, warnings);

                // Get the satellite assemblies
                var satelliteItems = this.GetSatellites(deploymentItems, testSource, warnings);
                foreach (var satelliteItem in satelliteItems)
                {
                    this.deploymentItemUtility.AddDeploymentItem(deploymentItems, satelliteItem);
                }
            }
            else
            {
                EqtTrace.Info("Adding the test source directory to the deploymentitems list");
                this.deploymentItemUtility.AddDeploymentItem(deploymentItems, new DeploymentItem(Path.GetDirectoryName(testSource)));
            }

            // Maps relative to Out dir destination -> source and used to determine if there are conflicted items.
            var destToSource = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            // Copy the deployment items. (As deployment item can correspond to directories as well, so each deployment item may map to n files)
            foreach (var deploymentItem in deploymentItems)
            {
                ValidateArg.NotNull(deploymentItem, "deploymentItem should not be null.");

                // Validate the output directory.
                if (!this.IsOutputDirectoryValid(deploymentItem, deploymentDirectory, warnings))
                {
                    continue;
                }

                // Get the files corresponding to this deployment item
                var deploymentItemFiles = this.GetFullPathToFilesCorrespondingToDeploymentItem(deploymentItem, testSource, resultsDirectory, warnings, out bool itemIsDirectory);
                if (deploymentItemFiles == null)
                {
                    continue;
                }

                var fullPathToDeploymentItemSource = this.GetFullPathToDeploymentItemSource(deploymentItem.SourcePath, testSource);

                // Note: source is already rooted.
                foreach (var deploymentItemFile in deploymentItemFiles)
                {
                    Debug.Assert(Path.IsPathRooted(deploymentItemFile), "File " + deploymentItemFile + " is not rooted");

                    // List of files to deploy, by default, just itemFile.
                    var filesToDeploy = new List <string>(1);
                    filesToDeploy.Add(deploymentItemFile);

                    // Find dependencies of test deployment items and deploy them at the same time as master file.
                    if (deploymentItem.OriginType == DeploymentItemOriginType.PerTestDeployment &&
                        this.assemblyUtility.IsAssemblyExtension(Path.GetExtension(deploymentItemFile)))
                    {
                        this.AddDependenciesOfDeploymentItem(deploymentItemFile, filesToDeploy, warnings);
                    }

                    foreach (var fileToDeploy in filesToDeploy)
                    {
                        Debug.Assert(Path.IsPathRooted(fileToDeploy), "File " + fileToDeploy + " is not rooted");

                        // Ignore the test platform files.
                        var tempFile     = Path.GetFileName(fileToDeploy);
                        var assemblyName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
                        if (tempFile.Equals(assemblyName, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        string relativeDestination;
                        if (itemIsDirectory)
                        {
                            // Deploy into subdirectory of deployment (Out) dir.
                            Debug.Assert(fileToDeploy.StartsWith(fullPathToDeploymentItemSource, StringComparison.Ordinal), "Somehow source is outside original dir.");
                            relativeDestination = this.fileUtility.TryConvertPathToRelative(fileToDeploy, fullPathToDeploymentItemSource);
                        }
                        else
                        {
                            // Deploy just to the deployment (Out) dir.
                            relativeDestination = Path.GetFileName(fileToDeploy);
                        }

                        relativeDestination = Path.Combine(deploymentItem.RelativeOutputDirectory, relativeDestination);  // Ignores empty arg1.
                        var destination = Path.Combine(deploymentDirectory, relativeDestination);
                        try
                        {
                            destination = Path.GetFullPath(destination);
                        }
                        catch (Exception e)
                        {
                            var warning = string.Format(CultureInfo.CurrentCulture, Resource.DeploymentErrorFailedToAccessFile, destination, e.GetType(), e.Message);
                            warnings.Add(warning);

                            continue;
                        }

                        if (!destToSource.ContainsKey(relativeDestination))
                        {
                            destToSource.Add(relativeDestination, fileToDeploy);

                            // Now, finally we can copy the file...
                            destination = this.fileUtility.CopyFileOverwrite(fileToDeploy, destination, out string warning);
                            if (!string.IsNullOrEmpty(warning))
                            {
                                warnings.Add(warning);
                            }

                            if (string.IsNullOrEmpty(destination))
                            {
                                continue;
                            }

                            // We clear the attributes so that e.g. you can write to the copies of files originally under SCC.
                            this.fileUtility.SetAttributes(destination, FileAttributes.Normal);

                            // Deploy PDB for line number info in stack trace.
                            this.fileUtility.FindAndDeployPdb(destination, relativeDestination, fileToDeploy, destToSource);
                        }
                        else if (
                            !string.Equals(
                                fileToDeploy,
                                destToSource[relativeDestination],
                                StringComparison.OrdinalIgnoreCase))
                        {
                            EqtTrace.WarningIf(
                                EqtTrace.IsWarningEnabled,
                                "Conflict during copiyng file: '{0}' and '{1}' are from different origins although they might be the same.",
                                fileToDeploy,
                                destToSource[relativeDestination]);
                        }
                    } // foreach fileToDeploy.
                }     // foreach itemFile.
            }

            return(warnings);
        }
 private void SendData(string data)
 {
     EqtTrace.Verbose("TestRequestHandler.SendData:  sending data from testhost: {0}", data);
     this.channel.Send(data);
 }
        /// <summary>
        /// Triggers the execution for the next data object on the concurrent executor
        /// Each concurrent executor calls this method, once its completed working on previous data
        /// </summary>
        /// <param name="proxyExecutionManager">Proxy execution manager instance.</param>
        /// <returns>True, if execution triggered</returns>
        private void StartTestRunOnConcurrentManager(IProxyExecutionManager proxyExecutionManager)
        {
            TestRunCriteria testRunCriteria = null;

            if (!this.hasSpecificTestsRun)
            {
                if (this.TryFetchNextSource(this.sourceEnumerator, out string nextSource))
                {
                    EqtTrace.Info("ProxyParallelExecutionManager: Triggering test run for next source: {0}", nextSource);

                    testRunCriteria = new TestRunCriteria(
                        new[] { nextSource },
                        this.actualTestRunCriteria.FrequencyOfRunStatsChangeEvent,
                        this.actualTestRunCriteria.KeepAlive,
                        this.actualTestRunCriteria.TestRunSettings,
                        this.actualTestRunCriteria.RunStatsChangeEventTimeout,
                        this.actualTestRunCriteria.TestHostLauncher)
                    {
                        TestCaseFilter = this.actualTestRunCriteria.TestCaseFilter
                    };
                }
            }
            else
            {
                if (this.TryFetchNextSource(this.testCaseListEnumerator, out List <TestCase> nextSetOfTests))
                {
                    EqtTrace.Info("ProxyParallelExecutionManager: Triggering test run for next source: {0}", nextSetOfTests?.FirstOrDefault()?.Source);

                    testRunCriteria = new TestRunCriteria(
                        nextSetOfTests,
                        this.actualTestRunCriteria.FrequencyOfRunStatsChangeEvent,
                        this.actualTestRunCriteria.KeepAlive,
                        this.actualTestRunCriteria.TestRunSettings,
                        this.actualTestRunCriteria.RunStatsChangeEventTimeout,
                        this.actualTestRunCriteria.TestHostLauncher);
                }
            }

            if (testRunCriteria != null)
            {
                if (!proxyExecutionManager.IsInitialized)
                {
                    proxyExecutionManager.Initialize();
                }

                Task.Run(() =>
                {
                    Interlocked.Increment(ref this.runStartedClients);
                    if (EqtTrace.IsVerboseEnabled)
                    {
                        EqtTrace.Verbose("ParallelProxyExecutionManager: Execution started. Started clients: " + this.runStartedClients);
                    }

                    proxyExecutionManager.StartTestRun(testRunCriteria, this.GetHandlerForGivenManager(proxyExecutionManager));
                })
                .ContinueWith(t =>
                {
                    // Just in case, the actual execution couldn't start for an instance. Ensure that
                    // we call execution complete since we have already fetched a source. Otherwise
                    // execution will not terminate
                    if (EqtTrace.IsWarningEnabled)
                    {
                        EqtTrace.Warning("ParallelProxyExecutionManager: Failed to trigger execution. Exception: " + t.Exception);
                    }

                    // Send a run complete to caller. Similar logic is also used in ProxyExecutionManager.StartTestRun
                    // Differences:
                    // Aborted is sent to allow the current execution manager replaced with another instance
                    // Ensure that the test run aggregator in parallel run events handler doesn't add these statistics
                    // (since the test run didn't even start)
                    var completeArgs = new TestRunCompleteEventArgs(null, false, true, null, new Collection <AttachmentSet>(), TimeSpan.Zero);
                    this.GetHandlerForGivenManager(proxyExecutionManager).HandleTestRunComplete(completeArgs, null, null, null);
                },
                              TaskContinuationOptions.OnlyOnFaulted);
            }

            if (EqtTrace.IsVerboseEnabled)
            {
                EqtTrace.Verbose("ProxyParallelExecutionManager: No sources available for execution.");
            }
        }
示例#16
0
        /// <summary>
        /// Validates the collectors in runsettings when an in-lined testsettings is specified
        /// </summary>
        /// <param name="runsettings">RunSettings used for the run</param>
        /// <returns>True if an incompatible collector is found</returns>
        public static bool AreRunSettingsCollectorsInCompatibleWithTestSettings(string runsettings)
        {
            // If there's no embedded testsettings.. bail out
            if (!IsTestSettingsEnabled(runsettings))
            {
                return(false);
            }

            // Explicitly blocking usage of data collectors through modes runsettings and testsettings except
            // for couple of scenarios where the IDE generates the collector settings in the runsettings file even when
            // it has an embedded testsettings file. Longterm runsettings will be the single run configuration source
            // In-proc collectors are incompatible with testsettings
            var inprocDataCollectionSettings = XmlRunSettingsUtilities.GetInProcDataCollectionRunSettings(runsettings);

            if (inprocDataCollectionSettings != null && inprocDataCollectionSettings.IsCollectionEnabled && inprocDataCollectionSettings.DataCollectorSettingsList != null)
            {
                foreach (var collectorSettings in inprocDataCollectionSettings.DataCollectorSettingsList)
                {
                    if (collectorSettings.IsEnabled)
                    {
                        EqtTrace.Warning($"Incompatible collector found. {collectorSettings.FriendlyName} : {collectorSettings.Uri}");
                        return(true);
                    }
                }
            }

            // TestSettings and collection is enabled in runsetttings.. the only allowed collectors are code coverage and fakes
            var datacollectionSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(runsettings);

            if (datacollectionSettings != null && datacollectionSettings.IsCollectionEnabled && datacollectionSettings.DataCollectorSettingsList != null)
            {
                foreach (var collectorRef in datacollectionSettings.DataCollectorSettingsList)
                {
                    // Ignore disabled collector
                    if (!collectorRef.IsEnabled)
                    {
                        continue;
                    }

                    // If the configured collector is code coverage or fakes.. ignore
                    if (!string.IsNullOrWhiteSpace(collectorRef.FriendlyName) &&
                        (FakesFriendlyName.Equals(collectorRef.FriendlyName, StringComparison.OrdinalIgnoreCase) ||
                         CodeCoverageFriendlyName.Equals(collectorRef.FriendlyName, StringComparison.OrdinalIgnoreCase)))
                    {
                        continue;
                    }

                    // If the configured collector is code coverage or fakes.. ignore
                    if (collectorRef.Uri != null &&
                        (CodeCoverageCollectorUri.Equals(collectorRef.Uri.ToString(), StringComparison.OrdinalIgnoreCase) ||
                         FakesCollectorUri.Equals(collectorRef.Uri.ToString(), StringComparison.OrdinalIgnoreCase)))
                    {
                        continue;
                    }

                    EqtTrace.Warning($"Incompatible collector found. {collectorRef.FriendlyName} : {collectorRef.Uri}");
                    return(true);
                }
            }

            return(false);
        }
示例#17
0
        /// <summary>
        /// Starts the test run
        /// </summary>
        /// <param name="testRunCriteria"> The settings/options for the test run. </param>
        /// <param name="eventHandler"> EventHandler for handling execution events from Engine. </param>
        /// <returns> The process id of the runner executing tests. </returns>
        public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsHandler eventHandler)
        {
            try
            {
                if (!this.testHostManager.Shared)
                {
                    // Non shared test host requires test source information to launch. Provide the sources
                    // information and create the channel.
                    EqtTrace.Verbose("ProxyExecutionManager: Test host is non shared. Lazy initialize.");
                    var testSources = testRunCriteria.Sources;

                    // If the test execution is with a test filter, group them by sources
                    if (testRunCriteria.HasSpecificTests)
                    {
                        testSources = testRunCriteria.Tests.GroupBy(tc => tc.Source).Select(g => g.Key);
                    }

                    this.InitializeExtensions(testSources);
                }

                this.SetupChannel(testRunCriteria.Sources);

                var executionContext = new TestExecutionContext(
                    testRunCriteria.FrequencyOfRunStatsChangeEvent,
                    testRunCriteria.RunStatsChangeEventTimeout,
                    inIsolation: false,
                    keepAlive: testRunCriteria.KeepAlive,
                    isDataCollectionEnabled: false,
                    areTestCaseLevelEventsRequired: false,
                    hasTestRun: true,
                    isDebug: (testRunCriteria.TestHostLauncher != null && testRunCriteria.TestHostLauncher.IsDebug),
                    testCaseFilter: testRunCriteria.TestCaseFilter);

                if (testRunCriteria.HasSpecificSources)
                {
                    var runRequest = new TestRunCriteriaWithSources(
                        testRunCriteria.AdapterSourceMap,
                        testRunCriteria.TestRunSettings,
                        executionContext);

                    this.RequestSender.StartTestRun(runRequest, eventHandler);
                }
                else
                {
                    var runRequest = new TestRunCriteriaWithTests(
                        testRunCriteria.Tests,
                        testRunCriteria.TestRunSettings,
                        executionContext);

                    this.RequestSender.StartTestRun(runRequest, eventHandler);
                }
            }
            catch (Exception exception)
            {
                EqtTrace.Error("ProxyExecutionManager.StartTestRun: Failed to start test run: {0}", exception);
                var completeArgs = new TestRunCompleteEventArgs(null, false, false, exception, new Collection <AttachmentSet>(), TimeSpan.Zero);
                eventHandler.HandleLogMessage(TestMessageLevel.Error, exception.Message);
                eventHandler.HandleTestRunComplete(completeArgs, null, null, null);
            }

            return(0);
        }
示例#18
0
        /// <summary>
        /// Returns true if legacy settings node is present in runsettings
        /// </summary>
        /// <param name="runsettingsXml">The run settings xml string</param>
        /// <param name="legacySettingsTelemetry">The telemetry data that needs to be captured</param>
        /// <returns></returns>
        public static bool TryGetLegacySettingElements(string runsettingsXml, out Dictionary <string, string> legacySettingsTelemetry)
        {
            legacySettingsTelemetry = new Dictionary <string, string>();
            try
            {
                using (var stream = new StringReader(runsettingsXml))
                    using (var reader = XmlReader.Create(stream, XmlRunSettingsUtilities.ReaderSettings))
                    {
                        var document = new XmlDocument();
                        document.Load(reader);
                        var runSettingsNavigator = document.CreateNavigator();

                        var node = runSettingsNavigator.SelectSingleNode(@"/RunSettings/LegacySettings");
                        if (node == null)
                        {
                            return(false);
                        }

                        var childNodes = node.SelectChildren(XPathNodeType.Element);

                        var legacySettingElements = new List <string>();
                        while (childNodes.MoveNext())
                        {
                            legacySettingElements.Add(childNodes.Current.Name);
                        }

                        foreach (var executionNodePath in ExecutionNodesPaths)
                        {
                            var executionNode = runSettingsNavigator.SelectSingleNode(executionNodePath);
                            if (executionNode != null)
                            {
                                legacySettingElements.Add(executionNode.Name);
                            }
                        }

                        if (legacySettingElements.Count > 0)
                        {
                            legacySettingsTelemetry.Add(LegacyElementsString, string.Join(", ", legacySettingElements));
                        }

                        var deploymentNode       = runSettingsNavigator.SelectSingleNode(@"/RunSettings/LegacySettings/Deployment");
                        var deploymentAttributes = GetNodeAttributes(deploymentNode);
                        if (deploymentAttributes != null)
                        {
                            legacySettingsTelemetry.Add(DeploymentAttributesString, string.Join(", ", deploymentAttributes));
                        }

                        var executiontNode       = runSettingsNavigator.SelectSingleNode(@"/RunSettings/LegacySettings/Execution");
                        var executiontAttributes = GetNodeAttributes(executiontNode);
                        if (executiontAttributes != null)
                        {
                            legacySettingsTelemetry.Add(ExecutionAttributesString, string.Join(", ", executiontAttributes));
                        }
                    }
            }
            catch (Exception ex)
            {
                EqtTrace.Error("Error while trying to read legacy settings. Message: {0}", ex.ToString());
                return(false);
            }

            return(true);
        }
示例#19
0
 /// <summary>
 /// Handles discovered tests
 /// </summary>
 /// <param name="discoveredTestCases">List of test cases</param>
 public void HandleDiscoveredTests(IEnumerable <TestCase> discoveredTestCases)
 {
     EqtTrace.Info("Test Cases found ");
     this.requestHandler.SendTestCases(discoveredTestCases);
 }
示例#20
0
        /// <summary>
        /// Make runsettings compatible with testhost of version 15.0.0-preview
        /// Due to bug https://github.com/Microsoft/vstest/issues/970 we need this function
        /// </summary>
        /// <param name="runsettingsXml">string content of runsettings </param>
        /// <returns>compatible runsettings</returns>
        public static string MakeRunsettingsCompatible(string runsettingsXml)
        {
            var updatedRunSettingsXml = runsettingsXml;

            if (!string.IsNullOrWhiteSpace(runsettingsXml))
            {
                using (var stream = new StringReader(runsettingsXml))
                    using (var reader = XmlReader.Create(stream, XmlRunSettingsUtilities.ReaderSettings))
                    {
                        var document = new XmlDocument();
                        document.Load(reader);

                        var runSettingsNavigator = document.CreateNavigator();

                        // Move navigator to RunConfiguration node
                        if (!runSettingsNavigator.MoveToChild(RunSettingsNodeName, string.Empty) ||
                            !runSettingsNavigator.MoveToChild(RunConfigurationNodeName, string.Empty))
                        {
                            EqtTrace.Error("InferRunSettingsHelper.MakeRunsettingsCompatible: Unable to navigate to RunConfiguration. Current node: " + runSettingsNavigator.LocalName);
                        }
                        else if (runSettingsNavigator.HasChildren)
                        {
                            var listOfInValidRunConfigurationSettings = new List <string>();

                            // These are the list of valid RunConfiguration setting name which old testhost understand.
                            var listOfValidRunConfigurationSettings = new HashSet <string>
                            {
                                "TargetPlatform",
                                "TargetFrameworkVersion",
                                "TestAdaptersPaths",
                                "ResultsDirectory",
                                "SolutionDirectory",
                                "MaxCpuCount",
                                "DisableParallelization",
                                "DisableAppDomain"
                            };

                            // Find all invalid RunConfiguration Settings
                            runSettingsNavigator.MoveToFirstChild();
                            do
                            {
                                if (!listOfValidRunConfigurationSettings.Contains(runSettingsNavigator.LocalName))
                                {
                                    listOfInValidRunConfigurationSettings.Add(runSettingsNavigator.LocalName);
                                }
                            } while (runSettingsNavigator.MoveToNext());

                            // Delete all invalid RunConfiguration Settings
                            if (listOfInValidRunConfigurationSettings.Count > 0)
                            {
                                if (EqtTrace.IsWarningEnabled)
                                {
                                    string settingsName = string.Join(", ", listOfInValidRunConfigurationSettings);
                                    EqtTrace.Warning(string.Format("InferRunSettingsHelper.MakeRunsettingsCompatible: Removing the following settings: {0} from RunSettings file. To use those settings please move to latest version of Microsoft.NET.Test.Sdk", settingsName));
                                }

                                // move navigator to RunConfiguration node
                                runSettingsNavigator.MoveToParent();

                                foreach (var s in listOfInValidRunConfigurationSettings)
                                {
                                    var nodePath = RunConfigurationNodePath + "/" + s;
                                    XmlUtilities.RemoveChildNode(runSettingsNavigator, nodePath, s);
                                }

                                runSettingsNavigator.MoveToRoot();
                                updatedRunSettingsXml = runSettingsNavigator.OuterXml;
                            }
                        }
                    }
            }

            return(updatedRunSettingsXml);
        }
示例#21
0
        /// <summary>
        /// Determines Architecture from sources.
        /// </summary>
        public Architecture AutoDetectArchitecture(List <string> sources, IDictionary <string, Architecture> sourcePlatforms)
        {
            Architecture architecture = Constants.DefaultPlatform;

            try
            {
                if (sources != null && sources.Count > 0)
                {
                    Architecture?finalArch = null;
                    foreach (string source in sources)
                    {
                        Architecture arch;
                        if (IsDotNETAssembly(source))
                        {
                            arch = assemblyMetadataProvider.GetArchitecture(source);
                        }
                        else
                        {
                            // Set AnyCPU for non dotnet test sources (js, py and other). Otherwise warning will
                            // show up if there is mismatch with user provided platform.
                            arch = Architecture.AnyCPU;
                        }
                        sourcePlatforms[source] = (Architecture)arch;

                        if (Architecture.AnyCPU.Equals(arch))
                        {
                            // If arch is AnyCPU ignore it.
                            continue;
                        }

                        if (finalArch == null)
                        {
                            finalArch = arch;
                            continue;
                        }

                        if (!finalArch.Equals(arch))
                        {
                            finalArch = Constants.DefaultPlatform;
                            EqtTrace.Info("Conflict in platform architecture, using default platform:{0}", finalArch);
                        }
                    }

                    if (finalArch != null)
                    {
                        architecture = (Architecture)finalArch;
                    }
                }
            }
            catch (Exception ex)
            {
                EqtTrace.Error("Failed to determine platform: {0}, using default: {1}", ex, architecture);
            }

            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("Determined platform for all sources: {0}", architecture);
            }

            return(architecture);
        }
示例#22
0
        /// <inheritdoc/>
        public virtual TestProcessStartInfo GetTestHostProcessStartInfo(
            IEnumerable <string> sources,
            IDictionary <string, string> environmentVariables,
            TestRunnerConnectionInfo connectionInfo)
        {
            var startInfo = new TestProcessStartInfo();

            var currentProcessPath = this.processHelper.GetCurrentProcessFileName();

            // This host manager can create process start info for dotnet core targets only.
            // If already running with the dotnet executable, use it; otherwise pick up the dotnet available on path.
            // Wrap the paths with quotes in case dotnet executable is installed on a path with whitespace.
            if (currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase) ||
                currentProcessPath.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase))
            {
                startInfo.FileName = currentProcessPath;
            }
            else
            {
                startInfo.FileName = this.dotnetHostHelper.GetDotnetPath();
            }

            EqtTrace.Verbose("DotnetTestHostmanager: Full path of dotnet.exe is {0}", startInfo.FileName);

            // .NET core host manager is not a shared host. It will expect a single test source to be provided.
            var args            = "exec";
            var sourcePath      = sources.Single();
            var sourceFile      = Path.GetFileNameWithoutExtension(sourcePath);
            var sourceDirectory = Path.GetDirectoryName(sourcePath);

            // Probe for runtimeconfig and deps file for the test source
            var runtimeConfigPath = Path.Combine(sourceDirectory, string.Concat(sourceFile, ".runtimeconfig.json"));

            if (this.fileHelper.Exists(runtimeConfigPath))
            {
                string argsToAdd = " --runtimeconfig " + runtimeConfigPath.AddDoubleQuote();
                args += argsToAdd;
                EqtTrace.Verbose("DotnetTestHostmanager: Adding {0} in args", argsToAdd);
            }
            else
            {
                EqtTrace.Verbose("DotnetTestHostmanager: File {0}, doesnot exist", runtimeConfigPath);
            }

            // Use the deps.json for test source
            var depsFilePath = Path.Combine(sourceDirectory, string.Concat(sourceFile, ".deps.json"));

            if (this.fileHelper.Exists(depsFilePath))
            {
                string argsToAdd = " --depsfile " + depsFilePath.AddDoubleQuote();
                args += argsToAdd;
                EqtTrace.Verbose("DotnetTestHostmanager: Adding {0} in args", argsToAdd);
            }
            else
            {
                EqtTrace.Verbose("DotnetTestHostmanager: File {0}, doesnot exist", depsFilePath);
            }

            var runtimeConfigDevPath = Path.Combine(sourceDirectory, string.Concat(sourceFile, ".runtimeconfig.dev.json"));
            var testHostPath         = this.GetTestHostPath(runtimeConfigDevPath, depsFilePath, sourceDirectory);

            if (this.fileHelper.Exists(testHostPath))
            {
                EqtTrace.Verbose("DotnetTestHostmanager: Full path of testhost.dll is {0}", testHostPath);
                args += " " + testHostPath.AddDoubleQuote() + " " + connectionInfo.ToCommandLineOptions();
            }
            else
            {
                string message = string.Format(CultureInfo.CurrentCulture, Resources.NoTestHostFileExist, sourcePath);
                EqtTrace.Verbose("DotnetTestHostmanager: " + message);
                throw new FileNotFoundException(message);
            }

            // Create a additional probing path args with Nuget.Client
            // args += "--additionalprobingpath xxx"
            // TODO this may be required in ASP.net, requires validation

            // Sample command line for the spawned test host
            // "D:\dd\gh\Microsoft\vstest\tools\dotnet\dotnet.exe" exec
            // --runtimeconfig G:\tmp\netcore-test\bin\Debug\netcoreapp1.0\netcore-test.runtimeconfig.json
            // --depsfile G:\tmp\netcore-test\bin\Debug\netcoreapp1.0\netcore-test.deps.json
            // --additionalprobingpath C:\Users\username\.nuget\packages\
            // G:\nuget-package-path\microsoft.testplatform.testhost\version\**\testhost.dll
            // G:\tmp\netcore-test\bin\Debug\netcoreapp1.0\netcore-test.dll
            startInfo.Arguments            = args;
            startInfo.EnvironmentVariables = environmentVariables ?? new Dictionary <string, string>();
            startInfo.WorkingDirectory     = sourceDirectory;

            return(startInfo);
        }
示例#23
0
        private void OnExecutionMessageReceived(object sender, MessageReceivedEventArgs messageReceived, ITestRunEventsHandler testRunEventsHandler)
        {
            try
            {
                var rawMessage = messageReceived.Data;
                if (EqtTrace.IsVerboseEnabled)
                {
                    EqtTrace.Verbose("TestRequestSender.OnExecutionMessageReceived: Received message: {0}", rawMessage);
                }

                // Send raw message first to unblock handlers waiting to send message to IDEs
                testRunEventsHandler.HandleRawMessage(rawMessage);

                var message = this.dataSerializer.DeserializeMessage(rawMessage);
                switch (message.MessageType)
                {
                case MessageType.TestRunStatsChange:
                    var testRunChangedArgs = this.dataSerializer.DeserializePayload <TestRunChangedEventArgs>(message);
                    testRunEventsHandler.HandleTestRunStatsChange(testRunChangedArgs);
                    break;

                case MessageType.ExecutionComplete:
                    var testRunCompletePayload = this.dataSerializer.DeserializePayload <TestRunCompletePayload>(message);

                    testRunEventsHandler.HandleTestRunComplete(
                        testRunCompletePayload.TestRunCompleteArgs,
                        testRunCompletePayload.LastRunTests,
                        testRunCompletePayload.RunAttachments,
                        testRunCompletePayload.ExecutorUris);

                    this.SetOperationComplete();
                    break;

                case MessageType.TestMessage:
                    var testMessagePayload = this.dataSerializer.DeserializePayload <TestMessagePayload>(message);
                    testRunEventsHandler.HandleLogMessage(testMessagePayload.MessageLevel, testMessagePayload.Message);
                    break;

                case MessageType.LaunchAdapterProcessWithDebuggerAttached:
                    var testProcessStartInfo = this.dataSerializer.DeserializePayload <TestProcessStartInfo>(message);
                    int processId            = testRunEventsHandler.LaunchProcessWithDebuggerAttached(testProcessStartInfo);

                    var data =
                        this.dataSerializer.SerializePayload(
                            MessageType.LaunchAdapterProcessWithDebuggerAttachedCallback,
                            processId,
                            this.protocolVersion);
                    if (EqtTrace.IsVerboseEnabled)
                    {
                        EqtTrace.Verbose("TestRequestSender.OnExecutionMessageReceived: Sending LaunchAdapterProcessWithDebuggerAttachedCallback message: {0}", data);
                    }

                    this.channel.Send(data);
                    break;

                case MessageType.AttachDebugger:
                    var  testProcessPid = this.dataSerializer.DeserializePayload <TestProcessAttachDebuggerPayload>(message);
                    bool result         = ((ITestRunEventsHandler2)testRunEventsHandler).AttachDebuggerToProcess(testProcessPid.ProcessID);

                    var resultMessage = this.dataSerializer.SerializePayload(
                        MessageType.AttachDebuggerCallback,
                        result,
                        this.protocolVersion);

                    this.channel.Send(resultMessage);

                    break;
                }
            }
            catch (Exception exception)
            {
                this.OnTestRunAbort(testRunEventsHandler, exception, false);
            }
        }
示例#24
0
        private string GetTestHostPath(string runtimeConfigDevPath, string depsFilePath, string sourceDirectory)
        {
            string testHostPackageName = "microsoft.testplatform.testhost";
            string testHostPath        = string.Empty;

            if (this.fileHelper.Exists(runtimeConfigDevPath) && this.fileHelper.Exists(depsFilePath))
            {
                EqtTrace.Verbose("DotnetTestHostmanager: Reading file {0} to get path of testhost.dll", depsFilePath);

                // Get testhost relative path
                using (var stream = this.fileHelper.GetStream(depsFilePath, FileMode.Open))
                {
                    var context         = new DependencyContextJsonReader().Read(stream);
                    var testhostPackage = context.RuntimeLibraries.Where(lib => lib.Name.Equals(testHostPackageName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

                    if (testhostPackage != null)
                    {
                        foreach (var runtimeAssemblyGroup in testhostPackage.RuntimeAssemblyGroups)
                        {
                            foreach (var path in runtimeAssemblyGroup.AssetPaths)
                            {
                                if (path.EndsWith("testhost.dll", StringComparison.OrdinalIgnoreCase))
                                {
                                    testHostPath = path;
                                    break;
                                }
                            }
                        }

                        testHostPath            = Path.Combine(testhostPackage.Path, testHostPath);
                        this.hostPackageVersion = testhostPackage.Version;
                        EqtTrace.Verbose("DotnetTestHostmanager: Relative path of testhost.dll with respect to package folder is {0}", testHostPath);
                    }
                }

                // Get probing path
                using (StreamReader file = new StreamReader(this.fileHelper.GetStream(runtimeConfigDevPath, FileMode.Open)))
                    using (JsonTextReader reader = new JsonTextReader(file))
                    {
                        JObject context                = (JObject)JToken.ReadFrom(reader);
                        JObject runtimeOptions         = (JObject)context.GetValue("runtimeOptions");
                        JToken  additionalProbingPaths = runtimeOptions.GetValue("additionalProbingPaths");
                        foreach (var x in additionalProbingPaths)
                        {
                            EqtTrace.Verbose("DotnetTestHostmanager: Looking for path {0} in folder {1}", testHostPath, x.ToString());
                            string testHostFullPath;
                            try
                            {
                                testHostFullPath = Path.Combine(x.ToString(), testHostPath);
                            }
                            catch (ArgumentException)
                            {
                                // https://github.com/Microsoft/vstest/issues/847
                                // skip any invalid paths and continue checking the others
                                continue;
                            }

                            if (this.fileHelper.Exists(testHostFullPath))
                            {
                                return(testHostFullPath);
                            }
                        }
                    }
            }

            // If we are here it means it couldnt resolve testhost.dll from nuget chache.
            // Try resolving testhost from output directory of test project. This is required if user has published the test project
            // and is running tests in an isolated machine. A second scenario is self test: test platform unit tests take a project
            // dependency on testhost (instead of nuget dependency), this drops testhost to output path.
            testHostPath = Path.Combine(sourceDirectory, "testhost.dll");
            EqtTrace.Verbose("DotnetTestHostManager: Assume published test project, with test host path = {0}.", testHostPath);

            return(testHostPath);
        }
示例#25
0
        public static bool SplitCommandLineIntoArguments(string args, out string[] arguments)
        {
            bool hadError   = false;
            var  argArray   = new List <string>();
            var  currentArg = new StringBuilder();
            bool inQuotes   = false;
            int  index      = 0;

            try
            {
                while (true)
                {
                    // skip whitespace
                    while (char.IsWhiteSpace(args[index]))
                    {
                        index++;
                    }

                    // # - comment to end of line
                    if (args[index] == '#')
                    {
                        index++;
                        while (args[index] != '\n')
                        {
                            index++;
                        }
                        continue;
                    }

                    // do one argument
                    do
                    {
                        if (args[index] == '\\')
                        {
                            int cSlashes = 1;
                            index++;
                            while (index == args.Length && args[index] == '\\')
                            {
                                cSlashes++;
                            }

                            if (index == args.Length || args[index] != '"')
                            {
                                currentArg.Append('\\', cSlashes);
                            }
                            else
                            {
                                currentArg.Append('\\', (cSlashes >> 1));
                                if (0 != (cSlashes & 1))
                                {
                                    currentArg.Append('"');
                                }
                                else
                                {
                                    inQuotes = !inQuotes;
                                }
                            }
                        }
                        else if (args[index] == '"')
                        {
                            inQuotes = !inQuotes;
                            index++;
                        }
                        else
                        {
                            currentArg.Append(args[index]);
                            index++;
                        }
                    } while (!char.IsWhiteSpace(args[index]) || inQuotes);
                    argArray.Add(currentArg.ToString());
                    currentArg.Clear();
                }
            }
            catch (IndexOutOfRangeException)
            {
                // got EOF
                if (inQuotes)
                {
                    EqtTrace.Verbose("Executor.Execute: Exiting with exit code of {0}", 1);
                    EqtTrace.Error(string.Format(CultureInfo.InvariantCulture, "Error: Unbalanced '\"' in command line argument file"));
                    hadError = true;
                }
                else if (currentArg.Length > 0)
                {
                    // valid argument can be terminated by EOF
                    argArray.Add(currentArg.ToString());
                }
            }

            arguments = argArray.ToArray();
            return(hadError);
        }
示例#26
0
        public override List <string> GetDataTablesAndViews()
        {
            WriteDiagnostics("GetDataTablesAndViews");
            List <string> tableNames = new List <string>();

            try
            {
                string defaultSchema = this.GetDefaultSchema();
                WriteDiagnostics("Default schema is {0}", defaultSchema);

                SchemaMetaData[] metadatas = this.GetSchemaMetaData();

                // TODO: may be find better way to enumerate tables/views.
                foreach (SchemaMetaData metadata in metadatas)
                {
                    DataTable dataTable = null;
                    try
                    {
                        WriteDiagnostics("Getting schema table {0}", metadata.SchemaTable);
                        dataTable = this.Connection.GetSchema(metadata.SchemaTable);
                    }
                    catch (Exception ex)
                    {
                        WriteDiagnostics("Failed to get schema table");

                        // This can be normal case as some providers do not support views.
                        EqtTrace.WarningIf(EqtTrace.IsWarningEnabled, "DataUtil.GetDataTablesAndViews: exception (can be normal case as some providers do not support views): " + ex);
                        continue;
                    }

                    Debug.Assert(dataTable != null, "Failed to get data table that contains metadata about tables!");

                    foreach (DataRow row in dataTable.Rows)
                    {
                        WriteDiagnostics("Row: {0}", row);
                        string tableSchema     = null;
                        bool   isDefaultSchema = false;

                        // Check the table type for validity
                        if (metadata.TableTypeColumn != null)
                        {
                            if (row[metadata.TableTypeColumn] != DBNull.Value)
                            {
                                string tableType = row[metadata.TableTypeColumn] as string;
                                if (!IsInArray(tableType, metadata.ValidTableTypes))
                                {
                                    WriteDiagnostics("Table type {0} is not acceptable", tableType);

                                    // Not a valid table type, get the next row
                                    continue;
                                }
                            }
                        }

                        // Get the schema name, and filter bad schemas
                        if (row[metadata.SchemaColumn] != DBNull.Value)
                        {
                            tableSchema = row[metadata.SchemaColumn] as string;

                            if (IsInArray(tableSchema, metadata.InvalidSchemas))
                            {
                                WriteDiagnostics("Schema {0} is not acceptable", tableSchema);

                                // A table in a schema we do not want to see, get the next row
                                continue;
                            }

                            isDefaultSchema = string.Equals(tableSchema, defaultSchema, StringComparison.OrdinalIgnoreCase);
                        }

                        string tableName = row[metadata.NameColumn] as string;
                        WriteDiagnostics("Table {0}{1} found", tableSchema != null ? tableSchema + "." : string.Empty, tableName);

                        // If schema is defined and is not equal to default, prepend table schema in front of the table.
                        string qualifiedTableName = tableName;
                        if (isDefaultSchema)
                        {
                            qualifiedTableName = this.FormatTableNameForDisplay(null, tableName);
                        }
                        else
                        {
                            qualifiedTableName = this.FormatTableNameForDisplay(tableSchema, tableName);
                        }

                        WriteDiagnostics("Adding Table {0}", qualifiedTableName);
                        tableNames.Add(qualifiedTableName);
                    }

                    tableNames.Sort(StringComparer.OrdinalIgnoreCase);
                }
            }
            catch (Exception e)
            {
                WriteDiagnostics("Failed to fetch tables for {0}, exception: {1}", this.Connection.ConnectionString, e);

                // OK to fall through and return whatever we do have...
            }

            return(tableNames);
        }
示例#27
0
        /// <inheritdoc/>
        public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable <TestCase> lastChunk)
        {
            if (EqtTrace.IsVerboseEnabled)
            {
                EqtTrace.Verbose("DiscoveryRequest.DiscoveryComplete: Starting. Aborted:{0}, TotalTests:{1}", discoveryCompleteEventArgs.IsAborted, discoveryCompleteEventArgs.TotalCount);
            }

            lock (this.syncObject)
            {
                if (this.disposed)
                {
                    if (EqtTrace.IsWarningEnabled)
                    {
                        EqtTrace.Warning("DiscoveryRequest.DiscoveryComplete: Ignoring as the object is disposed.");
                    }

                    return;
                }

                // If discovery event is already raised, ignore current one.
                if (this.discoveryCompleted.WaitOne(0))
                {
                    if (EqtTrace.IsVerboseEnabled)
                    {
                        EqtTrace.Verbose("DiscoveryRequest.DiscoveryComplete:Ignoring duplicate DiscoveryComplete. Aborted:{0}, TotalTests:{1}", discoveryCompleteEventArgs.IsAborted, discoveryCompleteEventArgs.TotalCount);
                    }

                    return;
                }

                // Close the discovery session and terminate any test host processes. This operation should never
                // throw.
                this.DiscoveryManager?.Close();

                try
                {
                    // Raise onDiscoveredTests event if there are some tests in the last chunk.
                    // (We don't want to send the tests in the discovery complete event so that programming on top of
                    // RS client is easier i.e. user does not have to listen on discovery complete event.)
                    if (lastChunk != null && lastChunk.Any())
                    {
                        var discoveredTestsEvent = new DiscoveredTestsEventArgs(lastChunk);
                        this.LoggerManager.HandleDiscoveredTests(discoveredTestsEvent);
                        this.OnDiscoveredTests.SafeInvoke(this, discoveredTestsEvent, "DiscoveryRequest.DiscoveryComplete");
                    }

                    this.LoggerManager.HandleDiscoveryComplete(discoveryCompleteEventArgs);
                    this.OnDiscoveryComplete.SafeInvoke(this, discoveryCompleteEventArgs, "DiscoveryRequest.DiscoveryComplete");
                }
                finally
                {
                    // Notify the waiting handle that discovery is complete
                    if (this.discoveryCompleted != null)
                    {
                        this.discoveryCompleted.Set();
                        if (EqtTrace.IsVerboseEnabled)
                        {
                            EqtTrace.Verbose("DiscoveryRequest.DiscoveryComplete: Notified the discovery complete event.");
                        }
                    }
                    else
                    {
                        if (EqtTrace.IsWarningEnabled)
                        {
                            EqtTrace.Warning("DiscoveryRequest.DiscoveryComplete: Discovery complete event was null.");
                        }
                    }

                    this.discoveryInProgress = false;
                    var discoveryFinalTimeTaken = DateTime.UtcNow - this.discoveryStartTime;

                    // Fill in the Metrics From Test Host Process
                    var metrics = discoveryCompleteEventArgs.Metrics;
                    if (metrics != null && metrics.Count != 0)
                    {
                        foreach (var metric in metrics)
                        {
                            this.requestData.MetricsCollection.Add(metric.Key, metric.Value);
                        }
                    }

                    // Collecting Total Time Taken
                    this.requestData.MetricsCollection.Add(
                        TelemetryDataConstants.TimeTakenInSecForDiscovery, discoveryFinalTimeTaken.TotalSeconds);
                }
            }

            if (EqtTrace.IsInfoEnabled)
            {
                EqtTrace.Info("DiscoveryRequest.DiscoveryComplete: Completed.");
            }
        }
        /// <summary>
        /// Handles Partial Run Complete event coming from a specific concurrent proxy exceution manager
        /// Each concurrent proxy execution manager will signal the parallel execution manager when its complete
        /// </summary>
        /// <param name="proxyExecutionManager">Concurrent Execution manager that completed the run</param>
        /// <param name="testRunCompleteArgs">RunCompleteArgs for the concurrent run</param>
        /// <param name="lastChunkArgs">LastChunk testresults for the concurrent run</param>
        /// <param name="runContextAttachments">RunAttachments for the concurrent run</param>
        /// <param name="executorUris">ExecutorURIs of the adapters involved in executing the tests</param>
        /// <returns>True if parallel run is complete</returns>
        public bool HandlePartialRunComplete(
            IProxyExecutionManager proxyExecutionManager,
            TestRunCompleteEventArgs testRunCompleteArgs,
            TestRunChangedEventArgs lastChunkArgs,
            ICollection <AttachmentSet> runContextAttachments,
            ICollection <string> executorUris)
        {
            var allRunsCompleted = false;

            lock (this.executionStatusLockObject)
            {
                // Each concurrent Executor calls this method
                // So, we need to keep track of total runcomplete calls
                this.runCompletedClients++;

                if (testRunCompleteArgs.IsCanceled)
                {
                    allRunsCompleted = this.runCompletedClients == this.runStartedClients;
                }
                else
                {
                    allRunsCompleted = this.runCompletedClients == this.availableTestSources;
                }

                if (EqtTrace.IsVerboseEnabled)
                {
                    EqtTrace.Verbose("ParallelProxyExecutionManager: HandlePartialRunComplete: Total completed clients = {0}, Run complete = {1}, Run canceled: {2}.", this.runCompletedClients, allRunsCompleted, testRunCompleteArgs.IsCanceled);
                }
            }

            // verify that all executors are done with the execution and there are no more sources/testcases to execute
            if (allRunsCompleted)
            {
                // Reset enumerators
                this.sourceEnumerator       = null;
                this.testCaseListEnumerator = null;

                this.currentRunDataAggregator = null;
                this.currentRunEventsHandler  = null;

                // Dispose concurrent executors
                // Do not do the cleanuptask in the current thread as we will unncessarily add to execution time
                this.lastParallelRunCleanUpTask = Task.Run(() =>
                {
                    this.UpdateParallelLevel(0);
                });

                return(true);
            }

            // In case of DataCollection we only start dc.exe on initialize, & close once the TestRun is complete,
            // So instead of resuing ProxyExecutionManager, we will close it here, & create new PEMWDC
            // In Case of Abort, clean old one and create new proxyExecutionManager in place of old one.
            if (!this.SharedHosts || testRunCompleteArgs.IsAborted || (proxyExecutionManager is ProxyExecutionManagerWithDataCollection))
            {
                if (EqtTrace.IsVerboseEnabled)
                {
                    EqtTrace.Verbose("ParallelProxyExecutionManager: HandlePartialRunComplete: Replace execution manager. Shared: {0}, Aborted: {1}.", this.SharedHosts, testRunCompleteArgs.IsAborted);
                }

                this.RemoveManager(proxyExecutionManager);
                proxyExecutionManager = CreateNewConcurrentManager();
                var parallelEventsHandler = this.GetEventsHandler(proxyExecutionManager);
                this.AddManager(proxyExecutionManager, parallelEventsHandler);
            }

            // If cancel is triggered for any one run, there is no reason to fetch next source
            // and queue another test run
            if (!testRunCompleteArgs.IsCanceled)
            {
                this.StartTestRunOnConcurrentManager(proxyExecutionManager);
            }

            return(false);
        }
示例#29
0
 /// <inheritdoc />
 public void Close()
 {
     this.Dispose();
     EqtTrace.Info("Closing the connection");
 }
示例#30
0
        public void Invoke(IDictionary <string, string> argsDictionary)
        {
            // Setup logging if enabled
            string logFile;

            if (argsDictionary.TryGetValue(LogFileArgument, out logFile))
            {
                EqtTrace.InitializeVerboseTrace(logFile);
            }

#if NET451
            if (EqtTrace.IsInfoEnabled)
            {
                var appConfigText = System.IO.File.ReadAllText(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                EqtTrace.Info("DefaultEngineInvoker: Using Application Configuration: '{0}'", appConfigText);
            }
#endif

            // vstest.console < 15.5 won't send endpoint and role arguments.
            // So derive endpoint from port argument and Make connectionRole as Client.
            string endpoint = CommandLineArgumentsHelper.GetStringArgFromDict(argsDictionary, EndpointArgument);
            if (string.IsNullOrWhiteSpace(endpoint))
            {
                var port = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, "--port");
                endpoint = IPAddress.Loopback + ":" + port;
            }

            var    connectionRole = ConnectionRole.Client;
            string role           = CommandLineArgumentsHelper.GetStringArgFromDict(argsDictionary, RoleArgument);
            if (!string.IsNullOrWhiteSpace(role) && string.Equals(role, "host", StringComparison.OrdinalIgnoreCase))
            {
                connectionRole = ConnectionRole.Host;
            }

            // Start Processing of requests
            using (var requestHandler = new TestRequestHandler(new TestHostConnectionInfo {
                Endpoint = endpoint, Role = connectionRole, Transport = Transport.Sockets
            }))
            {
                // Attach to exit of parent process
                var parentProcessId = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, ParentProcessIdArgument);
                EqtTrace.Info("DefaultEngineInvoker: Monitoring parent process with id: '{0}'", parentProcessId);

                // In remote scenario we cannot monitor parent process, so we expect user to pass parentProcessId as -1
                if (parentProcessId != -1)
                {
                    var processHelper = new ProcessHelper();
                    processHelper.SetExitCallback(
                        parentProcessId,
                        () =>
                    {
                        EqtTrace.Info("DefaultEngineInvoker: ParentProcess '{0}' Exited.", parentProcessId);
                        new PlatformEnvironment().Exit(1);
                    });
                }

                // Initialize Communication
                EqtTrace.Info("DefaultEngineInvoker: Initialize communication on endpoint address: '{0}'", endpoint);
                requestHandler.InitializeCommunication();

                // Initialize DataCollection Communication if data collection port is provided.
                var dcPort = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, DataCollectionPortArgument);
                if (dcPort > 0)
                {
                    var dataCollectionTestCaseEventSender = DataCollectionTestCaseEventSender.Create();
                    dataCollectionTestCaseEventSender.InitializeCommunication(dcPort);
                    dataCollectionTestCaseEventSender.WaitForRequestSenderConnection(ClientListenTimeOut);
                }

                // Start processing async in a different task
                EqtTrace.Info("DefaultEngineInvoker: Start Request Processing.");
                var requestData    = new RequestData(new MetricsCollection());
                var processingTask = this.StartProcessingAsync(requestHandler, new TestHostManagerFactory(requestData));

                // Wait for processing to complete.
                Task.WaitAny(processingTask);

                if (dcPort > 0)
                {
                    // Close socket communication connection.
                    DataCollectionTestCaseEventSender.Instance.Close();
                }
            }
        }