-
Notifications
You must be signed in to change notification settings - Fork 323
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
Event based communication over sockets. #1294
Conversation
…d implementation). Update test request handler to use the new socket implementation.
# Conflicts: # src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs # src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender2.cs # test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs # test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests2.cs
# Conflicts: # src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs # src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender2.cs # test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs # test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests2.cs Added debug launches to debug tests.
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.
not taken a look at tests yet, will do it later
|
||
/// <inheritdoc /> | ||
public void Start(string connectionInfo) | ||
// public void Start(string connectionInfo) |
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.
nit: remove this
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.
// { | ||
// throw connectAsyncTask.Exception; | ||
// } | ||
if (this.Connected != null) |
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.
Can Connected ever be null in this class?
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's an event so it can be null. But in our case it will not be null.
{ | ||
if (this.connectionInfo.Role == ConnectionRole.Client) |
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.
The connectioninfo here is that of the RuntimeProvider, which tells how the testhost will act, so we should reverse the role the of vstest.console right?
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.
Yeah, it happens in another constructor. Ln 92-94.
// 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)) |
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 did we remove these checks? were they bogus?
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.
Earlier they were needed only for those scenarios, and in other scenarios they were reusing the execution manager. But since the test host dies it's not good to have that around. and was observing an exception, which tries to send message over a channel that's already closed.
{ | ||
if (this.connectionInfo.Role == ConnectionRole.Client) |
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 put a comment to move this to Communication factory, which returns ICommEndPoint based on Role, & ConnectionType (Socket, NamedPipe etc..) Once another communication mechanism is implemented
@dotnet-bot test Windows_NT / Release Build |
@dotnet-bot test |
@@ -24,11 +24,28 @@ public ConnectedEventArgs() | |||
public ConnectedEventArgs(ICommunicationChannel channel) | |||
{ | |||
this.Channel = channel; | |||
this.Connected = true; |
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 communicationutilities namespace in common assembly?
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.
Moved the files.
{ | ||
using System; | ||
|
||
public interface ICommunicationEndPoint |
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.
Doc?
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.
Sent it.
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.
Can be put it in vstest-docs, once refined.
@@ -57,10 +57,7 @@ public Task NotifyDataAvailable() | |||
// connection is closed. | |||
var data = this.reader.ReadString(); |
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.
ReadString
can throw the exception.
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's caught in MessageLoopAsync method.
@@ -17,7 +17,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities | |||
/// <summary> | |||
/// Communication server implementation over sockets. | |||
/// </summary> | |||
public class SocketServer : ICommunicationServer | |||
public class SocketServer : ICommunicationEndPoint |
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.
Delete ICommunicationServer
and ICommunicationClient
.
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.
var ipEndPoint = endpoint.GetIPEndPoint(); | ||
|
||
// Don't start if the endpoint port is zero | ||
this.tcpClient.ConnectAsync(ipEndPoint.Address, ipEndPoint.Port).ContinueWith(this.OnServerConnected); |
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 EqtTrace here saying that "Waiting for connecting to server".
|
||
// Don't start if the endpoint port is zero | ||
this.tcpClient.ConnectAsync(ipEndPoint.Address, ipEndPoint.Port).ContinueWith(this.OnServerConnected); | ||
return endpoint; |
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 return endpoint
or ipEndPoint
?
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 void Start(string connectionInfo) | ||
public string Start(string endpoint) |
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.
Nit: endPoint
.
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.ServerConnected.SafeInvoke(this, new ConnectedEventArgs(this.channel), "SocketClient: ServerConnected"); | ||
if (connectAsyncTask.IsFaulted) | ||
{ |
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 EqtTrace on failure and success scenarios.
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.channel = this.channelFactory(this.tcpClient.GetStream()); | ||
this.ClientConnected.SafeInvoke(this, new ConnectedEventArgs(this.channel), "SocketServer: ClientConnected"); | ||
this.Connected.SafeInvoke(this, new ConnectedEventArgs(this.channel), "SocketServer: ClientConnected"); |
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 EqtTrace on failure and success scenarios.
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 ICommunicationManager communicationManager; | ||
// Time to wait for test host exit (in seconds) | ||
private const int CLIENTPROCESSEXITWAIT = 10 * 1000; |
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.
Nit: ClientProcessExitWaitTimeout?(Change it in other places too.)
In seconds?
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.communicationEndpoint.Disconnected += (sender, args) => | ||
{ | ||
// If there's an disconnected event handler, call it |
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.
On disconnect should set this.connected.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.
NA
else if (message.MessageType == MessageType.TestMessage) | ||
{ | ||
// There are some test hosts which sends log messages, hence logging and ignoring. | ||
var testMessage = this.dataSerializer.DeserializePayload<TestMessagePayload>(message); |
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 TestMessage expected? Should this log to client?
{ | ||
throw new TestPlatformException(string.Format(CultureInfo.CurrentUICulture, CommonResources.UnexpectedMessage, MessageType.VersionCheck, message.MessageType)); | ||
this.channel.MessageReceived -= this.onMessageReceived; |
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.
What will happens messages sent after version check message type, Like this
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.
Reading from binary reader only when there's a corresponding event handler.
@@ -10,31 +10,20 @@ | |||
<TargetFrameworks>netcoreapp1.0;net451</TargetFrameworks> | |||
<AssemblyName>Microsoft.TestPlatform.Common.UnitTests</AssemblyName> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<!--<ItemGroup> |
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.
Nit: Remove comment.
@@ -7,12 +7,12 @@ | |||
<Import Project="$(TestPlatformRoot)scripts/build/TestPlatform.Settings.targets" /> | |||
<PropertyGroup> | |||
<OutputType Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">Exe</OutputType> | |||
<TargetFrameworks>netcoreapp1.0;net451</TargetFrameworks> | |||
<TargetFrameworks>net451;netcoreapp1.0</TargetFrameworks> |
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.
Revert the change.
<AssemblyName>Microsoft.TestPlatform.CommunicationUtilities.PlatformTests</AssemblyName> | ||
<EnableCodeAnalysis>true</EnableCodeAnalysis> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Microsoft.TestPlatform.CommunicationUtilities\Microsoft.TestPlatform.CommunicationUtilities.csproj" /> | ||
<!--<ProjectReference Include="..\..\src\Microsoft.TestPlatform.CommunicationUtilities\Microsoft.TestPlatform.CommunicationUtilities.csproj" /> |
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.
Remove all the commented code.
|
||
protected IPEndPoint GetIpEndPoint(string value) | ||
{ | ||
if (Uri.TryCreate(string.Concat("tcp://", value), UriKind.Absolute, out Uri uri)) |
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.
DRY.
@@ -7,12 +7,12 @@ | |||
<Import Project="$(TestPlatformRoot)scripts/build/TestPlatform.Settings.targets" /> | |||
<PropertyGroup> | |||
<OutputType Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">Exe</OutputType> | |||
<TargetFrameworks>netcoreapp1.0;net451</TargetFrameworks> | |||
<TargetFrameworks>net451;netcoreapp1.0</TargetFrameworks> |
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.
Revert this change(And other places too).
{ | ||
throw new TestPlatformException(string.Format(CultureInfo.CurrentUICulture, CommonResources.VersionCheckFailed)); | ||
} | ||
else |
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.
Some other message type can also come if the communication is very fast, for e.g. version check can also send https://github.com/Microsoft/vstest/blob/a32cf559805a61cd491b5574bd3f365df8943878/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs#L102
which is Log message, & this will throw exception.
Ideal state would be to have one EventHandler method, which handles all possible message type, & throw if some garbage message comes.
Each time we are attaching an EventHandler, we can point to same method, & then detach once it is done
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 handler for message type MessageType.TestMessage
private void SetOperationComplete() | ||
{ | ||
// Complete the currently ongoing operation (Discovery/Execution) | ||
Interlocked.CompareExchange(ref this.operationCompleted, 1, 0); |
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 are we using a Thread safe operation, are we expecting that this can hit from multiple threads?
} | ||
this.channel = connectedArgs.Channel; | ||
this.channel.MessageReceived += this.OnMessageReceived; |
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 soon as we set handler to receive messages, we can get a Test Discovery/Execution request before ProcessRequest which supply testHostManagerFactory.
So move attaching to event handler in ProcessRequest
Again this is a corner scenario, but can happen
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.
You are right, there some unit test failing randomly because of this.I am handling this in the latest one. Please take a look.
@dotnet-bot test Windows_NT / Debug Build |
@dotnet-bot test Windows_NT / Release Build |
testRunEventsHandler.HandleTestRunComplete(completeArgs, null, null, null); | ||
} | ||
|
||
private void OnDiscoveryAbort(ITestDiscoveryEventsHandler2 eventHandler, Exception exception, bool getClientError) |
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.
OnDiscoveryAbort [](start = 21, length = 16)
exception handling has been removed.. any impact due to this ?
} | ||
this.channel = connectedArgs.Channel; | ||
this.channel.MessageReceived += this.OnMessageReceived; |
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.
MessageReceived [](start = 29, length = 15)
can the processing of a second message begin before the completion of an earlier one..? what is the impact..?
@dotnet-bot test Windows_NT / Release Build |
1 similar comment
@dotnet-bot test Windows_NT / Release Build |
d2329b2
to
fbb4922
Compare
Description