1 /*
2 ** mrbtest - Test for Embeddable Ruby
3 **
4 ** This program runs Ruby test programs in test/t directory
5 ** against the current mruby implementation.
6 */
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include <mruby.h>
14 #include <mruby/proc.h>
15 #include <mruby/data.h>
16 #include <mruby/compile.h>
17 #include <mruby/string.h>
18 #include <mruby/variable.h>
19 #include <mruby/array.h>
20
21 void
22 mrb_init_mrbtest(mrb_state *);
23
24 /* Print a short remark for the user */
25 static void
print_hint(void)26 print_hint(void)
27 {
28 printf("mrbtest - Embeddable Ruby Test\n\n");
29 }
30
31 static int
check_error(mrb_state * mrb)32 check_error(mrb_state *mrb)
33 {
34 /* Error check */
35 /* $ko_test and $kill_test should be 0 */
36 mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test"));
37 mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test"));
38
39 return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0;
40 }
41
42 static int
eval_test(mrb_state * mrb)43 eval_test(mrb_state *mrb)
44 {
45 /* evaluate the test */
46 mrb_funcall(mrb, mrb_top_self(mrb), "report", 0);
47 /* did an exception occur? */
48 if (mrb->exc) {
49 mrb_print_error(mrb);
50 mrb->exc = 0;
51 return EXIT_FAILURE;
52 }
53 else if (!check_error(mrb)) {
54 return EXIT_FAILURE;
55 }
56 return EXIT_SUCCESS;
57 }
58
59 static void
t_printstr(mrb_state * mrb,mrb_value obj)60 t_printstr(mrb_state *mrb, mrb_value obj)
61 {
62 char *s;
63 mrb_int len;
64
65 if (mrb_string_p(obj)) {
66 s = RSTRING_PTR(obj);
67 len = RSTRING_LEN(obj);
68 fwrite(s, len, 1, stdout);
69 fflush(stdout);
70 }
71 }
72
73 mrb_value
mrb_t_printstr(mrb_state * mrb,mrb_value self)74 mrb_t_printstr(mrb_state *mrb, mrb_value self)
75 {
76 mrb_value argv;
77
78 mrb_get_args(mrb, "o", &argv);
79 t_printstr(mrb, argv);
80
81 return argv;
82 }
83
84 void
mrb_init_test_driver(mrb_state * mrb,mrb_bool verbose)85 mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose)
86 {
87 struct RClass *krn, *mrbtest;
88
89 krn = mrb->kernel_module;
90 mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1));
91
92 mrbtest = mrb_define_module(mrb, "Mrbtest");
93
94 mrb_define_const(mrb, mrbtest, "FIXNUM_MAX", mrb_fixnum_value(MRB_INT_MAX));
95 mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN));
96 mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT));
97
98 #ifndef MRB_WITHOUT_FLOAT
99 #ifdef MRB_USE_FLOAT
100 mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-6));
101 #else
102 mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-12));
103 #endif
104 #endif
105
106 if (verbose) {
107 mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value());
108 }
109 }
110
111 void
mrb_t_pass_result(mrb_state * mrb_dst,mrb_state * mrb_src)112 mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src)
113 {
114 mrb_value res_src;
115
116 if (mrb_src->exc) {
117 mrb_print_error(mrb_src);
118 exit(EXIT_FAILURE);
119 }
120
121 #define TEST_COUNT_PASS(name) \
122 do { \
123 res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$" #name)); \
124 if (mrb_fixnum_p(res_src)) { \
125 mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name)); \
126 mrb_gv_set(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name), mrb_fixnum_value(mrb_fixnum(res_dst) + mrb_fixnum(res_src))); \
127 } \
128 } while (FALSE) \
129
130 TEST_COUNT_PASS(ok_test);
131 TEST_COUNT_PASS(ko_test);
132 TEST_COUNT_PASS(kill_test);
133
134 #undef TEST_COUNT_PASS
135
136 res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$asserts"));
137
138 if (mrb_array_p(res_src)) {
139 mrb_int i;
140 mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$asserts"));
141 for (i = 0; i < RARRAY_LEN(res_src); ++i) {
142 mrb_value val_src = RARRAY_PTR(res_src)[i];
143 mrb_ary_push(mrb_dst, res_dst, mrb_str_new(mrb_dst, RSTRING_PTR(val_src), RSTRING_LEN(val_src)));
144 }
145 }
146 }
147
148 int
main(int argc,char ** argv)149 main(int argc, char **argv)
150 {
151 mrb_state *mrb;
152 int ret;
153 mrb_bool verbose = FALSE;
154
155 print_hint();
156
157 /* new interpreter instance */
158 mrb = mrb_open();
159 if (mrb == NULL) {
160 fprintf(stderr, "Invalid mrb_state, exiting test driver");
161 return EXIT_FAILURE;
162 }
163
164 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') {
165 printf("verbose mode: enable\n\n");
166 verbose = TRUE;
167 }
168
169 mrb_init_test_driver(mrb, verbose);
170 mrb_init_mrbtest(mrb);
171 ret = eval_test(mrb);
172 mrb_close(mrb);
173
174 return ret;
175 }
176