Skip to content
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

Hardcode fixes for uwp #3280

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ internal static class DiscoveryCriteriaExtensions
{
public static void UpdateDiscoveryCriteria(this DiscoveryCriteria discoveryCriteria, ITestRuntimeProvider testRuntimeProvider)
{
var actualTestSources = testRuntimeProvider.GetTestSources(discoveryCriteria.Sources);
var actualTestSources = new[] { @"UITests.exe" }; // testRuntimeProvider.GetTestSources(discoveryCriteria.Sources);
Copy link
Member Author

@nohwnd nohwnd Jan 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get UITests.exe here from the real provider as well.


// If the actual testSources, & input test sources do differ it means that the User(IDE) actually sent a package.
// We are limiting that only one package can be sent per session, so picking the first entry in sources
if (discoveryCriteria.Sources.Except(actualTestSources).Any())
{
discoveryCriteria.Package = discoveryCriteria.Sources.FirstOrDefault();
discoveryCriteria.Package = @"C:\ProgramData\DeveloperTools\WinUI-Samples-UITestsVS.Debug_x64.jajares\UITests.build.appxrecipe"; // discoveryCriteria.Sources.FirstOrDefault();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the provider provides the local path: "C:\\p\\WinUI-Samples\\x64\\Debug\\UITests\\UITests.build.appxrecipe"; and we send it to the other side in DiscoveryRequest. The recipe path is used to lookup UITests.exe and it cannot find it. So no tests are discovered. If we pass this path (the appxrecipe actuall does not exist on the remote) it allows UITest.exe path to be determined correctly. All tests are discovered but TestWindow can't understand them because they come from an unknown source.


// Allow TestRuntimeProvider to update source map, this is required for remote scenarios.
// If we run for specific tests, then we expect the test case object to contain correct source path for remote scenario as well
Expand All @@ -37,5 +37,22 @@ private static void UpdateTestSources(IEnumerable<string> sources, Dictionary<st
adapterSourceMap.Clear();
adapterSourceMap.Add(Constants.UnspecifiedAdapterPath, sources);
}

private interface IRemoteSourceProvider
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore all this.

{

}

private class RemoteSourceProviderAdapter : IRemoteSourceProvider
{
private readonly ITestRuntimeProvider testRuntimeProvider;

public RemoteSourceProviderAdapter(ITestRuntimeProvider testRuntimeProvider)
{
this.testRuntimeProvider = testRuntimeProvider;
}


}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client
using System.Collections.Generic;
using System.Linq;
using System.Threading;

using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
Expand Down Expand Up @@ -130,25 +131,38 @@ public void Initialize(bool skipDefaultAdapters)
/// <inheritdoc/>
public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEventsHandler2 eventHandler)
{

if (this.proxyOperationManager == null)
{
this.proxyOperationManager = this.proxyOperationManagerCreator(
discoveryCriteria.Sources.First(),
this);

//TODO: here or below wrap the testhost manager to return sources that use the correct remote path
this.testHostManager = this.proxyOperationManager.TestHostManager;
this.requestData = this.proxyOperationManager.RequestData;
}

this.baseTestDiscoveryEventsHandler = eventHandler;
if (this.testHostManager.GetType().Name.Contains("Uwp"))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore all this, it just allows me to special case this for uwp, and change the responses.

{
this.baseTestDiscoveryEventsHandler = new ReflectionBasedRemoteTestDiscoveryEventHandler(eventHandler, this.dataSerializer);
}
else
{
//TODO: here wrap the handler to translate remote paths here and back
this.baseTestDiscoveryEventsHandler = eventHandler;
}

try
{
this.isCommunicationEstablished = this.proxyOperationManager.SetupChannel(discoveryCriteria.Sources, discoveryCriteria.RunSettings);

if (this.isCommunicationEstablished)
{
var thm = this.testHostManager.GetType().Name.Contains("Uwp")
? new ReflectionBasedRemoteTestHostManagerAdapter(this.testHostManager)
: this.testHostManager;
this.InitializeExtensions(discoveryCriteria.Sources);
discoveryCriteria.UpdateDiscoveryCriteria(testHostManager);
discoveryCriteria.UpdateDiscoveryCriteria(thm);

this.proxyOperationManager.RequestSender.DiscoverTests(discoveryCriteria, this);
}
Expand Down Expand Up @@ -294,5 +308,157 @@ private void LogMessage(TestMessageLevel testMessageLevel, string message)
// Log to vstest.console layer.
this.HandleLogMessage(testMessageLevel, message);
}

private class ReflectionBasedRemoteTestDiscoveryEventHandler : ITestDiscoveryEventsHandler2
{
private ITestDiscoveryEventsHandler2 eventHandler;
private readonly IDataSerializer dataSerializer;

public ReflectionBasedRemoteTestDiscoveryEventHandler(ITestDiscoveryEventsHandler2 eventHandler, IDataSerializer dataSerializer)
{
this.eventHandler = eventHandler;
this.dataSerializer = dataSerializer;
}

public void HandleDiscoveredTests(IEnumerable<TestCase> discoveredTestCases)
{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we get Source that is the actual remote path, and we need to translate it back to the appxrecipe we got originally. So TestWindow can match it back to the correct source.

foreach (var testCase in discoveredTestCases)
{
testCase.Source = "C:\\p\\WinUI-Samples\\x64\\Debug\\UITests\\UITests.build.appxrecipe";
}

eventHandler.HandleDiscoveredTests(discoveredTestCases);
}

public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable<TestCase> lastChunk)
{
foreach (var testCase in lastChunk)
{
testCase.Source = "C:\\p\\WinUI-Samples\\x64\\Debug\\UITests\\UITests.build.appxrecipe";
}

eventHandler.HandleDiscoveryComplete(discoveryCompleteEventArgs, lastChunk);
}

public void HandleLogMessage(TestMessageLevel level, string message)
{
eventHandler.HandleLogMessage(level, message);
}

public void HandleRawMessage(string rawMessage)
{
var message = this.dataSerializer.DeserializeMessage(rawMessage);
string newRawMessage = null;
if (string.Equals(message.MessageType, MessageType.DiscoveryComplete))
{
// rewrite paths and serialize
var payload = this.dataSerializer.DeserializePayload<DiscoveryCompletePayload>(message);
foreach (var testCase in payload.LastDiscoveredTests)
{
testCase.Source = "C:\\p\\WinUI-Samples\\x64\\Debug\\UITests\\UITests.build.appxrecipe";
}

newRawMessage = this.dataSerializer.SerializePayload(MessageType.DiscoveryComplete, payload);
}

if (string.Equals(message.MessageType, MessageType.TestCasesFound))
{
// rewrite paths and serialize
var payload = this.dataSerializer.DeserializePayload<IEnumerable<TestCase>>(message);
foreach (var testCase in payload)
{
testCase.Source = "C:\\p\\WinUI-Samples\\x64\\Debug\\UITests\\UITests.build.appxrecipe";
}

newRawMessage = this.dataSerializer.SerializePayload(MessageType.TestCasesFound, payload);
}

eventHandler.HandleRawMessage(newRawMessage ?? rawMessage);
}
}

private class ReflectionBasedRemoteTestHostManagerAdapter : ITestRuntimeProvider
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this class.

{
private ITestRuntimeProvider testHostManager;

public ReflectionBasedRemoteTestHostManagerAdapter(ITestRuntimeProvider testHostManager)
{
this.testHostManager = testHostManager;
}

public bool Shared => testHostManager.Shared;

public event EventHandler<HostProviderEventArgs> HostLaunched
{
add
{
testHostManager.HostLaunched += value;
}

remove
{
testHostManager.HostLaunched -= value;
}
}

public event EventHandler<HostProviderEventArgs> HostExited
{
add
{
testHostManager.HostExited += value;
}

remove
{
testHostManager.HostExited -= value;
}
}

public bool CanExecuteCurrentRunConfiguration(string runsettingsXml)
{
return testHostManager.CanExecuteCurrentRunConfiguration(runsettingsXml);
}

public Task CleanTestHostAsync(CancellationToken cancellationToken)
{
return testHostManager.CleanTestHostAsync(cancellationToken);
}

public TestHostConnectionInfo GetTestHostConnectionInfo()
{
return testHostManager.GetTestHostConnectionInfo();
}

public TestProcessStartInfo GetTestHostProcessStartInfo(IEnumerable<string> sources, IDictionary<string, string> environmentVariables, TestRunnerConnectionInfo connectionInfo)
{
return testHostManager.GetTestHostProcessStartInfo(sources, environmentVariables, connectionInfo);
}

public IEnumerable<string> GetTestPlatformExtensions(IEnumerable<string> sources, IEnumerable<string> extensions)
{
return testHostManager.GetTestPlatformExtensions(sources, extensions);
}

public IEnumerable<string> GetTestSources(IEnumerable<string> sources)
{
// return testHostManager.GetTestSources(sources).Select(s => s.Replace(@"", @"C:\ProgramData\DeveloperTools\WinUI-Samples-UITestsVS.Debug_x64.jajares"));
return new[] { @"C:\ProgramData\DeveloperTools\WinUI-Samples-UITestsVS.Debug_x64.jajares\UITests.build.appxrecipe" };
}

public void Initialize(IMessageLogger logger, string runsettingsXml)
{
testHostManager.Initialize(logger, runsettingsXml);
}

public Task<bool> LaunchTestHostAsync(TestProcessStartInfo testHostStartInfo, CancellationToken cancellationToken)
{
return testHostManager.LaunchTestHostAsync(testHostStartInfo, cancellationToken);
}

public void SetCustomLauncher(ITestHostLauncher customLauncher)
{
testHostManager.SetCustomLauncher(customLauncher);
}
}
}
}