[WinForms] Fix #18506 ActiveTracker, do not propagate message to control when it...
[mono-project.git] / mono / unit-tests / test-mono-callspec.c
blob186286c22c5342a35a1629e1e93132f1855026ba
1 /*
2 * test-mono-callspec.c: Unit test for the callspec parsing and evaluation.
4 * Copyright (C) 2017 vFunction, Inc.
6 */
8 // Embedders do not have the luxury of our config.h, so skip it here.
9 //#include "config.h"
11 // But we need MONO_INSIDE_RUNTIME to get MonoError mangled correctly
12 // because we also test unexported functions (mono_class_from_name_checked).
13 #define MONO_INSIDE_RUNTIME 1
15 #include "mono/utils/mono-publib.h"
17 // Allow to test external_only w/o deprecation error.
18 #undef MONO_RT_EXTERNAL_ONLY
19 #define MONO_RT_EXTERNAL_ONLY /* nothing */
21 #include <glib.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/callspec.h>
24 #include <mono/metadata/assembly.h>
25 #include <mono/metadata/assembly-internals.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/appdomain.h>
28 #include <mono/metadata/debug-helpers.h>
29 #include <mono/mini/jit.h>
30 #include <mono/utils/mono-error-internals.h>
32 #define TESTPROG "callspec.exe"
34 GArray *test_methods = NULL;
36 enum test_method_enums {
37 FOO_BAR,
38 FOO_BARP,
39 GOO_BAR,
40 FOO2_BAR,
41 CONSOLE_WRITELINE,
44 struct {
45 int method;
46 const char *callspec;
47 gboolean expect_match;
48 } test_entries[] = {
49 /* program tests */
50 {FOO_BAR, "program", TRUE},
51 {CONSOLE_WRITELINE, "program", FALSE},
52 {FOO_BAR, "all,-program", FALSE},
53 {CONSOLE_WRITELINE, "all,-program", TRUE},
55 /* assembly tests */
56 {FOO_BAR, "mscorlib", FALSE},
57 {CONSOLE_WRITELINE, "mscorlib", TRUE},
58 {FOO_BAR, "all,-mscorlib", TRUE},
59 {CONSOLE_WRITELINE, "all,-mscorlib", FALSE},
61 /* class tests */
62 {FOO_BAR, "T:Baz.Foo", TRUE},
63 {CONSOLE_WRITELINE, "T:Baz.Foo", FALSE},
64 {FOO_BAR, "all,-T:Baz.Foo", FALSE},
65 {CONSOLE_WRITELINE, "all,-T:Baz.Foo", TRUE},
67 /* namespace tests */
68 {FOO_BAR, "N:Baz", TRUE},
69 {CONSOLE_WRITELINE, "N:Baz", FALSE},
70 {FOO_BAR, "all,-N:Baz", FALSE},
71 {CONSOLE_WRITELINE, "all,-N:Baz", TRUE},
73 /* method tests without parameters */
74 {FOO_BAR, "M:Baz.Foo:Bar", TRUE},
75 {FOO_BARP, "M:Baz.Foo:Bar", TRUE},
76 {GOO_BAR, "M:Baz.Foo:Bar", FALSE},
77 {FOO2_BAR, "M:Baz.Foo:Bar", FALSE},
78 {CONSOLE_WRITELINE, "M:Baz.Foo:Bar", FALSE},
79 {FOO_BAR, "all,-M:Baz.Foo:Bar", FALSE},
80 {CONSOLE_WRITELINE, "all,-M:Baz.Foo:Bar", TRUE},
82 /* method tests without class */
83 {FOO_BAR, "M::Bar", TRUE},
84 {FOO_BARP, "M::Bar", TRUE},
85 {GOO_BAR, "M::Bar", TRUE},
86 {FOO2_BAR, "M::Bar", TRUE},
88 {0, NULL, FALSE}};
90 static int test_callspec (int test_idx,
91 MonoMethod *method,
92 const char *callspec,
93 gboolean expect_match)
95 int res = 0;
96 gboolean initialized = FALSE;
97 gboolean match;
98 MonoCallSpec spec = {0};
99 char *errstr;
100 char *method_name = mono_method_full_name (method, TRUE);
101 if (!method_name) {
102 printf ("FAILED getting method name in callspec test #%d\n",
103 test_idx);
104 res = 1;
105 goto out;
108 if (!mono_callspec_parse (callspec, &spec, &errstr)) {
109 printf ("FAILED parsing callspec '%s' - %s\n", callspec,
110 errstr);
111 g_free (errstr);
112 res = 1;
113 goto out;
115 initialized = TRUE;
117 match = mono_callspec_eval (method, &spec);
119 if (match && !expect_match) {
120 printf ("FAILED unexpected match '%s' against '%s'\n",
121 method_name, callspec);
122 res = 1;
123 goto out;
125 if (!match && expect_match) {
126 printf ("FAILED unexpected mismatch '%s' against '%s'\n",
127 method_name, callspec);
128 res = 1;
129 goto out;
132 out:
133 if (initialized)
134 mono_callspec_cleanup(&spec);
135 if (method_name)
136 g_free (method_name);
137 return res;
140 static int test_all_callspecs (void)
142 int idx;
143 for (idx = 0; test_entries[idx].callspec; ++idx) {
144 MonoMethod *meth = g_array_index (test_methods, MonoMethod *,
145 test_entries[idx].method);
146 if (test_callspec (idx, meth, test_entries[idx].callspec,
147 test_entries[idx].expect_match))
148 return 1;
151 return 0;
154 static MonoClass *test_mono_class_from_name (MonoImage *image,
155 const char *name_space,
156 const char *name)
158 ERROR_DECL (error);
159 MonoClass *klass;
161 klass = mono_class_from_name_checked (image, name_space, name, error);
162 mono_error_cleanup (error); /* FIXME Don't swallow the error */
164 return klass;
167 #ifdef __cplusplus
168 extern "C"
169 #endif
171 test_mono_callspec_main (void);
174 test_mono_callspec_main (void)
176 int res = 0;
177 MonoDomain *domain = NULL;
178 MonoAssembly *assembly = NULL;
179 MonoImage *prog_image = NULL;
180 MonoImage *corlib = NULL;
181 MonoClass *prog_klass, *console_klass;
182 MonoMethod *meth;
183 MonoImageOpenStatus status;
185 //FIXME This is a fugly hack due to embedding simply not working from the tree
186 mono_set_assemblies_path ("../../mcs/class/lib/net_4_x");
188 test_methods = g_array_new (FALSE, TRUE, sizeof (MonoMethod *));
189 if (!test_methods) {
190 res = 1;
191 printf ("FAILED INITIALIZING METHODS ARRAY\n");
192 goto out;
195 domain = mono_jit_init_version_for_test_only ("TEST RUNNER", "mobile");
196 assembly = mono_assembly_open (TESTPROG, &status);
197 if (!domain || !assembly) {
198 res = 1;
199 printf("FAILED LOADING TEST PROGRAM\n");
200 goto out;
203 mono_callspec_set_assembly(assembly);
205 prog_image = mono_assembly_get_image_internal (assembly);
207 prog_klass = test_mono_class_from_name (prog_image, "Baz", "Foo");
208 if (!prog_klass) {
209 res = 1;
210 printf ("FAILED FINDING Baz.Foo\n");
211 goto out;
213 meth = mono_class_get_method_from_name (prog_klass, "Bar", 0);
214 if (!meth) {
215 res = 1;
216 printf ("FAILED FINDING Baz.Foo:Bar ()\n");
217 goto out;
219 g_array_append_val (test_methods, meth);
220 meth = mono_class_get_method_from_name (prog_klass, "Bar", 1);
221 if (!meth) {
222 res = 1;
223 printf ("FAILED FINDING Baz.Foo:Bar (string)\n");
224 goto out;
226 g_array_append_val (test_methods, meth);
228 prog_klass = test_mono_class_from_name (prog_image, "Baz", "Goo");
229 if (!prog_klass) {
230 res = 1;
231 printf ("FAILED FINDING Baz.Goo\n");
232 goto out;
234 meth = mono_class_get_method_from_name (prog_klass, "Bar", 1);
235 if (!meth) {
236 res = 1;
237 printf ("FAILED FINDING Baz.Goo:Bar (string)\n");
238 goto out;
240 g_array_append_val (test_methods, meth);
242 prog_klass = test_mono_class_from_name (prog_image, "Baz", "Foo2");
243 if (!prog_klass) {
244 res = 1;
245 printf ("FAILED FINDING Baz.Foo2\n");
246 goto out;
248 meth = mono_class_get_method_from_name (prog_klass, "Bar", 1);
249 if (!meth) {
250 res = 1;
251 printf ("FAILED FINDING Baz.Foo2:Bar (string)\n");
252 goto out;
254 g_array_append_val (test_methods, meth);
256 corlib = mono_get_corlib ();
258 console_klass = test_mono_class_from_name (corlib, "System", "Console");
259 if (!console_klass) {
260 res = 1;
261 printf ("FAILED FINDING System.Console\n");
262 goto out;
264 meth = mono_class_get_method_from_name (console_klass, "WriteLine", 1);
265 if (!meth) {
266 res = 1;
267 printf ("FAILED FINDING System.Console:WriteLine\n");
268 goto out;
270 g_array_append_val (test_methods, meth);
272 res = test_all_callspecs ();
273 out:
274 return res;