6ee66bb8c585e6c33aa6c1e5cd9410c19126cd9e
[mono.git] / mono / mini / fsacheck.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/stat.h>
5
6 #include <mono/metadata/appdomain.h>
7 #include <mono/metadata/assembly.h>
8 #include <mono/metadata/debug-helpers.h>
9 #include <mono/metadata/object.h>
10 #include <mono/jit/jit.h>
11 #include <mono/utils/mono-logger.h>
12
13 extern void* mono_aot_module_mscorlib_info;
14 extern void* mono_aot_module_System_Core_info;
15 extern void* mono_aot_module_System_info;
16 extern void* mono_aot_module_Mono_Posix_info;
17 extern void* mono_aot_module_System_Configuration_info;
18 extern void* mono_aot_module_System_Security_info;
19 extern void* mono_aot_module_System_Xml_info;
20 /* extern void* mono_aot_module_System_Threading_info; */
21 extern void* mono_aot_module_Mono_Security_info;
22 extern void* mono_aot_module_Mono_Simd_info;
23 extern void* mono_aot_module_TestDriver_info;
24
25 extern void* mono_aot_module_basic_info;
26 extern void* mono_aot_module_basic_float_info;
27 extern void* mono_aot_module_basic_long_info;
28 extern void* mono_aot_module_basic_calls_info;
29 extern void* mono_aot_module_basic_simd_info;
30 extern void* mono_aot_module_objects_info;
31 extern void* mono_aot_module_arrays_info;
32 extern void* mono_aot_module_basic_math_info;
33 extern void* mono_aot_module_exceptions_info;
34 extern void* mono_aot_module_devirtualization_info;
35 extern void* mono_aot_module_generics_info;
36 extern void* mono_aot_module_generics_variant_types_info;
37 extern void* mono_aot_module_basic_simd_info;
38 extern void* mono_aot_module_gc_stress_info;
39 extern void* mono_aot_module_imt_big_iface_test_info;
40 extern void* mono_aot_module_make_imt_test_info;
41 /* extern void* mono_aot_module_thread_stress_info; */
42 extern void* mono_aot_module_iltests_info;
43
44 extern void mono_aot_register_module(void *aot_info);
45 extern void mono_aot_init(void);
46 extern void mono_jit_set_aot_only(mono_bool aot_only);
47 extern MonoDomain * mini_init (const char *filename, const char *runtime_version);
48
49 int run_all_test_methods(MonoClass *klass) {
50   void * iter = NULL;
51   MonoMethod *mm = NULL;
52   int count = 0;
53   int passed = 0;
54   printf("Running test methods without reflection\n");
55   while (NULL != (mm = mono_class_get_methods(klass, &iter))) {
56     long expected_result;
57     const char *name = mono_method_get_name(mm);
58     char *end = NULL;
59     if (strncmp(name, "test_", 5)) continue;
60     printf("=== Test %d, method %s\n", count, mono_method_get_name(mm));
61     expected_result = strtol(name + 5, &end, 10);
62     if (name == end) {
63       printf(" warning: could not determine expected return value\n");
64       expected_result = 0;
65     }
66     MonoObject *mo = mono_runtime_invoke(mm, NULL, NULL, NULL);
67     int *ret = mono_object_unbox(mo);
68     if (ret && *ret == expected_result) {
69       printf(" passed!\n");
70       passed++;
71     } else {
72       printf(" FAILED, expected %d, returned %p, %d\n", expected_result, ret,
73              ret != NULL ? *ret : 0);
74     }
75     count++;
76   }
77   if (count > 0) {
78     printf("============================================\n");
79     printf("Final count: %d tests, %d pass, %.2f%%\n", count, passed,
80            (double)passed / count * 100.0);
81   } else {
82     printf("no test methods found.\n");
83   }
84   return count;
85 }
86
87 #if defined(__native_client__)
88 extern void* mono_aot_module_nacl_info;
89 extern char* nacl_mono_path;
90 char *load_corlib_data() {
91   FILE *mscorlib;
92   static char *corlib_data = NULL;
93   if (corlib_data) return corlib_data;
94
95   mscorlib = fopen("mscorlib.dll", "r");
96   if (NULL != mscorlib) {
97     size_t size;
98     struct stat st;
99     if (0 == stat("mscorlib.dll", &st)) {
100       size = st.st_size;
101       printf("reading mscorlib.dll, size %ld\n", size);
102       corlib_data = malloc(size);
103       if (corlib_data != NULL) {
104         while (fread(corlib_data, 1, size, mscorlib) != 0) ;
105         if (!ferror(mscorlib)) {
106           mono_set_corlib_data(corlib_data, size);
107         } else {
108           perror("error reading mscorlib.dll");
109           free(corlib_data);
110           corlib_data = NULL;
111         }
112       } else {
113         perror("Could not allocate memory");
114       }
115     } else {
116       perror("stat error");
117     }
118     fclose(mscorlib);
119   }
120   return corlib_data;
121 }
122 #endif
123
124 /* Initialize Mono. Must run only once per process */
125 MonoDomain *init_mono(char *mname) {
126   MonoDomain *domain = NULL;
127 #ifdef AOT_VERSION
128   mono_jit_set_aot_only(1);
129   mono_aot_register_module(mono_aot_module_mscorlib_info);
130   mono_aot_register_module(mono_aot_module_TestDriver_info);
131   mono_aot_register_module(mono_aot_module_System_Core_info);
132   mono_aot_register_module(mono_aot_module_System_info);
133   mono_aot_register_module(mono_aot_module_Mono_Posix_info);
134   mono_aot_register_module(mono_aot_module_System_Configuration_info);
135   mono_aot_register_module(mono_aot_module_System_Security_info);
136   mono_aot_register_module(mono_aot_module_System_Xml_info);
137   mono_aot_register_module(mono_aot_module_Mono_Security_info);
138   /*  mono_aot_register_module(mono_aot_module_System_Threading_info); */
139   mono_aot_register_module(mono_aot_module_Mono_Simd_info);
140
141   mono_aot_register_module(mono_aot_module_basic_info);
142   mono_aot_register_module(mono_aot_module_basic_float_info);
143   mono_aot_register_module(mono_aot_module_basic_long_info);
144   mono_aot_register_module(mono_aot_module_basic_calls_info);
145   mono_aot_register_module(mono_aot_module_basic_simd_info);
146   mono_aot_register_module(mono_aot_module_objects_info);
147   mono_aot_register_module(mono_aot_module_arrays_info);
148   mono_aot_register_module(mono_aot_module_basic_math_info);
149   mono_aot_register_module(mono_aot_module_exceptions_info);
150   mono_aot_register_module(mono_aot_module_devirtualization_info);
151   mono_aot_register_module(mono_aot_module_generics_info);
152   mono_aot_register_module(mono_aot_module_generics_variant_types_info);
153   mono_aot_register_module(mono_aot_module_gc_stress_info);
154   mono_aot_register_module(mono_aot_module_imt_big_iface_test_info);
155   mono_aot_register_module(mono_aot_module_iltests_info);
156 #endif
157   /* mono_aot_register_module(mono_aot_module_make_imt_test_info); */
158   /* mono_aot_register_module(mono_aot_module_thread_stress_info); */
159 #if defined(__native_client__)
160 #ifdef AOT_VERSION
161   mono_aot_register_module(mono_aot_module_nacl_info);
162 #endif
163
164   /* Test file-less shortcut for loading mscorlib metadata */
165   load_corlib_data();
166   nacl_mono_path = strdup(".");
167 #endif
168   /* Uncomment the following if something is going wrong */
169   /* mono_trace_set_level_string("info"); */
170   domain = mono_jit_init(mname);
171   if (NULL == domain) {
172     printf("ERROR: mono_jit_init failure\n");
173     exit(-1);
174   }
175   return domain;
176 }
177
178 /* Run all tests from one assembly file */
179 int try_one(char *mname, MonoDomain *domain) {
180   MonoAssembly *ma;
181   MonoImage *mi;
182   MonoClass *mc;
183   MonoMethodDesc *mmd;
184   MonoMethod *mm;
185   MonoObject *mo;
186   MonoString *monostring_arg;
187   MonoArray *arg_array;
188   int *failures = NULL;
189   const int kUseTestDriver = 1;
190   int test_count = 0;
191   void *args [1];
192   char *cstr_arg = "--timing";
193
194   ma = mono_domain_assembly_open(domain, mname);
195   if (NULL == ma) {
196     printf("ERROR: could not open mono assembly\n");
197     exit(-1);
198   }
199
200   mi = mono_assembly_get_image(ma);
201   if (NULL == mi) {
202     printf("ERROR: could not get assembly image\n");
203     exit(-1);
204   }
205
206   monostring_arg = mono_string_new(domain, cstr_arg);
207   mc = mono_class_from_name(mono_get_corlib(), "System", "String");
208   if (0 == mc) {
209     printf("ERROR: could not mono string class\n");
210     exit(-1);
211   }
212
213   // to pass a string argument, change the 0 to a 1 and uncomment
214   // mono_array_setref below
215   arg_array = mono_array_new(domain, mc, 0);
216   //mono_array_setref(arg_array, 0, monostring_arg);
217   args[0] = arg_array;
218
219   if (!kUseTestDriver) {
220     mc = mono_class_from_name(mi, "", "Tests");
221     if (NULL == mc) {
222       printf("could not open Tests class\n");
223       exit(-1);
224     }
225     test_count = run_all_test_methods(mc);
226   }
227   /* If run_all_test_methods didn't find any tests, try Main */
228   if (kUseTestDriver || test_count == 0) {
229     mmd = mono_method_desc_new("Tests:Main()", 1);
230     mm = mono_method_desc_search_in_image(mmd, mi);
231     if (0 == mm) {
232       mmd = mono_method_desc_new("Tests:Main(string[])", 1);
233       mm = mono_method_desc_search_in_image(mmd, mi);
234       if (0 == mm) {
235         printf("Couldn't find Tests:Main() or Tests:Main(string[])\n");
236         exit(-1);
237       }
238     }
239
240     mo = mono_runtime_invoke(mm, NULL, args, NULL);
241     failures = mo != NULL ? mono_object_unbox(mo) : NULL;
242     if (NULL == failures || *failures != 0) {
243       printf("--------------------> Failed");
244     }
245   }
246   return failures != NULL ? failures : 1;
247 }
248
249 int main(int argc, char *argv[]) {
250    MonoDomain *domain;
251    int failures = 0;
252
253   if (argc < 2) {
254     printf("no test specified; running basic.exe\n");
255     printf("================================\n");
256     domain = init_mono("basic.exe");
257     try_one("basic.exe", domain);
258   } else {
259     domain = init_mono(argv[1]);
260     int i;
261     for (i = 1; i < argc; i++) {
262       printf("\nRunning tests from %s:\n", argv[i]);
263       printf("===============================\n\n");
264       failures += try_one(argv[i], domain);
265     }
266   }
267   mono_jit_cleanup(domain);
268   return failures;
269 }