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

Added API to provide mutiple regex patterns for enumerating files. #922

Merged
merged 17 commits into from Jul 14, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/Microsoft.TestPlatform.Client/TestPlatform.cs
Expand Up @@ -175,15 +175,17 @@ private void AddExtensionAssemblies(string runSettings)
var adapterPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(customTestAdaptersPath));
if (!Directory.Exists(adapterPath))
{
EqtTrace.Warning(string.Format("AdapterPath Not Found:", adapterPath));
if (EqtTrace.IsWarningEnabled)
{
EqtTrace.Warning(string.Format("AdapterPath Not Found:", adapterPath));
}

continue;
}

var extensionAssemblies = new List<string>(this.fileHelper.EnumerateFiles(adapterPath, TestPlatformConstants.TestAdapterRegexPattern, SearchOption.AllDirectories));
extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(adapterPath, TestPlatformConstants.TestLoggerRegexPattern, SearchOption.AllDirectories));
extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(adapterPath, TestPlatformConstants.RunTimeRegexPattern, SearchOption.AllDirectories));
extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(adapterPath, TestPlatformConstants.SettingsProviderRegexPattern, SearchOption.AllDirectories));
var patterns = new string[] { TestPlatformConstants.TestAdapterRegexPattern, TestPlatformConstants.TestLoggerRegexPattern, TestPlatformConstants.RunTimeRegexPattern, TestPlatformConstants.SettingsProviderRegexPattern };
Copy link
Contributor

Choose a reason for hiding this comment

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

If all these patterns are known why not Regex.Compile it directly in this class. We will save some time during runtime?

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: runtime is one word

Copy link
Contributor

Choose a reason for hiding this comment

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

Most of the patterns are compatible with string.EndsWith. Do we know how does string comparison compare with regex? Is there any observable startup time impact in regex compiled?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On measuring perf, it is observed that String.EndsWith performs better than Regex, therefore switched to String.EndsWith approach.


var extensionAssemblies = new List<string>(this.fileHelper.EnumerateFiles(adapterPath, patterns, SearchOption.AllDirectories));
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if the responsibility to combine and create a regex should be with EnumerateFiles.

if (extensionAssemblies.Count > 0)
{
this.UpdateExtensions(extensionAssemblies, true);
Expand Down Expand Up @@ -215,7 +217,7 @@ private void AddExtensionAssembliesFromSource(TestRunCriteria testRunCriteria)
var sourceDirectory = Path.GetDirectoryName(source);
if (!string.IsNullOrEmpty(sourceDirectory) && this.fileHelper.DirectoryExists(sourceDirectory))
{
loggersToUpdate.AddRange(this.fileHelper.EnumerateFiles(sourceDirectory, TestPlatformConstants.TestLoggerRegexPattern, SearchOption.TopDirectoryOnly).ToList());
loggersToUpdate.AddRange(this.fileHelper.EnumerateFiles(sourceDirectory, TestPlatformConstants.TestLoggerRegexPattern, SearchOption.TopDirectoryOnly));
}
}

Expand All @@ -233,13 +235,9 @@ private static void AddExtensionAssembliesFromExtensionDirectory()
{
var fileHelper = new FileHelper();
var extensionsFolder = Path.Combine(Path.GetDirectoryName(typeof(TestPlatform).GetTypeInfo().Assembly.Location), "Extensions");
var defaultExtensionPaths = new List<string>();
if (fileHelper.DirectoryExists(extensionsFolder))
{
var dlls = fileHelper.EnumerateFiles(extensionsFolder, ".*.dll", SearchOption.TopDirectoryOnly);
defaultExtensionPaths.AddRange(dlls);
var exes = fileHelper.EnumerateFiles(extensionsFolder, ".*.exe", SearchOption.TopDirectoryOnly);
defaultExtensionPaths.AddRange(exes);
var defaultExtensionPaths = fileHelper.EnumerateFiles(extensionsFolder, new string[] { ".*.dll", ".*.exe" }, SearchOption.TopDirectoryOnly);
TestPluginCache.Instance.DefaultExtensionPaths = defaultExtensionPaths;
}
}
Expand Down
Expand Up @@ -53,6 +53,12 @@ public IEnumerable<string> EnumerateFiles(string directory, string pattern, Sear
return Directory.EnumerateFiles(directory, "*", searchOption).Where(f => regex.IsMatch(f));
}

/// <inheritdoc/>
public IEnumerable<string> EnumerateFiles(string directory, string[] patterns, SearchOption searchOption)
{
return this.EnumerateFiles(directory, string.Join("|", patterns), searchOption);
}

/// <inheritdoc/>
public FileAttributes GetFileAttributes(string path)
{
Expand Down
Expand Up @@ -56,6 +56,15 @@ public interface IFileHelper
/// <returns>List of files matching the pattern.</returns>
IEnumerable<string> EnumerateFiles(string directory, string pattern, SearchOption searchOption);

/// <summary>
/// Enumerates files which match multiple patterns (case insensitive) in a directory.
/// </summary>
/// <param name="directory">Parent directory to search.</param>
/// <param name="patterns">Search patterns.</param>
/// <param name="searchOption"><see cref="SearchOption"/> for directory.</param>
/// <returns>List of files matching the pattern.</returns>
IEnumerable<string> EnumerateFiles(string directory, string[] patterns, SearchOption searchOption);

/// <summary>
/// Gets attributes of a file.
/// </summary>
Expand Down
67 changes: 67 additions & 0 deletions test/Microsoft.TestPlatform.PerformanceTests/FileHelperTests.cs
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.TestPlatform.PerformanceTests
{
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

using Microsoft.TestPlatform.TestUtilities.PerfInstrumentation;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class FileHelperTests : PerformanceTestBase
{
[TestMethod]
public void EnumerateFilesPerfTests()
{
var fileHelper = new FileHelper();
var stopwatch = new Stopwatch();
var adapterPath = Directory.GetCurrentDirectory();
var patterns = new string[]
{
".*CoreUtilities.dll",
".*CommunicationUtilities.dll",
".*CrossPlatEngine.dll",
".*TestUtilities.dll"
};

stopwatch.Start();
var extensionAssemblies =
new List<string>(
fileHelper.EnumerateFiles(
adapterPath,
patterns[0],
SearchOption.AllDirectories));
extensionAssemblies.AddRange(
fileHelper.EnumerateFiles(
adapterPath,
patterns[1],
SearchOption.AllDirectories));
extensionAssemblies.AddRange(
fileHelper.EnumerateFiles(
adapterPath,
patterns[2],
SearchOption.AllDirectories));
extensionAssemblies.AddRange(
fileHelper.EnumerateFiles(
adapterPath,
patterns[3],
SearchOption.AllDirectories));

stopwatch.Stop();
var timeForOldApi = stopwatch.ElapsedMilliseconds;

stopwatch.Restart();
var extensionAssembliesNew =
new List<string>(fileHelper.EnumerateFiles(adapterPath, patterns, SearchOption.AllDirectories));
stopwatch.Stop();
var timeForNewApi = stopwatch.ElapsedMilliseconds;

Assert.AreEqual(extensionAssemblies.Count, extensionAssembliesNew.Count);
Assert.IsTrue(timeForNewApi < timeForOldApi);
}
}
}