Skip to content

Commit bfc60ed

Browse files
committed
Add tests
1 parent 16f8a89 commit bfc60ed

File tree

3 files changed

+474
-8
lines changed

3 files changed

+474
-8
lines changed

src/installer/tests/Assets/Projects/HostApiInvokerApp/HostFXR.cs

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace HostApiInvokerApp
1010
{
11-
public static class HostFXR
11+
public static unsafe class HostFXR
1212
{
1313
internal static class hostfxr
1414
{
@@ -59,6 +59,34 @@ internal struct hostfxr_dotnet_environment_info
5959
internal IntPtr frameworks;
6060
}
6161

62+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
63+
internal struct hostfxr_framework_result
64+
{
65+
public nuint size;
66+
public string name;
67+
public string requested_version;
68+
public string resolved_version;
69+
public string resolved_path;
70+
};
71+
72+
[StructLayout(LayoutKind.Sequential)]
73+
internal struct hostfxr_resolve_frameworks_result
74+
{
75+
public nuint size;
76+
public nuint resolved_count;
77+
public IntPtr resolved_frameworks;
78+
public nuint unresolved_count;
79+
public IntPtr unresolved_frameworks;
80+
};
81+
82+
[StructLayout(LayoutKind.Sequential)]
83+
internal struct hostfxr_initialize_parameters
84+
{
85+
public nuint size;
86+
public IntPtr host_path;
87+
public IntPtr dotnet_root;
88+
}
89+
6290
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)]
6391
internal delegate void hostfxr_resolve_sdk2_result_fn(
6492
hostfxr_resolve_sdk2_result_key_t key,
@@ -101,6 +129,18 @@ internal static extern int hostfxr_get_dotnet_environment_info(
101129
IntPtr reserved,
102130
hostfxr_get_dotnet_environment_info_result_fn result,
103131
IntPtr result_context);
132+
133+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
134+
internal delegate void hostfxr_resolve_frameworks_result_fn(
135+
IntPtr result,
136+
IntPtr result_context);
137+
138+
[DllImport(nameof(hostfxr), CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
139+
internal static extern int hostfxr_resolve_frameworks_for_runtime_config(
140+
string runtime_config_path,
141+
hostfxr_initialize_parameters* parameters,
142+
hostfxr_resolve_frameworks_result_fn callback,
143+
IntPtr result_context);
104144
}
105145

106146
/// <summary>
@@ -250,6 +290,85 @@ static void Test_hostfxr_get_dotnet_environment_info(string[] args)
250290
Console.WriteLine($"{api} framework paths:[{string.Join(";", frameworks.Select(f => f.path).ToList())}]");
251291
}
252292

293+
/// <summary>
294+
/// Test that invokes hostfxr_resolve_frameworks_for_runtime_config.
295+
/// </summary>
296+
/// <param name="args[0]">Path to runtime config file</param>
297+
/// <param name="args[1]">(Optional) Path to the directory with dotnet.exe</param>
298+
static unsafe void Test_hostfxr_resolve_frameworks_for_runtime_config(string[] args)
299+
{
300+
if (args.Length < 1)
301+
throw new ArgumentException($"Invalid arguments. Expected: {nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config)} <runtimeConfigPath> [<dotnetRoot>]");
302+
303+
string runtimeConfigPath = args[0];
304+
string dotnetRoot = null;
305+
if (args.Length >= 2)
306+
dotnetRoot = args[1];
307+
308+
List<hostfxr.hostfxr_framework_result> resolved = new();
309+
List<hostfxr.hostfxr_framework_result> unresolved = new();
310+
311+
IntPtr resultContext = new IntPtr(123);
312+
313+
hostfxr.hostfxr_resolve_frameworks_result_fn callback = (IntPtr resultPtr, IntPtr contextPtr) =>
314+
{
315+
hostfxr.hostfxr_resolve_frameworks_result result = Marshal.PtrToStructure<hostfxr.hostfxr_resolve_frameworks_result>(resultPtr);
316+
317+
if (result.size != (nuint)sizeof(hostfxr.hostfxr_resolve_frameworks_result))
318+
throw new Exception($"Unexpected {nameof(hostfxr.hostfxr_resolve_frameworks_result)}.size: {result.size}. Expected: {sizeof(hostfxr.hostfxr_resolve_frameworks_result)}.");
319+
320+
if (contextPtr != resultContext)
321+
throw new Exception($"Unexpected result_context value: {contextPtr}. Expected: {resultContext}.");
322+
323+
for (int i = 0; i < (int)result.resolved_count; i++)
324+
{
325+
nint ptr = result.resolved_frameworks + i * Marshal.SizeOf<hostfxr.hostfxr_framework_result>();
326+
resolved.Add(Marshal.PtrToStructure<hostfxr.hostfxr_framework_result>(ptr));
327+
}
328+
329+
for (int i = 0; i < (int)result.unresolved_count; i++)
330+
{
331+
nint ptr = result.unresolved_frameworks + i * Marshal.SizeOf<hostfxr.hostfxr_framework_result>();
332+
unresolved.Add(Marshal.PtrToStructure<hostfxr.hostfxr_framework_result>(ptr));
333+
}
334+
};
335+
336+
int rc;
337+
hostfxr.hostfxr_initialize_parameters parameters = new()
338+
{
339+
size = (nuint)sizeof(hostfxr.hostfxr_initialize_parameters),
340+
host_path = IntPtr.Zero,
341+
dotnet_root = dotnetRoot != null ? Marshal.StringToCoTaskMemAuto(dotnetRoot) : IntPtr.Zero
342+
};
343+
try
344+
{
345+
rc = hostfxr.hostfxr_resolve_frameworks_for_runtime_config(
346+
runtime_config_path: runtimeConfigPath,
347+
parameters: &parameters,
348+
callback: callback,
349+
result_context: resultContext);
350+
}
351+
finally
352+
{
353+
Marshal.FreeCoTaskMem(parameters.dotnet_root);
354+
}
355+
356+
string api = nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config);
357+
LogResult(api, rc);
358+
359+
Console.WriteLine($"{api} resolved_count: {resolved.Count}");
360+
foreach (var framework in resolved)
361+
{
362+
Console.WriteLine($"{api} resolved_framework: name={framework.name}, version={framework.resolved_version}, path=[{framework.resolved_path}]");
363+
}
364+
365+
Console.WriteLine($"{api} unresolved_count: {unresolved.Count}");
366+
foreach (var framework in unresolved)
367+
{
368+
Console.WriteLine($"{api} unresolved_framework: name={framework.name}, requested_version={framework.requested_version}, path=[{framework.resolved_path}]");
369+
}
370+
}
371+
253372
private static void LogResult(string apiName, int rc)
254373
=> Console.WriteLine(rc == 0 ? $"{apiName}:Success" : $"{apiName}:Fail[0x{rc:x}]");
255374

@@ -269,6 +388,9 @@ public static bool RunTest(string apiToTest, string[] args)
269388
case nameof(hostfxr.hostfxr_get_dotnet_environment_info):
270389
Test_hostfxr_get_dotnet_environment_info(args);
271390
break;
391+
case nameof(hostfxr.hostfxr_resolve_frameworks_for_runtime_config):
392+
Test_hostfxr_resolve_frameworks_for_runtime_config(args);
393+
break;
272394
default:
273395
return false;
274396
}

0 commit comments

Comments
 (0)