-
Notifications
You must be signed in to change notification settings - Fork 325
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feature blame (#1) This feature gets the faulty test case name in event of a test host crash of reason unknown. There are various scenarios in which the test host crashes due to a faulty test case and the reason cannot be diagnosed. This pull request gets the name of the test case which caused the crash and displays it on the console. To enable the blame mode, use --Blame|/Blame * Unit tests added and minor changes * Suggested changes made * Spaces removed * Build updated * Integration test added * Blame Processor priority changed in test * BlameUnitTestProject updated * SDK Previous version updated to 15.3.0-preview-20170628-02
- Loading branch information
1 parent
a08c38a
commit c62f4d3
Showing
59 changed files
with
2,344 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 174 additions & 0 deletions
174
src/Microsoft.TestPlatform.Extensions.BlameDataCollector/BlameCollector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Xml; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; | ||
|
||
/// <summary> | ||
/// The blame collector. | ||
/// </summary> | ||
[DataCollectorFriendlyName("Blame")] | ||
[DataCollectorTypeUri("datacollector://Microsoft/TestPlatform/Extensions/Blame/v1")] | ||
public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | ||
{ | ||
private DataCollectionSink dataCollectionSink; | ||
private DataCollectionEnvironmentContext context; | ||
private DataCollectionEvents events; | ||
private List<TestCase> testSequence; | ||
private IBlameReaderWriter blameReaderWriter; | ||
private XmlElement configurationElement; | ||
private int testStartCount; | ||
private int testEndCount; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BlameCollector"/> class. | ||
/// Using XmlReaderWriter by default | ||
/// </summary> | ||
public BlameCollector() | ||
: this(new XmlReaderWriter()) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BlameCollector"/> class. | ||
/// </summary> | ||
/// <param name="blameReaderWriter"> | ||
/// BlameReaderWriter instance. | ||
/// </param> | ||
protected BlameCollector(IBlameReaderWriter blameReaderWriter) | ||
{ | ||
this.blameReaderWriter = blameReaderWriter; | ||
} | ||
|
||
/// <summary> | ||
/// Gets environment variables that should be set in the test execution environment | ||
/// </summary> | ||
/// <returns>Environment variables that should be set in the test execution environment</returns> | ||
public IEnumerable<KeyValuePair<string, string>> GetTestExecutionEnvironmentVariables() | ||
{ | ||
return Enumerable.Empty<KeyValuePair<string, string>>(); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes parameters for the new instance of the class <see cref="BlameDataCollector"/> | ||
/// </summary> | ||
/// <param name="configurationElement">The Xml Element to save to</param> | ||
/// <param name="events">Data collection events to which methods subscribe</param> | ||
/// <param name="dataSink">A data collection sink for data transfer</param> | ||
/// <param name="logger">Data Collection Logger to send messages to the client </param> | ||
/// <param name="environmentContext">Context of data collector environment</param> | ||
public override void Initialize( | ||
XmlElement configurationElement, | ||
DataCollectionEvents events, | ||
DataCollectionSink dataSink, | ||
DataCollectionLogger logger, | ||
DataCollectionEnvironmentContext environmentContext) | ||
{ | ||
ValidateArg.NotNull(logger, nameof(logger)); | ||
|
||
this.events = events; | ||
this.dataCollectionSink = dataSink; | ||
this.context = environmentContext; | ||
this.configurationElement = configurationElement; | ||
this.testSequence = new List<TestCase>(); | ||
|
||
// Subscribing to events | ||
this.events.SessionEnd += this.SessionEnded_Handler; | ||
this.events.TestCaseStart += this.EventsTestCaseStart; | ||
this.events.TestCaseEnd += this.EventsTestCaseEnd; | ||
} | ||
|
||
/// <summary> | ||
/// Called when Test Case Start event is invoked | ||
/// </summary> | ||
/// <param name="sender">Sender</param> | ||
/// <param name="e">TestCaseStartEventArgs</param> | ||
private void EventsTestCaseStart(object sender, TestCaseStartEventArgs e) | ||
{ | ||
if (EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info("Blame Collector : Test Case Start"); | ||
} | ||
|
||
this.testSequence.Add(e.TestElement); | ||
this.testStartCount++; | ||
} | ||
|
||
/// <summary> | ||
/// Called when Test Case End event is invoked | ||
/// </summary> | ||
/// <param name="sender">Sender</param> | ||
/// <param name="e">TestCaseEndEventArgs</param> | ||
private void EventsTestCaseEnd(object sender, TestCaseEndEventArgs e) | ||
{ | ||
if (EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info("Blame Collector : Test Case End"); | ||
} | ||
|
||
this.testEndCount++; | ||
} | ||
|
||
/// <summary> | ||
/// Called when Session End event is invoked | ||
/// </summary> | ||
/// <param name="sender">Sender</param> | ||
/// <param name="args">SessionEndEventArgs</param> | ||
private void SessionEnded_Handler(object sender, SessionEndEventArgs args) | ||
{ | ||
if (EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info("Blame Collector : Session End"); | ||
} | ||
|
||
// If the last test crashes, it will not invoke a test case end and therefore | ||
// In case of crash testStartCount will be greater than testEndCount and we need to write the sequence | ||
// And send the attachment | ||
if (this.testStartCount > this.testEndCount) | ||
{ | ||
var filepath = Path.Combine(this.GetResultsDirectory(), Constants.AttachmentFileName); | ||
filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, filepath); | ||
var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true); | ||
this.dataCollectionSink.SendFileAsync(fileTranferInformation); | ||
} | ||
|
||
this.DeregisterEvents(); | ||
} | ||
|
||
/// <summary> | ||
/// Method to deregister handlers and cleanup | ||
/// </summary> | ||
private void DeregisterEvents() | ||
{ | ||
this.events.SessionEnd -= this.SessionEnded_Handler; | ||
this.events.TestCaseStart -= this.EventsTestCaseStart; | ||
this.events.TestCaseEnd -= this.EventsTestCaseEnd; | ||
} | ||
|
||
private string GetResultsDirectory() | ||
{ | ||
try | ||
{ | ||
XmlElement resultsDirectoryElement = this.configurationElement["ResultsDirectory"]; | ||
string resultsDirectory = resultsDirectoryElement != null ? resultsDirectoryElement.InnerText : string.Empty; | ||
return resultsDirectory; | ||
} | ||
catch (NullReferenceException exception) | ||
{ | ||
if (EqtTrace.IsErrorEnabled) | ||
{ | ||
EqtTrace.Error("Blame Collector : " + exception); | ||
} | ||
|
||
return string.Empty; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.