Refactor the helper project for host API tests (dotnet/core-setup#4629)
authorVitek Karas <vitek.karas@microsoft.com>
Sun, 7 Oct 2018 11:42:07 +0000 (04:42 -0700)
committerGitHub <noreply@github.com>
Sun, 7 Oct 2018 11:42:07 +0000 (04:42 -0700)
This makes the project modular - with ability to easily add tests for other APIs (the upcomming hostpolicy ones).
This is a pure refactoring, the only functional change is the addition of logging the full path to the hostfxr being used by the tests.

Commit migrated from https://github.com/dotnet/core-setup/commit/6a82a759ec695bda5aa4ef7f231aa4f07b345d70

src/installer/test/Assets/TestProjects/HostApiInvokerApp/HostFXR.cs [new file with mode: 0644]
src/installer/test/Assets/TestProjects/HostApiInvokerApp/Program.cs
src/installer/test/Assets/TestProjects/HostApiInvokerApp/Utils.cs [new file with mode: 0644]
src/installer/test/HostActivationTests/GivenThatICareAboutNativeHostApis.cs

diff --git a/src/installer/test/Assets/TestProjects/HostApiInvokerApp/HostFXR.cs b/src/installer/test/Assets/TestProjects/HostApiInvokerApp/HostFXR.cs
new file mode 100644 (file)
index 0000000..99d1a7d
--- /dev/null
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace HostApiInvokerApp
+{
+    public static class HostFXR
+    {
+        internal static class hostfxr
+        {
+            [DllImport(nameof(hostfxr), CharSet = Utils.OSCharSet)]
+            internal static extern uint hostfxr_get_native_search_directories(
+                int argc, 
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
+                string[] argv, 
+                StringBuilder buffer, 
+                int bufferSize, 
+                ref int required_buffer_size);
+
+            [Flags]
+            internal enum hostfxr_resolve_sdk2_flags_t : int
+            {
+                disallow_prerelease = 0x1,
+            }
+
+            internal enum hostfxr_resolve_sdk2_result_key_t : int
+            {
+                resolved_sdk_dir = 0,
+                global_json_path = 1,
+            }
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = Utils.OSCharSet)]
+            internal delegate void hostfxr_resolve_sdk2_result_fn(
+                hostfxr_resolve_sdk2_result_key_t key,
+                string value);
+
+            [DllImport(nameof(hostfxr), CharSet = Utils.OSCharSet, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+            internal static extern int hostfxr_resolve_sdk2(
+                string exe_dir,
+                string working_dir,
+                hostfxr_resolve_sdk2_flags_t flags,
+                hostfxr_resolve_sdk2_result_fn result);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = Utils.OSCharSet)]
+            internal delegate void hostfxr_get_available_sdks_result_fn(
+                int sdk_count,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
+                string[] sdk_dirs);
+
+            [DllImport(nameof(hostfxr), CharSet = Utils.OSCharSet, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+            internal static extern int hostfxr_get_available_sdks(
+                string exe_dir,
+                hostfxr_get_available_sdks_result_fn result);
+
+            internal const uint HostApiBufferTooSmall = 0x80008098;
+        }
+
+        /// <summary>
+        /// Test invoking the native hostfxr api hostfxr_get_native_search_directories
+        /// </summary>
+        /// <param name="args[0]">hostfxr_get_native_search_directories</param>
+        /// <param name="args[1]">Path to dotnet.exe</param>
+        /// <param name="args[2]">Path to application</param>
+        static void Test_hostfxr_get_native_search_directories(string[] args)
+        {
+            if (args.Length != 3)
+            {
+                throw new ArgumentException("Invalid number of arguments passed");
+            }
+
+            string pathToDotnet = args[1];
+            string pathToApp = args[2];
+            string[] argv = new[] { pathToDotnet, pathToApp };
+
+            // Start with 0 bytes allocated to test re-entry and required_buffer_size
+            StringBuilder buffer = new StringBuilder(0);
+            int required_buffer_size = 0;
+
+            uint rc = 0;
+            for (int i = 0; i < 2; i++)
+            {
+                rc = hostfxr.hostfxr_get_native_search_directories(argv.Length, argv, buffer, buffer.Capacity + 1, ref required_buffer_size);
+                if (rc != hostfxr.HostApiBufferTooSmall)
+                {
+                    break;
+                }
+
+                buffer = new StringBuilder(required_buffer_size);
+            }
+
+            if (rc == 0)
+            {
+                Console.WriteLine("hostfxr_get_native_search_directories:Success");
+                Console.WriteLine($"hostfxr_get_native_search_directories buffer:[{buffer}]");
+            }
+            else
+            {
+                Console.WriteLine($"hostfxr_get_native_search_directories:Fail[{rc}]");
+            }
+        }
+
+        /// <summary>
+        /// Test invoking the native hostfxr api hostfxr_resolve_sdk2
+        /// </summary>
+        /// <param name="args[0]">hostfxr_get_available_sdks</param>
+        /// <param name="args[1]">Directory of dotnet executable</param>
+        /// <param name="args[2]">Working directory where search for global.json begins</param>
+        /// <param name="args[3]">Flags</param>
+        static void Test_hostfxr_resolve_sdk2(string[] args)
+        {
+            if (args.Length != 4)
+            {
+                throw new ArgumentException("Invalid number of arguments passed");
+            }
+
+            var data = new List<(hostfxr.hostfxr_resolve_sdk2_result_key_t, string)>();
+            int rc = hostfxr.hostfxr_resolve_sdk2(
+                exe_dir: args[1],
+                working_dir: args[2],
+                flags: Enum.Parse<hostfxr.hostfxr_resolve_sdk2_flags_t>(args[3]),
+                result: (key, value) => data.Add((key, value)));
+
+            if (rc == 0)
+            {
+                Console.WriteLine("hostfxr_resolve_sdk2:Success");
+            }
+            else
+            {
+                Console.WriteLine($"hostfxr_resolve_sdk2:Fail[{rc}]");
+            }
+
+            Console.WriteLine($"hostfxr_resolve_sdk2 data:[{string.Join(';', data)}]");
+        }
+
+        /// <summary>
+        /// Test invoking the native hostfxr api hostfxr_get_available_sdks
+        /// </summary>
+        /// <param name="args[0]">hostfxr_get_available_sdks</param>
+        /// <param name="args[1]">Directory of dotnet executable</param>
+        static void Test_hostfxr_get_available_sdks(string[] args)
+        {
+            if (args.Length != 2)
+            {
+                throw new ArgumentException("Invalid number of arguments passed");
+            }
+
+            string[] sdks = null;
+            int rc = hostfxr.hostfxr_get_available_sdks(
+                exe_dir: args[1], 
+                (sdk_count, sdk_dirs) => sdks = sdk_dirs);
+
+            if (rc == 0)
+            {
+                Console.WriteLine("hostfxr_get_available_sdks:Success");
+                Console.WriteLine($"hostfxr_get_available_sdks sdks:[{string.Join(';', sdks)}]");
+            }
+            else
+            {
+                Console.WriteLine($"hostfxr_get_available_sdks:Fail[{rc}]");
+            }
+        }
+
+        public static bool RunTest(string apiToTest, string[] args)
+        {
+            switch (apiToTest)
+            {
+                case nameof(hostfxr.hostfxr_get_native_search_directories):
+                    Test_hostfxr_get_native_search_directories(args);
+                    break;
+                case nameof(hostfxr.hostfxr_resolve_sdk2):
+                    Test_hostfxr_resolve_sdk2(args);
+                    break;
+                case nameof(hostfxr.hostfxr_get_available_sdks):
+                    Test_hostfxr_get_available_sdks(args);
+                    break;
+                default:
+                    return false;
+            }
+
+            Utils.LogModulePath("hostfxr");
+
+            return true;
+        }
+    }
+}
\ No newline at end of file
index 1da6db1..df20970 100644 (file)
@@ -3,65 +3,13 @@ using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Text;
 
-namespace StandaloneApp
+namespace HostApiInvokerApp
 {
     public static class Program
     {
-#if WINDOWS
-       const CharSet OSCharSet = CharSet.Unicode;
-#else
-       const CharSet OSCharSet = CharSet.Ansi; // actually UTF8 on Unix
-#endif
-
-        [DllImport("hostfxr", CharSet = OSCharSet)]
-        static extern uint hostfxr_get_native_search_directories(
-            int argc, 
-            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
-            string[] argv, 
-            StringBuilder buffer, 
-            int bufferSize, 
-            ref int required_buffer_size);
-
-        [Flags]
-        internal enum hostfxr_resolve_sdk2_flags_t : int
-        {
-            disallow_prerelease = 0x1,
-        }
-
-        internal enum hostfxr_resolve_sdk2_result_key_t : int
-        {
-            resolved_sdk_dir = 0,
-            global_json_path = 1,
-        }
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = OSCharSet)]
-        internal delegate void hostfxr_resolve_sdk2_result_fn(
-            hostfxr_resolve_sdk2_result_key_t key,
-            string value);
-
-        [DllImport("hostfxr", CharSet = OSCharSet, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
-        internal static extern int hostfxr_resolve_sdk2(
-            string exe_dir,
-            string working_dir,
-            hostfxr_resolve_sdk2_flags_t flags,
-            hostfxr_resolve_sdk2_result_fn result);
-
-        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = OSCharSet)]
-        internal delegate void hostfxr_get_available_sdks_result_fn(
-            int sdk_count,
-            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
-            string[] sdk_dirs);
-
-        [DllImport("hostfxr", CharSet = OSCharSet, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
-        internal static extern int hostfxr_get_available_sdks(
-            string exe_dir,
-            hostfxr_get_available_sdks_result_fn result);
-
-        const uint HostApiBufferTooSmall = 0x80008098;
-
         public static int Main(string[] args)
         {
-            // write exception details to stdout so tha they can be seen in test assertion failures.
+            // write exception details to stdout so that they can be seen in test assertion failures.
             try
             {
                 MainCore(args);
@@ -110,124 +58,13 @@ namespace StandaloneApp
             }
 
             string apiToTest = args[0];
-            switch (apiToTest)
-            {
-                case nameof(hostfxr_get_native_search_directories):
-                    Test_hostfxr_get_native_search_directories(args);
-                    break;
-                case nameof(hostfxr_resolve_sdk2):
-                    Test_hostfxr_resolve_sdk2(args);
-                    break;
-                case nameof(hostfxr_get_available_sdks):
-                    Test_hostfxr_get_available_sdks(args);
-                    break;
-                default:
-                    throw new ArgumentException($"Invalid API to test passed as args[0]): {apiToTest}");
-            }
-        }
-
-        /// <summary>
-        /// Test invoking the native hostfxr api hostfxr_get_native_search_directories
-        /// </summary>
-        /// <param name="args[0]">hostfxr_get_native_search_directories</param>
-        /// <param name="args[1]">Path to dotnet.exe</param>
-        /// <param name="args[2]">Path to application</param>
-        static void Test_hostfxr_get_native_search_directories(string[] args)
-        {
-            if (args.Length != 3)
-            {
-                throw new ArgumentException("Invalid number of arguments passed");
-            }
-
-            string pathToDotnet = args[1];
-            string pathToApp = args[2];
-            string[] argv = new[] { pathToDotnet, pathToApp };
-
-            // Start with 0 bytes allocated to test re-entry and required_buffer_size
-            StringBuilder buffer = new StringBuilder(0);
-            int required_buffer_size = 0;
-
-            uint rc = 0;
-            for (int i = 0; i < 2; i++)
-            {
-                rc = hostfxr_get_native_search_directories(argv.Length, argv, buffer, buffer.Capacity + 1, ref required_buffer_size);
-                if (rc != HostApiBufferTooSmall)
-                {
-                    break;
-                }
-
-                buffer = new StringBuilder(required_buffer_size);
-            }
-
-            if (rc == 0)
-            {
-                Console.WriteLine("hostfxr_get_native_search_directories:Success");
-                Console.WriteLine($"hostfxr_get_native_search_directories buffer:[{buffer}]");
-            }
-            else
-            {
-                Console.WriteLine($"hostfxr_get_native_search_directories:Fail[{rc}]");
-            }
-        }
-
-        /// <summary>
-        /// Test invoking the native hostfxr api hostfxr_resolve_sdk2
-        /// </summary>
-        /// <param name="args[0]">hostfxr_get_available_sdks</param>
-        /// <param name="args[1]">Directory of dotnet executable</param>
-        /// <param name="args[2]">Working directory where search for global.json begins</param>
-        /// <param name="args[3]">Flags</param>
-        static void Test_hostfxr_resolve_sdk2(string[] args)
-        {
-            if (args.Length != 4)
-            {
-                throw new ArgumentException("Invalid number of arguments passed");
-            }
-
-            var data = new List<(hostfxr_resolve_sdk2_result_key_t, string)>();
-            int rc = hostfxr_resolve_sdk2(
-                exe_dir: args[1],
-                working_dir: args[2],
-                flags: Enum.Parse<hostfxr_resolve_sdk2_flags_t>(args[3]),
-                result: (key, value) => data.Add((key, value)));
-
-            if (rc == 0)
-            {
-                Console.WriteLine("hostfxr_resolve_sdk2:Success");
-            }
-            else
-            {
-                Console.WriteLine($"hostfxr_resolve_sdk2:Fail[{rc}]");
-            }
-
-            Console.WriteLine($"hostfxr_resolve_sdk2 data:[{string.Join(';', data)}]");
-        }
-
-        /// <summary>
-        /// Test invoking the native hostfxr api hostfxr_get_available_sdks
-        /// </summary>
-        /// <param name="args[0]">hostfxr_get_available_sdks</param>
-        /// <param name="args[1]">Directory of dotnet executable</param>
-        static void Test_hostfxr_get_available_sdks(string[] args)
-        {
-            if (args.Length != 2)
-            {
-                throw new ArgumentException("Invalid number of arguments passed");
-            }
-
-            string[] sdks = null;
-            int rc = hostfxr_get_available_sdks(
-                exe_dir: args[1], 
-                (sdk_count, sdk_dirs) => sdks = sdk_dirs);
-
-            if (rc == 0)
+            if (HostFXR.RunTest(apiToTest, args))
             {
-                Console.WriteLine("hostfxr_get_available_sdks:Success");
-                Console.WriteLine($"hostfxr_get_available_sdks sdks:[{string.Join(';', sdks)}]");
+                return;
             }
             else
             {
-                Console.WriteLine($"hostfxr_get_native_search_directories:Fail[{rc}]");
+                throw new ArgumentException($"Invalid API to test passed as args[0]): {apiToTest}");
             }
         }
     }
diff --git a/src/installer/test/Assets/TestProjects/HostApiInvokerApp/Utils.cs b/src/installer/test/Assets/TestProjects/HostApiInvokerApp/Utils.cs
new file mode 100644 (file)
index 0000000..103e79c
--- /dev/null
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace HostApiInvokerApp
+{
+    public static class Utils
+    {
+#if WINDOWS
+       public const CharSet OSCharSet = CharSet.Unicode;
+#else
+       public const CharSet OSCharSet = CharSet.Ansi; // actually UTF8 on Unix
+#endif
+
+#if WINDOWS
+        internal static class kernel32
+        {
+            [DllImport(nameof(kernel32), CharSet = CharSet.Auto, BestFitMapping = false, SetLastError = true)]
+            internal static extern IntPtr GetModuleHandle(String moduleName);
+
+            [DllImport(nameof(kernel32), CharSet = CharSet.Auto)]
+            internal static extern uint GetModuleFileName(IntPtr hModule, StringBuilder fileName, int size);
+        }
+#endif
+
+        public static void LogModulePath(string moduleName)
+        {
+#if WINDOWS
+            IntPtr hModule = kernel32.GetModuleHandle(moduleName);
+            if (hModule == IntPtr.Zero)
+            {
+                Console.WriteLine($"Can't find module {moduleName} in the process.");
+                return;
+            }
+
+            StringBuilder buffer = new StringBuilder(2048);
+            if (kernel32.GetModuleFileName(hModule, buffer, buffer.Capacity) <= 0)
+            {
+                Console.WriteLine($"Failed to get module file path for module {moduleName}.");
+                return;
+            }
+
+            Console.WriteLine($"{moduleName}: {buffer.ToString()}");
+#endif
+        }
+    }
+}
index ccea62f..30cbfe7 100644 (file)
@@ -1,14 +1,11 @@
 // Copyright (c) .NET Foundation and contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+using Microsoft.DotNet.Cli.Build;
 using System;
 using System.IO;
 using System.Runtime.InteropServices;
 using Xunit;
-using FluentAssertions;
-using Microsoft.DotNet.CoreSetup.Test;
-using System.Collections.Generic;
-using Microsoft.DotNet.Cli.Build;
 
 namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.NativeHostApis
 {
@@ -16,7 +13,7 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.NativeHostApis
     {
         private SharedTestState sharedTestState;
 
-        public GivenThatICareAboutNativeHostApis(GivenThatICareAboutNativeHostApis.SharedTestState fixture)
+        public GivenThatICareAboutNativeHostApis(SharedTestState fixture)
         {
             sharedTestState = fixture;
         }