2 * test-mono-callspec.c: Unit test for the callspec parsing and evaluation.
4 * Copyright (C) 2017 vFunction, Inc.
8 // Embedders do not have the luxury of our config.h, so skip it here.
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 */
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
{
47 gboolean expect_match
;
50 {FOO_BAR
, "program", TRUE
},
51 {CONSOLE_WRITELINE
, "program", FALSE
},
52 {FOO_BAR
, "all,-program", FALSE
},
53 {CONSOLE_WRITELINE
, "all,-program", TRUE
},
56 {FOO_BAR
, "mscorlib", FALSE
},
57 {CONSOLE_WRITELINE
, "mscorlib", TRUE
},
58 {FOO_BAR
, "all,-mscorlib", TRUE
},
59 {CONSOLE_WRITELINE
, "all,-mscorlib", FALSE
},
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
},
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
},
90 static int test_callspec (int test_idx
,
93 gboolean expect_match
)
96 gboolean initialized
= FALSE
;
98 MonoCallSpec spec
= {0};
100 char *method_name
= mono_method_full_name (method
, TRUE
);
102 printf ("FAILED getting method name in callspec test #%d\n",
108 if (!mono_callspec_parse (callspec
, &spec
, &errstr
)) {
109 printf ("FAILED parsing callspec '%s' - %s\n", callspec
,
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
);
125 if (!match
&& expect_match
) {
126 printf ("FAILED unexpected mismatch '%s' against '%s'\n",
127 method_name
, callspec
);
134 mono_callspec_cleanup(&spec
);
136 g_free (method_name
);
140 static int test_all_callspecs (void)
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
))
154 static MonoClass
*test_mono_class_from_name (MonoImage
*image
,
155 const char *name_space
,
161 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
162 mono_error_cleanup (error
); /* FIXME Don't swallow the error */
171 test_mono_callspec_main (void);
174 test_mono_callspec_main (void)
177 MonoDomain
*domain
= NULL
;
178 MonoAssembly
*assembly
= NULL
;
179 MonoImage
*prog_image
= NULL
;
180 MonoImage
*corlib
= NULL
;
181 MonoClass
*prog_klass
, *console_klass
;
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
*));
191 printf ("FAILED INITIALIZING METHODS ARRAY\n");
195 domain
= mono_jit_init_version_for_test_only ("TEST RUNNER", "mobile");
196 assembly
= mono_assembly_open (TESTPROG
, &status
);
197 if (!domain
|| !assembly
) {
199 printf("FAILED LOADING TEST PROGRAM\n");
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");
210 printf ("FAILED FINDING Baz.Foo\n");
213 meth
= mono_class_get_method_from_name (prog_klass
, "Bar", 0);
216 printf ("FAILED FINDING Baz.Foo:Bar ()\n");
219 g_array_append_val (test_methods
, meth
);
220 meth
= mono_class_get_method_from_name (prog_klass
, "Bar", 1);
223 printf ("FAILED FINDING Baz.Foo:Bar (string)\n");
226 g_array_append_val (test_methods
, meth
);
228 prog_klass
= test_mono_class_from_name (prog_image
, "Baz", "Goo");
231 printf ("FAILED FINDING Baz.Goo\n");
234 meth
= mono_class_get_method_from_name (prog_klass
, "Bar", 1);
237 printf ("FAILED FINDING Baz.Goo:Bar (string)\n");
240 g_array_append_val (test_methods
, meth
);
242 prog_klass
= test_mono_class_from_name (prog_image
, "Baz", "Foo2");
245 printf ("FAILED FINDING Baz.Foo2\n");
248 meth
= mono_class_get_method_from_name (prog_klass
, "Bar", 1);
251 printf ("FAILED FINDING Baz.Foo2:Bar (string)\n");
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
) {
261 printf ("FAILED FINDING System.Console\n");
264 meth
= mono_class_get_method_from_name (console_klass
, "WriteLine", 1);
267 printf ("FAILED FINDING System.Console:WriteLine\n");
270 g_array_append_val (test_methods
, meth
);
272 res
= test_all_callspecs ();