-
Notifications
You must be signed in to change notification settings - Fork 331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Data Collector Process #369
Conversation
Hi @harshjain2, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
TTYL, MSBOT; |
@dotnet-bot test this please |
public static bool IsSessionStartedInvoked = false; | ||
public static bool IsSessionEndedInvoked = false; | ||
public static bool GetTestExecutionEnvironmentVariablesThrowException; | ||
public static IEnumerable<KeyValuePair<string, string>> EnvVarList; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a spy, can we use Moq?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we are loading the datacollectors through run settings, it is not possible to dynamically construct the object and load it through run settings.
this.mockMessageSink = new DummyMessageSink(); | ||
this.dataCollectionManager = new DataCollectionManager(new DataCollectionAttachmentManager(), new DummyMessageSink()); | ||
|
||
this.dataCollectorSettings = string.Format("<DataCollector friendlyName=\"CustomDataCollector\" uri=\"my://custom/datacollector\" assemblyQualifiedName=\"Microsoft.VisualStudio.TestPlatform.DataCollector.UnitTests.CustomDataCollector, datacollector.UnitTests, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" codebase=\"{0}\" />", typeof(CustomDataCollector).GetTypeInfo().Assembly.Location); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ft.VisualStudio.TestPlatform.DataCollector.UnitTests.CustomDataCollector, datacollector.UnitTests, Version=15.0.0.0, [](start = 173, length = 116)
Derive this from typeof(CustomDataCollector).GetTypeInfo().Assembly.AssemblyName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
ValidateArg.NotNull(settingsXml, "settingsXml"); | ||
|
||
var sessionId = new SessionId(Guid.NewGuid()); | ||
var dataCollectionContext = new DataCollectionContext(sessionId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DataCollectionContext [](start = 44, length = 21)
Please remove DataCollectionContext(TestCase) ctor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is getting used in InProcDataCollector. We can revisit this later.
|
||
|
||
[TestInitialize] | ||
public void Init() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Init [](start = 20, length = 4)
See if this can be put in ctor.
|
||
this.attachmentManager.Initialize(sessionId, sourceDirectory, this.messageSink); | ||
|
||
var executionEnvironmentVariables = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
executionEnvironmentVariables [](start = 16, length = 29)
Please add a comment with rationale for stringcomparer.
[TestMethod] | ||
public void InitializeDataCollectorsShouldReturnEmptyDictionaryIfDataCollectorsAreNotConfigured() | ||
{ | ||
var RunSettings = string.Format(this.defaultRunSettings, string.Empty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RunSettings [](start = 16, length = 11)
nit: camelCase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
/// <inheritdoc/> | ||
public IDictionary<string, string> InitializeDataCollectors(string settingsXml) | ||
{ | ||
ValidateArg.NotNull(settingsXml, "settingsXml"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add tracing
var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(settingsXml); | ||
sourceDirectory = RunSettingsUtilities.GetTestResultsDirectory(runConfiguration); | ||
|
||
var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(settingsXml); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XmlRunSettingsUtilities, DataCollectionRunSettings does not have traces. Please add.
var result = this.dataCollectionManager.InitializeDataCollectors(runSettings); | ||
|
||
Assert.AreEqual(1, result.Count); | ||
Assert.AreEqual("key", result.Keys.First()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert [](start = 12, length = 6)
Use CollectionAssert.
Assert.IsTrue(CustomDataCollector.IsInitialized); | ||
} | ||
|
||
[TestMethod] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestMethod [](start = 9, length = 10)
Add test for InitializeShouldNotAddDataCollectorIfItIsDisabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
private void LoadAndInitialize(DataCollectorSettings dataCollectorSettings) | ||
{ | ||
var collectorTypeName = dataCollectorSettings.AssemblyQualifiedName; | ||
var collectorDisplayName = string.IsNullOrWhiteSpace(dataCollectorSettings.FriendlyName) ? collectorTypeName : dataCollectorSettings.FriendlyName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test case for this
{ | ||
assembly = null; | ||
Type dctype = null; | ||
if (File.Exists(binaryPath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add test case for negative scenario. May need to use IFileHelper.
assembly = LoadAssemblyFromPath(binaryPath); | ||
} | ||
|
||
dctype = assembly?.GetTypes().FirstOrDefault(type => type.AssemblyQualifiedName != null && type.AssemblyQualifiedName.Equals(dataCollectorTypeName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assembly.GetType(typeName)
// The type uri can not be null or empty. | ||
if (string.IsNullOrEmpty(typeUriAttribute.TypeUri)) | ||
{ | ||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Resources.DataCollector_TypeIsNull, dataCollectorType.FullName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ArgumentException [](start = 26, length = 17)
Need tests for these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} | ||
|
||
[TestMethod] | ||
public void InitializeDataCollectorsShouldReturnOnlyOneEnvirnmentVariableIfMoreThanOneVariablesWithSameKeyIsSpecified() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InitializeDataCollectorsShouldReturnOnlyOneEnvirnmentVariableIfMoreThanOneVariablesWithSameKeyIsSpecified [](start = 20, length = 105)
nit: spell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
return; | ||
} | ||
|
||
if (this.RunDataCollectors.ContainsKey(dataCollectorConfig.DataCollectorType)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is not required since RunSettings already deduplicates
/// <summary> | ||
/// Encapsulates datacollector object and other objects required to facilitate datacollection. | ||
/// </summary> | ||
internal class DataCollectorWrapper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DataCollectorWrapper [](start = 19, length = 20)
Rename to DataCollectorInformation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} | ||
} | ||
|
||
internal class MockDataCollectionAttachmentManager : IDataCollectionAttachmentManager |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MockDataCollectionAttachmentManager [](start = 19, length = 35)
Replace with Moq
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} | ||
|
||
/// <inheritdoc/> | ||
public Collection<AttachmentSet> SessionEnded() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SessionEnded [](start = 41, length = 12)
This should not return null. If it does, every consumer has to add an extra null check. May be an empty set if better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
|
||
if (string.IsNullOrEmpty(outputDirectory)) | ||
{ | ||
this.SessionOutputDirectory = Path.Combine(Path.GetTempPath(), DefaultOutputDirectoryName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SessionOutputDirectory [](start = 21, length = 22)
Path.Combine takes N number of strings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
|
||
try | ||
{ | ||
dataCollectorWrapper.Events.RaiseEvent(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dataCollectorWrapper [](start = 20, length = 20)
Should be this.events.RaiseEvent
/// <summary> | ||
/// Gets the list of attachment requests. | ||
/// </summary> | ||
internal List<AttachmentRequest> AttachmentRequests { get; private set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AttachmentRequests [](start = 41, length = 18)
It should be possible to replace this with async Tasks for Copy/Move. We could wait on Task.WhenAll(attachmentRequests)?
public void Dispose() | ||
{ | ||
// Dispose all attachment requests.. | ||
this.AttachmentRequests.ForEach(request => request.Dispose()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AttachmentRequests [](start = 17, length = 18)
If AttachmentRequests are not required (in case of Task), we may not need Dispose.
🕐 |
/// <summary> | ||
/// Dispose event object | ||
/// </summary> | ||
/// <inheritdoc/> | ||
public void Dispose() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this required? Do we not allocate a new DataCollectionAttachmentManager
for data collection session?
if (!Directory.Exists(directoryName)) | ||
{ | ||
Directory.CreateDirectory(directoryName); | ||
} | ||
else if (File.Exists(attachmentRequest.LocalFilePath)) | ||
else if (File.Exists(localFilePath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should deletion of existing file be responsibility of Validate
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be logged that we're removing existing file. What happens if we cannot remove the file?
|
||
var directoryPath = Path.Combine( | ||
this.SessionOutputDirectory, | ||
testCaseId.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testCaseId
is already a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
{ | ||
if (fileTransferInfo.PerformCleanup) | ||
{ | ||
File.Move(fileTransferInfo.FileName, localFilePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please log these operations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} | ||
}); | ||
|
||
this.attachmentTasks.Add(task); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're waiting on the task
, not the continuationTask
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
|
||
try | ||
{ | ||
if (fileTransferInfo.PerformCleanup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible user may want to cancel a test run or the runner/communication channel crash during these operations. What is the strategy in such cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to handle user triggered test run cancellation, we will use cancellation token to cancel the in-progress file transfer tasks.
For crash, we need to detect the socket communication failure and then cancellation of in-progress transfer operations before exiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a todo for now, will handle this scenario with integration of vstest.console process with datacollector process.
@dotnet-bot test this please. |
What is the change to fix build issues? Please undo the change in TestPlatform.targets before merge. It is required for localization targets. |
Implemented following features :
Load Data Collectors.
Data Collection Events.
Data Collection Message Sink.
Data Collector Message Logger
Removed x86 version of DataCollector, added AnyCPU Version.