diff --git a/build.gradle b/build.gradle index 5c60b176..f45c065e 100644 --- a/build.gradle +++ b/build.gradle @@ -2246,6 +2246,8 @@ task gitTagRelease(type: Exec) { // - Conflicting dependencies // - FAT ABI vs. single ABI selection +// TODO: Build and run NUnit tests for #602 + // TODO: iOS Resolver tests (on OSX only) // - Import plugin test Cocoapods bootstrap // - Pod specification, with reflection & XML, validate both are present in the diff --git a/source/AndroidResolver/src/PlayServicesResolver.cs b/source/AndroidResolver/src/PlayServicesResolver.cs index bbfb5ead..5353a4a1 100644 --- a/source/AndroidResolver/src/PlayServicesResolver.cs +++ b/source/AndroidResolver/src/PlayServicesResolver.cs @@ -18,6 +18,7 @@ namespace GooglePlayServices { using System; using System.Collections.Generic; using System.IO; + using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Xml; @@ -992,7 +993,7 @@ private static bool Initialize() { } // Monitor Android dependency XML files to perform auto-resolution. - AddAutoResolutionFilePatterns(xmlDependencies.fileRegularExpressions); + autoResolveFilePatterns.Add(XmlDependencies.IsDependenciesFile); svcSupport = PlayServicesSupport.CreateInstance( "PlayServicesResolver", @@ -1079,7 +1080,7 @@ internal static void Log(string message, Google.LogLevel level = LogLevel.Info) /// /// Patterns of files that are monitored to trigger auto resolution. /// - private static HashSet autoResolveFilePatterns = new HashSet(); + private static HashSet> autoResolveFilePatterns = new HashSet>(); /// /// Add file patterns to monitor to trigger auto resolution. @@ -1087,7 +1088,8 @@ internal static void Log(string message, Google.LogLevel level = LogLevel.Info) /// Set of file patterns to monitor to trigger auto /// resolution. public static void AddAutoResolutionFilePatterns(IEnumerable patterns) { - autoResolveFilePatterns.UnionWith(patterns); + // Only regex patterns are supported in the public API, but a more performant default is used internally. + autoResolveFilePatterns.UnionWith(patterns.Select>(p => p.IsMatch)); } /// @@ -1099,7 +1101,7 @@ private static bool CheckFilesForAutoResolution(HashSet filesToCheck) { bool resolve = false; foreach (var asset in filesToCheck) { foreach (var pattern in autoResolveFilePatterns) { - if (pattern.Match(asset).Success) { + if (pattern.Invoke(asset)) { Log(String.Format("Found asset {0} matching {1}, attempting " + "auto-resolution.", asset, pattern.ToString()), diff --git a/source/AndroidResolver/src/XmlDependencies.cs b/source/AndroidResolver/src/XmlDependencies.cs index 24a02594..d0ea5bf5 100644 --- a/source/AndroidResolver/src/XmlDependencies.cs +++ b/source/AndroidResolver/src/XmlDependencies.cs @@ -28,14 +28,6 @@ namespace GooglePlayServices { /// internal class XmlDependencies { - /// - /// Set of regular expressions that match files which contain dependency - /// specifications. - /// - internal HashSet fileRegularExpressions = new HashSet { - new Regex(@".*[/\\]Editor[/\\].*Dependencies\.xml$") - }; - /// /// Human readable name for dependency files managed by this class. /// @@ -44,15 +36,13 @@ internal class XmlDependencies { /// /// Determines whether a filename matches an XML dependencies file. /// - /// /// true if it is a match, false otherwise. - internal bool IsDependenciesFile(string filename) { - foreach (var regex in fileRegularExpressions) { - if (regex.Match(filename).Success) { - return true; - } + internal static bool IsDependenciesFile(string filename) { + if (!filename.EndsWith("Dependencies.xml")) { + return false; } - return false; + // This method was optimized to avoid using regex after profiling results from a large Unity project. + return filename.Contains("/Editor/") || filename.Contains(@"\Editor\"); } /// diff --git a/source/AndroidResolver/unit_tests/AndroidResolverTests.csproj b/source/AndroidResolver/unit_tests/AndroidResolverTests.csproj new file mode 100644 index 00000000..d4df5848 --- /dev/null +++ b/source/AndroidResolver/unit_tests/AndroidResolverTests.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {12F40968-4B80-4DCF-8D51-4C8E06F9CC4B} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + Google + Google.AndroidResolverTests + v3.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + {82eedfbe-afe4-4def-99d9-bc929747dd9a} + AndroidResolver + + + + + + diff --git a/source/AndroidResolver/unit_tests/Properties/AssemblyInfo.cs b/source/AndroidResolver/unit_tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..db9ba593 --- /dev/null +++ b/source/AndroidResolver/unit_tests/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("AndroidResolverTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("AndroidResolverTests")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("12F40968-4B80-4DCF-8D51-4C8E06F9CC4B")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/source/AndroidResolver/unit_tests/XmlDependenciesTests.cs b/source/AndroidResolver/unit_tests/XmlDependenciesTests.cs new file mode 100644 index 00000000..f71d880e --- /dev/null +++ b/source/AndroidResolver/unit_tests/XmlDependenciesTests.cs @@ -0,0 +1,28 @@ +using System.Text.RegularExpressions; + +namespace GooglePlayServices.Tests { + using System; + using NUnit.Framework; + + [TestFixture] + public class XmlDependenciesTests + { + [TestCase("Assets/Editor/Dependencies.xml")] + [TestCase("Assets/Editor/MyFolder/Dependencies.xml")] + [TestCase("Editor/Dependencies.xml")] + [TestCase("Editor/MyFolder/Dependencies.xml")] + [TestCase("Assets/Editor/SomeDependencies.xml")] + [TestCase("Assets/MyEditorCode/Dependencies.xml")] + [TestCase("Assets/MyEditorCode/SomeDependencies.xml")] + [TestCase("Assets/Editor/")] + [TestCase("Assets/Editor/Dependendencies")] + public void IsDependenciesFileReturnsExpected(string path) { + bool actualResult = XmlDependencies.IsDependenciesFile(path); + + // This was the previous implementation before the optimization attempt and acts as a test reference. + bool expectedResult = Regex.IsMatch(input: path, pattern: @".*[/\\]Editor[/\\].*Dependencies\.xml$"); + + Assert.AreEqual(expectedResult, actualResult); + } + } +} \ No newline at end of file diff --git a/source/AndroidResolver/unit_tests/packages.config b/source/AndroidResolver/unit_tests/packages.config new file mode 100644 index 00000000..ad37a528 --- /dev/null +++ b/source/AndroidResolver/unit_tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/source/ExternalDependencyManager.sln b/source/ExternalDependencyManager.sln index 9dda1103..2702c081 100644 --- a/source/ExternalDependencyManager.sln +++ b/source/ExternalDependencyManager.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageManagerClientIntegra EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageMigratorIntegrationTests", "PackageManagerResolver\test\PackageMigratorIntegrationTests.csproj", "{4DBDEE33-4B6C-A866-93FE-04C15486BB03}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidResolverTests", "AndroidResolver\unit_tests\AndroidResolverTests.csproj", "{12F40968-4B80-4DCF-8D51-4C8E06F9CC4B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,5 +87,9 @@ Global {4DBDEE33-4B6C-A866-93FE-04C15486BB03}.Debug|Any CPU.Build.0 = Debug|Any CPU {4DBDEE33-4B6C-A866-93FE-04C15486BB03}.Release|Any CPU.ActiveCfg = Release|Any CPU {4DBDEE33-4B6C-A866-93FE-04C15486BB03}.Release|Any CPU.Build.0 = Release|Any CPU + {12F40968-4B80-4DCF-8D51-4C8E06F9CC4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12F40968-4B80-4DCF-8D51-4C8E06F9CC4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12F40968-4B80-4DCF-8D51-4C8E06F9CC4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12F40968-4B80-4DCF-8D51-4C8E06F9CC4B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/source/IOSResolver/src/IOSResolver.cs b/source/IOSResolver/src/IOSResolver.cs index ab6c2cf1..d1311909 100644 --- a/source/IOSResolver/src/IOSResolver.cs +++ b/source/IOSResolver/src/IOSResolver.cs @@ -1939,7 +1939,7 @@ private static void OnPostprocessAllAssets(string[] importedAssets, var changedAssets = new List(importedAssets); changedAssets.AddRange(deletedAssets); foreach (var asset in changedAssets) { - dependencyFileChanged = xmlDependencies.IsDependenciesFile(asset); + dependencyFileChanged = XmlDependencies.IsDependenciesFile(asset); if (dependencyFileChanged) break; } if (dependencyFileChanged) RefreshXmlDependencies();