summaryrefslogtreecommitdiff
path: root/tests/src/Loader/AssemblyDependencyResolverTests/HostPolicyMock.cs
blob: 1c212efd4809097fe1c48758ce32aa2422bc4b07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace AssemblyDependencyResolverTests
{
    class HostPolicyMock
    {
#if WINDOWS
        private const CharSet HostpolicyCharSet = CharSet.Unicode;
#else
        private const CharSet HostpolicyCharSet = CharSet.Ansi;
#endif

        [DllImport("hostpolicy", CharSet = HostpolicyCharSet)]
        private static extern int Set_corehost_resolve_component_dependencies_Values(
            int returnValue,
            string assemblyPaths,
            string nativeSearchPaths,
            string resourceSearchPaths);

        [DllImport("hostpolicy", CharSet = HostpolicyCharSet)]
        private static extern void Set_corehost_set_error_writer_returnValue(IntPtr error_writer);

        [DllImport("hostpolicy", CharSet = HostpolicyCharSet)]
        private static extern IntPtr Get_corehost_set_error_writer_lastSet_error_writer();

        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = HostpolicyCharSet)]
        internal delegate void Callback_corehost_resolve_component_dependencies(
            string component_main_assembly_path);

        [DllImport("hostpolicy", CharSet = HostpolicyCharSet)]
        private static extern void Set_corehost_resolve_component_dependencies_Callback(
            IntPtr callback);

        private static Type _assemblyDependencyResolverType;
        private static Type _corehost_error_writer_fnType;

        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = HostpolicyCharSet)]
        public delegate void ErrorWriterDelegate(string message);

        public static string DeleteExistingHostpolicy(string coreRoot)
        {
            string hostPolicyFileName = XPlatformUtils.GetStandardNativeLibraryFileName("hostpolicy");
            string destinationPath = Path.Combine(coreRoot, hostPolicyFileName);
            if (File.Exists(destinationPath))
            {
                File.Delete(destinationPath);
            }

            return destinationPath;
        }

        public static void Initialize(string testBasePath, string coreRoot)
        {
            string hostPolicyFileName = XPlatformUtils.GetStandardNativeLibraryFileName("hostpolicy");
            string destinationPath = DeleteExistingHostpolicy(coreRoot);

            File.Copy(
                Path.Combine(testBasePath, hostPolicyFileName),
                destinationPath);

            _assemblyDependencyResolverType = typeof(object).Assembly.GetType("System.Runtime.Loader.AssemblyDependencyResolver");

            // This is needed for marshalling of function pointers to work - requires private access to the CDR unfortunately
            // Delegate marshalling doesn't support casting delegates to anything but the original type
            // so we need to use the original type.
            _corehost_error_writer_fnType = _assemblyDependencyResolverType.GetNestedType("corehost_error_writer_fn", System.Reflection.BindingFlags.NonPublic);
        }

        public static MockValues_corehost_resolve_componet_dependencies Mock_corehost_resolve_componet_dependencies(
            int returnValue,
            string assemblyPaths,
            string nativeSearchPaths,
            string resourceSearchPaths)
        {
            Set_corehost_resolve_component_dependencies_Values(
                returnValue,
                assemblyPaths,
                nativeSearchPaths,
                resourceSearchPaths);

            return new MockValues_corehost_resolve_componet_dependencies();
        }

        internal class MockValues_corehost_resolve_componet_dependencies : IDisposable
        {
            public Action<string> Callback
            {
                set
                {
                    var callback = new Callback_corehost_resolve_component_dependencies(value);
                    if (callback != null)
                    {
                        Set_corehost_resolve_component_dependencies_Callback(
                            Marshal.GetFunctionPointerForDelegate(callback));
                    }
                    else
                    {
                        Set_corehost_resolve_component_dependencies_Callback(IntPtr.Zero);
                    }
                }
            }

            public void Dispose()
            {
                Set_corehost_resolve_component_dependencies_Values(
                    -1,
                    string.Empty,
                    string.Empty,
                    string.Empty);
                Set_corehost_resolve_component_dependencies_Callback(IntPtr.Zero);
            }
        }

        public static MockValues_corehost_set_error_writer Mock_corehost_set_error_writer()
        {
            return Mock_corehost_set_error_writer(IntPtr.Zero);
        }

        public static MockValues_corehost_set_error_writer Mock_corehost_set_error_writer(IntPtr existingErrorWriter)
        {
            Set_corehost_set_error_writer_returnValue(existingErrorWriter);

            return new MockValues_corehost_set_error_writer();
        }

        internal class MockValues_corehost_set_error_writer : IDisposable
        {
            public IntPtr LastSetErrorWriterPtr
            {
                get
                {
                    return Get_corehost_set_error_writer_lastSet_error_writer();
                }
            }

            public Action<string> LastSetErrorWriter
            {
                get
                {
                    IntPtr errorWriterPtr = LastSetErrorWriterPtr;
                    if (errorWriterPtr == IntPtr.Zero)
                    {
                        return null;
                    }
                    else
                    {
                        Delegate d = Marshal.GetDelegateForFunctionPointer(errorWriterPtr, _corehost_error_writer_fnType);
                        return (string message) => { d.DynamicInvoke(message); };
                    }
                }
            }

            public void Dispose()
            {
                Set_corehost_set_error_writer_returnValue(IntPtr.Zero);
            }
        }
    }
}