Skip to content

Refactor tests#7702

Open
hassan20990 wants to merge 2 commits into
microsoft:mainfrom
hassan20990:refactor_tests
Open

Refactor tests#7702
hassan20990 wants to merge 2 commits into
microsoft:mainfrom
hassan20990:refactor_tests

Conversation

@hassan20990

Copy link
Copy Markdown

No description provided.

@hassan20990 hassan20990 requested a review from a team as a code owner August 23, 2023 12:57
@sonarqubecloud

Copy link
Copy Markdown

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@rchiodo

rchiodo commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors parts of the UI test utilities to make Solution Explorer interactions and project loading more robust, primarily by adjusting solution-node identification, adding UI-thread helpers for IVs* interactions, and hardening TreeView node-name comparisons.

Changes:

  • Simplifies how the solution root node text is computed for Solution Explorer interactions.
  • Updates VisualStudioApp.OpenProject to route more IVs* API calls through new UI-thread helper methods.
  • Sanitizes AutomationElement.NameProperty values during Solution Explorer tree traversal to handle non-printable characters.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
Common/Tests/Utilities.UI/UI/VisualStudioInstance.cs Changes solution root node label construction used for Solution Explorer lookups.
Common/Tests/Utilities.UI/UI/VisualStudioApp.cs Refactors project/solution open flow and adds UI-thread helper methods for IVs* calls.
Common/Tests/Utilities.UI/UI/TreeView.cs Sanitizes node names (regex) before comparing path segments.
Common/Tests/Utilities.UI/TestUtilities.UI.csproj Adds a project reference to VSCommon.
.vscode/settings.json Adds a VS Code workspace setting for a specific extension.

Comment on lines +160 to +161
var solutionName = Path.GetFileNameWithoutExtension(_solution.Filename);
return $"Solution '{solutionName}'";
Comment on lines +96 to +101
var name = (node.GetCurrentPropertyValue(AutomationElement.NameProperty) as string);

// Sometimes AutomationElement.NameProperty contains non-printable characters that mess up the
// string compare, so get rid of those.
// See https://stackoverflow.com/questions/40564692/c-sharp-regex-to-remove-non-printable-characters-and-control-characters-in-a
name = Regex.Replace(name, @"\p{C}+", string.Empty).Trim();
Comment on lines 35 to 38
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudioTools;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
Comment on lines +942 to 945
t = CreateTaskOnUIThread(async () =>
{
ErrorHandler.ThrowOnFailure(solution.OpenSolutionFile((uint)0, fullPath));
});
Comment on lines +949 to 953
t = CreateTaskOnUIThread(async () =>
{
Guid guidNull = Guid.Empty;
Guid iidUnknown = Guid.Empty;
IntPtr projPtr;
Comment on lines 1056 to 1058
object o;
ErrorHandler.ThrowOnFailure(vsProject.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out o));
var project = (Project)o;
Comment thread .vscode/settings.json
Comment on lines +1 to +5
{
"marquee.widgets.npm-stats.packageNames": [
"ptvs"
]
} No newline at end of file
@bschnurr

bschnurr commented Jul 7, 2026

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

while (!t.Wait(1000, cts.Token)) {
while (!t.Wait(1000, cts.Token))
{
ErrorHandler.ThrowOnFailure(uiShell.GetDialogOwnerHwnd(out hwnd));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The threading fix is incomplete: the new comment states "everything from the IVs* APIs need to run on the UI thread," but IVsUIShell.GetDialogOwnerHwnd here — and vsProject.GetProperty at ~1057 — still run on the calling background thread while their neighbors (GetSolutionInfo, EnumerateLoadedProjects, GetGuidOfProject, ReloadProject) were wrapped in RunOnUIThread. Off-thread IVs* calls can throw RPC_E_WRONG_THREAD or silently COM-marshal. Either wrap these in RunOnUIThread too, or narrow the "everything" wording to match reality.

{
try
{
if (!t.Wait(1000, cts.Token))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CreateTaskOnUIThread returns the raw .Task from a JoinableTask, and the caller blocks with t.Wait(1000, cts.Token). Extracting and blocking on JoinableTask.Task bypasses JTF's joinable-collection deadlock mitigation. It's safe today only because OpenProject runs off the UI thread and the lambda bodies are synchronous; if OpenProject is ever invoked on the UI thread, the scheduled main-thread continuation can't run while Wait() blocks that thread, deadlocking until the 30s CTS fires. Prefer returning the JoinableTask and driving the dialog-poll loop via Join()/JoinAsync.

Comment thread .vscode/settings.json
"marquee.widgets.npm-stats.packageNames": [
"ptvs"
]
} No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file appears to be unrelated scope creep in a "Refactor tests" PR — it only sets a personal Marquee npm-stats widget config and is unrelated to test reliability. Consider dropping it from the change. (It is also missing a trailing newline.)

else
{
t = CreateTaskOnUIThread(async () =>
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These async () => { ... } lambdas contain no await, producing CS1998 ("runs synchronously"). Harmless at runtime since the body executes on the UI thread after SwitchToMainThreadAsync() inside the helper, but if the harness project sets TreatWarningsAsErrors the build breaks. Drop the async keyword (return Task.CompletedTask) to silence the warning.

@rchiodo

rchiodo commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Solid test-reliability refactor. A few non-blocking notes: the UI-thread marshaling is applied inconsistently (a couple of IVs* calls remain off-thread), the JTF .Task/Wait pattern is a latent deadlock footgun if OpenProject is ever called on the UI thread, and the .vscode/settings.json addition looks unrelated to this PR.

@rchiodo rchiodo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved via Review Center.

@heejaechang heejaechang left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved via Review Center.


var solutionName = Path.GetFileNameWithoutExtension(_solution.Filename);
return $"Solution '{solutionName}'";
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Collapsing SolutionNodeText to $"Solution '{solutionName}'" drops the (N of N projects) suffix and no longer consults _solution.Projects. This may be correct if a newer VS version removed the count from the solution root node, but it's an unexplained behavioral change. A one-line comment citing the VS-version behavior that motivated it would help; any consumer/FindNode match still expecting the old count text would silently mismatch.

@rchiodo

rchiodo commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Overall this looks fine to merge. A couple of non-blocking notes: the UI-thread wrapping is applied inconsistently across the IVs* calls, and there's an unrelated .vscode/settings.json change that should probably be dropped from a test-refactor PR.

@rchiodo rchiodo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved via Review Center.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants