1 #include <stdio.h>
2 #include <string.h>
3
4 #include "py/obj.h"
5 #include "py/objstr.h"
6 #include "py/runtime.h"
7 #include "py/gc.h"
8 #include "py/repl.h"
9 #include "py/mpz.h"
10 #include "py/builtin.h"
11 #include "py/emit.h"
12 #include "py/formatfloat.h"
13 #include "py/ringbuf.h"
14 #include "py/pairheap.h"
15 #include "py/stream.h"
16 #include "py/binary.h"
17 #include "py/bc.h"
18
19 // expected output of this file is found in extra_coverage.py.exp
20
21 #if defined(MICROPY_UNIX_COVERAGE)
22
23 // stream testing object
24 typedef struct _mp_obj_streamtest_t {
25 mp_obj_base_t base;
26 uint8_t *buf;
27 size_t len;
28 size_t pos;
29 int error_code;
30 } mp_obj_streamtest_t;
31
stest_set_buf(mp_obj_t o_in,mp_obj_t buf_in)32 STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) {
33 mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
34 mp_buffer_info_t bufinfo;
35 mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
36 o->buf = m_new(uint8_t, bufinfo.len);
37 memcpy(o->buf, bufinfo.buf, bufinfo.len);
38 o->len = bufinfo.len;
39 o->pos = 0;
40 return mp_const_none;
41 }
42 STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf);
43
stest_set_error(mp_obj_t o_in,mp_obj_t err_in)44 STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) {
45 mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
46 o->error_code = mp_obj_get_int(err_in);
47 return mp_const_none;
48 }
49 STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error);
50
stest_read(mp_obj_t o_in,void * buf,mp_uint_t size,int * errcode)51 STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
52 mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
53 if (o->pos < o->len) {
54 if (size > o->len - o->pos) {
55 size = o->len - o->pos;
56 }
57 memcpy(buf, o->buf + o->pos, size);
58 o->pos += size;
59 return size;
60 } else if (o->error_code == 0) {
61 return 0;
62 } else {
63 *errcode = o->error_code;
64 return MP_STREAM_ERROR;
65 }
66 }
67
stest_write(mp_obj_t o_in,const void * buf,mp_uint_t size,int * errcode)68 STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
69 mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
70 (void)buf;
71 (void)size;
72 *errcode = o->error_code;
73 return MP_STREAM_ERROR;
74 }
75
stest_ioctl(mp_obj_t o_in,mp_uint_t request,uintptr_t arg,int * errcode)76 STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
77 mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in);
78 (void)arg;
79 (void)request;
80 (void)errcode;
81 if (o->error_code != 0) {
82 *errcode = o->error_code;
83 return MP_STREAM_ERROR;
84 }
85 return 0;
86 }
87
88 STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
89 { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) },
90 { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) },
91 { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
92 { MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) },
93 { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
94 { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) },
95 { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
96 { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
97 { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
98 };
99
100 STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
101
102 STATIC const mp_stream_p_t fileio_stream_p = {
103 .read = stest_read,
104 .write = stest_write,
105 .ioctl = stest_ioctl,
106 };
107
108 STATIC const mp_obj_type_t mp_type_stest_fileio = {
109 { &mp_type_type },
110 .protocol = &fileio_stream_p,
111 .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict,
112 };
113
114 // stream read returns non-blocking error
stest_read2(mp_obj_t o_in,void * buf,mp_uint_t size,int * errcode)115 STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
116 (void)o_in;
117 (void)buf;
118 (void)size;
119 *errcode = MP_EAGAIN;
120 return MP_STREAM_ERROR;
121 }
122
123 STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
124 { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
125 };
126
127 STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
128
129 STATIC const mp_stream_p_t textio_stream_p2 = {
130 .read = stest_read2,
131 .write = NULL,
132 .is_text = true,
133 };
134
135 STATIC const mp_obj_type_t mp_type_stest_textio2 = {
136 { &mp_type_type },
137 .protocol = &textio_stream_p2,
138 .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict2,
139 };
140
141 // str/bytes objects without a valid hash
142 STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"};
143 STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte *)"0123456789"};
144
pairheap_lt(mp_pairheap_t * a,mp_pairheap_t * b)145 STATIC int pairheap_lt(mp_pairheap_t *a, mp_pairheap_t *b) {
146 return (uintptr_t)a < (uintptr_t)b;
147 }
148
149 // ops array contain operations: x>=0 means push(x), x<0 means delete(-x)
pairheap_test(size_t nops,int * ops)150 STATIC void pairheap_test(size_t nops, int *ops) {
151 mp_pairheap_t node[8];
152 for (size_t i = 0; i < MP_ARRAY_SIZE(node); ++i) {
153 mp_pairheap_init_node(pairheap_lt, &node[i]);
154 }
155 mp_pairheap_t *heap = mp_pairheap_new(pairheap_lt);
156 printf("create:");
157 for (size_t i = 0; i < nops; ++i) {
158 if (ops[i] >= 0) {
159 heap = mp_pairheap_push(pairheap_lt, heap, &node[ops[i]]);
160 } else {
161 heap = mp_pairheap_delete(pairheap_lt, heap, &node[-ops[i]]);
162 }
163 if (mp_pairheap_is_empty(pairheap_lt, heap)) {
164 mp_printf(&mp_plat_print, " -");
165 } else {
166 mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);
167 ;
168 }
169 }
170 printf("\npop all:");
171 while (!mp_pairheap_is_empty(pairheap_lt, heap)) {
172 mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);
173 ;
174 heap = mp_pairheap_pop(pairheap_lt, heap);
175 }
176 printf("\n");
177 }
178
179 // function to run extra tests for things that can't be checked by scripts
extra_coverage(void)180 STATIC mp_obj_t extra_coverage(void) {
181 // mp_printf (used by ports that don't have a native printf)
182 {
183 mp_printf(&mp_plat_print, "# mp_printf\n");
184 mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign
185 mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding
186 mp_printf(&mp_plat_print, "%ld\n", 123); // long
187 mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex
188 mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex
189 mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", MP_QSTR_True, MP_QSTR_True); // fixed string precision
190 mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision
191 mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools
192 #ifndef NDEBUG
193 mp_printf(&mp_plat_print, "%s\n", NULL); // null string
194 #else
195 mp_printf(&mp_plat_print, "(null)\n"); // without debugging mp_printf won't check for null
196 #endif
197 mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed
198 mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned
199 mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned
200 mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned
201 mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier
202 mp_printf(&mp_plat_print, "%%\n"); // literal % character
203 }
204
205 // GC
206 {
207 mp_printf(&mp_plat_print, "# GC\n");
208
209 // calling gc_free while GC is locked
210 gc_lock();
211 gc_free(NULL);
212 gc_unlock();
213
214 // using gc_realloc to resize to 0, which means free the memory
215 void *p = gc_alloc(4, false);
216 mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false));
217
218 // calling gc_nbytes with a non-heap pointer
219 mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL));
220 }
221
222 // vstr
223 {
224 mp_printf(&mp_plat_print, "# vstr\n");
225 vstr_t *vstr = vstr_new(16);
226 vstr_hint_size(vstr, 32);
227 vstr_add_str(vstr, "ts");
228 vstr_ins_byte(vstr, 1, 'e');
229 vstr_ins_char(vstr, 3, 't');
230 vstr_ins_char(vstr, 10, 's');
231 mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
232
233 vstr_cut_head_bytes(vstr, 2);
234 mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
235
236 vstr_cut_tail_bytes(vstr, 10);
237 mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
238
239 vstr_printf(vstr, "t%cst", 'e');
240 mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
241
242 vstr_cut_out_bytes(vstr, 3, 10);
243 mp_printf(&mp_plat_print, "%.*s\n", (int)vstr->len, vstr->buf);
244
245 VSTR_FIXED(fix, 4);
246 nlr_buf_t nlr;
247 if (nlr_push(&nlr) == 0) {
248 vstr_add_str(&fix, "large");
249 nlr_pop();
250 } else {
251 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
252 }
253
254 fix.len = fix.alloc;
255 if (nlr_push(&nlr) == 0) {
256 vstr_null_terminated_str(&fix);
257 nlr_pop();
258 } else {
259 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
260 }
261 }
262
263 // repl autocomplete
264 {
265 mp_printf(&mp_plat_print, "# repl\n");
266
267 const char *str;
268 size_t len = mp_repl_autocomplete("__n", 3, &mp_plat_print, &str);
269 mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
270
271 len = mp_repl_autocomplete("i", 1, &mp_plat_print, &str);
272 mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
273 mp_repl_autocomplete("import ", 7, &mp_plat_print, &str);
274 len = mp_repl_autocomplete("import ut", 9, &mp_plat_print, &str);
275 mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
276 mp_repl_autocomplete("import utime", 12, &mp_plat_print, &str);
277
278 mp_store_global(MP_QSTR_sys, mp_import_name(MP_QSTR_sys, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)));
279 mp_repl_autocomplete("sys.", 4, &mp_plat_print, &str);
280 len = mp_repl_autocomplete("sys.impl", 8, &mp_plat_print, &str);
281 mp_printf(&mp_plat_print, "%.*s\n", (int)len, str);
282 }
283
284 // attrtuple
285 {
286 mp_printf(&mp_plat_print, "# attrtuple\n");
287
288 static const qstr fields[] = {MP_QSTR_start, MP_QSTR_stop, MP_QSTR_step};
289 static const mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(2), MP_OBJ_NEW_SMALL_INT(3)};
290 mp_obj_print_helper(&mp_plat_print, mp_obj_new_attrtuple(fields, 3, items), PRINT_REPR);
291 mp_printf(&mp_plat_print, "\n");
292 }
293
294 // str
295 {
296 mp_printf(&mp_plat_print, "# str\n");
297
298 // intern string
299 mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str("intern me", 9))));
300 }
301
302 // bytearray
303 {
304 mp_printf(&mp_plat_print, "# bytearray\n");
305
306 // create a bytearray via mp_obj_new_bytearray
307 mp_buffer_info_t bufinfo;
308 mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW);
309 mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf);
310 }
311
312 // mpz
313 {
314 mp_printf(&mp_plat_print, "# mpz\n");
315
316 mp_uint_t value;
317 mpz_t mpz;
318 mpz_init_zero(&mpz);
319
320 // mpz_as_uint_checked, with success
321 mpz_set_from_int(&mpz, 12345678);
322 mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
323 mp_printf(&mp_plat_print, "%d\n", (int)value);
324
325 // mpz_as_uint_checked, with negative arg
326 mpz_set_from_int(&mpz, -1);
327 mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
328
329 // mpz_as_uint_checked, with overflowing arg
330 mpz_set_from_int(&mpz, 1);
331 mpz_shl_inpl(&mpz, &mpz, 70);
332 mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
333
334 // mpz_set_from_float with inf as argument
335 mpz_set_from_float(&mpz, 1.0 / 0.0);
336 mpz_as_uint_checked(&mpz, &value);
337 mp_printf(&mp_plat_print, "%d\n", (int)value);
338
339 // mpz_set_from_float with 0 as argument
340 mpz_set_from_float(&mpz, 0);
341 mpz_as_uint_checked(&mpz, &value);
342 mp_printf(&mp_plat_print, "%d\n", (int)value);
343
344 // mpz_set_from_float with 0<x<1 as argument
345 mpz_set_from_float(&mpz, 1e-10);
346 mpz_as_uint_checked(&mpz, &value);
347 mp_printf(&mp_plat_print, "%d\n", (int)value);
348
349 // mpz_set_from_float with 1<=x<2 as argument
350 mpz_set_from_float(&mpz, 1.5);
351 mpz_as_uint_checked(&mpz, &value);
352 mp_printf(&mp_plat_print, "%d\n", (int)value);
353
354 // mpz_set_from_float with 2<x as argument
355 mpz_set_from_float(&mpz, 12345);
356 mpz_as_uint_checked(&mpz, &value);
357 mp_printf(&mp_plat_print, "%d\n", (int)value);
358
359 // mpz_mul_inpl with dest==rhs, lhs!=rhs
360 mpz_t mpz2;
361 mpz_set_from_int(&mpz, 2);
362 mpz_init_from_int(&mpz2, 3);
363 mpz_mul_inpl(&mpz, &mpz2, &mpz);
364 mpz_as_uint_checked(&mpz, &value);
365 mp_printf(&mp_plat_print, "%d\n", (int)value);
366 }
367
368 // runtime utils
369 {
370 mp_printf(&mp_plat_print, "# runtime utils\n");
371
372 // call mp_call_function_1_protected
373 mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), MP_OBJ_NEW_SMALL_INT(1));
374 // call mp_call_function_1_protected with invalid args
375 mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str("abc", 3));
376
377 // call mp_call_function_2_protected
378 mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(1));
379 // call mp_call_function_2_protected with invalid args
380 mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str("abc", 3), mp_obj_new_str("abc", 3));
381
382 // mp_obj_int_get_uint_checked with non-negative small-int
383 mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1)));
384
385 // mp_obj_int_get_uint_checked with non-negative big-int
386 mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(2)));
387
388 // mp_obj_int_get_uint_checked with negative small-int (should raise exception)
389 nlr_buf_t nlr;
390 if (nlr_push(&nlr) == 0) {
391 mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(-1));
392 nlr_pop();
393 } else {
394 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
395 }
396
397 // mp_obj_int_get_uint_checked with negative big-int (should raise exception)
398 if (nlr_push(&nlr) == 0) {
399 mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(-2));
400 nlr_pop();
401 } else {
402 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
403 }
404
405 // call mp_obj_new_exception_args (it's a part of the public C API and not used in the core)
406 mp_obj_print_exception(&mp_plat_print, mp_obj_new_exception_args(&mp_type_ValueError, 0, NULL));
407 }
408
409 // warning
410 {
411 mp_emitter_warning(MP_PASS_CODE_SIZE, "test");
412 }
413
414 // format float
415 {
416 mp_printf(&mp_plat_print, "# format float\n");
417
418 // format with inadequate buffer size
419 char buf[5];
420 mp_format_float(1, buf, sizeof(buf), 'g', 0, '+');
421 mp_printf(&mp_plat_print, "%s\n", buf);
422
423 // format with just enough buffer so that precision must be
424 // set from 0 to 1 twice
425 char buf2[8];
426 mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+');
427 mp_printf(&mp_plat_print, "%s\n", buf2);
428
429 // format where precision is trimmed to avoid buffer overflow
430 mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+');
431 mp_printf(&mp_plat_print, "%s\n", buf2);
432 }
433
434 // binary
435 {
436 mp_printf(&mp_plat_print, "# binary\n");
437
438 // call function with float and double typecodes
439 float far[1];
440 double dar[1];
441 mp_binary_set_val_array_from_int('f', far, 0, 123);
442 mp_printf(&mp_plat_print, "%.0f\n", (double)far[0]);
443 mp_binary_set_val_array_from_int('d', dar, 0, 456);
444 mp_printf(&mp_plat_print, "%.0lf\n", dar[0]);
445 }
446
447 // VM
448 {
449 mp_printf(&mp_plat_print, "# VM\n");
450
451 // call mp_execute_bytecode with invalide bytecode (should raise NotImplementedError)
452 mp_obj_fun_bc_t fun_bc;
453 fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state
454 mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, mp_obj_t, 1);
455 code_state->fun_bc = &fun_bc;
456 code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode
457 code_state->sp = &code_state->state[0];
458 code_state->exc_sp_idx = 0;
459 code_state->old_globals = NULL;
460 mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL);
461 mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError);
462 }
463
464 // scheduler
465 {
466 mp_printf(&mp_plat_print, "# scheduler\n");
467
468 // lock scheduler
469 mp_sched_lock();
470
471 // schedule multiple callbacks; last one should fail
472 for (int i = 0; i < 5; ++i) {
473 mp_printf(&mp_plat_print, "sched(%d)=%d\n", i, mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(i)));
474 }
475
476 // test nested locking/unlocking
477 mp_sched_lock();
478 mp_sched_unlock();
479
480 // shouldn't do anything while scheduler is locked
481 mp_handle_pending(true);
482
483 // unlock scheduler
484 mp_sched_unlock();
485 mp_printf(&mp_plat_print, "unlocked\n");
486
487 // drain pending callbacks
488 while (mp_sched_num_pending()) {
489 mp_handle_pending(true);
490 }
491
492 // setting the keyboard interrupt and raising it during mp_handle_pending
493 mp_sched_keyboard_interrupt();
494 nlr_buf_t nlr;
495 if (nlr_push(&nlr) == 0) {
496 mp_handle_pending(true);
497 nlr_pop();
498 } else {
499 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
500 }
501
502 // setting the keyboard interrupt (twice) and cancelling it during mp_handle_pending
503 mp_sched_keyboard_interrupt();
504 mp_sched_keyboard_interrupt();
505 mp_handle_pending(false);
506
507 // setting keyboard interrupt and a pending event (intr should be handled first)
508 mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(10));
509 mp_sched_keyboard_interrupt();
510 if (nlr_push(&nlr) == 0) {
511 mp_handle_pending(true);
512 nlr_pop();
513 } else {
514 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
515 }
516 mp_handle_pending(true);
517 }
518
519 // ringbuf
520 {
521 byte buf[100];
522 ringbuf_t ringbuf = {buf, sizeof(buf), 0, 0};
523
524 mp_printf(&mp_plat_print, "# ringbuf\n");
525
526 // Single-byte put/get with empty ringbuf.
527 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
528 ringbuf_put(&ringbuf, 22);
529 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
530 mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf));
531 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
532
533 // Two-byte put/get with empty ringbuf.
534 ringbuf_put16(&ringbuf, 0xaa55);
535 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
536 mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
537 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
538
539 // Two-byte put with full ringbuf.
540 for (int i = 0; i < 99; ++i) {
541 ringbuf_put(&ringbuf, i);
542 }
543 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
544 mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
545 // Two-byte put with one byte free.
546 ringbuf_get(&ringbuf);
547 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
548 mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377));
549 ringbuf_get(&ringbuf);
550 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
551 mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99));
552 for (int i = 0; i < 97; ++i) {
553 ringbuf_get(&ringbuf);
554 }
555 mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
556 mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf));
557
558 // Two-byte put with wrap around on first byte:
559 ringbuf.iput = 0;
560 ringbuf.iget = 0;
561 for (int i = 0; i < 99; ++i) {
562 ringbuf_put(&ringbuf, i);
563 ringbuf_get(&ringbuf);
564 }
565 mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb));
566 mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
567
568 // Two-byte put with wrap around on second byte:
569 ringbuf.iput = 0;
570 ringbuf.iget = 0;
571 for (int i = 0; i < 98; ++i) {
572 ringbuf_put(&ringbuf, i);
573 ringbuf_get(&ringbuf);
574 }
575 mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x22ff));
576 mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf));
577
578 // Two-byte get from empty ringbuf.
579 ringbuf.iput = 0;
580 ringbuf.iget = 0;
581 mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
582
583 // Two-byte get from ringbuf with one byte available.
584 ringbuf.iput = 0;
585 ringbuf.iget = 0;
586 ringbuf_put(&ringbuf, 0xaa);
587 mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf));
588 }
589
590 // pairheap
591 {
592 mp_printf(&mp_plat_print, "# pairheap\n");
593
594 // Basic case.
595 int t0[] = {0, 2, 1, 3};
596 pairheap_test(MP_ARRAY_SIZE(t0), t0);
597
598 // All pushed in reverse order.
599 int t1[] = {7, 6, 5, 4, 3, 2, 1, 0};
600 pairheap_test(MP_ARRAY_SIZE(t1), t1);
601
602 // Basic deletion.
603 int t2[] = {1, -1, -1, 1, 2, -2, 2, 3, -3};
604 pairheap_test(MP_ARRAY_SIZE(t2), t2);
605
606 // Deletion of first child that has next node (the -3).
607 int t3[] = {1, 2, 3, 4, -1, -3};
608 pairheap_test(MP_ARRAY_SIZE(t3), t3);
609
610 // Deletion of node that's not first child (the -2).
611 int t4[] = {1, 2, 3, 4, -2};
612 pairheap_test(MP_ARRAY_SIZE(t4), t4);
613
614 // Deletion of node that's not first child and has children (the -3).
615 int t5[] = {3, 4, 5, 1, 2, -3};
616 pairheap_test(MP_ARRAY_SIZE(t5), t5);
617 }
618
619 // mp_obj_is_type and derivatives
620 {
621 mp_printf(&mp_plat_print, "# mp_obj_is_type\n");
622
623 // mp_obj_is_bool accepts only booleans
624 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(mp_const_true), mp_obj_is_bool(mp_const_false));
625 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_bool(mp_const_none));
626
627 // mp_obj_is_integer accepts ints and booleans
628 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_integer(mp_obj_new_int_from_ll(1)));
629 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false));
630 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str("1", 1)), mp_obj_is_integer(mp_const_none));
631
632 // mp_obj_is_int accepts small int and object ints
633 mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_int(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_int(mp_obj_new_int_from_ll(1)));
634 }
635
636 mp_printf(&mp_plat_print, "# end coverage.c\n");
637
638 mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t);
639 s->base.type = &mp_type_stest_fileio;
640 s->buf = NULL;
641 s->len = 0;
642 s->pos = 0;
643 s->error_code = 0;
644 mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t);
645 s2->base.type = &mp_type_stest_textio2;
646
647 // return a tuple of data for testing on the Python side
648 mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)};
649 return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items);
650 }
651 MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage);
652
653 #endif
654