Skip to content

Implement better way to test for in-memory file #645

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

Merged
merged 4 commits into from
Mar 25, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
32 changes: 20 additions & 12 deletions src/PowerShellEditorServices/Workspace/Workspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,22 +390,30 @@ internal static bool IsPathInMemory(string filePath)
// view of the current file or an untitled file.
try
{
// NotSupportedException or ArgumentException gets thrown when
// given an invalid path. Since any non-standard path will
// trigger this, assume that it means it's an in-memory file
// unless the path starts with file:
Path.GetFullPath(filePath);
// File system absoulute paths will have a URI scheme of file:.
// Other schemes like "untitled:" and "gitlens-git:" will return false for IsFile.
var uri = new Uri(filePath);
isInMemory = !uri.IsFile;
Copy link
Member

Choose a reason for hiding this comment

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

nit: maybe combine these into 1 line since uri isn't used? I don't feel strongly either way but it's something I thought about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Having uri as a variable makes it easier to inspect the entire URI when debugging - not just the resulting string.

Copy link
Member

Choose a reason for hiding this comment

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

Good point 👍

}
catch (ArgumentException)
catch (UriFormatException)
{
isInMemory = true;
}
catch (NotSupportedException)
{
isInMemory = true;
// Relative file paths cause a UriFormatException.
// In this case, fallback to using Path.GetFullPath().
try
{
Path.GetFullPath(filePath);
}
catch (Exception ex) when (ex is ArgumentException || ex is NotSupportedException)
{
isInMemory = true;
}
catch (PathTooLongException)
{
// If we ever get here, it should be an actual file so, not in memory
}
}

return !filePath.ToLower().StartsWith("file:") && isInMemory;
return isInMemory;
}

private string GetBaseFilePath(string filePath)
Expand Down
30 changes: 30 additions & 0 deletions test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,35 @@ public void CanResolveWorkspaceRelativePath()
Assert.Equal(@"..\PeerPath\FilePath.ps1", workspace.GetRelativePath(testPathOutside));
Assert.Equal(testPathAnotherDrive, workspace.GetRelativePath(testPathAnotherDrive));
}

[Fact]
public void CanDetermineIsPathInMemory()
{
var tempDir = Environment.GetEnvironmentVariable("TEMP");

var shortDirPath = Path.Combine(tempDir, "GitHub", "PowerShellEditorServices");
var shortFilePath = Path.Combine(shortDirPath, "foo.ps1");
var shortDirUriForm = new Uri(shortDirPath).ToString();
var shortFileUriForm = new Uri(shortFilePath).ToString();

// Test short file absolute paths
Assert.False(Workspace.IsPathInMemory(shortDirPath));
Assert.False(Workspace.IsPathInMemory(shortFilePath));
Assert.False(Workspace.IsPathInMemory(shortDirUriForm));
Assert.False(Workspace.IsPathInMemory(shortFileUriForm));

// Test short file relative paths - not sure we'll ever get these but just in case
Assert.False(Workspace.IsPathInMemory("foo.ps1"));
Assert.False(Workspace.IsPathInMemory(".." + Path.DirectorySeparatorChar + "foo.ps1"));

// Test short non-file paths
Assert.True(Workspace.IsPathInMemory("untitled:untitled-1"));
var shortUriForm = "git:/c%3A/Users/Keith/GitHub/dahlbyk/posh-git/src/PoshGitTypes.ps1?%7B%22path%22%3A%22c%3A%5C%5CUsers%5C%5CKeith%5C%5CGitHub%5C%5Cdahlbyk%5C%5Cposh-git%5C%5Csrc%5C%5CPoshGitTypes.ps1%22%2C%22ref%22%3A%22~%22%7D";
Assert.True(Workspace.IsPathInMemory(shortUriForm));

// Test long non-file path - known to have crashed PSES
var longUriForm = "gitlens-git:c%3A%5CUsers%5CKeith%5CGitHub%5Cdahlbyk%5Cposh-git%5Csrc%5CPoshGitTypes%3Ae0022701.ps1?%7B%22fileName%22%3A%22src%2FPoshGitTypes.ps1%22%2C%22repoPath%22%3A%22c%3A%2FUsers%2FKeith%2FGitHub%2Fdahlbyk%2Fposh-git%22%2C%22sha%22%3A%22e0022701fa12e0bc22d0458673d6443c942b974a%22%7D";
Assert.True(Workspace.IsPathInMemory(longUriForm));
}
Copy link
Member

Choose a reason for hiding this comment

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

Do you think you could refactor this test to be an array and an assert?

Something like:

var testCases = new[]{
    { Path = "foo.ps1", IsInMemory = false },
    { Path = Path.Combine(tempDir, "GitHub", "PowerShellEditorServices"), IsInMemory = false },
    { Path = new Uri(shortDirPath).ToString(), IsInMemory = false }
}
foreach (var testCase in testCases) {
    Assert.IsEqual(Worspace.IsPathInMemory(testCase.Path), testCase.IsInMemory);
}

I think it's a little cleaner and involves writing less Asserts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can make that change (have actually) but when a test fails, we only get this:

Message: Assert.Equal() Failure
Expected: False
Actual:   True

And the line number with no indication of which test case failed. I could do a Debug.WriteLine of the Path being tested. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Think I have a solution to that last issue - found an Assert method that allows me to specify a message to emit when the assert fails.

}
}